archive_write_disk_posix.c (305188) | archive_write_disk_posix.c (306321) |
---|---|
1/*- 2 * Copyright (c) 2003-2010 Tim Kientzle 3 * Copyright (c) 2012 Michihiro NAKAJIMA 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 126 unchanged lines hidden (view full) --- 135#include "archive_entry.h" 136#include "archive_private.h" 137#include "archive_write_disk_private.h" 138 139#ifndef O_BINARY 140#define O_BINARY 0 141#endif 142#ifndef O_CLOEXEC | 1/*- 2 * Copyright (c) 2003-2010 Tim Kientzle 3 * Copyright (c) 2012 Michihiro NAKAJIMA 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 126 unchanged lines hidden (view full) --- 135#include "archive_entry.h" 136#include "archive_private.h" 137#include "archive_write_disk_private.h" 138 139#ifndef O_BINARY 140#define O_BINARY 0 141#endif 142#ifndef O_CLOEXEC |
143#define O_CLOEXEC 0 | 143#define O_CLOEXEC 0 |
144#endif 145 | 144#endif 145 |
146/* Ignore non-int O_NOFOLLOW constant. */ 147/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */ 148#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) 149#undef O_NOFOLLOW 150#endif 151 152#ifndef O_NOFOLLOW 153#define O_NOFOLLOW 0 154#endif 155 |
|
146struct fixup_entry { 147 struct fixup_entry *next; 148 struct archive_acl acl; 149 mode_t mode; 150 int64_t atime; 151 int64_t birthtime; 152 int64_t mtime; 153 int64_t ctime; --- 167 unchanged lines hidden (view full) --- 321#define DECMPFS_MAGIC 0x636d7066 322#define DECMPFS_COMPRESSION_MAGIC 0 323#define DECMPFS_COMPRESSION_TYPE 4 324#define DECMPFS_UNCOMPRESSED_SIZE 8 325#define DECMPFS_HEADER_SIZE 16 326 327#define HFS_BLOCKS(s) ((s) >> 12) 328 | 156struct fixup_entry { 157 struct fixup_entry *next; 158 struct archive_acl acl; 159 mode_t mode; 160 int64_t atime; 161 int64_t birthtime; 162 int64_t mtime; 163 int64_t ctime; --- 167 unchanged lines hidden (view full) --- 331#define DECMPFS_MAGIC 0x636d7066 332#define DECMPFS_COMPRESSION_MAGIC 0 333#define DECMPFS_COMPRESSION_TYPE 4 334#define DECMPFS_UNCOMPRESSED_SIZE 8 335#define DECMPFS_HEADER_SIZE 16 336 337#define HFS_BLOCKS(s) ((s) >> 12) 338 |
339static int check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags); |
|
329static int check_symlinks(struct archive_write_disk *); 330static int create_filesystem_object(struct archive_write_disk *); 331static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname); 332#if defined(HAVE_FCHDIR) && defined(PATH_MAX) 333static void edit_deep_directories(struct archive_write_disk *ad); 334#endif | 340static int check_symlinks(struct archive_write_disk *); 341static int create_filesystem_object(struct archive_write_disk *); 342static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname); 343#if defined(HAVE_FCHDIR) && defined(PATH_MAX) 344static void edit_deep_directories(struct archive_write_disk *ad); 345#endif |
346static int cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags); |
|
335static int cleanup_pathname(struct archive_write_disk *); 336static int create_dir(struct archive_write_disk *, char *); 337static int create_parent_dir(struct archive_write_disk *, char *); 338static ssize_t hfs_write_data_block(struct archive_write_disk *, 339 const char *, size_t); 340static int fixup_appledouble(struct archive_write_disk *, const char *); 341static int older(struct stat *, struct archive_entry *); 342static int restore_entry(struct archive_write_disk *); --- 1666 unchanged lines hidden (view full) --- 2009 */ 2010static int 2011create_filesystem_object(struct archive_write_disk *a) 2012{ 2013 /* Create the entry. */ 2014 const char *linkname; 2015 mode_t final_mode, mode; 2016 int r; | 347static int cleanup_pathname(struct archive_write_disk *); 348static int create_dir(struct archive_write_disk *, char *); 349static int create_parent_dir(struct archive_write_disk *, char *); 350static ssize_t hfs_write_data_block(struct archive_write_disk *, 351 const char *, size_t); 352static int fixup_appledouble(struct archive_write_disk *, const char *); 353static int older(struct stat *, struct archive_entry *); 354static int restore_entry(struct archive_write_disk *); --- 1666 unchanged lines hidden (view full) --- 2021 */ 2022static int 2023create_filesystem_object(struct archive_write_disk *a) 2024{ 2025 /* Create the entry. */ 2026 const char *linkname; 2027 mode_t final_mode, mode; 2028 int r; |
2029 /* these for check_symlinks_fsobj */ 2030 char *linkname_copy; /* non-const copy of linkname */ 2031 struct archive_string error_string; 2032 int error_number; |
|
2017 2018 /* We identify hard/symlinks according to the link names. */ 2019 /* Since link(2) and symlink(2) don't handle modes, we're done here. */ 2020 linkname = archive_entry_hardlink(a->entry); 2021 if (linkname != NULL) { 2022#if !HAVE_LINK 2023 return (EPERM); 2024#else | 2033 2034 /* We identify hard/symlinks according to the link names. */ 2035 /* Since link(2) and symlink(2) don't handle modes, we're done here. */ 2036 linkname = archive_entry_hardlink(a->entry); 2037 if (linkname != NULL) { 2038#if !HAVE_LINK 2039 return (EPERM); 2040#else |
2041 archive_string_init(&error_string); 2042 linkname_copy = strdup(linkname); 2043 if (linkname_copy == NULL) { 2044 return (EPERM); 2045 } 2046 /* TODO: consider using the cleaned-up path as the link target? */ 2047 r = cleanup_pathname_fsobj(linkname_copy, &error_number, &error_string, a->flags); 2048 if (r != ARCHIVE_OK) { 2049 archive_set_error(&a->archive, error_number, "%s", error_string.s); 2050 free(linkname_copy); 2051 /* EPERM is more appropriate than error_number for our callers */ 2052 return (EPERM); 2053 } 2054 r = check_symlinks_fsobj(linkname_copy, &error_number, &error_string, a->flags); 2055 if (r != ARCHIVE_OK) { 2056 archive_set_error(&a->archive, error_number, "%s", error_string.s); 2057 free(linkname_copy); 2058 /* EPERM is more appropriate than error_number for our callers */ 2059 return (EPERM); 2060 } 2061 free(linkname_copy); |
|
2025 r = link(linkname, a->name) ? errno : 0; 2026 /* 2027 * New cpio and pax formats allow hardlink entries 2028 * to carry data, so we may have to open the file 2029 * for hardlink entries. 2030 * 2031 * If the hardlink was successfully created and 2032 * the archive doesn't have carry data for it, 2033 * consider it to be non-authoritative for meta data. 2034 * This is consistent with GNU tar and BSD pax. 2035 * If the hardlink does carry data, let the last 2036 * archive entry decide ownership. 2037 */ 2038 if (r == 0 && a->filesize <= 0) { 2039 a->todo = 0; 2040 a->deferred = 0; 2041 } else if (r == 0 && a->filesize > 0) { 2042 a->fd = open(a->name, | 2062 r = link(linkname, a->name) ? errno : 0; 2063 /* 2064 * New cpio and pax formats allow hardlink entries 2065 * to carry data, so we may have to open the file 2066 * for hardlink entries. 2067 * 2068 * If the hardlink was successfully created and 2069 * the archive doesn't have carry data for it, 2070 * consider it to be non-authoritative for meta data. 2071 * This is consistent with GNU tar and BSD pax. 2072 * If the hardlink does carry data, let the last 2073 * archive entry decide ownership. 2074 */ 2075 if (r == 0 && a->filesize <= 0) { 2076 a->todo = 0; 2077 a->deferred = 0; 2078 } else if (r == 0 && a->filesize > 0) { 2079 a->fd = open(a->name, |
2043 O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC); | 2080 O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC | O_NOFOLLOW); |
2044 __archive_ensure_cloexec_flag(a->fd); 2045 if (a->fd < 0) 2046 r = errno; 2047 } 2048 return (r); 2049#endif 2050 } 2051 linkname = archive_entry_symlink(a->entry); --- 294 unchanged lines hidden (view full) --- 2346static struct fixup_entry * 2347current_fixup(struct archive_write_disk *a, const char *pathname) 2348{ 2349 if (a->current_fixup == NULL) 2350 a->current_fixup = new_fixup(a, pathname); 2351 return (a->current_fixup); 2352} 2353 | 2081 __archive_ensure_cloexec_flag(a->fd); 2082 if (a->fd < 0) 2083 r = errno; 2084 } 2085 return (r); 2086#endif 2087 } 2088 linkname = archive_entry_symlink(a->entry); --- 294 unchanged lines hidden (view full) --- 2383static struct fixup_entry * 2384current_fixup(struct archive_write_disk *a, const char *pathname) 2385{ 2386 if (a->current_fixup == NULL) 2387 a->current_fixup = new_fixup(a, pathname); 2388 return (a->current_fixup); 2389} 2390 |
2354/* TODO: Make this work. */ | |
2355/* | 2391/* |
2356 * TODO: The deep-directory support bypasses this; disable deep directory 2357 * support if we're doing symlink checks. 2358 */ 2359/* | |
2360 * TODO: Someday, integrate this with the deep dir support; they both 2361 * scan the path and both can be optimized by comparing against other 2362 * recent paths. 2363 */ 2364/* TODO: Extend this to support symlinks on Windows Vista and later. */ | 2392 * TODO: Someday, integrate this with the deep dir support; they both 2393 * scan the path and both can be optimized by comparing against other 2394 * recent paths. 2395 */ 2396/* TODO: Extend this to support symlinks on Windows Vista and later. */ |
2397 2398/* 2399 * Checks the given path to see if any elements along it are symlinks. Returns 2400 * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. 2401 */ |
|
2365static int | 2402static int |
2366check_symlinks(struct archive_write_disk *a) | 2403check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags) |
2367{ 2368#if !defined(HAVE_LSTAT) 2369 /* Platform doesn't have lstat, so we can't look for symlinks. */ | 2404{ 2405#if !defined(HAVE_LSTAT) 2406 /* Platform doesn't have lstat, so we can't look for symlinks. */ |
2370 (void)a; /* UNUSED */ | 2407 (void)path; /* UNUSED */ 2408 (void)error_number; /* UNUSED */ 2409 (void)error_string; /* UNUSED */ 2410 (void)flags; /* UNUSED */ |
2371 return (ARCHIVE_OK); 2372#else | 2411 return (ARCHIVE_OK); 2412#else |
2373 char *pn; | 2413 int res = ARCHIVE_OK; 2414 char *tail; 2415 char *head; 2416 int last; |
2374 char c; 2375 int r; 2376 struct stat st; | 2417 char c; 2418 int r; 2419 struct stat st; |
2420 int restore_pwd; |
|
2377 | 2421 |
2422 /* Nothing to do here if name is empty */ 2423 if(path[0] == '\0') 2424 return (ARCHIVE_OK); 2425 |
|
2378 /* 2379 * Guard against symlink tricks. Reject any archive entry whose 2380 * destination would be altered by a symlink. | 2426 /* 2427 * Guard against symlink tricks. Reject any archive entry whose 2428 * destination would be altered by a symlink. |
2429 * 2430 * Walk the filename in chunks separated by '/'. For each segment: 2431 * - if it doesn't exist, continue 2432 * - if it's symlink, abort or remove it 2433 * - if it's a directory and it's not the last chunk, cd into it 2434 * As we go: 2435 * head points to the current (relative) path 2436 * tail points to the temporary \0 terminating the segment we're currently examining 2437 * c holds what used to be in *tail 2438 * last is 1 if this is the last tail |
|
2381 */ | 2439 */ |
2382 /* Whatever we checked last time doesn't need to be re-checked. */ 2383 pn = a->name; 2384 if (archive_strlen(&(a->path_safe)) > 0) { 2385 char *p = a->path_safe.s; 2386 while ((*pn != '\0') && (*p == *pn)) 2387 ++p, ++pn; 2388 } | 2440 restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); 2441 __archive_ensure_cloexec_flag(restore_pwd); 2442 if (restore_pwd < 0) 2443 return (ARCHIVE_FATAL); 2444 head = path; 2445 tail = path; 2446 last = 0; 2447 /* TODO: reintroduce a safe cache here? */ |
2389 /* Skip the root directory if the path is absolute. */ | 2448 /* Skip the root directory if the path is absolute. */ |
2390 if(pn == a->name && pn[0] == '/') 2391 ++pn; 2392 c = pn[0]; 2393 /* Keep going until we've checked the entire name. */ 2394 while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) { | 2449 if(tail == path && tail[0] == '/') 2450 ++tail; 2451 /* Keep going until we've checked the entire name. 2452 * head, tail, path all alias the same string, which is 2453 * temporarily zeroed at tail, so be careful restoring the 2454 * stashed (c=tail[0]) for error messages. 2455 * Exiting the loop with break is okay; continue is not. 2456 */ 2457 while (!last) { 2458 /* Skip the separator we just consumed, plus any adjacent ones */ 2459 while (*tail == '/') 2460 ++tail; |
2395 /* Skip the next path element. */ | 2461 /* Skip the next path element. */ |
2396 while (*pn != '\0' && *pn != '/') 2397 ++pn; 2398 c = pn[0]; 2399 pn[0] = '\0'; | 2462 while (*tail != '\0' && *tail != '/') 2463 ++tail; 2464 /* is this the last path component? */ 2465 last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0'); 2466 /* temporarily truncate the string here */ 2467 c = tail[0]; 2468 tail[0] = '\0'; |
2400 /* Check that we haven't hit a symlink. */ | 2469 /* Check that we haven't hit a symlink. */ |
2401 r = lstat(a->name, &st); | 2470 r = lstat(head, &st); |
2402 if (r != 0) { | 2471 if (r != 0) { |
2472 tail[0] = c; |
|
2403 /* We've hit a dir that doesn't exist; stop now. */ 2404 if (errno == ENOENT) { 2405 break; 2406 } else { | 2473 /* We've hit a dir that doesn't exist; stop now. */ 2474 if (errno == ENOENT) { 2475 break; 2476 } else { |
2407 /* Note: This effectively disables deep directory | 2477 /* Treat any other error as fatal - best to be paranoid here 2478 * Note: This effectively disables deep directory |
2408 * support when security checks are enabled. 2409 * Otherwise, very long pathnames that trigger 2410 * an error here could evade the sandbox. 2411 * TODO: We could do better, but it would probably 2412 * require merging the symlink checks with the 2413 * deep-directory editing. */ | 2479 * support when security checks are enabled. 2480 * Otherwise, very long pathnames that trigger 2481 * an error here could evade the sandbox. 2482 * TODO: We could do better, but it would probably 2483 * require merging the symlink checks with the 2484 * deep-directory editing. */ |
2414 return (ARCHIVE_FAILED); | 2485 if (error_number) *error_number = errno; 2486 if (error_string) 2487 archive_string_sprintf(error_string, 2488 "Could not stat %s", 2489 path); 2490 res = ARCHIVE_FAILED; 2491 break; |
2415 } | 2492 } |
2493 } else if (S_ISDIR(st.st_mode)) { 2494 if (!last) { 2495 if (chdir(head) != 0) { 2496 tail[0] = c; 2497 if (error_number) *error_number = errno; 2498 if (error_string) 2499 archive_string_sprintf(error_string, 2500 "Could not chdir %s", 2501 path); 2502 res = (ARCHIVE_FATAL); 2503 break; 2504 } 2505 /* Our view is now from inside this dir: */ 2506 head = tail + 1; 2507 } |
|
2416 } else if (S_ISLNK(st.st_mode)) { | 2508 } else if (S_ISLNK(st.st_mode)) { |
2417 if (c == '\0') { | 2509 if (last) { |
2418 /* 2419 * Last element is symlink; remove it 2420 * so we can overwrite it with the 2421 * item being extracted. 2422 */ | 2510 /* 2511 * Last element is symlink; remove it 2512 * so we can overwrite it with the 2513 * item being extracted. 2514 */ |
2423 if (unlink(a->name)) { 2424 archive_set_error(&a->archive, errno, 2425 "Could not remove symlink %s", 2426 a->name); 2427 pn[0] = c; 2428 return (ARCHIVE_FAILED); | 2515 if (unlink(head)) { 2516 tail[0] = c; 2517 if (error_number) *error_number = errno; 2518 if (error_string) 2519 archive_string_sprintf(error_string, 2520 "Could not remove symlink %s", 2521 path); 2522 res = ARCHIVE_FAILED; 2523 break; |
2429 } | 2524 } |
2430 a->pst = NULL; | |
2431 /* 2432 * Even if we did remove it, a warning 2433 * is in order. The warning is silly, 2434 * though, if we're just replacing one 2435 * symlink with another symlink. 2436 */ | 2525 /* 2526 * Even if we did remove it, a warning 2527 * is in order. The warning is silly, 2528 * though, if we're just replacing one 2529 * symlink with another symlink. 2530 */ |
2437 if (!S_ISLNK(a->mode)) { 2438 archive_set_error(&a->archive, 0, 2439 "Removing symlink %s", 2440 a->name); | 2531 tail[0] = c; 2532 /* FIXME: not sure how important this is to restore 2533 if (!S_ISLNK(path)) { 2534 if (error_number) *error_number = 0; 2535 if (error_string) 2536 archive_string_sprintf(error_string, 2537 "Removing symlink %s", 2538 path); |
2441 } | 2539 } |
2540 */ |
|
2442 /* Symlink gone. No more problem! */ | 2541 /* Symlink gone. No more problem! */ |
2443 pn[0] = c; 2444 return (0); 2445 } else if (a->flags & ARCHIVE_EXTRACT_UNLINK) { | 2542 res = ARCHIVE_OK; 2543 break; 2544 } else if (flags & ARCHIVE_EXTRACT_UNLINK) { |
2446 /* User asked us to remove problems. */ | 2545 /* User asked us to remove problems. */ |
2447 if (unlink(a->name) != 0) { 2448 archive_set_error(&a->archive, 0, 2449 "Cannot remove intervening symlink %s", 2450 a->name); 2451 pn[0] = c; 2452 return (ARCHIVE_FAILED); | 2546 if (unlink(head) != 0) { 2547 tail[0] = c; 2548 if (error_number) *error_number = 0; 2549 if (error_string) 2550 archive_string_sprintf(error_string, 2551 "Cannot remove intervening symlink %s", 2552 path); 2553 res = ARCHIVE_FAILED; 2554 break; |
2453 } | 2555 } |
2454 a->pst = NULL; | 2556 tail[0] = c; |
2455 } else { | 2557 } else { |
2456 archive_set_error(&a->archive, 0, 2457 "Cannot extract through symlink %s", 2458 a->name); 2459 pn[0] = c; 2460 return (ARCHIVE_FAILED); | 2558 tail[0] = c; 2559 if (error_number) *error_number = 0; 2560 if (error_string) 2561 archive_string_sprintf(error_string, 2562 "Cannot extract through symlink %s", 2563 path); 2564 res = ARCHIVE_FAILED; 2565 break; |
2461 } 2462 } | 2566 } 2567 } |
2463 pn[0] = c; 2464 if (pn[0] != '\0') 2465 pn++; /* Advance to the next segment. */ | 2568 /* be sure to always maintain this */ 2569 tail[0] = c; 2570 if (tail[0] != '\0') 2571 tail++; /* Advance to the next segment. */ |
2466 } | 2572 } |
2467 pn[0] = c; 2468 /* We've checked and/or cleaned the whole path, so remember it. */ 2469 archive_strcpy(&a->path_safe, a->name); 2470 return (ARCHIVE_OK); | 2573 /* Catches loop exits via break */ 2574 tail[0] = c; 2575#ifdef HAVE_FCHDIR 2576 /* If we changed directory above, restore it here. */ 2577 if (restore_pwd >= 0) { 2578 r = fchdir(restore_pwd); 2579 if (r != 0) { 2580 if(error_number) *error_number = errno; 2581 if(error_string) 2582 archive_string_sprintf(error_string, 2583 "chdir() failure"); 2584 } 2585 close(restore_pwd); 2586 restore_pwd = -1; 2587 if (r != 0) { 2588 res = (ARCHIVE_FATAL); 2589 } 2590 } |
2471#endif | 2591#endif |
2592 /* TODO: reintroduce a safe cache here? */ 2593 return res; 2594#endif |
|
2472} 2473 | 2595} 2596 |
2597/* 2598 * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise 2599 * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED} 2600 */ 2601static int 2602check_symlinks(struct archive_write_disk *a) 2603{ 2604 struct archive_string error_string; 2605 int error_number; 2606 int rc; 2607 archive_string_init(&error_string); 2608 rc = check_symlinks_fsobj(a->name, &error_number, &error_string, a->flags); 2609 if (rc != ARCHIVE_OK) { 2610 archive_set_error(&a->archive, error_number, "%s", error_string.s); 2611 } 2612 archive_string_free(&error_string); 2613 a->pst = NULL; /* to be safe */ 2614 return rc; 2615} 2616 2617 |
|
2474#if defined(__CYGWIN__) 2475/* 2476 * 1. Convert a path separator from '\' to '/' . 2477 * We shouldn't check multibyte character directly because some 2478 * character-set have been using the '\' character for a part of 2479 * its multibyte character code. 2480 * 2. Replace unusable characters in Windows with underscore('_'). 2481 * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx --- 57 unchanged lines hidden (view full) --- 2539/* 2540 * Canonicalize the pathname. In particular, this strips duplicate 2541 * '/' characters, '.' elements, and trailing '/'. It also raises an 2542 * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is 2543 * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS 2544 * is set) if the path is absolute. 2545 */ 2546static int | 2618#if defined(__CYGWIN__) 2619/* 2620 * 1. Convert a path separator from '\' to '/' . 2621 * We shouldn't check multibyte character directly because some 2622 * character-set have been using the '\' character for a part of 2623 * its multibyte character code. 2624 * 2. Replace unusable characters in Windows with underscore('_'). 2625 * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx --- 57 unchanged lines hidden (view full) --- 2683/* 2684 * Canonicalize the pathname. In particular, this strips duplicate 2685 * '/' characters, '.' elements, and trailing '/'. It also raises an 2686 * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is 2687 * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS 2688 * is set) if the path is absolute. 2689 */ 2690static int |
2547cleanup_pathname(struct archive_write_disk *a) | 2691cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags) |
2548{ 2549 char *dest, *src; 2550 char separator = '\0'; 2551 | 2692{ 2693 char *dest, *src; 2694 char separator = '\0'; 2695 |
2552 dest = src = a->name; | 2696 dest = src = path; |
2553 if (*src == '\0') { | 2697 if (*src == '\0') { |
2554 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 2555 "Invalid empty pathname"); | 2698 if (error_number) *error_number = ARCHIVE_ERRNO_MISC; 2699 if (error_string) 2700 archive_string_sprintf(error_string, 2701 "Invalid empty pathname"); |
2556 return (ARCHIVE_FAILED); 2557 } 2558 2559#if defined(__CYGWIN__) 2560 cleanup_pathname_win(a); 2561#endif 2562 /* Skip leading '/'. */ 2563 if (*src == '/') { | 2702 return (ARCHIVE_FAILED); 2703 } 2704 2705#if defined(__CYGWIN__) 2706 cleanup_pathname_win(a); 2707#endif 2708 /* Skip leading '/'. */ 2709 if (*src == '/') { |
2564 if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { 2565 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 2566 "Path is absolute"); | 2710 if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { 2711 if (error_number) *error_number = ARCHIVE_ERRNO_MISC; 2712 if (error_string) 2713 archive_string_sprintf(error_string, 2714 "Path is absolute"); |
2567 return (ARCHIVE_FAILED); 2568 } 2569 2570 separator = *src++; 2571 } 2572 2573 /* Scan the pathname one element at a time. */ 2574 for (;;) { --- 10 unchanged lines hidden (view full) --- 2585 break; 2586 } else if (src[1] == '/') { 2587 /* Skip './'. */ 2588 src += 2; 2589 continue; 2590 } else if (src[1] == '.') { 2591 if (src[2] == '/' || src[2] == '\0') { 2592 /* Conditionally warn about '..' */ | 2715 return (ARCHIVE_FAILED); 2716 } 2717 2718 separator = *src++; 2719 } 2720 2721 /* Scan the pathname one element at a time. */ 2722 for (;;) { --- 10 unchanged lines hidden (view full) --- 2733 break; 2734 } else if (src[1] == '/') { 2735 /* Skip './'. */ 2736 src += 2; 2737 continue; 2738 } else if (src[1] == '.') { 2739 if (src[2] == '/' || src[2] == '\0') { 2740 /* Conditionally warn about '..' */ |
2593 if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { 2594 archive_set_error(&a->archive, 2595 ARCHIVE_ERRNO_MISC, 2596 "Path contains '..'"); | 2741 if (flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { 2742 if (error_number) *error_number = ARCHIVE_ERRNO_MISC; 2743 if (error_string) 2744 archive_string_sprintf(error_string, 2745 "Path contains '..'"); |
2597 return (ARCHIVE_FAILED); 2598 } 2599 } 2600 /* 2601 * Note: Under no circumstances do we 2602 * remove '..' elements. In 2603 * particular, restoring 2604 * '/foo/../bar/' should create the --- 14 unchanged lines hidden (view full) --- 2619 2620 /* Skip '/' separator. */ 2621 separator = *src++; 2622 } 2623 /* 2624 * We've just copied zero or more path elements, not including the 2625 * final '/'. 2626 */ | 2746 return (ARCHIVE_FAILED); 2747 } 2748 } 2749 /* 2750 * Note: Under no circumstances do we 2751 * remove '..' elements. In 2752 * particular, restoring 2753 * '/foo/../bar/' should create the --- 14 unchanged lines hidden (view full) --- 2768 2769 /* Skip '/' separator. */ 2770 separator = *src++; 2771 } 2772 /* 2773 * We've just copied zero or more path elements, not including the 2774 * final '/'. 2775 */ |
2627 if (dest == a->name) { | 2776 if (dest == path) { |
2628 /* 2629 * Nothing got copied. The path must have been something 2630 * like '.' or '/' or './' or '/././././/./'. 2631 */ 2632 if (separator) 2633 *dest++ = '/'; 2634 else 2635 *dest++ = '.'; 2636 } 2637 /* Terminate the result. */ 2638 *dest = '\0'; 2639 return (ARCHIVE_OK); 2640} 2641 | 2777 /* 2778 * Nothing got copied. The path must have been something 2779 * like '.' or '/' or './' or '/././././/./'. 2780 */ 2781 if (separator) 2782 *dest++ = '/'; 2783 else 2784 *dest++ = '.'; 2785 } 2786 /* Terminate the result. */ 2787 *dest = '\0'; 2788 return (ARCHIVE_OK); 2789} 2790 |
2791static int 2792cleanup_pathname(struct archive_write_disk *a) 2793{ 2794 struct archive_string error_string; 2795 int error_number; 2796 int rc; 2797 archive_string_init(&error_string); 2798 rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, a->flags); 2799 if (rc != ARCHIVE_OK) { 2800 archive_set_error(&a->archive, error_number, "%s", error_string.s); 2801 } 2802 archive_string_free(&error_string); 2803 return rc; 2804} 2805 |
|
2642/* 2643 * Create the parent directory of the specified path, assuming path 2644 * is already in mutable storage. 2645 */ 2646static int 2647create_parent_dir(struct archive_write_disk *a, char *path) 2648{ 2649 char *slash; --- 1268 unchanged lines hidden --- | 2806/* 2807 * Create the parent directory of the specified path, assuming path 2808 * is already in mutable storage. 2809 */ 2810static int 2811create_parent_dir(struct archive_write_disk *a, char *path) 2812{ 2813 char *slash; --- 1268 unchanged lines hidden --- |