Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

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  
    1212    int dst_fd;
    1313    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
    1420
    1521#if ENABLE_FEATURE_TAR_SELINUX
     
    2430#endif
    2531
     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
    2670    if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
    27         char *slash = strrchr(file_header->name, '/');
     71        char *slash = strrchr(dst_name, '/');
    2872        if (slash) {
    2973            *slash = '\0';
    30             bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
     74            bb_make_directory(dst_name, -1, FILEUTILS_RECUR);
    3175            *slash = '/';
    3276        }
     
    3680        /* Remove the entry if it exists */
    3781        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) {
    4483                /* Ugly special case:
    4584                 * tar cf t.tar hardlink1 hardlink2 hardlink1
     
    4988                 * hardlink1 -> hardlink1 <== !!!
    5089                 */
    51                 if (strcmp(file_header->link_target, file_header->name) == 0)
     90                if (strcmp(hard_link, dst_name) == 0)
    5291                    goto ret;
    5392            }
    5493            /* Proceed with deleting */
    55             if (unlink(file_header->name) == -1
     94            if (unlink(dst_name) == -1
    5695             && errno != ENOENT
    5796            ) {
    5897                bb_perror_msg_and_die("can't remove old file %s",
    59                         file_header->name);
     98                        dst_name);
    6099            }
    61100        }
     
    64103        /* Remove the existing entry if its older than the extracted entry */
    65104        struct stat existing_sb;
    66         if (lstat(file_header->name, &existing_sb) == -1) {
     105        if (lstat(dst_name, &existing_sb) == -1) {
    67106            if (errno != ENOENT) {
    68107                bb_perror_msg_and_die("can't stat old file");
     
    74113            ) {
    75114                bb_error_msg("%s not created: newer or "
    76                     "same age file exists", file_header->name);
     115                    "same age file exists", dst_name);
    77116            }
    78117            data_skip(archive_handle);
    79118            goto ret;
    80119        }
    81         else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
     120        else if ((unlink(dst_name) == -1) && (errno != EISDIR)) {
    82121            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)) {
    96130            bb_perror_msg("can't create %slink "
    97131                    "from %s to %s", "hard",
    98                     file_header->name,
    99                     file_header->link_target);
     132                    dst_name,
     133                    hard_link);
    100134        }
    101135        /* Hardlinks have no separate mode/ownership, skip chown/chmod */
     
    107141    case S_IFREG: {
    108142        /* Regular file */
     143        char *dst_nameN;
    109144        int flags = O_WRONLY | O_CREAT | O_EXCL;
    110145        if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
    111146            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,
    113154            flags,
    114155            file_header->mode
     
    116157        bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
    117158        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
    118165        break;
    119166    }
    120167    case S_IFDIR:
    121         res = mkdir(file_header->name, file_header->mode);
     168        res = mkdir(dst_name, file_header->mode);
    122169        if ((res == -1)
    123170         && (errno != EISDIR) /* btw, Linux doesn't return this */
     
    125172         && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
    126173        ) {
    127             bb_perror_msg("can't make dir %s", file_header->name);
     174            bb_perror_msg("can't make dir %s", dst_name);
    128175        }
    129176        break;
     
    131178        /* Symlink */
    132179//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
    135182         && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
    136183        ) {
    137184            bb_perror_msg("can't create %slink "
    138185                "from %s to %s", "sym",
    139                 file_header->name,
     186                dst_name,
    140187                file_header->link_target);
    141188        }
     
    145192    case S_IFCHR:
    146193    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);
    148195        if ((res == -1)
    149196         && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
    150197        ) {
    151             bb_perror_msg("can't create node %s", file_header->name);
     198            bb_perror_msg("can't create node %s", dst_name);
    152199        }
    153200        break;
     
    174221#endif
    175222            /* GNU tar 1.15.1 uses chown, not lchown */
    176             chown(file_header->name, uid, gid);
     223            chown(dst_name, uid, gid);
    177224        }
    178225        /* uclibc has no lchmod, glibc is even stranger -
     
    180227         * so we use chmod... */
    181228        if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
    182             chmod(file_header->name, file_header->mode);
     229            chmod(dst_name, file_header->mode);
    183230        }
    184231        if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
     
    187234            t[1].tv_sec = t[0].tv_sec = file_header->mtime;
    188235            t[1].tv_usec = t[0].tv_usec = 0;
    189             utimes(file_header->name, t);
     236            utimes(dst_name, t);
    190237        }
    191238    }
Note: See TracChangeset for help on using the changeset viewer.