Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/archival/libarchive/data_extract_all.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/archival/libarchive/data_extract_all.c
r3232 r3621 12 12 int dst_fd; 13 13 int res; 14 char *hard_link; 15 #if ENABLE_FEATURE_TAR_LONG_OPTIONS 16 char *dst_name; 17 #else 18 # define dst_name (file_header->name) 19 #endif 14 20 15 21 #if ENABLE_FEATURE_TAR_SELINUX … … 24 30 #endif 25 31 32 /* Hard links are encoded as regular files of size 0 33 * with a nonempty link field */ 34 hard_link = NULL; 35 if (S_ISREG(file_header->mode) && file_header->size == 0) 36 hard_link = file_header->link_target; 37 38 #if ENABLE_FEATURE_TAR_LONG_OPTIONS 39 dst_name = file_header->name; 40 if (archive_handle->tar__strip_components) { 41 unsigned n = archive_handle->tar__strip_components; 42 do { 43 dst_name = strchr(dst_name, '/'); 44 if (!dst_name || dst_name[1] == '\0') { 45 data_skip(archive_handle); 46 goto ret; 47 } 48 dst_name++; 49 /* 50 * Link target is shortened only for hardlinks: 51 * softlinks restored unchanged. 52 */ 53 if (hard_link) { 54 // GNU tar 1.26 does not check that we reached end of link name: 55 // if "dir/hardlink" is hardlinked to "file", 56 // tar xvf a.tar --strip-components=1 says: 57 // tar: hardlink: Cannot hard link to '': No such file or directory 58 // and continues processing. We silently skip such entries. 59 hard_link = strchr(hard_link, '/'); 60 if (!hard_link || hard_link[1] == '\0') { 61 data_skip(archive_handle); 62 goto ret; 63 } 64 hard_link++; 65 } 66 } while (--n != 0); 67 } 68 #endif 69 26 70 if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) { 27 char *slash = strrchr( file_header->name, '/');71 char *slash = strrchr(dst_name, '/'); 28 72 if (slash) { 29 73 *slash = '\0'; 30 bb_make_directory( file_header->name, -1, FILEUTILS_RECUR);74 bb_make_directory(dst_name, -1, FILEUTILS_RECUR); 31 75 *slash = '/'; 32 76 } … … 36 80 /* Remove the entry if it exists */ 37 81 if (!S_ISDIR(file_header->mode)) { 38 /* Is it hardlink? 39 * We encode hard links as regular files of size 0 with a symlink */ 40 if (S_ISREG(file_header->mode) 41 && file_header->link_target 42 && file_header->size == 0 43 ) { 82 if (hard_link) { 44 83 /* Ugly special case: 45 84 * tar cf t.tar hardlink1 hardlink2 hardlink1 … … 49 88 * hardlink1 -> hardlink1 <== !!! 50 89 */ 51 if (strcmp( file_header->link_target, file_header->name) == 0)90 if (strcmp(hard_link, dst_name) == 0) 52 91 goto ret; 53 92 } 54 93 /* Proceed with deleting */ 55 if (unlink( file_header->name) == -194 if (unlink(dst_name) == -1 56 95 && errno != ENOENT 57 96 ) { 58 97 bb_perror_msg_and_die("can't remove old file %s", 59 file_header->name);98 dst_name); 60 99 } 61 100 } … … 64 103 /* Remove the existing entry if its older than the extracted entry */ 65 104 struct stat existing_sb; 66 if (lstat( file_header->name, &existing_sb) == -1) {105 if (lstat(dst_name, &existing_sb) == -1) { 67 106 if (errno != ENOENT) { 68 107 bb_perror_msg_and_die("can't stat old file"); … … 74 113 ) { 75 114 bb_error_msg("%s not created: newer or " 76 "same age file exists", file_header->name);115 "same age file exists", dst_name); 77 116 } 78 117 data_skip(archive_handle); 79 118 goto ret; 80 119 } 81 else if ((unlink( file_header->name) == -1) && (errno != EISDIR)) {120 else if ((unlink(dst_name) == -1) && (errno != EISDIR)) { 82 121 bb_perror_msg_and_die("can't remove old file %s", 83 file_header->name); 84 } 85 } 86 87 /* Handle hard links separately 88 * We encode hard links as regular files of size 0 with a symlink */ 89 if (S_ISREG(file_header->mode) 90 && file_header->link_target 91 && file_header->size == 0 92 ) { 93 /* hard link */ 94 res = link(file_header->link_target, file_header->name); 95 if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { 122 dst_name); 123 } 124 } 125 126 /* Handle hard links separately */ 127 if (hard_link) { 128 res = link(hard_link, dst_name); 129 if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { 96 130 bb_perror_msg("can't create %slink " 97 131 "from %s to %s", "hard", 98 file_header->name,99 file_header->link_target);132 dst_name, 133 hard_link); 100 134 } 101 135 /* Hardlinks have no separate mode/ownership, skip chown/chmod */ … … 107 141 case S_IFREG: { 108 142 /* Regular file */ 143 char *dst_nameN; 109 144 int flags = O_WRONLY | O_CREAT | O_EXCL; 110 145 if (archive_handle->ah_flags & ARCHIVE_O_TRUNC) 111 146 flags = O_WRONLY | O_CREAT | O_TRUNC; 112 dst_fd = xopen3(file_header->name, 147 dst_nameN = dst_name; 148 #ifdef ARCHIVE_REPLACE_VIA_RENAME 149 if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) 150 /* rpm-style temp file name */ 151 dst_nameN = xasprintf("%s;%x", dst_name, (int)getpid()); 152 #endif 153 dst_fd = xopen3(dst_nameN, 113 154 flags, 114 155 file_header->mode … … 116 157 bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size); 117 158 close(dst_fd); 159 #ifdef ARCHIVE_REPLACE_VIA_RENAME 160 if (archive_handle->ah_flags & ARCHIVE_REPLACE_VIA_RENAME) { 161 xrename(dst_nameN, dst_name); 162 free(dst_nameN); 163 } 164 #endif 118 165 break; 119 166 } 120 167 case S_IFDIR: 121 res = mkdir( file_header->name, file_header->mode);168 res = mkdir(dst_name, file_header->mode); 122 169 if ((res == -1) 123 170 && (errno != EISDIR) /* btw, Linux doesn't return this */ … … 125 172 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) 126 173 ) { 127 bb_perror_msg("can't make dir %s", file_header->name);174 bb_perror_msg("can't make dir %s", dst_name); 128 175 } 129 176 break; … … 131 178 /* Symlink */ 132 179 //TODO: what if file_header->link_target == NULL (say, corrupted tarball?) 133 res = symlink(file_header->link_target, file_header->name);134 if ( (res == -1)180 res = symlink(file_header->link_target, dst_name); 181 if (res != 0 135 182 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) 136 183 ) { 137 184 bb_perror_msg("can't create %slink " 138 185 "from %s to %s", "sym", 139 file_header->name,186 dst_name, 140 187 file_header->link_target); 141 188 } … … 145 192 case S_IFCHR: 146 193 case S_IFIFO: 147 res = mknod( file_header->name, file_header->mode, file_header->device);194 res = mknod(dst_name, file_header->mode, file_header->device); 148 195 if ((res == -1) 149 196 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) 150 197 ) { 151 bb_perror_msg("can't create node %s", file_header->name);198 bb_perror_msg("can't create node %s", dst_name); 152 199 } 153 200 break; … … 174 221 #endif 175 222 /* GNU tar 1.15.1 uses chown, not lchown */ 176 chown( file_header->name, uid, gid);223 chown(dst_name, uid, gid); 177 224 } 178 225 /* uclibc has no lchmod, glibc is even stranger - … … 180 227 * so we use chmod... */ 181 228 if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) { 182 chmod( file_header->name, file_header->mode);229 chmod(dst_name, file_header->mode); 183 230 } 184 231 if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) { … … 187 234 t[1].tv_sec = t[0].tv_sec = file_header->mtime; 188 235 t[1].tv_usec = t[0].tv_usec = 0; 189 utimes( file_header->name, t);236 utimes(dst_name, t); 190 237 } 191 238 }
Note:
See TracChangeset
for help on using the changeset viewer.