aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-02-12 23:07:25 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2010-02-12 23:07:25 +0200
commit5864f3267f4c1c002a5f405477c113a093f3b5bd (patch)
tree4cd7bd51f188825116ff0316e22fd779e9c722f9 /src
parent7c5fda3fbada772e53e0c347621921a8111738c0 (diff)
downloadcpio-5864f3267f4c1c002a5f405477c113a093f3b5bd.tar.gz
cpio-5864f3267f4c1c002a5f405477c113a093f3b5bd.tar.bz2
Use same code when creating directories in copy-in and copy-pass modes.
* src/copyin.c (copyin_mkdir): Remove. (copyin_directory): Remove. (copyin_file): Use cpio_create_dir instead of copyin_directory. * src/copypass.c (process_copy_pass): Use cpio_create_dir to create directories. * src/extern.h (delay_cpio_set_stat): New proto. * src/util.c (delay_cpio_set_stat): New function. (delay_set_stat): Rewrite as a wrapper to the above. (cpio_create_dir): New function. * tests/setstat01.at: Fix testcase. * tests/setstat02.at: Likewise. * tests/setstat03.at: New testcase. * tests/setstat04.at: New testcase. * tests/setstat05.at: New testcase. * tests/Makefile.am: Add new testcases. * tests/testsuite.at: Likewise.
Diffstat (limited to 'src')
-rw-r--r--src/copyin.c112
-rw-r--r--src/copypass.c49
-rw-r--r--src/extern.h5
-rw-r--r--src/util.c129
4 files changed, 134 insertions, 161 deletions
diff --git a/src/copyin.c b/src/copyin.c
index 2db6bb3..ac921e1 100644
--- a/src/copyin.c
+++ b/src/copyin.c
@@ -566,114 +566,6 @@ copyin_regular_file (struct cpio_file_stat* file_hdr, int in_file_des)
}
}
-static int
-copyin_mkdir (struct cpio_file_stat *file_hdr, int *setstat_delayed)
-{
- int rc;
- mode_t mode = file_hdr->c_mode;
- if (!(file_hdr->c_mode & S_IWUSR))
- {
- rc = mkdir (file_hdr->c_name, mode | S_IWUSR);
- if (rc == 0)
- {
- struct stat st;
- cpio_to_stat (&st, file_hdr);
- delay_set_stat (file_hdr->c_name, &st, false);
- *setstat_delayed = 1;
- }
- }
- else
- {
- rc = mkdir (file_hdr->c_name, mode);
- *setstat_delayed = 0;
- }
- return rc;
-}
-
-static void
-copyin_directory (struct cpio_file_stat *file_hdr, int existing_dir)
-{
- int res; /* Result of various function calls. */
-#ifdef HPUX_CDF
- int cdf_flag; /* True if file is a CDF. */
- int cdf_char; /* Index of `+' char indicating a CDF. */
-#endif
- int setstat_delayed = 0;
-
- if (to_stdout_option)
- return;
-
- /* Strip any trailing `/'s off the filename; tar puts
- them on. We might as well do it here in case anybody
- else does too, since they cause strange things to happen. */
- strip_trailing_slashes (file_hdr->c_name);
-
- /* Ignore the current directory. It must already exist,
- and we don't want to change its permission, ownership
- or time. */
- if (file_hdr->c_name[0] == '.' && file_hdr->c_name[1] == '\0')
- {
- return;
- }
-
-#ifdef HPUX_CDF
- cdf_flag = 0;
-#endif
- if (!existing_dir)
-
- {
-#ifdef HPUX_CDF
- /* If the directory name ends in a + and is SUID,
- then it is a CDF. Strip the trailing + from
- the name before creating it. */
- cdf_char = strlen (file_hdr->c_name) - 1;
- if ( (cdf_char > 0) &&
- (file_hdr->c_mode & 04000) &&
- (file_hdr->c_name [cdf_char] == '+') )
- {
- file_hdr->c_name [cdf_char] = '\0';
- cdf_flag = 1;
- }
-#endif
- res = copyin_mkdir (file_hdr, &setstat_delayed);
- }
- else
- res = 0;
- if (res < 0 && create_dir_flag)
- {
- create_all_directories (file_hdr->c_name);
- res = copyin_mkdir (file_hdr, &setstat_delayed);
- }
- if (res < 0)
- {
- /* In some odd cases where the file_hdr->c_name includes `.',
- the directory may have actually been created by
- create_all_directories(), so the mkdir will fail
- because the directory exists. If that's the case,
- don't complain about it. */
- struct stat file_stat;
- if (errno != EEXIST)
- {
- mkdir_error (file_hdr->c_name);
- return;
- }
- if (lstat (file_hdr->c_name, &file_stat))
- {
- stat_error (file_hdr->c_name);
- return;
- }
- if (!(S_ISDIR (file_stat.st_mode)))
- {
- error (0, 0, _("%s is not a directory"),
- quotearg_colon (file_hdr->c_name));
- return;
- }
- }
-
- if (!setstat_delayed && repair_delayed_set_stat (file_hdr) == 0)
- set_perms (-1, file_hdr);
-}
-
static void
copyin_device (struct cpio_file_stat* file_hdr)
{
@@ -795,7 +687,7 @@ copyin_link(struct cpio_file_stat *file_hdr, int in_file_des)
}
static void
-copyin_file (struct cpio_file_stat* file_hdr, int in_file_des)
+copyin_file (struct cpio_file_stat *file_hdr, int in_file_des)
{
int existing_dir;
@@ -811,7 +703,7 @@ copyin_file (struct cpio_file_stat* file_hdr, int in_file_des)
break;
case CP_IFDIR:
- copyin_directory (file_hdr, existing_dir);
+ cpio_create_dir (file_hdr, existing_dir);
break;
case CP_IFCHR:
diff --git a/src/copypass.c b/src/copypass.c
index ab44c20..d249a31 100644
--- a/src/copypass.c
+++ b/src/copypass.c
@@ -221,50 +221,11 @@ process_copy_pass ()
}
else if (S_ISDIR (in_file_stat.st_mode))
{
-#ifdef HPUX_CDF
- cdf_flag = 0;
-#endif
- if (!existing_dir)
- {
-#ifdef HPUX_CDF
- /* If the directory name ends in a + and is SUID,
- then it is a CDF. Strip the trailing + from the name
- before creating it. */
- cdf_char = strlen (output_name.ds_string) - 1;
- if ( (cdf_char > 0) &&
- (in_file_stat.st_mode & 04000) &&
- (output_name.ds_string [cdf_char] == '+') )
- {
- output_name.ds_string [cdf_char] = '\0';
- cdf_flag = 1;
- }
-#endif
- res = mkdir (output_name.ds_string, in_file_stat.st_mode);
-
- }
- else
- res = 0;
- if (res < 0 && create_dir_flag)
- {
- create_all_directories (output_name.ds_string);
- res = mkdir (output_name.ds_string, in_file_stat.st_mode);
- }
- if (res < 0)
- {
- /* In some odd cases where the output_name includes `.',
- the directory may have actually been created by
- create_all_directories(), so the mkdir will fail
- because the directory exists. If that's the case,
- don't complain about it. */
- if ( (errno != EEXIST) ||
- (lstat (output_name.ds_string, &out_file_stat) != 0) ||
- !(S_ISDIR (out_file_stat.st_mode) ) )
- {
- stat_error (output_name.ds_string);
- continue;
- }
- }
- set_copypass_perms (-1, output_name.ds_string, &in_file_stat);
+ struct cpio_file_stat file_stat;
+
+ stat_to_cpio (&file_stat, &in_file_stat);
+ file_stat.c_name = output_name.ds_string;
+ cpio_create_dir (&file_stat, existing_dir);
}
else if (S_ISCHR (in_file_stat.st_mode) ||
S_ISBLK (in_file_stat.st_mode) ||
diff --git a/src/extern.h b/src/extern.h
index a2a08b7..4f94d40 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -199,6 +199,7 @@ void stat_to_cpio (struct cpio_file_stat *hdr, struct stat *st);
void cpio_to_stat (struct stat *st, struct cpio_file_stat *hdr);
void cpio_safer_name_suffix (char *name, bool link_target,
bool absolute_names, bool strip_leading_dots);
+int cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir);
/* FIXME: These two defines should be defined in paxutils */
#define LG_8 3
@@ -208,7 +209,9 @@ uintmax_t from_ascii (char const *where, size_t digs, unsigned logbase);
#define FROM_OCTAL(f) from_ascii (f, sizeof f, LG_8)
#define FROM_HEX(f) from_ascii (f, sizeof f, LG_16)
-
+
+void delay_cpio_set_stat (struct cpio_file_stat *file_stat,
+ mode_t invert_permissions);
void delay_set_stat (char const *file_name, struct stat *st,
mode_t invert_permissions);
int repair_delayed_set_stat (struct cpio_file_stat *file_hdr);
diff --git a/src/util.c b/src/util.c
index d029f6e..ae6a3de 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1418,21 +1418,31 @@ struct delayed_set_stat
static struct delayed_set_stat *delayed_set_stat_head;
void
-delay_set_stat (char const *file_name, struct stat *st,
- mode_t invert_permissions)
+delay_cpio_set_stat (struct cpio_file_stat *file_stat,
+ mode_t invert_permissions)
{
- size_t file_name_len = strlen (file_name);
+ size_t file_name_len = strlen (file_stat->c_name);
struct delayed_set_stat *data =
xmalloc (sizeof (struct delayed_set_stat) + file_name_len + 1);
data->next = delayed_set_stat_head;
- memset (&data->stat, 0, sizeof data->stat);
- stat_to_cpio (&data->stat, st);
+ memcpy (&data->stat, file_stat, sizeof data->stat);
data->stat.c_name = (char*) (data + 1);
- strcpy (data->stat.c_name, file_name);
+ strcpy (data->stat.c_name, file_stat->c_name);
data->invert_permissions = invert_permissions;
delayed_set_stat_head = data;
}
+void
+delay_set_stat (char const *file_name, struct stat *st,
+ mode_t invert_permissions)
+{
+ struct cpio_file_stat fs;
+
+ stat_to_cpio (&fs, st);
+ fs.c_name = (char*) file_name;
+ delay_cpio_set_stat (&fs, invert_permissions);
+}
+
/* Update the delayed_set_stat info for an intermediate directory
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
@@ -1500,4 +1510,111 @@ apply_delayed_set_stat ()
}
}
+
+static int
+cpio_mkdir (struct cpio_file_stat *file_hdr, int *setstat_delayed)
+{
+ int rc;
+ mode_t mode = file_hdr->c_mode;
+
+ if (!(file_hdr->c_mode & S_IWUSR))
+ {
+ rc = mkdir (file_hdr->c_name, mode | S_IWUSR);
+ if (rc == 0)
+ {
+ delay_cpio_set_stat (file_hdr, 0);
+ *setstat_delayed = 1;
+ }
+ }
+ else
+ {
+ rc = mkdir (file_hdr->c_name, mode);
+ *setstat_delayed = 0;
+ }
+ return rc;
+}
+
+int
+cpio_create_dir (struct cpio_file_stat *file_hdr, int existing_dir)
+{
+ int res; /* Result of various function calls. */
+#ifdef HPUX_CDF
+ int cdf_flag; /* True if file is a CDF. */
+ int cdf_char; /* Index of `+' char indicating a CDF. */
+#endif
+ int setstat_delayed = 0;
+
+ if (to_stdout_option)
+ return 0;
+
+ /* Strip any trailing `/'s off the filename; tar puts
+ them on. We might as well do it here in case anybody
+ else does too, since they cause strange things to happen. */
+ strip_trailing_slashes (file_hdr->c_name);
+
+ /* Ignore the current directory. It must already exist,
+ and we don't want to change its permission, ownership
+ or time. */
+ if (file_hdr->c_name[0] == '.' && file_hdr->c_name[1] == '\0')
+ {
+ return 0;
+ }
+
+#ifdef HPUX_CDF
+ cdf_flag = 0;
+#endif
+ if (!existing_dir)
+ {
+#ifdef HPUX_CDF
+ /* If the directory name ends in a + and is SUID,
+ then it is a CDF. Strip the trailing + from
+ the name before creating it. */
+ cdf_char = strlen (file_hdr->c_name) - 1;
+ if ( (cdf_char > 0) &&
+ (file_hdr->c_mode & 04000) &&
+ (file_hdr->c_name [cdf_char] == '+') )
+ {
+ file_hdr->c_name [cdf_char] = '\0';
+ cdf_flag = 1;
+ }
+#endif
+ res = cpio_mkdir (file_hdr, &setstat_delayed);
+ }
+ else
+ res = 0;
+ if (res < 0 && create_dir_flag)
+ {
+ create_all_directories (file_hdr->c_name);
+ res = cpio_mkdir (file_hdr, &setstat_delayed);
+ }
+ if (res < 0)
+ {
+ /* In some odd cases where the file_hdr->c_name includes `.',
+ the directory may have actually been created by
+ create_all_directories(), so the mkdir will fail
+ because the directory exists. If that's the case,
+ don't complain about it. */
+ struct stat file_stat;
+ if (errno != EEXIST)
+ {
+ mkdir_error (file_hdr->c_name);
+ return -1;
+ }
+ if (lstat (file_hdr->c_name, &file_stat))
+ {
+ stat_error (file_hdr->c_name);
+ return -1;
+ }
+ if (!(S_ISDIR (file_stat.st_mode)))
+ {
+ error (0, 0, _("%s is not a directory"),
+ quotearg_colon (file_hdr->c_name));
+ return -1;
+ }
+ }
+
+ if (!setstat_delayed && repair_delayed_set_stat (file_hdr) == 0)
+ set_perms (-1, file_hdr);
+ return 0;
+}

Return to:

Send suggestions and report system problems to the System administrator.