The branch main has been updated by khng:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=5ee2c35751ef5d131222423bf3e25073f997c337

commit 5ee2c35751ef5d131222423bf3e25073f997c337
Author:     Ka Ho Ng <[email protected]>
AuthorDate: 2021-08-19 10:30:41 +0000
Commit:     Ka Ho Ng <[email protected]>
CommitDate: 2021-08-19 10:30:41 +0000

    truncate(1): Add hole-punching support
    
    This commit adds hole-punching support to the truncate(1) utility. If
    the option -d is specified, truncate(1) performs zeroing, and if
    possible hole-punching in case the operation is supported by the
    underlying file system of the specified files.
    
    Sponsored by:   The FreeBSD Foundation
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D31556
---
 usr.bin/truncate/truncate.1 | 63 +++++++++++++++++++++++++++++++-----
 usr.bin/truncate/truncate.c | 79 ++++++++++++++++++++++++++++++++++-----------
 2 files changed, 115 insertions(+), 27 deletions(-)

diff --git a/usr.bin/truncate/truncate.1 b/usr.bin/truncate/truncate.1
index 2058530162c5..54780ccbca83 100644
--- a/usr.bin/truncate/truncate.1
+++ b/usr.bin/truncate/truncate.1
@@ -1,6 +1,10 @@
 .\"
 .\" Copyright (c) 2000 Sheldon Hearn <[email protected]>.
 .\" All rights reserved.
+.\" Copyright (c) 2021 The FreeBSD Foundation
+.\"
+.\" Portions of this manual page were written by Ka Ho Ng <[email protected]>
+.\" 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
@@ -25,12 +29,12 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 27, 2020
+.Dd August 18, 2021
 .Dt TRUNCATE 1
 .Os
 .Sh NAME
 .Nm truncate
-.Nd truncate or extend the length of files
+.Nd truncate, extend the length of files, or perform space management in files
 .Sh SYNOPSIS
 .Nm
 .Op Fl c
@@ -39,7 +43,7 @@
 .Sm off
 .Op Cm + | - | % | /
 .Ar size
-.Op Cm K | k | M | m | G | g | T | t
+.Op Cm SUFFIX
 .Sm on
 .Xc
 .Ek
@@ -50,10 +54,32 @@
 .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.
+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
@@ -71,7 +97,7 @@ Truncate or extend files to the length of the file
 .Sm off
 .Op Cm + | - | % | /
 .Ar size
-.Op Cm K | k | M | m | G | g | T | t
+.Op Cm SUFFIX
 .Sm on
 .Xc
 If the
@@ -100,10 +126,28 @@ 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
-argument may be suffixed with one of
+.Ar size ,
+.Ar offset
+and
+.Ar length
+arguments may be suffixed with one of
 .Cm K ,
 .Cm M ,
 .Cm G
@@ -112,7 +156,6 @@ or
 (either upper or lower case) to indicate a multiple of
 Kilobytes, Megabytes, Gigabytes or Terabytes
 respectively.
-.El
 .Pp
 Exactly one of the
 .Fl r
@@ -183,6 +226,7 @@ ls -l test_file*
 .Sh SEE ALSO
 .Xr dd 1 ,
 .Xr touch 1 ,
+.Xr fspacectl 2 ,
 .Xr truncate 2
 .Sh STANDARDS
 The
@@ -198,3 +242,6 @@ The
 .Nm
 utility was written by
 .An Sheldon Hearn Aq Mt [email protected] .
