Переглянути джерело

Port to Solaris 10's treatment of unlinking directories.
* gnulib-modules: Add unlinkdir.
* lib/.cvsignore: Add unlinkdir.h, unlinkdir.c.
* src/common.h (we_are_root): Remove extern decl; it's now static.
* src/extract.c (we_are_root): Now static.
* src/misc.c: Include <unlinkdir.h>.
(remove_any_file): Use cannot_unlink_dir () rather than we_are_root.

Paul Eggert 20 роки тому
батько
коміт
46f09016e8
6 змінених файлів з 58 додано та 47 видалено
  1. 8 0
      ChangeLog
  2. 1 0
      gnulib.modules
  3. 2 1
      lib/.cvsignore
  4. 0 1
      src/common.h
  5. 36 36
      src/extract.c
  6. 11 9
      src/misc.c

+ 8 - 0
ChangeLog

@@ -1,5 +1,13 @@
 2005-05-14  Paul Eggert  <eggert@cs.ucla.edu>
 2005-05-14  Paul Eggert  <eggert@cs.ucla.edu>
 
 
+	Port to Solaris 10's treatment of unlinking directories.
+	* gnulib-modules: Add unlinkdir.
+	* lib/.cvsignore: Add unlinkdir.h, unlinkdir.c.
+	* src/common.h (we_are_root): Remove extern decl; it's now static.
+	* src/extract.c (we_are_root): Now static.
+	* src/misc.c: Include <unlinkdir.h>.
+	(remove_any_file): Use cannot_unlink_dir () rather than	we_are_root.
+
 	* ChangeLog, ChangeLog.1, Makefile.am, NEWS, PORTS, README,
 	* ChangeLog, ChangeLog.1, Makefile.am, NEWS, PORTS, README,
 	README-alpha, TODO, bootstrap, configure.ac, doc/Makefile.am,
 	README-alpha, TODO, bootstrap, configure.ac, doc/Makefile.am,
 	doc/convtexi.pl, doc/fdl.texi, doc/gendocs_template,
 	doc/convtexi.pl, doc/fdl.texi, doc/gendocs_template,

+ 1 - 0
gnulib.modules

@@ -37,6 +37,7 @@ stpcpy
 strtol
 strtol
 strtoul
 strtoul
 timespec
 timespec
+unlinkdir
 unlocked-io
 unlocked-io
 utime
 utime
 xalloc
 xalloc

+ 2 - 1
lib/.cvsignore

@@ -145,6 +145,8 @@ time_r.c
 time_r.h
 time_r.h
 timespec.h
 timespec.h
 unistd-safer.h
 unistd-safer.h
+unlinkdir.c
+unlinkdir.h
 unlocked-io.h
 unlocked-io.h
 unsetenv.c
 unsetenv.c
 utime.c
 utime.c
@@ -163,4 +165,3 @@ xstrtol.c
 xstrtol.h
 xstrtol.h
 xstrtoul.c
 xstrtoul.c
 xstrtoumax.c
 xstrtoumax.c
-

+ 0 - 1
src/common.h

@@ -441,7 +441,6 @@ void verify_volume (void);
 
 
 /* Module extract.c.  */
 /* Module extract.c.  */
 
 
-extern bool we_are_root;
 void extr_init (void);
 void extr_init (void);
 void extract_archive (void);
 void extract_archive (void);
 void extract_finish (void);
 void extract_finish (void);

+ 36 - 36
src/extract.c

@@ -36,7 +36,7 @@ struct utimbuf
 
 
 #include "common.h"
 #include "common.h"
 
 
-bool we_are_root;		/* true if our effective uid == 0 */
+static bool we_are_root;	/* true if our effective uid == 0 */
 static mode_t newdir_umask;	/* umask when creating new directories */
 static mode_t newdir_umask;	/* umask when creating new directories */
 static mode_t current_umask;	/* current umask (which is set to 0 if -p) */
 static mode_t current_umask;	/* current umask (which is set to 0 if -p) */
 
 
