Deleted Added
full compact
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 ---