+Hole-punching support of this
+utility was developed by
+.An Ka Ho Ng Aq Mt [email protected] .
diff --git a/usr.bin/truncate/truncate.c b/usr.bin/truncate/truncate.c
index a7579227f299..529d2c7e6dab 100644
--- a/usr.bin/truncate/truncate.c
+++ b/usr.bin/truncate/truncate.c
@@ -4,6 +4,11 @@
  * Copyright (c) 2000 Sheldon Hearn <[email protected]>.
  * All rights reserved.
  *
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Ka Ho Ng <[email protected]>
+ * 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:
@@ -49,26 +54,36 @@ main(int argc, char **argv)
 {
        struct stat sb;
        mode_t omode;
-       off_t oflow, rsize, sz, tsize, round;
+       off_t oflow, rsize, sz, tsize, round, off, len;
        uint64_t usz;
-       int ch, error, fd, oflags;
+       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;
+       struct spacectl_range sr;
 
        fd = -1;
-       rsize = tsize = sz = 0;
-       no_create = do_relative = do_round = do_refer = got_size = 0;
-       error = 0;
+       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, "cr:s:")) != -1)
+       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;
@@ -89,6 +104,22 @@ main(int argc, char **argv)
                                -(off_t)usz : (off_t)usz;
                        got_size = 1;
                        break;
+               case 'o':
+                       if (expand_number(optarg, &usz) == -1 ||
+                           (off_t)usz < 0)
+                               errx(EXIT_FAILURE,
+                                   "invalid offset argument `%s'", optarg);
+
+                       off = usz;
+                       break;
+               case 'l':
+                       if (expand_number(optarg, &usz) == -1 ||
+                           (off_t)usz <= 0)
+                               errx(EXIT_FAILURE,
+                                   "invalid length argument `%s'", optarg);
+
+                       len = usz;
+                       break;
                default:
                        usage();
                        /* NOTREACHED */
@@ -98,19 +129,22 @@ main(int argc, char **argv)
        argc -= optind;
 
        /*
-        * Exactly one of do_refer or got_size must be specified.  Since
-        * do_relative implies got_size, do_relative and do_refer are
-        * also mutually exclusive.  See usage() for allowed invocations.
+        * 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 (do_refer + got_size != 1 || argc < 1)
+       if (argc < 1 || do_refer + got_size + do_dealloc != 1 ||
+           (do_dealloc == 1 && len == -1))
                usage();
-       if (do_refer) {
+       if (do_refer == 1) {
                if (stat(rname, &sb) == -1)
                        err(EXIT_FAILURE, "%s", rname);
                tsize = sb.st_size;
-       } else if (do_relative || do_round)
+       } else if (do_relative == 1 || do_round == 1)
                rsize = sz;
-       else
+       else if (do_dealloc == 0)
                tsize = sz;
 
        if (no_create)
@@ -129,7 +163,7 @@ main(int argc, char **argv)
                        }
                        continue;
                }
-               if (do_relative) {
+               if (do_relative == 1) {
                        if (fstat(fd, &sb) == -1) {
                                warn("%s", fname);
                                error++;
@@ -144,7 +178,7 @@ main(int argc, char **argv)
                        }
                        tsize = oflow;
                }
-               if (do_round) {
+               if (do_round == 1) {
                        if (fstat(fd, &sb) == -1) {
                                warn("%s", fname);
                                error++;
@@ -166,10 +200,16 @@ main(int argc, char **argv)
                if (tsize < 0)
                        tsize = 0;
 
-               if (ftruncate(fd, tsize) == -1) {
+               if (do_dealloc == 1) {
+                       sr.r_offset = off;
+                       sr.r_len = len;
+                       r = fspacectl(fd, SPACECTL_DEALLOC, &sr, 0, &sr);
+               }
+               if (do_truncate == 1)
+                       r = ftruncate(fd, tsize);
+               if (r == -1) {
                        warn("%s", fname);
                        error++;
-                       continue;
                }
        }
        if (fd != -1)
@@ -181,8 +221,9 @@ main(int argc, char **argv)
 static void
 usage(void)
 {
-       fprintf(stderr, "%s\n%s\n",
+       fprintf(stderr, "%s\n%s\n%s\n",
            "usage: truncate [-c] -s [+|-|%|/]size[K|k|M|m|G|g|T|t] file ...",
-           "       truncate [-c] -r rfile file ...");
+           "       truncate [-c] -r rfile file ...",
+           "       truncate [-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);
 }
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "[email protected]"

Reply via email to