@@ -119,7 +119,7 @@ extr_init (void)
      FIXME: Should the same be done after handling -C option ? */
      FIXME: Should the same be done after handling -C option ? */
   if (one_file_system_option)
   if (one_file_system_option)
     {
     {
-      struct stat st;      
+      struct stat st;
       char *dir = xgetcwd ();
       char *dir = xgetcwd ();
 
 
       if (deref_stat (true, dir, &st))
       if (deref_stat (true, dir, &st))
@@ -127,7 +127,7 @@ extr_init (void)
       else
       else
 	root_device = st.st_dev;
 	root_device = st.st_dev;
     }
     }
-  
+
   /* Option -p clears the kernel umask, so it does not affect proper
   /* Option -p clears the kernel umask, so it does not affect proper
      restoration of file permissions.  New intermediate directories will
      restoration of file permissions.  New intermediate directories will
      comply with umask at start of program.  */
      comply with umask at start of program.  */
@@ -576,7 +576,7 @@ extract_dir (char *file_name, int typeflag)
   int status;
   int status;
   mode_t mode;
   mode_t mode;
   int interdir_made = 0;
   int interdir_made = 0;
-  
+
   if (incremental_option)
   if (incremental_option)
     /* Read the entry and delete files that aren't listed in the archive.  */
     /* Read the entry and delete files that aren't listed in the archive.  */
     purge_directory (file_name);
     purge_directory (file_name);
@@ -608,10 +608,10 @@ extract_dir (char *file_name, int typeflag)
 	    }
 	    }
 	  errno = EEXIST;
 	  errno = EEXIST;
 	}
 	}
-      
+
       if (maybe_recoverable (file_name, &interdir_made))
       if (maybe_recoverable (file_name, &interdir_made))
 	continue;
 	continue;
-      
+
       if (errno != EEXIST)
       if (errno != EEXIST)
 	{
 	{
 	  mkdir_error (file_name);
 	  mkdir_error (file_name);
@@ -619,7 +619,7 @@ extract_dir (char *file_name, int typeflag)
 	}
 	}
       break;
       break;
     }
     }
-  
+
   if (status == 0
   if (status == 0
       || old_files_option == DEFAULT_OLD_FILES
       || old_files_option == DEFAULT_OLD_FILES
       || old_files_option == OVERWRITE_OLD_FILES)
       || old_files_option == OVERWRITE_OLD_FILES)
@@ -666,7 +666,7 @@ open_output_file (char *file_name, int typeflag)
   fd = open (file_name, openflag, mode);
   fd = open (file_name, openflag, mode);
 
 
 #endif /* not O_CTG */
 #endif /* not O_CTG */
-  
+
   return fd;
   return fd;
 }
 }
 
 
@@ -680,7 +680,7 @@ extract_file (char *file_name, int typeflag)
   size_t count;
   size_t count;
   size_t written;
   size_t written;
   int interdir_made = 0;
   int interdir_made = 0;
-  
+
   /* FIXME: deal with protection issues.  */
   /* FIXME: deal with protection issues.  */
 
 
   if (to_stdout_option)
   if (to_stdout_option)
@@ -699,14 +699,14 @@ extract_file (char *file_name, int typeflag)
       do
       do
 	fd = open_output_file (file_name, typeflag);
 	fd = open_output_file (file_name, typeflag);
       while (fd < 0 && maybe_recoverable (file_name, &interdir_made));
       while (fd < 0 && maybe_recoverable (file_name, &interdir_made));
-    
+
       if (fd < 0)
       if (fd < 0)
 	{
 	{
 	  open_error (file_name);
 	  open_error (file_name);
 	  return 1;
 	  return 1;
 	}
 	}
     }
     }
-    
+
   if (current_stat_info.is_sparse)
   if (current_stat_info.is_sparse)
     sparse_extract_file (fd, &current_stat_info, &size);
     sparse_extract_file (fd, &current_stat_info, &size);
   else
   else
@@ -722,7 +722,7 @@ extract_file (char *file_name, int typeflag)
 	/* Locate data, determine max length writeable, write it,
 	/* Locate data, determine max length writeable, write it,
 	   block that we have used the data, then check if the write
 	   block that we have used the data, then check if the write
 	   worked.  */
 	   worked.  */
-	
+
 	data_block = find_next_block ();
 	data_block = find_next_block ();
 	if (! data_block)
 	if (! data_block)
 	  {
 	  {
@@ -731,13 +731,13 @@ extract_file (char *file_name, int typeflag)
 	  }
 	  }
 
 
 	written = available_space_after (data_block);
 	written = available_space_after (data_block);
