Author: manu
Date: Mon Jul  9 19:03:30 2018
New Revision: 336140
URL: https://svnweb.freebsd.org/changeset/base/336140

Log:
  truncate: Add support for -s % and /
  
  % round up to the multiple size and / round down
  This is compatible with gnu truncate.
  Add tests and document in the man page.

Modified:
  head/usr.bin/truncate/tests/truncate_test.sh
  head/usr.bin/truncate/truncate.1
  head/usr.bin/truncate/truncate.c

Modified: head/usr.bin/truncate/tests/truncate_test.sh
==============================================================================
--- head/usr.bin/truncate/tests/truncate_test.sh        Mon Jul  9 19:02:05 
2018        (r336139)
+++ head/usr.bin/truncate/tests/truncate_test.sh        Mon Jul  9 19:03:30 
2018        (r336140)
@@ -57,7 +57,7 @@ create_stderr_usage_file()
        _custom_create_file creat
        _custom_create_file print "${1}"
        _custom_create_file print \
-           "usage: truncate [-c] -s [+|-]size[K|k|M|m|G|g|T|t] file ..."
+           "usage: truncate [-c] -s [+|-|%|/]size[K|k|M|m|G|g|T|t] file ..."
        _custom_create_file print "       truncate [-c] -r rfile file ..."
 }
 
@@ -378,6 +378,66 @@ negative_body()
        [ ${st_size} -eq 0 ] || atf_fail "new file should now be zero bytes"
 }
 
+atf_test_case roundup
+roundup_head()
+{
+       atf_set "descr" "Verifies truncate round up"
+}
+roundup_body()
+{
+       # Create a 5 byte file.
+       printf "abcd\n" > afile
+       eval $(stat -s afile)
+       [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes"
+
+       create_stderr_file
+
+       # Create a new file and do a 100 byte roundup.
+       atf_check -e file:stderr.txt truncate -s%100 afile
+       eval $(stat -s afile)
+       [ ${st_size} -eq 100 ] || atf_fail "new file should now be 100 bytes"
+}
+
+atf_test_case rounddown
+rounddown_head()
+{
+       atf_set "descr" "Verifies truncate round down"
+}
+rounddown_body()
+{
+       # Create a 5 byte file.
+       printf "abcd\n" > afile
+       eval $(stat -s afile)
+       [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes"
+
+       create_stderr_file
+
+       # Create a new file and do a 2 byte roundup.
+       atf_check -e file:stderr.txt truncate -s/2 afile
+       eval $(stat -s afile)
+       [ ${st_size} -eq 4 ] || atf_fail "new file should now be 4 bytes"
+}
+
+atf_test_case rounddown_zero
+rounddown_zero_head()
+{
+       atf_set "descr" "Verifies truncate round down to zero"
+}
+rounddown_zero_body()
+{
+       # Create a 5 byte file.
+       printf "abcd\n" > afile
+       eval $(stat -s afile)
+       [ ${st_size} -eq 5 ] || atf_fail "afile file should be 5 bytes"
+
+       create_stderr_file
+
+       # Create a new file and do a 10 byte roundup.
+       atf_check -e file:stderr.txt truncate -s/10 afile
+       eval $(stat -s afile)
+       [ ${st_size} -eq 0 ] || atf_fail "new file should now be 0 bytes"
+}
+
 atf_init_test_cases()
 {
        atf_add_test_case illegal_option
@@ -396,4 +456,7 @@ atf_init_test_cases()
        atf_add_test_case reference
        atf_add_test_case new_zero
        atf_add_test_case negative
+       atf_add_test_case roundup
+       atf_add_test_case rounddown
+       atf_add_test_case rounddown_zero
 }

Modified: head/usr.bin/truncate/truncate.1
==============================================================================
--- head/usr.bin/truncate/truncate.1    Mon Jul  9 19:02:05 2018        
(r336139)
+++ head/usr.bin/truncate/truncate.1    Mon Jul  9 19:03:30 2018        
(r336140)
@@ -37,7 +37,7 @@
 .Bk -words
 .Fl s Xo
 .Sm off
-.Op Cm + | -
+.Op Cm + | - | % | /
 .Ar size
 .Op Cm K | k | M | m | G | g | T | t
 .Sm on
@@ -69,7 +69,7 @@ Truncate or extend files to the length of the file
 .Ar rfile .
 .It Fl s Xo
 .Sm off
-.Op Cm + | -
+.Op Cm + | - | % | /
 .Ar size
 .Op Cm K | k | M | m | G | g | T | t
 .Sm on
@@ -84,6 +84,17 @@ If the
 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

Modified: head/usr.bin/truncate/truncate.c
==============================================================================
--- head/usr.bin/truncate/truncate.c    Mon Jul  9 19:02:05 2018        
(r336139)
+++ head/usr.bin/truncate/truncate.c    Mon Jul  9 19:03:30 2018        
(r336140)
@@ -56,13 +56,15 @@ main(int argc, char **argv)
        int ch, error, fd, oflags;
        int no_create;
        int do_relative;
+       int do_round;
        int do_refer;
        int got_size;
+       int round;
        char *fname, *rname;
 
        fd = -1;
        rsize = tsize = sz = 0;
-       no_create = do_relative = do_refer = got_size = 0;
+       no_create = do_relative = do_round = do_refer = got_size = 0;
        error = 0;
        rname = NULL;
        while ((ch = getopt(argc, argv, "cr:s:")) != -1)
@@ -75,13 +77,19 @@ main(int argc, char **argv)
                        rname = optarg;
                        break;
                case 's':
-                       do_relative = *optarg == '+' || *optarg == '-';
-                       if (expand_number(do_relative ? optarg + 1 : optarg,
+                       if (*optarg == '+' || *optarg == '-') {
+                               do_relative = 1;
+                       } else if (*optarg == '%' || *optarg == '/') {
+                               do_round = 1;
+                       }
+                       if (expand_number(do_relative || do_round ?
+                           optarg + 1 : optarg,
                            &usz) == -1 || (off_t)usz < 0)
                                errx(EXIT_FAILURE,
                                    "invalid size argument `%s'", optarg);
 
-                       sz = (*optarg == '-') ? -(off_t)usz : (off_t)usz;
+                       sz = (*optarg == '-' || *optarg == '/') ?
+                               -(off_t)usz : (off_t)usz;
                        got_size = 1;
                        break;
                default:
@@ -103,7 +111,7 @@ main(int argc, char **argv)
                if (stat(rname, &sb) == -1)
                        err(EXIT_FAILURE, "%s", rname);
                tsize = sb.st_size;
-       } else if (do_relative)
+       } else if (do_relative || do_round)
                rsize = sz;
        else
                tsize = sz;
@@ -139,6 +147,25 @@ main(int argc, char **argv)
                        }
                        tsize = oflow;
                }
+               if (do_round) {
+                       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 (round != sz && rsize < 0)
+                                       round--;
+                               else if (rsize > 0)
+                                       round++;
+                               tsize = (round < 0 ? 0 : round) * sz;
+                       } else
+                               tsize = sb.st_size;
+               }
                if (tsize < 0)
                        tsize = 0;
 
@@ -158,7 +185,7 @@ static void
 usage(void)
 {
        fprintf(stderr, "%s\n%s\n",
-           "usage: truncate [-c] -s [+|-]size[K|k|M|m|G|g|T|t] file ...",
+           "usage: truncate [-c] -s [+|-|%|/]size[K|k|M|m|G|g|T|t] file ...",
            "       truncate [-c] -r rfile file ...");
        exit(EXIT_FAILURE);
 }
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to