aboutsummaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-07-31 17:45:38 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-07-31 17:45:38 +0300
commit400d6b61b98c3be5eebb095019dfe6310e1ca253 (patch)
tree27c542ecd4643c27d55f31aca0ef222779a02527 /src/util.c
parent15d29bd0863a819ed950f65523b6000961d1213e (diff)
downloadcpio-400d6b61b98c3be5eebb095019dfe6310e1ca253.tar.gz
cpio-400d6b61b98c3be5eebb095019dfe6310e1ca253.tar.bz2
Delay setting directory attributes until end of run, if they do not permit writing. Fix debian bug #458079.
* src/copyin.c (copyin_mkdir): New function. (copyin_directory): Use copyin_mkdir to create directory. Call set_perms only when safe, otherwise use repair_delayed_set_stat. * src/extern.h (cpio_to_stat): New prototype. (repair_delayed_set_stat): Change prototype. * src/util.c (cpio_to_stat): New function. (repair_delayed_set_stat): New function. * tests/setstat01.at: New test case. * tests/setstat02.at: New test case. * tests/Makefile.am (TESTSUITE_AT): Add setstat01.at and setstat02.at * tests/testsuite.at: Include setstat01.at and setstat02.at. * NEWS: Update.
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c79
1 files changed, 70 insertions, 9 deletions
diff --git a/src/util.c b/src/util.c
index 2b765d9..1eb92ae 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1256,9 +1256,9 @@ stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st)
else if (S_ISNWK (st->st_mode))
hdr->c_mode |= CP_IFNWK;
#endif
+ hdr->c_nlink = st->st_nlink;
hdr->c_uid = CPIO_UID (st->st_uid);
hdr->c_gid = CPIO_GID (st->st_gid);
- hdr->c_nlink = st->st_nlink;
hdr->c_rdev_maj = major (st->st_rdev);
hdr->c_rdev_min = minor (st->st_rdev);
hdr->c_mtime = st->st_mtime;
@@ -1267,6 +1267,49 @@ stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st)
hdr->c_tar_linkname = NULL;
}
+void
+cpio_to_stat (struct stat *st, struct cpio_file_stat *hdr)
+{
+ memset (st, 0, sizeof (*st));
+ st->st_dev = makedev (hdr->c_dev_maj, hdr->c_dev_min);
+ st->st_ino = hdr->c_ino;
+ st->st_mode = hdr->c_mode & 0777;
+ if (hdr->c_mode & CP_IFREG)
+ st->st_mode |= S_IFREG;
+ else if (hdr->c_mode & CP_IFDIR)
+ st->st_mode |= S_IFDIR;
+#ifdef S_IFBLK
+ else if (hdr->c_mode & CP_IFBLK)
+ st->st_mode |= S_IFBLK;
+#endif
+#ifdef S_IFCHR
+ else if (hdr->c_mode & CP_IFCHR)
+ st->st_mode |= S_IFCHR;
+#endif
+#ifdef S_IFFIFO
+ else if (hdr->c_mode & CP_IFIFO)
+ st->st_mode |= S_IFIFO;
+#endif
+#ifdef S_IFLNK
+ else if (hdr->c_mode & CP_IFLNK)
+ st->st_mode |= S_IFLNK;
+#endif
+#ifdef S_IFSOCK
+ else if (hdr->c_mode & CP_IFSOCK)
+ st->st_mode |= S_IFSOCK;
+#endif
+#ifdef S_IFNWK
+ else if (hdr->c_mode & CP_IFNWK)
+ st->st_mode |= S_IFNWK;
+#endif
+ st->st_nlink = hdr->c_nlink;
+ st->st_uid = CPIO_UID (hdr->c_uid);
+ st->st_gid = CPIO_GID (hdr->c_gid);
+ st->st_rdev = makedev (hdr->c_rdev_maj, hdr->c_rdev_min);
+ st->st_mtime = hdr->c_mtime;
+ st->st_size = hdr->c_filesize;
+}
+
#ifndef HAVE_FCHOWN
# define HAVE_FCHOWN 0
#endif
@@ -1289,7 +1332,7 @@ fchmod_or_chmod (int fd, const char *name, mode_t mode)
if (HAVE_FCHMOD && fd != -1)
return fchmod (fd, mode);
else
- return chmod(name, mode);
+ return chmod (name, mode);
}
void
@@ -1394,9 +1437,8 @@ delay_set_stat (char const *file_name, struct stat *st,
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. */
-void
-repair_delayed_set_stat (char const *dir,
- struct stat *dir_stat_info)
+int
+repair_inter_delayed_set_stat (struct stat *dir_stat_info)
{
struct delayed_set_stat *data;
for (data = delayed_set_stat_head; data; data = data->next)
@@ -1405,7 +1447,7 @@ repair_delayed_set_stat (char const *dir,
if (stat (data->stat.c_name, &st) != 0)
{
stat_error (data->stat.c_name);
- return;
+ return -1;
}
if (st.st_dev == dir_stat_info->st_dev
@@ -1415,12 +1457,31 @@ repair_delayed_set_stat (char const *dir,
data->invert_permissions =
((dir_stat_info->st_mode ^ st.st_mode)
& MODE_RWX & ~ newdir_umask);
- return;
+ return 0;
}
}
+ return 1;
+}
+
+/* Update the delayed_set_stat info for a directory matching
+ FILE_HDR.
- ERROR ((0, 0, _("%s: Unexpected inconsistency when making directory"),
- quotearg_colon (dir)));
+ Return 0 if such info was found, 1 otherwise. */
+int
+repair_delayed_set_stat (struct cpio_file_stat *file_hdr)
+{
+ struct delayed_set_stat *data;
+ for (data = delayed_set_stat_head; data; data = data->next)
+ {
+ if (strcmp (file_hdr->c_name, data->stat.c_name) == 0)
+ {
+ data->invert_permissions = 0;
+ memcpy (&data->stat, file_hdr,
+ offsetof (struct cpio_file_stat, c_name));
+ return 0;
+ }
+ }
+ return 1;
}
void

Return to:

Send suggestions and report system problems to the System administrator.