-	
+
 	if (written > size)
 	if (written > size)
 	  written = size;
 	  written = size;
 	errno = 0;
 	errno = 0;
 	count = full_write (fd, data_block->buffer, written);
 	count = full_write (fd, data_block->buffer, written);
 	size -= written;
 	size -= written;
-	
+
 	set_next_block_after ((union block *)
 	set_next_block_after ((union block *)
 			      (data_block->buffer + written - 1));
 			      (data_block->buffer + written - 1));
 	if (count != written)
 	if (count != written)
@@ -748,7 +748,7 @@ extract_file (char *file_name, int typeflag)
 	    break;
 	    break;
 	  }
 	  }
       }
       }
-  
+
   skip_file (size);
   skip_file (size);
 
 
   if (multi_volume_option)
   if (multi_volume_option)
@@ -773,14 +773,14 @@ extract_file (char *file_name, int typeflag)
 	      typeflag);
 	      typeflag);
 
 
   return status;
   return status;
-}  
+}
 
 
 static int
 static int
 extract_link (char *file_name, int typeflag)
 extract_link (char *file_name, int typeflag)
 {
 {
   char const *link_name = safer_name_suffix (current_stat_info.link_name, true);
   char const *link_name = safer_name_suffix (current_stat_info.link_name, true);
   int interdir_made = 0;
   int interdir_made = 0;
-  
+
   do
   do
     {
     {
       struct stat st1, st2;
       struct stat st1, st2;
@@ -812,7 +812,7 @@ extract_link (char *file_name, int typeflag)
 		   && st1.st_dev == st2.st_dev
 		   && st1.st_dev == st2.st_dev
 		   && st1.st_ino == st2.st_ino))
 		   && st1.st_ino == st2.st_ino))
 	return 0;
 	return 0;
-      
+
       errno = e;
       errno = e;
     }
     }
   while (maybe_recoverable (file_name, &interdir_made));
   while (maybe_recoverable (file_name, &interdir_made));
@@ -823,7 +823,7 @@ extract_link (char *file_name, int typeflag)
       return 1;
       return 1;
     }
     }
   return 0;
   return 0;
-}  
+}
 
 
 static int
 static int
 extract_symlink (char *file_name, int typeflag)
 extract_symlink (char *file_name, int typeflag)
@@ -831,7 +831,7 @@ extract_symlink (char *file_name, int typeflag)
 #ifdef HAVE_SYMLINK
 #ifdef HAVE_SYMLINK
   int status, fd;
   int status, fd;
   int interdir_made = 0;
   int interdir_made = 0;
-  
+
   if (absolute_names_option
   if (absolute_names_option
       || ! (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name)
       || ! (IS_ABSOLUTE_FILE_NAME (current_stat_info.link_name)
 	    || contains_dot_dot (current_stat_info.link_name)))
 	    || contains_dot_dot (current_stat_info.link_name)))
@@ -894,7 +894,7 @@ extract_symlink (char *file_name, int typeflag)
 	      do
 	      do
 		{
 		{
 		  h->after_symlinks = 1;
 		  h->after_symlinks = 1;
-		  
+
 		  if (stat (h->file_name, &st) != 0)
 		  if (stat (h->file_name, &st) != 0)
 		    stat_error (h->file_name);
 		    stat_error (h->file_name);
 		  else
 		  else
@@ -905,7 +905,7 @@ extract_symlink (char *file_name, int typeflag)
 		}
 		}
 	      while ((h = h->next) && ! h->after_symlinks);
 	      while ((h = h->next) && ! h->after_symlinks);
 	    }
 	    }
-	  
+
 	  status = 0;
 	  status = 0;
 	}
 	}
     }
     }
@@ -920,9 +920,9 @@ extract_symlink (char *file_name, int typeflag)
       warned_once = 1;
       warned_once = 1;
       WARN ((0, 0, _("Attempting extraction of symbolic links as hard links")));
       WARN ((0, 0, _("Attempting extraction of symbolic links as hard links")));
     }
     }
-  return extract_link (file_name, typeflag);  
+  return extract_link (file_name, typeflag);
 #endif
 #endif
-}  
+}
 
 
 #if S_IFCHR || S_IFBLK
 #if S_IFCHR || S_IFBLK
 static int
 static int
