coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH] truncate: add --data-size (-d) option


From: Emil Karlson
Subject: [RFC PATCH] truncate: add --data-size (-d) option
Date: Fri, 2 Nov 2018 19:42:52 +0200

From: Emil Karlson <address@hidden>

Add a new option to truncate to the smallest size that contains all its extents
ie. truncate to the offset of the end of the last extent in the file. This may
be convenient when passing very large images with long sparse tails to systems
that do not handle sparse images reasonably and do not need the sparse tails.
---
 src/truncate.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 5 deletions(-)

diff --git a/src/truncate.c b/src/truncate.c
index f43637e9b..175b4adac 100644
--- a/src/truncate.c
+++ b/src/truncate.c
@@ -43,6 +43,9 @@ static bool no_create;
 /* (-o) If true, --size refers to blocks not bytes */
 static bool block_mode;
 
+/* (-d) If true, truncate to the offset of the end of the last extent */
+static bool data_size;
+
 /* (-r) Reference file to use size from */
 static char const *ref_file;
 
@@ -50,6 +53,7 @@ static struct option const longopts[] =
 {
   {"no-create", no_argument, NULL, 'c'},
   {"io-blocks", no_argument, NULL, 'o'},
+  {"data-size", no_argument, NULL, 'd'},
   {"reference", required_argument, NULL, 'r'},
   {"size", required_argument, NULL, 's'},
   {GETOPT_HELP_OPTION_DECL},
@@ -88,7 +92,9 @@ reads as zero bytes.\n\
 "), stdout);
       fputs (_("\
   -r, --reference=RFILE  base size on RFILE\n\
-  -s, --size=SIZE        set or adjust the file size by SIZE bytes\n"), 
stdout);
+  -s, --size=SIZE        set or adjust the file size by SIZE bytes\n\
+  -d, --data-size        set or adjust the file size to last data extent\n\
+"), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
       emit_size_note ();
@@ -193,6 +199,37 @@ do_ftruncate (int fd, char const *fname, off_t ssize, 
off_t rsize,
           nsize = fsize + ssize;
         }
     }
+  else if (data_size)
+    {
+      off_t last_hole = 0, offset = 0;
+      while (0 <= (offset = lseek (fd, offset, SEEK_DATA)))
+       {
+         if (0 <= (last_hole = lseek (fd, offset, SEEK_HOLE)))
+           {
+             offset = last_hole;
+           }
+         else
+           {
+             if (ENXIO != errno)
+               {
+                 error (0, errno, _("failed to seek holes in %s"),
+                        quoteaf (fname), (intmax_t) nsize);
+                 return false;
+               }
+             return EXIT_FAILURE;
+           }
+       }
+      if (ENXIO == errno)
+       {
+         nsize = last_hole;
+       }
+      else
+        {
+         error (0, errno, _("unexpected error when seeking data in %s"),
+                quoteaf (fname), (intmax_t) nsize);
+         return false;
+       }
+    }
   else
     nsize = ssize;
   if (nsize < 0)
@@ -228,7 +265,7 @@ main (int argc, char **argv)
 
   atexit (close_stdout);
 
-  while ((c = getopt_long (argc, argv, "cor:s:", longopts, NULL)) != -1)
+  while ((c = getopt_long (argc, argv, "codr:s:", longopts, NULL)) != -1)
     {
       switch (c)
         {
@@ -240,6 +277,10 @@ main (int argc, char **argv)
           block_mode = true;
           break;
 
+        case 'd':
+          data_size = true;
+          break;
+
         case 'r':
           ref_file = optarg;
           break;
@@ -303,10 +344,10 @@ main (int argc, char **argv)
   argc -= optind;
 
   /* must specify either size or reference file */
-  if (!ref_file && !got_size)
+  if (!ref_file && !got_size && !data_size)
     {
-      error (0, 0, _("you must specify either %s or %s"),
-             quote_n (0, "--size"), quote_n (1, "--reference"));
+      error (0, 0, _("you must specify either %s, %s or %s"),
+             quote_n (0, "--size"), quote_n (1, "--reference"), quote_n (1, 
"--data-size"));
       usage (EXIT_FAILURE);
     }
   /* must specify a relative size with a reference file */
-- 
2.19.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]