+ /* Option -p clears the kernel umask, so it does not affect proper
+ restoration of file permissions. New intermediate directories will
+ comply with umask at start of program. */
+
+ newdir_umask = umask (0);
+ if (same_permissions_option)
+ current_umask = 0;
+ else
+ {
+ umask (newdir_umask); /* restore the kernel umask */
+ current_umask = newdir_umask;
+ }
+
+ /* FIXME: Just make sure we can add files in directories we create. Maybe
+ should we later remove permissions we are adding, here? */
+ newdir_umask &= ~ MODE_WXUSR;
+}
+
+/*------------------------------------------------------------------.
+| Restore mode for FILE_NAME, from information given in STAT_INFO. |
+`------------------------------------------------------------------*/
+
+static void
+set_mode (char *file_name, struct stat *stat_info)
+{
+ /* Do nothing unless we are restoring the original permissions.
+
+ We must force permission when -k and -U are not selected, because if the
+ file already existed, open or creat would save the permission bits from
+ the previously created file, ignoring the ones we specified.
+
+ But with -k or -U selected, we know *we* created this file, so the mode
+ bits were set by our open. If the file has abnormal mode bits, we must
+ chmod since writing or chown has probably reset them. If the file is
+ normal, we merely skip the chmod. This works because we did umask (0)
+ when -p, so umask will have left the specified mode alone. */
+
+ if ((we_are_root || same_permissions_option)
+ && ((!keep_old_files_option && !unlink_first_option)
+ || (stat_info->st_mode & (S_ISUID | S_ISGID | S_ISVTX))))
+ if (chmod (file_name, ~current_umask & stat_info->st_mode) < 0)
+ ERROR ((0, errno, _("%s: Cannot change mode to %04lo"),
+ file_name,
+ (unsigned long) (~current_umask & stat_info->st_mode)));
+}
+
+/*----------------------------------------------------------------------.
+| Restore stat attributes (owner, group, mode and times) for FILE_NAME, |
+| using information given in STAT_INFO. SYMLINK_FLAG is non-zero for a |
+| freshly restored symbolic link. |
+`----------------------------------------------------------------------*/
+
+/* FIXME: About proper restoration of symbolic link attributes, we still do
+ not have it right. Pretesters' reports tell us we need further study and
+ probably more configuration. For now, just use lchown if it exists, and
+ punt for the rest. Sigh! */
+
+static void
+set_stat (char *file_name, struct stat *stat_info, int symlink_flag)
+{
+ struct utimbuf utimbuf;
+
+ if (!symlink_flag)
+ {
+ /* We do the utime before the chmod because some versions of utime are
+ broken and trash the modes of the file. */
+
+ if (!touch_option)
+ {
+ /* We set the accessed time to `now', which is really the time we
+ started extracting files, unless incremental_option is used, in
+ which case .st_atime is used. */
+
+ /* FIXME: incremental_option should set ctime too, but how? */
+
+ if (incremental_option)
+ utimbuf.actime = stat_info->st_atime;
+ else
+ utimbuf.actime = now;
+
+ utimbuf.modtime = stat_info->st_mtime;
+
+ if (utime (file_name, &utimbuf) < 0)
+ ERROR ((0, errno,
+ _("%s: Could not change access and modification times"),
+ file_name));
+ }