]> Dogcows Code - chaz/tar/blobdiff - src/create.c
(write_header_name) In pax format, use "path" keyword if the file name is not ASCII
[chaz/tar] / src / create.c
index 6e49b59be090b0e45c620e580248d3c8266f4c8d..065e6fafd511fcb454b891cef56c43a91b4d7bba 100644 (file)
@@ -1,7 +1,7 @@
 /* Create a tar archive.
 
    Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003 Free Software Foundation, Inc.
+   2003, 2004 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1985-08-25.
 
@@ -186,6 +186,8 @@ to_chars (int negative, uintmax_t value, size_t valsize,
        {
          int negsub;
          uintmax_t sub = substitute (&negsub) & maxval;
+         /* FIXME: This is the only place where GNU_FORMAT differs from
+             OLDGNU_FORMAT. Apart from this they are completely identical. */
          uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
          char subbuf[UINTMAX_STRSIZE_BOUND + 1];
          char *sub_string = STRINGIFY_BIGINT (s, subbuf + 1);
@@ -369,7 +371,7 @@ tar_copy_str (char *dst, const char *src, size_t len)
 }
 
 /* Write a "private" header */
-static union block *
+union block *
 start_private_header (const char *name, size_t size)
 {
   time_t t;
@@ -532,9 +534,9 @@ write_long_name (struct tar_stat_info *st)
     }
   return write_short_name (st);
 }
-
+                      
 static union block *
-write_extended (struct tar_stat_info *st, union block *old_header, char type)
+write_extended (struct tar_stat_info *st, union block *old_header)
 {
   union block *header, hp;
   size_t size;
@@ -544,35 +546,10 @@ write_extended (struct tar_stat_info *st, union block *old_header, char type)
     return old_header; 
   
   xheader_finish (&extended_header);
-  size = extended_header.size;
-
   memcpy (hp.buffer, old_header, sizeof (hp));
-  
-  header = start_private_header ("././@PaxHeader", size);
-  header->header.typeflag = type;
-
-  finish_header (st, header, -1);
-
-  p = extended_header.buffer;
-
-  do
-    {
-      size_t len;
-      
-      header = find_next_block ();
-      len = BLOCKSIZE;
-      if (len > size)
-       len = size;
-      memcpy (header->buffer, p, len);
-      if (len < BLOCKSIZE)
-       memset (header->buffer + len, 0, BLOCKSIZE - len);
-      p += len;
-      size -= len;
-      set_next_block_after (header);
-    }
-  while (size > 0);
-  
-  xheader_destroy (&extended_header);
+  p = xheader_xhdr_name (st);
+  xheader_write (XHDTYPE, p, &extended_header);
+  free (p);
   header = find_next_block ();
   memcpy (header, &hp.buffer, sizeof (hp.buffer));
   return header;
@@ -581,7 +558,12 @@ write_extended (struct tar_stat_info *st, union block *old_header, char type)
 static union block * 
 write_header_name (struct tar_stat_info *st)
 {
-  if (NAME_FIELD_SIZE < strlen (st->file_name))
+  if (archive_format == POSIX_FORMAT && !string_ascii_p (st->file_name))
+    {
+      xheader_store ("path", st, NULL);
+      return write_short_name (st);
+    }
+  else if (NAME_FIELD_SIZE < strlen (st->file_name))
     return write_long_name (st);
   else
     return write_short_name (st);
@@ -725,13 +707,15 @@ start_header (struct tar_stat_info *st)
       gid_to_gname (st->stat.st_gid, &st->gname);
       
       if (archive_format == POSIX_FORMAT
-         && strlen (st->uname) > UNAME_FIELD_SIZE)
+         && (strlen (st->uname) > UNAME_FIELD_SIZE
+             || !string_ascii_p (st->uname)))
        xheader_store ("uname", st, NULL);
       else
        UNAME_TO_CHARS (st->uname, header->header.uname);
 
       if (archive_format == POSIX_FORMAT
-         && strlen (st->gname) > GNAME_FIELD_SIZE)
+         && (strlen (st->gname) > GNAME_FIELD_SIZE
+             || !string_ascii_p (st->gname)))
        xheader_store ("gname", st, NULL);
       else
        GNAME_TO_CHARS (st->gname, header->header.gname);
@@ -740,35 +724,13 @@ start_header (struct tar_stat_info *st)
   return header;
 }
 