@@ -930,12 +930,12 @@ extract_node (char *file_name, int typeflag)
 {
 {
   int status;
   int status;
   int interdir_made = 0;
   int interdir_made = 0;
-  
+
   do
   do
     status = mknod (file_name, current_stat_info.stat.st_mode,
     status = mknod (file_name, current_stat_info.stat.st_mode,
 		    current_stat_info.stat.st_rdev);
 		    current_stat_info.stat.st_rdev);
   while (status && maybe_recoverable (file_name, &interdir_made));
   while (status && maybe_recoverable (file_name, &interdir_made));
-  
+
   if (status != 0)
   if (status != 0)
     mknod_error (file_name);
     mknod_error (file_name);
   else
   else
@@ -950,7 +950,7 @@ extract_fifo (char *file_name, int typeflag)
 {
 {
   int status;
   int status;
   int interdir_made = 0;
   int interdir_made = 0;
-  
+
   while ((status = mkfifo (file_name, current_stat_info.stat.st_mode)))
   while ((status = mkfifo (file_name, current_stat_info.stat.st_mode)))
     if (!maybe_recoverable (file_name, &interdir_made))
     if (!maybe_recoverable (file_name, &interdir_made))
       break;
       break;
@@ -961,7 +961,7 @@ extract_fifo (char *file_name, int typeflag)
   else
   else
     mkfifo_error (file_name);
     mkfifo_error (file_name);
   return status;
   return status;
-}  
+}
 #endif
 #endif
 
 
 static int
 static int
@@ -971,7 +971,7 @@ extract_mangle_wrapper (char *file_name, int typeflag)
   return 0;
   return 0;
 }
 }
 
 
