1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2003-2007 Tim Kientzle 5 * All rights reserved. 6 */ 7 8 #include "bsdtar_platform.h" 9 10 #ifdef HAVE_SYS_TYPES_H 11 #include <sys/types.h> 12 #endif 13 #ifdef HAVE_SYS_PARAM_H 14 #include <sys/param.h> 15 #endif 16 #ifdef HAVE_SYS_STAT_H 17 #include <sys/stat.h> 18 #endif 19 20 #ifdef HAVE_ERRNO_H 21 #include <errno.h> 22 #endif 23 24 #ifdef HAVE_FCNTL_H 25 #include <fcntl.h> 26 #endif 27 28 #ifdef HAVE_GRP_H 29 #include <grp.h> 30 #endif 31 32 #ifdef HAVE_IO_H 33 #include <io.h> 34 #endif 35 36 #ifdef HAVE_LIMITS_H 37 #include <limits.h> 38 #endif 39 #ifdef HAVE_PWD_H 40 #include <pwd.h> 41 #endif 42 #ifdef HAVE_STDINT_H 43 #include <stdint.h> 44 #endif 45 #include <stdio.h> 46 #ifdef HAVE_STDLIB_H 47 #include <stdlib.h> 48 #endif 49 #ifdef HAVE_STRING_H 50 #include <string.h> 51 #endif 52 #ifdef HAVE_TIME_H 53 #include <time.h> 54 #endif 55 #ifdef HAVE_UNISTD_H 56 #include <unistd.h> 57 #endif 58 59 #include "bsdtar.h" 60 #include "err.h" 61 62 struct progress_data { 63 struct bsdtar *bsdtar; 64 struct archive *archive; 65 struct archive_entry *entry; 66 }; 67 68 static void read_archive(struct bsdtar *bsdtar, char mode, struct archive *); 69 static int unmatched_inclusions_warn(struct archive *matching, const char *); 70 71 72 void 73 tar_mode_t(struct bsdtar *bsdtar) 74 { 75 read_archive(bsdtar, 't', NULL); 76 if (unmatched_inclusions_warn(bsdtar->matching, 77 "Not found in archive") != 0) 78 bsdtar->return_value = 1; 79 } 80 81 void 82 tar_mode_x(struct bsdtar *bsdtar) 83 { 84 struct archive *writer; 85 86 writer = archive_write_disk_new(); 87 if (writer == NULL) 88 lafe_errc(1, ENOMEM, "Cannot allocate disk writer object"); 89 if ((bsdtar->flags & OPTFLAG_NUMERIC_OWNER) == 0) 90 archive_write_disk_set_standard_lookup(writer); 91 archive_write_disk_set_options(writer, bsdtar->extract_flags); 92 93 read_archive(bsdtar, 'x', writer); 94 95 if (unmatched_inclusions_warn(bsdtar->matching, 96 "Not found in archive") != 0) 97 bsdtar->return_value = 1; 98 archive_write_free(writer); 99 } 100 101 static void 102 progress_func(void *cookie) 103 { 104 struct progress_data *progress_data = (struct progress_data *)cookie; 105 struct bsdtar *bsdtar = progress_data->bsdtar; 106 struct archive *a = progress_data->archive; 107 struct archive_entry *entry = progress_data->entry; 108 uint64_t comp, uncomp; 109 int compression; 110 111 if (!need_report()) 112 return; 113 114 if (bsdtar->verbose) 115 fprintf(stderr, "\n"); 116 if (a != NULL) { 117 comp = archive_filter_bytes(a, -1); 118 uncomp = archive_filter_bytes(a, 0); 119 if (comp > uncomp) 120 compression = 0; 121 else 122 compression = (int)((uncomp - comp) * 100 / uncomp); 123 fprintf(stderr, 124 "In: %s bytes, compression %d%%;", 125 tar_i64toa(comp), compression); 126 fprintf(stderr, " Out: %d files, %s bytes\n", 127 archive_file_count(a), tar_i64toa(uncomp)); 128 } 129 if (entry != NULL) { 130 safe_fprintf(stderr, "Current: %s", 131 archive_entry_pathname(entry)); 132 fprintf(stderr, " (%s bytes)\n", 133 tar_i64toa(archive_entry_size(entry))); 134 } 135 } 136 137 /* 138 * Handle 'x' and 't' modes. 139 */ 140 static void 141 read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer) 142 { 143 struct progress_data progress_data; 144 FILE *out; 145 struct archive *a; 146 struct archive_entry *entry; 147 const char *reader_options; 148 int r; 149 150 while (*bsdtar->argv) { 151 if (archive_match_include_pattern(bsdtar->matching, 152 *bsdtar->argv) != ARCHIVE_OK) 153 lafe_errc(1, 0, "Error inclusion pattern: %s", 154 archive_error_string(bsdtar->matching)); 155 bsdtar->argv++; 156 } 157 158 if (bsdtar->names_from_file != NULL) 159 if (archive_match_include_pattern_from_file( 160 bsdtar->matching, bsdtar->names_from_file, 161 (bsdtar->flags & OPTFLAG_NULL)) != ARCHIVE_OK) 162 lafe_errc(1, 0, "Error inclusion pattern: %s", 163 archive_error_string(bsdtar->matching)); 164 165 a = archive_read_new(); 166 if (cset_read_support_filter_program(bsdtar->cset, a) == 0) 167 archive_read_support_filter_all(a); 168 archive_read_support_format_all(a); 169 170 reader_options = getenv(ENV_READER_OPTIONS); 171 if (reader_options != NULL) { 172 size_t module_len = sizeof(IGNORE_WRONG_MODULE_NAME) - 1; 173 size_t opt_len = strlen(reader_options) + 1; 174 char *p; 175 /* Set default read options. */ 176 if ((p = malloc(module_len + opt_len)) == NULL) 177 lafe_errc(1, errno, "Out of memory"); 178 /* Prepend magic code to ignore options for 179 * a format or modules which are not added to 180 * the archive read object. */ 181 memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len); 182 memcpy(p + module_len, reader_options, opt_len); 183 r = archive_read_set_options(a, p); 184 free(p); 185 if (r == ARCHIVE_FATAL) 186 lafe_errc(1, 0, "%s", archive_error_string(a)); 187 else 188 archive_clear_error(a); 189 } 190 if (ARCHIVE_OK != archive_read_set_options(a, bsdtar->option_options)) 191 lafe_errc(1, 0, "%s", archive_error_string(a)); 192 if (bsdtar->flags & OPTFLAG_IGNORE_ZEROS) 193 if (archive_read_set_options(a, 194 "read_concatenated_archives") != ARCHIVE_OK) 195 lafe_errc(1, 0, "%s", archive_error_string(a)); 196 if (bsdtar->passphrase != NULL) 197 r = archive_read_add_passphrase(a, bsdtar->passphrase); 198 else 199 r = archive_read_set_passphrase_callback(a, bsdtar, 200 &passphrase_callback); 201 if (r != ARCHIVE_OK) 202 lafe_errc(1, 0, "%s", archive_error_string(a)); 203 if (archive_read_open_filename(a, bsdtar->filename, 204 bsdtar->bytes_per_block)) 205 lafe_errc(1, 0, "Error opening archive: %s", 206 archive_error_string(a)); 207 208 do_chdir(bsdtar); 209 210 if (mode == 'x') { 211 /* Set an extract callback so that we can handle SIGINFO. */ 212 progress_data.bsdtar = bsdtar; 213 progress_data.archive = a; 214 archive_read_extract_set_progress_callback(a, progress_func, 215 &progress_data); 216 } 217 218 if (mode == 'x' && (bsdtar->flags & OPTFLAG_CHROOT)) { 219 #if HAVE_CHROOT 220 if (chroot(".") != 0) 221 lafe_errc(1, errno, "Can't chroot to \".\""); 222 #else 223 lafe_errc(1, 0, 224 "chroot isn't supported on this platform"); 225 #endif 226 } 227 228 #if defined(_WIN32) && !defined(__CYGWIN__) 229 if (mode == 'x' && (bsdtar->flags & OPTFLAG_STDOUT)) { 230 _setmode(1, _O_BINARY); 231 } 232 #endif 233 234 for (;;) { 235 /* Support --fast-read option */ 236 const char *p; 237 if ((bsdtar->flags & OPTFLAG_FAST_READ) && 238 archive_match_path_unmatched_inclusions(bsdtar->matching) == 0) 239 break; 240 241 r = archive_read_next_header(a, &entry); 242 progress_data.entry = entry; 243 if (r == ARCHIVE_EOF) 244 break; 245 if (r < ARCHIVE_OK) 246 lafe_warnc(0, "%s", archive_error_string(a)); 247 if (r <= ARCHIVE_WARN) 248 bsdtar->return_value = 1; 249 if (r == ARCHIVE_RETRY) { 250 /* Retryable error: try again */ 251 lafe_warnc(0, "Retrying..."); 252 continue; 253 } 254 if (r == ARCHIVE_FATAL) 255 break; 256 p = archive_entry_pathname(entry); 257 if (p == NULL || p[0] == '\0') { 258 lafe_warnc(0, "Archive entry has empty or unreadable filename ... skipping."); 259 bsdtar->return_value = 1; 260 continue; 261 } 262 263 if (bsdtar->uid >= 0) { 264 archive_entry_set_uid(entry, bsdtar->uid); 265 archive_entry_set_uname(entry, NULL); 266 } 267 if (bsdtar->gid >= 0) { 268 archive_entry_set_gid(entry, bsdtar->gid); 269 archive_entry_set_gname(entry, NULL); 270 } 271 if (bsdtar->uname) 272 archive_entry_set_uname(entry, bsdtar->uname); 273 if (bsdtar->gname) 274 archive_entry_set_gname(entry, bsdtar->gname); 275 276 /* 277 * Note that pattern exclusions are checked before 278 * pathname rewrites are handled. This gives more 279 * control over exclusions, since rewrites always lose 280 * information. (For example, consider a rewrite 281 * s/foo[0-9]/foo/. If we check exclusions after the 282 * rewrite, there would be no way to exclude foo1/bar 283 * while allowing foo2/bar.) 284 */ 285 if (archive_match_excluded(bsdtar->matching, entry)) 286 continue; /* Excluded by a pattern test. */ 287 288 if (mode == 't') { 289 /* Perversely, gtar uses -O to mean "send to stderr" 290 * when used with -t. */ 291 out = (bsdtar->flags & OPTFLAG_STDOUT) ? 292 stderr : stdout; 293 294 /* 295 * TODO: Provide some reasonable way to 296 * preview rewrites. gtar always displays 297 * the unedited path in -t output, which means 298 * you cannot easily preview rewrites. 299 */ 300 if (bsdtar->verbose < 2) 301 safe_fprintf(out, "%s", 302 archive_entry_pathname(entry)); 303 else 304 list_item_verbose(bsdtar, out, entry); 305 fflush(out); 306 r = archive_read_data_skip(a); 307 if (r == ARCHIVE_WARN) { 308 fprintf(out, "\n"); 309 lafe_warnc(0, "%s", 310 archive_error_string(a)); 311 } 312 if (r == ARCHIVE_RETRY) { 313 fprintf(out, "\n"); 314 lafe_warnc(0, "%s", 315 archive_error_string(a)); 316 } 317 if (r == ARCHIVE_FATAL) { 318 fprintf(out, "\n"); 319 lafe_warnc(0, "%s", 320 archive_error_string(a)); 321 bsdtar->return_value = 1; 322 break; 323 } 324 fprintf(out, "\n"); 325 } else { 326 /* Note: some rewrite failures prevent extraction. */ 327 if (edit_pathname(bsdtar, entry)) 328 continue; /* Excluded by a rewrite failure. */ 329 330 if ((bsdtar->flags & OPTFLAG_INTERACTIVE) && 331 !yes("extract '%s'", archive_entry_pathname(entry))) 332 continue; 333 334 if (bsdtar->verbose > 1) { 335 /* GNU tar uses -tv format with -xvv */ 336 safe_fprintf(stderr, "x "); 337 list_item_verbose(bsdtar, stderr, entry); 338 fflush(stderr); 339 } else if (bsdtar->verbose > 0) { 340 /* Format follows SUSv2, including the 341 * deferred '\n'. */ 342 safe_fprintf(stderr, "x %s", 343 archive_entry_pathname(entry)); 344 fflush(stderr); 345 } 346 347 /* TODO siginfo_printinfo(bsdtar, 0); */ 348 349 if (bsdtar->flags & OPTFLAG_STDOUT) 350 r = archive_read_data_into_fd(a, 1); 351 else 352 r = archive_read_extract2(a, entry, writer); 353 if (r != ARCHIVE_OK) { 354 if (!bsdtar->verbose) 355 safe_fprintf(stderr, "%s", archive_entry_pathname(entry)); 356 safe_fprintf(stderr, ": %s: %s", 357 archive_error_string(a), 358 strerror(archive_errno(a))); 359 if (!bsdtar->verbose) 360 fprintf(stderr, "\n"); 361 bsdtar->return_value = 1; 362 } 363 if (bsdtar->verbose) 364 fprintf(stderr, "\n"); 365 if (r == ARCHIVE_FATAL) 366 break; 367 } 368 } 369 370 371 r = archive_read_close(a); 372 if (r != ARCHIVE_OK) 373 lafe_warnc(0, "%s", archive_error_string(a)); 374 if (r <= ARCHIVE_WARN) 375 bsdtar->return_value = 1; 376 377 if (bsdtar->verbose > 2) 378 fprintf(stdout, "Archive Format: %s, Compression: %s\n", 379 archive_format_name(a), archive_filter_name(a, 0)); 380 381 archive_read_free(a); 382 } 383 384 385 static int 386 unmatched_inclusions_warn(struct archive *matching, const char *msg) 387 { 388 const char *p; 389 int r; 390 391 if (matching == NULL) 392 return (0); 393 394 while ((r = archive_match_path_unmatched_inclusions_next( 395 matching, &p)) == ARCHIVE_OK) 396 lafe_warnc(0, "%s: %s", p, msg); 397 if (r == ARCHIVE_FATAL) 398 lafe_errc(1, errno, "Out of memory"); 399 400 return (archive_match_path_unmatched_inclusions(matching)); 401 } 402