-/* Finish off a filled-in header block and write it out.  We also
-   print the file name and/or full info if verbose is on.  If BLOCK_ORDINAL
-   is not negative, is the block ordinal of the first record for this
-   file, which may be a preceding long name or long link record.  */
 void
-finish_header (struct tar_stat_info *st,
-              union block *header, off_t block_ordinal)
+simple_finish_header (union block *header)
 {
   size_t i;
   int sum;
   char *p;
 
-  /* Note: It is important to do this before the call to write_extended(),
-     so that the actual ustar header is printed */
-  if (verbose_option
-      && header->header.typeflag != GNUTYPE_LONGLINK
-      && header->header.typeflag != GNUTYPE_LONGNAME
-      && header->header.typeflag != XHDTYPE
-      && header->header.typeflag != XGLTYPE)
-    {
-      /* These globals are parameters to print_header, sigh.  */
-
-      current_header = header;
-      current_format = archive_format;
-      print_header (st, block_ordinal);
-    }
-
-  header = write_extended (st, header, XHDTYPE);
-  
   memcpy (header->header.chksum, CHKBLANKS, sizeof header->header.chksum);
 
   sum = 0;
@@ -791,6 +753,37 @@ finish_header (struct tar_stat_info *st,
 
   set_next_block_after (header);
 }
+
+/* Finish off a filled-in header block and write it out.  We also
+   print the file name and/or full info if verbose is on.  If BLOCK_ORDINAL
+   is not negative, is the block ordinal of the first record for this
+   file, which may be a preceding long name or long link record.  */
+void
+finish_header (struct tar_stat_info *st,
+              union block *header, off_t block_ordinal)
+{
+  size_t i;
+  int sum;
+  char *p;
+
+  /* Note: It is important to do this before the call to write_extended(),
+     so that the actual ustar header is printed */
+  if (verbose_option
+      && header->header.typeflag != GNUTYPE_LONGLINK
+      && header->header.typeflag != GNUTYPE_LONGNAME
+      && header->header.typeflag != XHDTYPE
+      && header->header.typeflag != XGLTYPE)
+    {
+      /* These globals are parameters to print_header, sigh.  */
+
+      current_header = header;
+      current_format = archive_format;
+      print_header (st, block_ordinal);
+    }
+
+  header = write_extended (st, header);
+  simple_finish_header (header);
+}
 \f
 
 void
@@ -986,8 +979,8 @@ dump_dir0 (char *directory,
     return;
 
   if (one_file_system_option
-          && !top_level
-          && parent_device != stat->stat.st_dev)
+      && !top_level
+      && parent_device != stat->stat.st_dev)
     {
       if (verbose_option)
        WARN ((0, 0,
@@ -1066,7 +1059,8 @@ create_archive (void)
   char *p;
 
   open_archive (ACCESS_WRITE);
-
+  xheader_write_global ();
+  
   if (incremental_option)
     {
       size_t buffer_size = 1000;
@@ -1181,7 +1175,7 @@ dump_hard_link (struct tar_stat_info *stat)
       if ((dup = hash_lookup (link_table, &lp)))
        {
          /* We found a link.  */
-         char const *link_name = safer_name_suffix (dup->name, 1);
+         char const *link_name = safer_name_suffix (dup->name, true);
 
          dup->nlink--;
              
@@ -1277,7 +1271,7 @@ dump_file0 (struct tar_stat_info *stat, char *p,
     return;
 
   assign_string (&stat->orig_file_name, p);
-  assign_string (&stat->file_name, safer_name_suffix (p, 0));
+  assign_string (&stat->file_name, safer_name_suffix (p, false));
 
   if (deref_stat (dereference_option, p, &stat->stat) != 0)
     {
@@ -1306,12 +1300,11 @@ dump_file0 (struct tar_stat_info *stat, char *p,
   /* See if we want only new files, and check if this one is too old to
      put in the archive.  */
 
-  if ((0 < top_level || !incremental_option)
-      && !S_ISDIR (stat->stat.st_mode)
+  if (!S_ISDIR (stat->stat.st_mode)
       && stat->stat.st_mtime < newer_mtime_option
       && (!after_date_option || stat->stat.st_ctime < newer_ctime_option))
     {
-      if (0 < top_level)
+      if (0 < top_level) /* equivalent to !incremental_option */
        WARN ((0, 0, _("%s: file is unchanged; not dumped"),
               quotearg_colon (p)));
       /* FIXME: recheck this return.  */
This page took 0.025742 seconds and 4 git commands to generate.