Hi,

I would like to submit a patch for importing truncate(1) from FreeBSD.

You can find the original source here:
https://github.com/freebsd/freebsd-src/tree/main/usr.bin/truncate

Please let me know what you think of it and if I should, perhaps,
change something.

        Naveen

Index: usr.bin/truncate/Makefile
===================================================================
RCS file: usr.bin/truncate/Makefile
diff -N usr.bin/truncate/Makefile
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- usr.bin/truncate/Makefile   11 Sep 2021 10:22:51 -0000
***************
*** 0 ****
--- 1,8 ----
+ #     $NetBSD$
+ 
+ PROG= truncate
+ 
+ DPADD+= ${LIBUTIL}
+ LDADD+= -lutil
+ 
+ .include <bsd.prog.mk>
Index: usr.bin/truncate/truncate.1
===================================================================
RCS file: usr.bin/truncate/truncate.1
diff -N usr.bin/truncate/truncate.1
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- usr.bin/truncate/truncate.1 11 Sep 2021 10:22:51 -0000
***************
*** 0 ****
--- 1,249 ----
+ .\"   $NetBSD$
+ .\"
+ .\" Copyright (c) 2000 Sheldon Hearn <sheld...@freebsd.org>.
+ .\" All rights reserved.
+ .\" Copyright (c) 2021 The FreeBSD Foundation
+ .\"
+ .\" Portions of this manual page were written by Ka Ho Ng <k...@freebsd.org>
+ .\" under sponsorship from the FreeBSD Foundation.
+ .\"
+ .\" Redistribution and use in source and binary forms, with or without
+ .\" modification, are permitted provided that the following conditions
+ .\" are met:
+ .\" 1. Redistributions of source code must retain the above copyright
+ .\"    notice, this list of conditions and the following disclaimer.
+ .\" 2. Redistributions in binary form must reproduce the above copyright
+ .\"    notice, this list of conditions and the following disclaimer in the
+ .\"    documentation and/or other materials provided with the distribution.
+ .\"
+ .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ .\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ .\" SUCH DAMAGE.
+ .\"
+ .\" $FreeBSD$
+ .\"
+ .Dd August 19, 2021
+ .Dt TRUNCATE 1
+ .Os
+ .Sh NAME
+ .Nm truncate
+ .Nd truncate, extend the length of files, or perform space management in files
+ .Sh SYNOPSIS
+ .Nm
+ .Op Fl c
+ .Bk -words
+ .Fl s Xo
+ .Sm off
+ .Op Cm + | - | % | /
+ .Ar size
+ .Op Cm SUFFIX
+ .Sm on
+ .Xc
+ .Ek
+ .Ar
+ .Nm
+ .Op Fl c
+ .Bk -words
+ .Fl r Ar rfile
+ .Ek
+ .Ar
+ .Nm
+ .Op Fl c
+ .Bk -words
+ .Fl d
+ .Oo
+ .Fl o Xo
+ .Sm off
+ .Ar offset
+ .Op Cm SUFFIX
+ .Sm on
+ .Xc
+ .Oc
+ .Fl l Xo
+ .Sm off
+ .Ar length
+ .Op Cm SUFFIX
+ .Sm on
+ .Xc
+ .Ek
+ .Ar
+ .Sh DESCRIPTION
+ The
+ .Nm
+ utility adjusts the length of each regular file given on the command-line, or
+ performs space management with the given offset and the length over a regular
+ file given on the command-line.
+ .Pp
+ The following options are available:
+ .Bl -tag -width indent
+ .It Fl c
+ Do not create files if they do not exist.
+ The
+ .Nm
+ utility does not treat this as an error.
+ No error messages are displayed
+ and the exit value is not affected.
+ .It Fl r Ar rfile
+ Truncate or extend files to the length of the file
+ .Ar rfile .
+ .It Fl s Xo
+ .Sm off
+ .Op Cm + | - | % | /
+ .Ar size
+ .Op Cm SUFFIX
+ .Sm on
+ .Xc
+ If the
+ .Ar size
+ argument is preceded by a plus sign
+ .Pq Cm + ,
+ files will be extended by this number of bytes.
+ If the
+ .Ar size
+ argument is preceded by a dash
+ .Pq Cm - ,
+ file lengths will be reduced by no more than this number of bytes,
+ to a minimum length of zero bytes.
+ If the
+ .Ar size
+ argument is preceded by a percent sign
+ .Pq Cm % ,
+ files will be round up to a multiple of this number of bytes.
+ If the
+ .Ar size
+ argument is preceded by a slash sign
+ .Pq Cm / ,
+ files will be round down to a multiple of this number of bytes,
+ to a minimum length of zero bytes.
+ Otherwise, the
+ .Ar size
+ argument specifies an absolute length to which all files
+ should be extended or reduced as appropriate.
+ .It Fl d
+ Zero a region in the specified file.
+ If the underlying file system of the given file supports hole-punching,
+ file system space deallocation may be performed in the operation region.
+ .It Fl o Ar offset
+ The space management operation is performed at the given
+ .Ar offset
+ bytes in the file.
+ If this option is not specified, the operation is performed at the beginning 
of the file.
+ .It Fl l Ar length
+ The length of the operation range in bytes.
+ This option must always be specified if option
+ .Fl d
+ is specified, and must be greater than 0.
+ .El
+ .Pp
+ The
+ .Ar size ,
+ .Ar offset
+ and
+ .Ar length
+ arguments may be suffixed with one of
+ .Cm K ,
+ .Cm M ,
+ .Cm G
+ or
+ .Cm T
+ (either upper or lower case) to indicate a multiple of
+ Kilobytes, Megabytes, Gigabytes or Terabytes
+ respectively.
+ .Pp
+ Exactly one of the
+ .Fl r ,
+ .Fl s
+ and
+ .Fl d
+ options must be specified.
+ .Pp
+ If a file is made smaller, its extra data is lost.
+ If a file is made larger,
+ it will be extended as if by writing bytes with the value zero.
+ If the file does not exist,
+ it is created unless the
+ .Fl c
+ option is specified.
+ .Pp
+ Note that,
+ while truncating a file causes space on disk to be freed,
+ extending a file does not cause space to be allocated.
+ To extend a file and actually allocate the space,
+ it is necessary to explicitly write data to it,
+ using (for example) the shell's
+ .Ql >>
+ redirection syntax, or
+ .Xr dd 1 .
+ .Sh EXIT STATUS
+ .Ex -std
+ If the operation fails for an argument,
+ .Nm
+ will issue a diagnostic
+ and continue processing the remaining arguments.
+ .Sh EXAMPLES
+ Adjust the size of the file
+ .Pa test_file
+ to 10 Megabytes but do not create it if it does not exist:
+ .Bd -literal -offset indent
+ truncate -c -s +10M test_file
+ .Ed
+ .Pp
+ Same as above but create the file if it does not exist:
+ .Bd -literal -offset indent
+ truncate -s +10M test_file
+ ls -l test_file
+ -rw-r--r--  1 root  wheel  10485760 Jul 22 18:48 test_file
+ .Ed
+ .Pp
+ Adjust the size of
+ .Pa test_file
+ to the size of the kernel and create another file
+ .Pa test_file2
+ with the same size:
+ .Bd -literal -offset indent
+ truncate -r /boot/kernel/kernel test_file test_file2
+ ls -l /boot/kernel/kernel test_file*
+ -r-xr-xr-x  1 root  wheel    31352552 May 15 14:18 /boot/kernel/kernel*
+ -rw-r--r--  1 root  wheel    31352552 Jul 22 19:15 test_file
+ -rw-r--r--  1 root  wheel    31352552 Jul 22 19:15 test_file2
+ .Ed
+ .Pp
+ Downsize
+ .Pa test_file
+ in 5 Megabytes:
+ .Bd -literal -offset indent
+ # truncate -s -5M test_file
+ ls -l test_file*
+ -rw-r--r--  1 root  wheel    26109672 Jul 22 19:17 test_file
+ -rw-r--r--  1 root  wheel    31352552 Jul 22 19:15 test_file2
+ .Ed
+ .Sh SEE ALSO
+ .Xr dd 1 ,
+ .Xr touch 1 ,
+ .Xr fspacectl 2 ,
+ .Xr truncate 2
+ .Sh STANDARDS
+ The
+ .Nm
+ utility conforms to no known standards.
+ .Sh HISTORY
+ The
+ .Nm
+ utility first appeared in
+ .Fx 4.2 .
+ .Sh AUTHORS
+ The
+ .Nm
+ utility was written by
+ .An Sheldon Hearn Aq Mt sheld...@starjuice.net .
+ Hole-punching support of this
+ utility was developed by
+ .An Ka Ho Ng Aq Mt k...@freebsd.org .
Index: usr.bin/truncate/truncate.c
===================================================================
RCS file: usr.bin/truncate/truncate.c
diff -N usr.bin/truncate/truncate.c
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- usr.bin/truncate/truncate.c 11 Sep 2021 10:22:51 -0000
***************
*** 0 ****
--- 1,222 ----
+ /* $NetBSD$ */
+ /*-
+  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+  *
+  * Copyright (c) 2000 Sheldon Hearn <sheld...@freebsd.org>.
+  * All rights reserved.
+  *
+  * Copyright (c) 2021 The FreeBSD Foundation
+  *
+  * Portions of this software were developed by Ka Ho Ng <k...@freebsd.org>
+  * under sponsorship from the FreeBSD Foundation.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice, this list of conditions and the following disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  * SUCH DAMAGE.
+  *
+  */
+ 
+ #include <sys/stat.h>
+ 
+ #include <ctype.h>
+ #include <err.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <util.h>
+ 
+ __dead static void    usage(void);
+ 
+ int
+ main(int argc, char **argv)
+ {
+       struct stat sb;
+       mode_t omode;
+       off_t oflow, rsize, sz, tsize, round, off, len;
+       int64_t usz;
+       int ch, error, fd, oflags, r;
+       int do_dealloc;
+       int do_truncate;
+       int no_create;
+       int do_relative;
+       int do_round;
+       int do_refer;
+       int got_size;
+       char *fname, *rname;
+ 
+       fd = -1;
+       rsize = tsize = sz = off = 0;
+       len = -1;
+       do_dealloc = no_create = do_relative = do_round = do_refer =
+           got_size = 0;
+       do_truncate = 1;
+       error = r = 0;
+       rname = NULL;
+       while ((ch = getopt(argc, argv, "cdr:s:o:l:")) != -1)
+               switch (ch) {
+               case 'c':
+                       no_create = 1;
+                       break;
+               case 'd':
+                       do_dealloc = 1;
+                       do_truncate = 0;
+                       break;
+               case 'r':
+                       do_refer = 1;
+                       rname = optarg;
+                       break;
+               case 's':
+                       if (*optarg == '+' || *optarg == '-') {
+                               do_relative = 1;
+                       } else if (*optarg == '%' || *optarg == '/') {
+                               do_round = 1;
+                       }
+                       if (dehumanize_number(do_relative || do_round ?
+                               optarg + 1 : optarg,
+                               &usz) == -1 || usz <= 0)
+                               errx(EXIT_FAILURE,
+                                   "invalid size argument `%s'", optarg);
+ 
+                       sz = (*optarg == '-' || *optarg == '/') ?
+                           -usz : usz;
+                       got_size = 1;
+                       break;
+               case 'o':
+                       if (dehumanize_number(optarg, &usz) == -1 ||
+                           usz < 0)
+                               errx(EXIT_FAILURE,
+                                   "invalid offset argument `%s'", optarg);
+ 
+                       off = usz;
+                       break;
+               case 'l':
+                       if (dehumanize_number(optarg, &usz) == -1 ||
+                           usz <= 0)
+                               errx(EXIT_FAILURE,
+                                   "invalid length argument `%s'", optarg);
+ 
+                       len = usz;
+                       break;
+               default:
+                       usage();
+                       /* NOTREACHED */
+               }
+ 
+       argv += optind;
+       argc -= optind;
+ 
+       /*
+        * Exactly one of do_refer, got_size or do_dealloc must be specified.
+        * Since do_relative implies got_size, do_relative, do_refer and
+        * do_dealloc are also mutually exclusive.  If do_dealloc is specified,
+        * the length argument must be set.  See usage() for allowed
+        * invocations.
+        */
+       if (argc < 1 || do_refer + got_size + do_dealloc != 1 ||
+           (do_dealloc == 1 && len == -1))
+               usage();
+       if (do_refer == 1) {
+               if (stat(rname, &sb) == -1)
+                       err(EXIT_FAILURE, "%s", rname);
+               tsize = sb.st_size;
+       } else if (do_relative == 1 || do_round == 1)
+               rsize = sz;
+       else if (do_dealloc == 0)
+               tsize = sz;
+ 
+       if (no_create)
+               oflags = O_WRONLY;
+       else
+               oflags = O_WRONLY | O_CREAT;
+       omode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ 
+       while ((fname = *argv++) != NULL) {
+               if (fd != -1)
+                       close(fd);
+               if ((fd = open(fname, oflags, omode)) == -1) {
+                       if (errno != ENOENT) {
+                               warn("%s", fname);
+                               error++;
+                       }
+                       continue;
+               }
+               if (do_relative == 1) {
+                       if (fstat(fd, &sb) == -1) {
+                               warn("%s", fname);
+                               error++;
+                               continue;
+                       }
+                       oflow = sb.st_size + rsize;
+                       if (oflow < (sb.st_size + rsize)) {
+                               errno = EFBIG;
+                               warn("%s", fname);
+                               error++;
+                               continue;
+                       }
+                       tsize = oflow;
+               }
+               if (do_round == 1) {
+                       if (fstat(fd, &sb) == -1) {
+                               warn("%s", fname);
+                               error++;
+                               continue;
+                       }
+                       sz = rsize;
+                       if (sz < 0)
+                               sz = -sz;
+                       if (sb.st_size % sz) {
+                               round = sb.st_size / sz;
+                               if (rsize > 0)
+                                       round++;
+                               tsize = round * sz;
+                       } else
+                               tsize = sb.st_size;
+               }
+               if (tsize < 0)
+                       tsize = 0;
+ 
+               if (do_dealloc == 1) {
+                       r = fdiscard(fd, off, len);
+               }
+               if (do_truncate == 1)
+                       r = ftruncate(fd, tsize);
+               if (r == -1) {
+                       warn("%s", fname);
+                       error++;
+               }
+       }
+       if (fd != -1)
+               close(fd);
+ 
+       return (error ? EXIT_FAILURE : EXIT_SUCCESS);
+ }
+ 
+ static void
+ usage(void)
+ {
+       const char *pnam = getprogname();
+       fprintf(stderr, "usage:\t%s %s\n\t%s %s\n\t%s %s\n",
+           pnam, "[-c] -s [+|-|%|/]size[K|k|M|m|G|g|T|t] file ...",
+           pnam, "[-c] -r rfile file ...",
+           pnam, "[-c] -d [-o offset[K|k|M|m|G|g|T|t]] -l 
length[K|k|M|m|G|g|T|t] file ...");
+       exit(EXIT_FAILURE);
+ }
? tests/usr.bin/truncate/Atffile
? tests/usr.bin/truncate/t_grow
? tests/usr.bin/truncate/t_misc
? tests/usr.bin/truncate/t_shrink
Index: usr.bin/Makefile
===================================================================
RCS file: /cvsroot/src/usr.bin/Makefile,v
retrieving revision 1.235
diff -c -c -r1.235 Makefile
*** usr.bin/Makefile    7 May 2021 21:51:20 -0000       1.235
--- usr.bin/Makefile    11 Sep 2021 10:22:53 -0000
***************
*** 29,35 ****
        spell split stat su sys_info systat \
        tabs tail talk tcopy tee telnet tftp tic time timeout tip touch \
        tput \
!       tr true tset tsort tty ul uname unexpand unifdef \
        uniq units unvis unzip usbhidaction usbhidctl users utoppya \
        uudecode uuencode uuidgen vacation vgrind videoctl vis \
        vmstat vndcompress w \
--- 29,35 ----
        spell split stat su sys_info systat \
        tabs tail talk tcopy tee telnet tftp tic time timeout tip touch \
        tput \
!       tr true truncate tset tsort tty ul uname unexpand unifdef \
        uniq units unvis unzip usbhidaction usbhidctl users utoppya \
        uudecode uuencode uuidgen vacation vgrind videoctl vis \
        vmstat vndcompress w \
Index: tests/usr.bin/Makefile
===================================================================
RCS file: /cvsroot/src/tests/usr.bin/Makefile,v
retrieving revision 1.34
diff -c -c -r1.34 Makefile
*** tests/usr.bin/Makefile      1 Nov 2020 22:28:32 -0000       1.34
--- tests/usr.bin/Makefile      11 Sep 2021 10:22:53 -0000
***************
*** 9,15 ****
                diff dirname find fstat gdb grep gzip id indent \
                infocmp jot ld locale m4 make mixerctl mkdep nbperf \
                netpgpverify patch pkill pr printf pwhash rump_server \
!               shmif_dumpbus sdiff sed sort tar tmux tr unifdef uniq \
                vmstat xlint ztest
  
  .if ${MKCXX} != "no"
--- 9,15 ----
                diff dirname find fstat gdb grep gzip id indent \
                infocmp jot ld locale m4 make mixerctl mkdep nbperf \
                netpgpverify patch pkill pr printf pwhash rump_server \
!               shmif_dumpbus sdiff sed sort tar tmux tr truncate unifdef uniq \
                vmstat xlint ztest
  
  .if ${MKCXX} != "no"
Index: etc/mtree/NetBSD.dist.tests
===================================================================
RCS file: /cvsroot/src/etc/mtree/NetBSD.dist.tests,v
retrieving revision 1.187
diff -c -c -r1.187 NetBSD.dist.tests
*** etc/mtree/NetBSD.dist.tests 12 Aug 2021 11:50:42 -0000      1.187
--- etc/mtree/NetBSD.dist.tests 11 Sep 2021 10:22:54 -0000
***************
*** 458,463 ****
--- 458,464 ----
  ./usr/tests/usr.bin/tar
  ./usr/tests/usr.bin/tmux
  ./usr/tests/usr.bin/tr
+ ./usr/tests/usr.bin/truncate
  ./usr/tests/usr.bin/unifdef
  ./usr/tests/usr.bin/uniq
  ./usr/tests/usr.bin/vmstat
Index: distrib/sets/lists/tests/mi
===================================================================
RCS file: /cvsroot/src/distrib/sets/lists/tests/mi,v
retrieving revision 1.1111
diff -c -c -r1.1111 mi
*** distrib/sets/lists/tests/mi 12 Aug 2021 15:06:39 -0000      1.1111
--- distrib/sets/lists/tests/mi 11 Sep 2021 10:22:56 -0000
***************
*** 6095,6100 ****
--- 6095,6105 ----
  ./usr/tests/usr.bin/tr/Atffile                                
tests-usr.bin-tests     compattestfile,atf
  ./usr/tests/usr.bin/tr/Kyuafile                               
tests-usr.bin-tests     compattestfile,atf,kyua
  ./usr/tests/usr.bin/tr/t_basic                                
tests-usr.bin-tests     compattestfile,atf
+ ./usr/tests/usr.bin/truncate/                         tests-usr.bin-tests     
compattestfile,atf
+ ./usr/tests/usr.bin/truncate/Atffile                  tests-usr.bin-tests     
compattestfile,atf
+ ./usr/tests/usr.bin/truncate/t_grow                   tests-usr.bin-tests     
compattestfile,atf
+ ./usr/tests/usr.bin/truncate/t_misc                   tests-usr.bin-tests     
compattestfile,atf
+ ./usr/tests/usr.bin/truncate/t_shrink                 tests-usr.bin-tests     
compattestfile,atf
  ./usr/tests/usr.bin/unifdef                           tests-usr.bin-tests     
compattestfile,atf
  ./usr/tests/usr.bin/unifdef/Atffile                   tests-usr.bin-tests     
compattestfile,atf
  ./usr/tests/usr.bin/unifdef/Kyuafile                  tests-usr.bin-tests     
compattestfile,atf,kyua
Index: tests/usr.bin/truncate/Makefile
===================================================================
RCS file: tests/usr.bin/truncate/Makefile
diff -N tests/usr.bin/truncate/Makefile
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- tests/usr.bin/truncate/Makefile     11 Sep 2021 10:22:56 -0000
***************
*** 0 ****
--- 1,11 ----
+ #     $NetBSD$
+ 
+ .include <bsd.own.mk>
+ 
+ TESTSDIR= ${TESTSBASE}/usr.bin/truncate
+ 
+ TESTS_SH+= t_grow
+ TESTS_SH+= t_shrink
+ TESTS_SH+= t_misc
+ 
+ .include <bsd.test.mk>
Index: tests/usr.bin/truncate/t_grow.sh
===================================================================
RCS file: tests/usr.bin/truncate/t_grow.sh
diff -N tests/usr.bin/truncate/t_grow.sh
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- tests/usr.bin/truncate/t_grow.sh    11 Sep 2021 10:22:56 -0000
***************
*** 0 ****
--- 1,122 ----
+ # $NetBSD$
+ # Copyright (c) 2021 The NetBSD Foundation, Inc.
+ # All rights reserved.
+ #
+ # Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions
+ # are met:
+ # 1. Redistributions of source code must retain the above copyright
+ #    notice, this list of conditions and the following disclaimer.
+ # 2. Redistributions in binary form must reproduce the above copyright
+ #    notice, this list of conditions and the following disclaimer in the
+ #    documentation and/or other materials provided with the distribution.
+ #
+ # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ # POSSIBILITY OF SUCH DAMAGE.
+ #
+ 
+ server="rump_server -lrumpvfs -lrumpdev_disk -lrumpfs_ffs -d 
key=/dev/dk,hostpath=ffs.img,size=host"
+ 
+ export RUMP_SERVER=unix://ffs
+ 
+ exmount='rumpfs on / type rumpfs (local)
+ /dev/dk on /mnt type ffs (local)
+ '
+ 
+ t_init()
+ {
+       atf_check -s exit:0 -o ignore -e ignore newfs -b 32k -f 4k -F -s 10M 
ffs.img
+ 
+       atf_check -s exit:0 -o ignore -e ignore ${server} ${RUMP_SERVER}
+ 
+       export LD_PRELOAD=/usr/lib/librumphijack.so
+       atf_check -s exit:0 -o ignore -e ignore mkdir /rump/mnt
+       export RUMPHIJACK=vfs=all,blanket=/dev/dk:/mnt
+       atf_check -s exit:0 -o ignore -e ignore mount /dev/dk /mnt
+       atf_check -s exit:0 -o inline:"${exmount}" mount
+ }
+ 
+ t_cleanup()
+ {
+       rump.halt
+ }
+ 
+ atf_test_case abs_grow
+ abs_grow_head()
+ {
+       atf_set "descr" "Tests that truncate can grow a file to absolute length"
+       atf_set "use.fs" "true"
+       atf_set "require.progs" "ls awk du"
+ }
+ abs_grow_body()
+ {
+       t_init
+ 
+       # truncate should allocate the first and the last block only
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 10M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 128
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((10 * 1024 
* 1024))
+ 
+       # truncate should allocate 3 blocks in this case since it extends the 
file
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 20M /mnt/test_file
+       atf_check_equal $(du /mnt/test_file | awk '{print $1}') 192
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((20 * 1024 
* 1024))
+ 
+       t_cleanup
+ }
+ 
+ atf_test_case rela_grow
+ rela_grow_head()
+ {
+       atf_set "descr" "Check truncate can grow file to relative length"
+       atf_set "use.fs" "true"
+       atf_set "require.progs" "ls awk du"
+ }
+ rela_grow_body()
+ {
+       t_init
+ 
+       # truncate should allocate the first and the last block only
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 10M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 128
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((10 * 1024 
* 1024))
+ 
+       # truncate should allocate 3 blocks in this case since it extends the 
file
+       atf_check -s exit:0 -o ignore -e ignore truncate -s +10M /mnt/test_file
+       atf_check_equal $(du /mnt/test_file | awk '{print $1}') 192
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((20 * 1024 
* 1024))
+ 
+       t_cleanup
+ }
+ 
+ atf_test_case nocreate
+ nocreate_head()
+ {
+       atf_set "descr" "Check file is not created with -c"
+       atf_set "use.fs" "true"
+ }
+ nocreate_body()
+ {
+       t_init
+ 
+       # test_file should not exist
+       atf_check -s exit:0 -o ignore -e ignore truncate -c -s 10M 
/mnt/test_file
+       atf_check -s not-exit:0 -e ignore 'ls /mnt/test_file'
+ 
+       t_cleanup
+ }
+ 
+ atf_init_test_cases() {
+       atf_add_test_case abs_grow
+       atf_add_test_case rela_grow
+       atf_add_test_case nocreate
+ }
Index: tests/usr.bin/truncate/t_misc.sh
===================================================================
RCS file: tests/usr.bin/truncate/t_misc.sh
diff -N tests/usr.bin/truncate/t_misc.sh
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- tests/usr.bin/truncate/t_misc.sh    11 Sep 2021 10:22:56 -0000
***************
*** 0 ****
--- 1,153 ----
+ # $NetBSD$
+ # Copyright (c) 2021 The NetBSD Foundation, Inc.
+ # All rights reserved.
+ #
+ # Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions
+ # are met:
+ # 1. Redistributions of source code must retain the above copyright
+ #    notice, this list of conditions and the following disclaimer.
+ # 2. Redistributions in binary form must reproduce the above copyright
+ #    notice, this list of conditions and the following disclaimer in the
+ #    documentation and/or other materials provided with the distribution.
+ #
+ # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ # POSSIBILITY OF SUCH DAMAGE.
+ #
+ 
+ server="rump_server -lrumpvfs -lrumpdev_disk -lrumpfs_ffs -d 
key=/dev/dk,hostpath=ffs.img,size=host"
+ 
+ export RUMP_SERVER=unix://ffs
+ 
+ exmount='rumpfs on / type rumpfs (local)
+ /dev/dk on /mnt type ffs (local)
+ '
+ 
+ t_init()
+ {
+       atf_check -s exit:0 -o ignore -e ignore newfs -b 32k -f 4k -F -s 10M 
ffs.img
+       atf_check -s exit:0 -o ignore -e ignore ${server} ${RUMP_SERVER}
+ 
+       export LD_PRELOAD=/usr/lib/librumphijack.so
+       atf_check -s exit:0 -o ignore -e ignore mkdir /rump/mnt
+       export RUMPHIJACK=vfs=all,blanket=/dev/dk:/mnt
+       atf_check -s exit:0 -o ignore -e ignore mount /dev/dk /mnt
+       atf_check -s exit:0 -o inline:"${exmount}" mount
+ }
+ 
+ t_cleanup()
+ {
+       rump.halt
+ }
+ 
+ atf_test_case reference
+ reference_head()
+ {
+       atf_set "descr" "Tests that truncate can use a reference file"
+       atf_set "use.fs" "true"
+       atf_set "require.progs" "ls awk du"
+ }
+ reference_body()
+ {
+       t_init
+ 
+       # create a reference file
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 10M /mnt/test_file1
+       atf_check_equal $(du -s /mnt/test_file1 | awk '{print $1}') 128
+       atf_check_equal $(ls -l /mnt/test_file1 | awk '{print $5}') $((10 * 
1024 * 1024))
+ 
+       # truncate should extend the file to the length of the reference file
+       atf_check -s exit:0 -o ignore -e ignore truncate -r /mnt/test_file1 
/mnt/test_file2
+       atf_check_equal $(du -s /mnt/test_file2 | awk '{print $1}') 128
+       atf_check_equal $(ls -l /mnt/test_file2 | awk '{print $5}') $((10 * 
1024 * 1024))
+ 
+       t_cleanup
+ }
+ 
+ atf_test_case negative
+ negative_head()
+ {
+       atf_set "descr" "Tests that truncate treats negative size as zero"
+       atf_set "use.fs" "true"
+       atf_set "require.progs" "ls awk du"
+ }
+ negative_body()
+ {
+       t_init
+ 
+       # create/extend a file
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 10M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 128
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((10 * 1024 
* 1024))
+ 
+       # truncate should shrink the file to zero size
+       atf_check -s exit:0 -o ignore -e ignore truncate -s -100M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 0
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') 0
+ 
+       t_cleanup
+ }
+ 
+ atf_test_case roundup
+ roundup_head()
+ {
+       atf_set "descr" "Tests that truncate rounds up the size of the file"
+       atf_set "use.fs" "true"
+       atf_set "require.progs" "ls awk du"
+ }
+ roundup_body()
+ {
+       t_init
+ 
+       # create/extend a file
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 6M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 128
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((6 * 1024 
* 1024))
+ 
+       # truncate should round up the size of the file
+       atf_check -s exit:0 -o ignore -e ignore truncate -s %5M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 192
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((10 * 1024 
* 1024))
+ 
+       t_cleanup
+ }
+ 
+ atf_test_case rounddown
+ rounddown_head()
+ {
+       atf_set "descr" "Tests that truncate rounds down the size of the file"
+       atf_set "use.fs" "true"
+       atf_set "require.progs" "ls awk du"
+ }
+ rounddown_body()
+ {
+       t_init
+ 
+       # create/extend a file
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 9M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 128
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((9 * 1024 
* 1024))
+ 
+       # truncate should round down the size of the file
+       atf_check -s exit:0 -o ignore -e ignore truncate -s /2M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 64
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((8 * 1024 
* 1024))
+ 
+       t_cleanup
+ }
+ 
+ atf_init_test_cases() {
+       atf_add_test_case reference
+       atf_add_test_case rounddown
+       atf_add_test_case roundup
+       atf_add_test_case negative
+ }
Index: tests/usr.bin/truncate/t_shrink.sh
===================================================================
RCS file: tests/usr.bin/truncate/t_shrink.sh
diff -N tests/usr.bin/truncate/t_shrink.sh
*** /dev/null   1 Jan 1970 00:00:00 -0000
--- tests/usr.bin/truncate/t_shrink.sh  11 Sep 2021 10:22:56 -0000
***************
*** 0 ****
--- 1,103 ----
+ # $NetBSD$
+ # Copyright (c) 2021 The NetBSD Foundation, Inc.
+ # All rights reserved.
+ #
+ # Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions
+ # are met:
+ # 1. Redistributions of source code must retain the above copyright
+ #    notice, this list of conditions and the following disclaimer.
+ # 2. Redistributions in binary form must reproduce the above copyright
+ #    notice, this list of conditions and the following disclaimer in the
+ #    documentation and/or other materials provided with the distribution.
+ #
+ # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ # POSSIBILITY OF SUCH DAMAGE.
+ #
+ 
+ server="rump_server -lrumpvfs -lrumpdev_disk -lrumpfs_ffs -d 
key=/dev/dk,hostpath=ffs.img,size=host"
+ 
+ export RUMP_SERVER=unix://ffs
+ 
+ exmount='rumpfs on / type rumpfs (local)
+ /dev/dk on /mnt type ffs (local)
+ '
+ 
+ t_init()
+ {
+       atf_check -s exit:0 -o ignore -e ignore newfs -b 32k -f 4k -F -s 10M 
ffs.img
+       atf_check -s exit:0 -o ignore -e ignore ${server} ${RUMP_SERVER}
+ 
+       export LD_PRELOAD=/usr/lib/librumphijack.so
+       atf_check -s exit:0 -o ignore -e ignore mkdir /rump/mnt
+       export RUMPHIJACK=vfs=all,blanket=/dev/dk:/mnt
+       atf_check -s exit:0 -o ignore -e ignore mount /dev/dk /mnt
+       atf_check -s exit:0 -o inline:"${exmount}" mount
+ }
+ 
+ t_cleanup()
+ {
+       rump.halt
+ }
+ 
+ atf_test_case abs_shrink
+ abs_shrink_head()
+ {
+       atf_set "descr" "Tests that truncate can shrink a file to absolute 
length"
+       atf_set "use.fs" "true"
+       atf_set "require.progs" "ls awk du"
+ }
+ abs_shrink_body()
+ {
+       t_init
+ 
+       # truncate should allocate the first and the last block only
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 10M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 128
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((10 * 1024 
* 1024))
+ 
+       # truncate should allocate only one block post shrink
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 5M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 64
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((5 * 1024 
* 1024))
+ 
+       t_cleanup
+ }
+ 
+ atf_test_case rela_shrink
+ rela_shrink_head()
+ {
+       atf_set "descr" "Tests that truncate can shrink a file to relative 
length"
+       atf_set "use.fs" "true"
+       atf_set "require.progs" "ls awk du"
+ }
+ rela_shrink_body()
+ {
+       t_init
+ 
+       # truncate should allocate the first and the last block only
+       atf_check -s exit:0 -o ignore -e ignore truncate -s 10M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 128
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((10 * 1024 
* 1024))
+ 
+       # truncate should allocate only one block post shrink
+       atf_check -s exit:0 -o ignore -e ignore truncate -s -5M /mnt/test_file
+       atf_check_equal $(du -s /mnt/test_file | awk '{print $1}') 64
+       atf_check_equal $(ls -l /mnt/test_file | awk '{print $5}') $((5 * 1024 
* 1024))
+ 
+       t_cleanup
+ }
+ 
+ atf_init_test_cases() {
+       atf_add_test_case abs_shrink
+       atf_add_test_case rela_shrink
+ }


----- End forwarded message -----

        Naveen

Reply via email to