]> Dogcows Code - chaz/tar/blobdiff - src/create.c
tar: optimize -c --sparse when file is entirely sparse
[chaz/tar] / src / create.c
index 6777f9cc078eac7b4c544a03d7a8b072d6d642ca..2ca1d6ee34ba342cf8431b88c52b2f5df8052295 100644 (file)
@@ -30,7 +30,7 @@ struct link
   {
     dev_t dev;
     ino_t ino;
-    size_t nlink;
+    nlink_t nlink;
     char name[1];
   };
 
@@ -214,6 +214,14 @@ to_base256 (int negative, uintmax_t value, char *where, size_t size)
   while (i);
 }
 
+#define GID_TO_CHARS(val, where) gid_to_chars (val, where, sizeof (where))
+#define MAJOR_TO_CHARS(val, where) major_to_chars (val, where, sizeof (where))
+#define MINOR_TO_CHARS(val, where) minor_to_chars (val, where, sizeof (where))
+#define MODE_TO_CHARS(val, where) mode_to_chars (val, where, sizeof (where))
+#define UID_TO_CHARS(val, where) uid_to_chars (val, where, sizeof (where))
+#define UINTMAX_TO_CHARS(val, where) uintmax_to_chars (val, where, sizeof (where))
+#define UNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
+#define GNAME_TO_CHARS(name,buf) string_to_chars (name, buf, sizeof(buf))
 
 static bool
 to_chars (int negative, uintmax_t value, size_t valsize,
@@ -368,25 +376,25 @@ gid_substitute (int *negative)
   return r;
 }
 
-bool
+static bool
 gid_to_chars (gid_t v, char *p, size_t s)
 {
   return to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
 }
 
-bool
+static bool
 major_to_chars (major_t v, char *p, size_t s)
 {
   return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
 }
 
-bool
+static bool
 minor_to_chars (minor_t v, char *p, size_t s)
 {
   return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
 }
 
-bool
+static bool
 mode_to_chars (mode_t v, char *p, size_t s)
 {
   /* In the common case where the internal and external mode bits are the same,
@@ -432,12 +440,6 @@ off_to_chars (off_t v, char *p, size_t s)
   return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
 }
 
-bool
-size_to_chars (size_t v, char *p, size_t s)
-{
-  return to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
-}
-
 bool
 time_to_chars (time_t v, char *p, size_t s)
 {
@@ -460,19 +462,19 @@ uid_substitute (int *negative)
   return r;
 }
 
-bool
+static bool
 uid_to_chars (uid_t v, char *p, size_t s)
 {
   return to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
 }
 
-bool
+static bool
 uintmax_to_chars (uintmax_t v, char *p, size_t s)
 {
   return to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
 }
 
-void
+static void
 string_to_chars (char const *str, char *p, size_t s)
 {
   tar_copy_str (p, str, s);
@@ -487,7 +489,7 @@ string_to_chars (char const *str, char *p, size_t s)
    a) it is empty *and* world-readable, or
    b) current archive is /dev/null */
 
-bool
+static bool
 file_dumpable_p (struct tar_stat_info *st)
 {
   if (dev_null_output)
@@ -1257,6 +1259,12 @@ dump_dir (int fd, struct tar_stat_info *st, bool top_level,
   return true;
 }
 
+\f
+/* Number of links a file can have without having to be entered into
+   the link table.  Typically this is 1, but in trickier circumstances
+   it is 0.  */
+static nlink_t trivial_link_count;
+
 \f
 /* Main functions of this module.  */
 
@@ -1265,6 +1273,8 @@ create_archive (void)
 {
   struct name const *p;
 
+  trivial_link_count = name_count <= 1 && ! dereference_option;
+
   open_archive (ACCESS_WRITE);
   buffer_write_global_xheader ();
 
@@ -1372,7 +1382,8 @@ static Hash_table *link_table;
 static bool
 dump_hard_link (struct tar_stat_info *st)
 {
-  if (link_table && (st->stat.st_nlink > 1 || remove_files_option))
+  if (link_table
+      && (trivial_link_count < st->stat.st_nlink || remove_files_option))
     {
       struct link lp;
       struct link *duplicate;
@@ -1419,7 +1430,7 @@ file_count_links (struct tar_stat_info *st)
 {
   if (hard_dereference_option)
     return;
-  if (st->stat.st_nlink > 1)
+  if (trivial_link_count < st->stat.st_nlink)
     {
       struct link *duplicate;
       char *linkname = NULL;
This page took 0.026276 seconds and 4 git commands to generate.