-     
+
 static int
 static int
 extract_failure (char *file_name, int typeflag)
 extract_failure (char *file_name, int typeflag)
 {
 {
@@ -989,7 +989,7 @@ static int
 prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
 prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
 {
 {
   int rc = 1;
   int rc = 1;
-  
+
   if (EXTRACT_OVER_PIPE)
   if (EXTRACT_OVER_PIPE)
     rc = 0;
     rc = 0;
 
 
@@ -1000,7 +1000,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
       *fun = extract_file;
       *fun = extract_file;
       rc = 1;
       rc = 1;
       break;
       break;
-      
+
     case AREGTYPE:
     case AREGTYPE:
     case REGTYPE:
     case REGTYPE:
     case CONTTYPE:
     case CONTTYPE:
@@ -1081,12 +1081,12 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun)
   /* Determine whether the extraction should proceed */
   /* Determine whether the extraction should proceed */
   if (rc == 0)
   if (rc == 0)
     return 0;
     return 0;
-  
+
   switch (old_files_option)
   switch (old_files_option)
     {
     {
     case UNLINK_FIRST_OLD_FILES:
     case UNLINK_FIRST_OLD_FILES:
-      if (!remove_any_file (file_name, 
-                            recursive_unlink_option ? RECURSIVE_REMOVE_OPTION 
+      if (!remove_any_file (file_name,
+                            recursive_unlink_option ? RECURSIVE_REMOVE_OPTION
                                                       : ORDINARY_REMOVE_OPTION)
                                                       : ORDINARY_REMOVE_OPTION)
 	  && errno && errno != ENOENT)
 	  && errno && errno != ENOENT)
 	{
 	{
@@ -1118,7 +1118,7 @@ extract_archive (void)
   char typeflag;
   char typeflag;
   char *file_name;
   char *file_name;
   tar_extractor_t fun;
   tar_extractor_t fun;
-  
+
   set_next_block_after (current_header);
   set_next_block_after (current_header);
   decode_header (current_header, &current_stat_info, &current_format, 1);
   decode_header (current_header, &current_stat_info, &current_format, 1);
 
 
@@ -1172,7 +1172,7 @@ extract_archive (void)
     }
     }
   else
   else
     skip_member ();
     skip_member ();
-  
+
 }
 }
 
 
 /* Extract the symbolic links whose final extraction were delayed.  */
 /* Extract the symbolic links whose final extraction were delayed.  */

+ 11 - 9
src/misc.c

@@ -22,6 +22,7 @@
 #include "common.h"
 #include "common.h"
 #include <quotearg.h>
 #include <quotearg.h>
 #include <save-cwd.h>
 #include <save-cwd.h>
+#include <unlinkdir.h>
 
 
 static void call_arg_fatal (char const *, char const *)
 static void call_arg_fatal (char const *, char const *)
      __attribute__ ((noreturn));
      __attribute__ ((noreturn));
@@ -127,7 +128,7 @@ unquote_string (char *string)
 	  *destination++ = '\a';
 	  *destination++ = '\a';
 	  source++;
 	  source++;
 	  break;
 	  break;
-	  
+
 	case 'b':
 	case 'b':
 	  *destination++ = '\b';
 	  *destination++ = '\b';
 	  source++;
 	  source++;
@@ -157,7 +158,7 @@ unquote_string (char *string)
 	  *destination++ = '\v';
 	  *destination++ = '\v';
 	  source++;
 	  source++;
 	  break;
 	  break;
-	  
+
 	case '?':
 	case '?':
 	  *destination++ = 0177;
 	  *destination++ = 0177;
 	  source++;
 	  source++;
@@ -224,7 +225,7 @@ must_be_dot_or_slash (char const *file_name)
       for (;;)
       for (;;)
 	if (ISSLASH (file_name[1]))
 	if (ISSLASH (file_name[1]))
 	  file_name++;
 	  file_name++;
-	else if (file_name[1] == '.' 
+	else if (file_name[1] == '.'
                  && ISSLASH (file_name[2 + (file_name[2] == '.')]))
                  && ISSLASH (file_name[2 + (file_name[2] == '.')]))
 	  file_name += 2 + (file_name[2] == '.');
 	  file_name += 2 + (file_name[2] == '.');
 	else
 	else
@@ -258,7 +259,7 @@ safer_rmdir (const char *file_name)
   return rmdir (file_name);
   return rmdir (file_name);
 }
 }
 
 
-/* Remove FILE_NAME, returning 1 on success.  If FILE_NAME is a directory, 
+/* Remove FILE_NAME, returning 1 on success.  If FILE_NAME is a directory,
    then if OPTION is RECURSIVE_REMOVE_OPTION is set remove FILE_NAME
    then if OPTION is RECURSIVE_REMOVE_OPTION is set remove FILE_NAME
    recursively; otherwise, remove it only if it is empty.  If FILE_NAME is
    recursively; otherwise, remove it only if it is empty.  If FILE_NAME is
    a directory that cannot be removed (e.g., because it is nonempty)
    a directory that cannot be removed (e.g., because it is nonempty)
@@ -268,9 +269,10 @@ safer_rmdir (const char *file_name)
 int
 int
 remove_any_file (const char *file_name, enum remove_option option)
 remove_any_file (const char *file_name, enum remove_option option)
 {
 {
-  /* Try unlink first if we are not root, as this saves us a system
-     call in the common case where we're removing a non-directory.  */
-  if (! we_are_root)
+  /* Try unlink first if we cannot unlink directories, as this saves
+     us a system call in the common case where we're removing a
+     non-directory.  */
+  if (cannot_unlink_dir ())
     {
     {
       if (unlink (file_name) == 0)
       if (unlink (file_name) == 0)
 	return 1;
 	return 1;
@@ -288,7 +290,7 @@ remove_any_file (const char *file_name, enum remove_option option)
   switch (errno)
   switch (errno)
     {
     {
     case ENOTDIR:
     case ENOTDIR:
-      return we_are_root && unlink (file_name) == 0;
+      return cannot_unlink_dir () && unlink (file_name) == 0;
 
 
     case 0:
     case 0:
     case EEXIST:
     case EEXIST:
@@ -317,7 +319,7 @@ remove_any_file (const char *file_name, enum remove_option option)
 		 entry += entrylen + 1)
 		 entry += entrylen + 1)
 	      {
 	      {
 		char *file_name_buffer = new_name (file_name, entry);
 		char *file_name_buffer = new_name (file_name, entry);
-		int r = remove_any_file (file_name_buffer, 
+		int r = remove_any_file (file_name_buffer,
                                          RECURSIVE_REMOVE_OPTION);
                                          RECURSIVE_REMOVE_OPTION);
 		int e = errno;
 		int e = errno;
 		free (file_name_buffer);
 		free (file_name_buffer);