/* Extract files from a tar archive.
- Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2013
- Free Software Foundation, Inc.
+ Copyright 1988, 1992-1994, 1996-2001, 2003-2007, 2010, 2012-2014,
+ 2016 Free Software Foundation, Inc.
This file is part of GNU tar.
struct xattr_array *xattr_map;
/* Length and contents of name. */
size_t file_name_len;
- char file_name[1];
+ char *file_name;
};
static struct delayed_set_stat *delayed_set_stat_head;
mode_t mode, int atflag)
{
size_t file_name_len = strlen (file_name);
- struct delayed_set_stat *data =
- xmalloc (offsetof (struct delayed_set_stat, file_name)
- + file_name_len + 1);
+ struct delayed_set_stat *data = xmalloc (sizeof (*data));
data->next = delayed_set_stat_head;
data->mode = mode;
if (st)
data->mtime = st->mtime;
}
data->file_name_len = file_name_len;
+ data->file_name = xstrdup (file_name);
data->current_mode = current_mode;
data->current_mode_mask = current_mode_mask;
data->interdir = ! st;
quotearg_colon (dir)));
}
+static void
+free_delayed_set_stat (struct delayed_set_stat *data)
+{
+ free (data->file_name);
+ xheader_xattr_free (data->xattr_map, data->xattr_map_size);
+ free (data->cntx_name);
+ free (data->acls_a_ptr);
+ free (data->acls_d_ptr);
+ free (data);
+}
+
+void
+remove_delayed_set_stat (const char *fname)
+{
+ struct delayed_set_stat *data, *next, *prev = NULL;
+ for (data = delayed_set_stat_head; data; data = next)
+ {
+ next = data->next;
+ if (chdir_current == data->change_dir
+ && strcmp (data->file_name, fname) == 0)
+ {
+ free_delayed_set_stat (data);
+ if (prev)
+ prev->next = next;
+ else
+ delayed_set_stat_head = next;
+ return;
+ }
+ else
+ prev = data;
+ }
+}
+
+static void
+fixup_delayed_set_stat (char const *src, char const *dst)
+{
+ struct delayed_set_stat *data;
+ for (data = delayed_set_stat_head; data; data = data->next)
+ {
+ if (chdir_current == data->change_dir
+ && strcmp (data->file_name, src) == 0)
+ {
+ free (data->file_name);
+ data->file_name = xstrdup (dst);
+ data->file_name_len = strlen (dst);
+ return;
+ }
+ }
+}
+
/* After a file/link/directory creation has failed, see if
it's because some required directory was not present, and if so,
create all required directories. Return zero if all the required
}
delayed_set_stat_head = data->next;
- xheader_xattr_free (data->xattr_map, data->xattr_map_size);
- free (data->cntx_name);
- free (data->acls_a_ptr);
- free (data->acls_d_ptr);
- free (data);
+ free_delayed_set_stat (data);
}
}
bool
rename_directory (char *src, char *dst)
{
- if (renameat (chdir_fd, src, chdir_fd, dst) != 0)
+ if (renameat (chdir_fd, src, chdir_fd, dst) == 0)
+ fixup_delayed_set_stat (src, dst);
+ else
{
int e = errno;
bool interdir_made;