diff options
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 316 |
1 files changed, 19 insertions, 297 deletions
@@ -1,10 +1,10 @@ /* util.c - Several utility routines for cpio. - Copyright (C) 1990, 1991, 1992, 2001, 2004, 2006, 2007, 2010 Free - Software Foundation, Inc. + Copyright (C) 1990, 1991, 1992, 2001, 2004, + 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) + the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -33,9 +33,7 @@ #include <hash.h> #include <utimens.h> -#ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> -#endif +#include <sys/ioctl.h> #ifdef HAVE_SYS_MTIO_H # ifdef HAVE_SYS_IO_TRIOCTL_H @@ -443,8 +441,8 @@ write_nuls_to_file (off_t num_bytes, int out_des, void copy_files_tape_to_disk (int in_des, int out_des, off_t num_bytes) { - off_t size; - off_t k; + long size; + long k; while (num_bytes > 0) { @@ -474,8 +472,8 @@ void copy_files_disk_to_tape (int in_des, int out_des, off_t num_bytes, char *filename) { - off_t size; - off_t k; + long size; + long k; int rc; off_t original_num_bytes; @@ -527,8 +525,8 @@ void copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes, char *filename) { - off_t size; - off_t k; + long size; + long k; off_t original_num_bytes; int rc; @@ -569,8 +567,8 @@ copy_files_disk_to_disk (int in_des, int out_des, off_t num_bytes, /* Warn if file changed while it was being copied. */ void -warn_if_file_changed (char *file_name, off_t old_file_size, - time_t old_file_mtime) +warn_if_file_changed (char *file_name, unsigned long old_file_size, + off_t old_file_mtime) { struct stat new_file_stat; if ((*xstat) (file_name, &new_file_stat) < 0) @@ -620,14 +618,7 @@ create_all_directories (char *name) error (2, 0, _("virtual memory exhausted")); if (dir[0] != '.' || dir[1] != '\0') - { - const char *fmt; - if (warn_option & CPIO_WARN_INTERDIR) - fmt = _("Creating intermediate directory `%s'"); - else - fmt = NULL; - make_path (dir, -1, -1, fmt); - } + make_path (dir, mode, 0700, -1, -1, (char *) NULL); free (dir); } @@ -686,7 +677,7 @@ prepare_append (int out_file_des) struct inode_val { - ino_t inode; + unsigned long inode; unsigned long major_num; unsigned long minor_num; char *file_name; @@ -713,7 +704,7 @@ inode_val_compare (const void *val1, const void *val2) } char * -find_inode_file (ino_t node_num, unsigned long major_num, +find_inode_file (unsigned long node_num, unsigned long major_num, unsigned long minor_num) { struct inode_val sample; @@ -732,7 +723,7 @@ find_inode_file (ino_t node_num, unsigned long major_num, /* Associate FILE_NAME with the inode NODE_NUM. (Insert into hash table.) */ void -add_inode (ino_t node_num, char *file_name, unsigned long major_num, +add_inode (unsigned long node_num, char *file_name, unsigned long major_num, unsigned long minor_num) { struct inode_val *temp; @@ -1256,9 +1247,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,54 +1258,8 @@ 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 -#ifndef HAVE_FCHMOD -# define HAVE_FCHMOD 0 +# define fchown(fd, uid, gid) (-1) #endif int @@ -1332,7 +1277,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 @@ -1395,226 +1340,3 @@ cpio_safer_name_suffix (char *name, bool link_target, bool absolute_names, memmove (name, p, (size_t)(strlen (p) + 1)); } - -/* This is a simplified form of delayed set_stat used by GNU tar. - With the time, both forms will merge and pass to paxutils - - List of directories whose statuses we need to extract after we've - finished extracting their subsidiary files. If you consider each - contiguous subsequence of elements of the form [D]?[^D]*, where [D] - represents an element where AFTER_LINKS is nonzero and [^D] - represents an element where AFTER_LINKS is zero, then the head - of the subsequence has the longest name, and each non-head element - in the prefix is an ancestor (in the directory hierarchy) of the - preceding element. */ - -struct delayed_set_stat - { - struct delayed_set_stat *next; - struct cpio_file_stat stat; - mode_t invert_permissions; - }; - -static struct delayed_set_stat *delayed_set_stat_head; - -void -delay_cpio_set_stat (struct cpio_file_stat *file_stat, - mode_t invert_permissions) -{ - 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; - memcpy (&data->stat, file_stat, sizeof data->stat); - data->stat.c_name = (char*) (data + 1); - 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 - links. *DIR_STAT_INFO is the status of the directory. */ -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) - { - struct stat st; - if (stat (data->stat.c_name, &st) != 0) - { - stat_error (data->stat.c_name); - return -1; - } - - if (st.st_dev == dir_stat_info->st_dev - && st.st_ino == dir_stat_info->st_ino) - { - stat_to_cpio (&data->stat, dir_stat_info); - data->invert_permissions = - ((dir_stat_info->st_mode ^ st.st_mode) - & MODE_RWX & ~ newdir_umask); - return 0; - } - } - return 1; -} - -/* Update the delayed_set_stat info for a directory matching - FILE_HDR. - - 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 -apply_delayed_set_stat () -{ - while (delayed_set_stat_head) - { - struct delayed_set_stat *data = delayed_set_stat_head; - if (data->invert_permissions) - { - data->stat.c_mode ^= data->invert_permissions; - } - set_perms (-1, &data->stat); - delayed_set_stat_head = data->next; - free (data); - } -} - - -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)) - set_perms (-1, file_hdr); - return 0; -} - |