same_owner_option += we_are_root;
xalloc_fail_func = extract_finish;
+ /* Save 'root device' to avoid purging mount points.
+ FIXME: Should the same be done after handling -C option ? */
+ if (one_file_system_option)
+ {
+ struct stat st;
+ char *dir = xgetcwd ();
+
+ if (deref_stat (true, dir, &st))
+ stat_diag (dir);
+ else
+ root_device = st.st_dev;
+ }
+
/* 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. */
}
/* Update the delayed_set_stat info for an intermediate directory
- created on the path to DIR. The intermediate directory turned
+ created within the file name of DIR. The intermediate directory turned
out to be the same as this directory, e.g. due to ".." or symbolic
links. *DIR_STAT_INFO is the status of the directory. */
static void
make_directories (char *file_name)
{
char *cursor0 = file_name + FILESYSTEM_PREFIX_LEN (file_name);
- char *cursor; /* points into path */
+ char *cursor; /* points into the file name */
int did_something = 0; /* did we do anything yet? */
int mode;
int invert_permissions;
if (cursor == cursor0 || ISSLASH (cursor[-1]))
continue;
- /* Avoid mkdir where last part of path is "." or "..". */
+ /* Avoid mkdir where last part of file name is "." or "..". */
if (cursor[-1] == '.'
&& (cursor == cursor0 + 1 || ISSLASH (cursor[-2])
&& (cursor == cursor0 + 2 || ISSLASH (cursor[-3])))))
continue;
- *cursor = '\0'; /* truncate the path there */
+ *cursor = '\0'; /* truncate the name there */
mode = MODE_RWX & ~ newdir_umask;
invert_permissions = we_are_root ? 0 : MODE_WXUSR & ~ mode;
status = mkdir (file_name, mode ^ invert_permissions);
/* MSDOS does not implement links. However, djgpp's link() actually
copies the file. */
status = link (link_name, file_name);
+ e = errno;
if (status == 0)
{
struct delayed_symlink *ds = delayed_symlink_head;
- if (ds && stat (link_name, &st1) == 0)
+ if (ds && lstat (link_name, &st1) == 0)
for (; ds; ds = ds->next)
if (ds->dev == st1.st_dev
&& ds->ino == st1.st_ino
}
break;
}
+
+ if ((e == EEXIST && strcmp (link_name, file_name) == 0)
+ || (lstat (link_name, &st1) == 0
+ && lstat (file_name, &st2) == 0
+ && st1.st_dev == st2.st_dev
+ && st1.st_ino == st2.st_ino))
+ break;
+
+ errno = e;
if (maybe_recoverable (file_name, &interdir_made))
goto again_link;
if (incremental_option && errno == EEXIST)
break;
- e = errno;
- if (stat (link_name, &st1) == 0
- && stat (file_name, &st2) == 0
- && st1.st_dev == st2.st_dev
- && st1.st_ino == st2.st_ino)
- break;
link_error (link_name, file_name);
if (backup_option)
/* Read the entry and delete files that aren't listed in the
archive. */
- gnu_restore (file_name);
+ purge_directory (file_name);
}
else if (typeflag == GNUTYPE_DUMPDIR)
skip_member ();