2629 }
2630 }
2631 (void) close(ifd);
2632 if (vflag)
2633 (void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d "
2634 "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)),
2635 extents);
2636 }
2637
2638 /*
2639 * convtoreg - determines whether the file should be converted to a
2640 * regular file when extracted
2641 *
2642 * Returns 1 when file size > 0 and typeflag is not recognized
2643 * Otherwise returns 0
2644 */
2645 static int
2646 convtoreg(off_t size)
2647 {
2648 if ((size > 0) && (dblock.dbuf.typeflag != '0') &&
2649 (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') &&
2650 (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') &&
2651 (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') &&
2652 (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') &&
2653 (dblock.dbuf.typeflag != 'L') &&
2654 (dblock.dbuf.typeflag != _XATTR_HDRTYPE) &&
2655 (dblock.dbuf.typeflag != 'X')) {
2656 return (1);
2657 }
2658 return (0);
2659 }
2660
2661 #if defined(O_XATTR)
2662 static int
2663 save_cwd(void)
2664 {
2665 return (open(".", O_RDONLY));
2666 }
2667 #endif
2668
2669 #if defined(O_XATTR)
3142 dir = 1;
3143 if (vflag) {
3144 (void) fprintf(vfile, "x %s, 0 %s, ",
3145 &dirname[0], gettext("bytes"));
3146 if (NotTape)
3147 (void) fprintf(vfile, "0K\n");
3148 else
3149 (void) fprintf(vfile, gettext("%"
3150 FMT_blkcnt_t " tape blocks\n"),
3151 (blkcnt_t)0);
3152 }
3153 goto filedone;
3154 }
3155
3156 if (dblock.dbuf.typeflag == '6') { /* FIFO */
3157 if (rmdir(namep) < 0) {
3158 if (errno == ENOTDIR)
3159 (void) unlink(namep);
3160 }
3161 linkp = templink;
3162 if (*linkp != NULL) {
3163 if (Aflag && *linkp == '/')
3164 linkp++;
3165 if (link(linkp, namep) < 0) {
3166 (void) fprintf(stderr, gettext(
3167 "tar: %s: cannot link\n"), namep);
3168 continue;
3169 }
3170 if (vflag)
3171 (void) fprintf(vfile, gettext(
3172 "x %s linked to %s\n"), namep,
3173 linkp);
3174 xcnt++; /* increment # files extracted */
3175 continue;
3176 }
3177 if (mknod(namep, (int)(Gen.g_mode|S_IFIFO),
3178 (int)Gen.g_devmajor) < 0) {
3179 vperror(0, gettext("%s: mknod failed"), namep);
3180 continue;
3181 }
3182 bytes = stbuf.st_size;
3183 blocks = TBLOCKS(bytes);
3184 if (vflag) {
3185 (void) fprintf(vfile, "x %s, %" FMT_off_t
3186 " %s, ", namep, bytes, gettext("bytes"));
3187 if (NotTape)
3188 (void) fprintf(vfile, "%" FMT_blkcnt_t
3189 "K\n", K(blocks));
3190 else
3191 (void) fprintf(vfile, gettext("%"
3192 FMT_blkcnt_t " tape blocks\n"),
3193 blocks);
3194 }
3195 goto filedone;
3196 }
3197 if (dblock.dbuf.typeflag == '3' && !Uid) { /* CHAR SPECIAL */
3198 if (rmdir(namep) < 0) {
3199 if (errno == ENOTDIR)
3200 (void) unlink(namep);
3201 }
3202 linkp = templink;
3203 if (*linkp != NULL) {
3204 if (Aflag && *linkp == '/')
3205 linkp++;
3206 if (link(linkp, namep) < 0) {
3207 (void) fprintf(stderr, gettext(
3208 "tar: %s: cannot link\n"), namep);
3209 continue;
3210 }
3211 if (vflag)
3212 (void) fprintf(vfile, gettext(
3213 "x %s linked to %s\n"), namep,
3214 linkp);
3215 xcnt++; /* increment # files extracted */
3216 continue;
3217 }
3218 if (mknod(namep, (int)(Gen.g_mode|S_IFCHR),
3219 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) {
3220 vperror(0, gettext(
3221 "%s: mknod failed"), namep);
3222 continue;
3223 }
3232 else
3233 (void) fprintf(vfile, gettext("%"
3234 FMT_blkcnt_t " tape blocks\n"),
3235 blocks);
3236 }
3237 goto filedone;
3238 } else if (dblock.dbuf.typeflag == '3' && Uid) {
3239 (void) fprintf(stderr, gettext(
3240 "Can't create special %s\n"), namep);
3241 continue;
3242 }
3243
3244 /* BLOCK SPECIAL */
3245
3246 if (dblock.dbuf.typeflag == '4' && !Uid) {
3247 if (rmdir(namep) < 0) {
3248 if (errno == ENOTDIR)
3249 (void) unlink(namep);
3250 }
3251 linkp = templink;
3252 if (*linkp != NULL) {
3253 if (Aflag && *linkp == '/')
3254 linkp++;
3255 if (link(linkp, namep) < 0) {
3256 (void) fprintf(stderr, gettext(
3257 "tar: %s: cannot link\n"), namep);
3258 continue;
3259 }
3260 if (vflag)
3261 (void) fprintf(vfile, gettext(
3262 "x %s linked to %s\n"), namep,
3263 linkp);
3264 xcnt++; /* increment # files extracted */
3265 continue;
3266 }
3267 if (mknod(namep, (int)(Gen.g_mode|S_IFBLK),
3268 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) {
3269 vperror(0, gettext("%s: mknod failed"), namep);
3270 continue;
3271 }
3272 bytes = stbuf.st_size;
3372 }
3373
3374 /* REGULAR FILES */
3375
3376 if (convtoreg(stbuf.st_size)) {
3377 convflag = 1;
3378 if (errflag) {
3379 (void) fprintf(stderr, gettext(
3380 "tar: %s: typeflag '%c' not recognized\n"),
3381 namep, dblock.dbuf.typeflag);
3382 done(1);
3383 } else {
3384 (void) fprintf(stderr, gettext(
3385 "tar: %s: typeflag '%c' not recognized, "
3386 "converting to regular file\n"), namep,
3387 dblock.dbuf.typeflag);
3388 Errflg = 1;
3389 }
3390 }
3391 if (dblock.dbuf.typeflag == '0' ||
3392 dblock.dbuf.typeflag == NULL || convflag) {
3393 delete_target(dirfd, comp, namep);
3394 linkp = templink;
3395 if (*linkp != NULL) {
3396 if (Aflag && *linkp == '/')
3397 linkp++;
3398 if (link(linkp, comp) < 0) {
3399 (void) fprintf(stderr, gettext(
3400 "tar: %s: cannot link\n"), namep);
3401 continue;
3402 }
3403 if (vflag)
3404 (void) fprintf(vfile, gettext(
3405 "x %s linked to %s\n"), comp,
3406 linkp);
3407 xcnt++; /* increment # files extracted */
3408 #if defined(O_XATTR)
3409 if (xattrp != NULL) {
3410 free(xattrhead);
3411 xattrp = NULL;
3412 xattr_linkp = NULL;
3413 xattrhead = NULL;
3414 }
3415 #endif
3581 "entries\n"), namep,
3582 (xattrp == NULL) ? "" :
3583 (rw_sysattr ? gettext(
3584 " system attribute ") :
3585 gettext(" attribute ")),
3586 (xattrp == NULL) ? "" :
3587 xattrapath);
3588 }
3589 /* else: silent and continue */
3590 }
3591 acl_free(aclp);
3592 aclp = NULL;
3593 }
3594
3595 if (!oflag)
3596 /* set file ownership */
3597 resugname(dirfd, comp, symflag);
3598
3599 if (pflag && newfile == TRUE && !dir &&
3600 (dblock.dbuf.typeflag == '0' ||
3601 dblock.dbuf.typeflag == NULL ||
3602 convflag || dblock.dbuf.typeflag == '1')) {
3603 if (fstat(ofile, &xtractbuf) == -1)
3604 (void) fprintf(stderr, gettext(
3605 "tar: cannot stat extracted file "
3606 "%s%s%s%s\n"),
3607 (xattrp == NULL) ? "" : (rw_sysattr ?
3608 gettext("system attribute ") :
3609 gettext("attribute ")),
3610 (xattrp == NULL) ? "" : xattrapath,
3611 (xattrp == NULL) ? "" :
3612 gettext(" of "), namep);
3613
3614 else if ((xtractbuf.st_mode & (MODEMASK & ~S_IFMT))
3615 != (stbuf.st_mode & (MODEMASK & ~S_IFMT))) {
3616 (void) fprintf(stderr, gettext(
3617 "tar: warning - file permissions have "
3618 "changed for %s%s%s%s (are 0%o, should be "
3619 "0%o)\n"),
3620 (xattrp == NULL) ? "" : (rw_sysattr ?
3621 gettext("system attribute ") :
5468 add_file_to_table(table, buf);
5469 }
5470 (void) fclose(fp);
5471 }
5472
5473
5474 /*
5475 * Add a file name to the the specified table, if the file name has any
5476 * trailing '/'s then delete them before inserting into the table
5477 */
5478
5479 static void
5480 add_file_to_table(file_list_t *table[], char *str)
5481 {
5482 char name[PATH_MAX + 1];
5483 unsigned int h;
5484 file_list_t *exp;
5485
5486 (void) strcpy(name, str);
5487 while (name[strlen(name) - 1] == '/') {
5488 name[strlen(name) - 1] = NULL;
5489 }
5490
5491 h = hash(name);
5492 if ((exp = (file_list_t *)calloc(sizeof (file_list_t),
5493 sizeof (char))) == NULL) {
5494 (void) fprintf(stderr, gettext(
5495 "tar: out of memory, exclude/include table(entry)\n"));
5496 exit(1);
5497 }
5498
5499 if ((exp->name = strdup(name)) == NULL) {
5500 (void) fprintf(stderr, gettext(
5501 "tar: out of memory, exclude/include table(file name)\n"));
5502 exit(1);
5503 }
5504
5505 exp->next = table[h];
5506 table[h] = exp;
5507 }
5508
5509
5510 /*
5511 * See if a file name or any of the file's parent directories is in the
5512 * specified table, if the file name has any trailing '/'s then delete
5513 * them before searching the table
5514 */
5515
5516 static int
5517 is_in_table(file_list_t *table[], char *str)
5518 {
5519 char name[PATH_MAX + 1];
5520 unsigned int h;
5521 file_list_t *exp;
5522 char *ptr;
5523
5524 (void) strcpy(name, str);
5525 while (name[strlen(name) - 1] == '/') {
5526 name[strlen(name) - 1] = NULL;
5527 }
5528
5529 /*
5530 * check for the file name in the passed list
5531 */
5532 h = hash(name);
5533 exp = table[h];
5534 while (exp != NULL) {
5535 if (strcmp(name, exp->name) == 0) {
5536 return (1);
5537 }
5538 exp = exp->next;
5539 }
5540
5541 /*
5542 * check for any parent directories in the file list
5543 */
5544 while ((ptr = strrchr(name, '/'))) {
5545 *ptr = NULL;
5546 h = hash(name);
5547 exp = table[h];
5548 while (exp != NULL) {
5549 if (strcmp(name, exp->name) == 0) {
5550 return (1);
5551 }
5552 exp = exp->next;
5553 }
5554 }
5555
5556 return (0);
5557 }
5558
5559
5560 /*
5561 * Compute a hash from a string.
5562 */
5563
5564 static unsigned int
5565 hash(char *str)
6598 * If !hflag then delete the target.
6599 */
6600
6601 static void
6602 delete_target(int fd, char *comp, char *namep)
6603 {
6604 struct stat xtractbuf;
6605 char buf[PATH_MAX + 1];
6606 int n;
6607
6608
6609 if (unlinkat(fd, comp, AT_REMOVEDIR) < 0) {
6610 if (errno == ENOTDIR && !hflag) {
6611 (void) unlinkat(fd, comp, 0);
6612 } else if (errno == ENOTDIR && hflag) {
6613 if (!lstat(namep, &xtractbuf)) {
6614 if ((xtractbuf.st_mode & S_IFMT) != S_IFLNK) {
6615 (void) unlinkat(fd, comp, 0);
6616 } else if ((n = readlink(namep, buf,
6617 PATH_MAX)) != -1) {
6618 buf[n] = (char)NULL;
6619 (void) unlinkat(fd, buf,
6620 AT_REMOVEDIR);
6621 if (errno == ENOTDIR)
6622 (void) unlinkat(fd, buf, 0);
6623 } else {
6624 (void) unlinkat(fd, comp, 0);
6625 }
6626 } else {
6627 (void) unlinkat(fd, comp, 0);
6628 }
6629 }
6630 }
6631 }
6632
6633
6634 /*
6635 * ACL changes:
6636 * putfile():
6637 * Get acl info after stat. Write out ancillary file
6638 * before the normal file, i.e. directory, regular, FIFO,
|
2629 }
2630 }
2631 (void) close(ifd);
2632 if (vflag)
2633 (void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d "
2634 "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)),
2635 extents);
2636 }
2637
2638 /*
2639 * convtoreg - determines whether the file should be converted to a
2640 * regular file when extracted
2641 *
2642 * Returns 1 when file size > 0 and typeflag is not recognized
2643 * Otherwise returns 0
2644 */
2645 static int
2646 convtoreg(off_t size)
2647 {
2648 if ((size > 0) && (dblock.dbuf.typeflag != '0') &&
2649 (dblock.dbuf.typeflag != '\0') && (dblock.dbuf.typeflag != '1') &&
2650 (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') &&
2651 (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') &&
2652 (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') &&
2653 (dblock.dbuf.typeflag != 'L') &&
2654 (dblock.dbuf.typeflag != _XATTR_HDRTYPE) &&
2655 (dblock.dbuf.typeflag != 'X')) {
2656 return (1);
2657 }
2658 return (0);
2659 }
2660
2661 #if defined(O_XATTR)
2662 static int
2663 save_cwd(void)
2664 {
2665 return (open(".", O_RDONLY));
2666 }
2667 #endif
2668
2669 #if defined(O_XATTR)
3142 dir = 1;
3143 if (vflag) {
3144 (void) fprintf(vfile, "x %s, 0 %s, ",
3145 &dirname[0], gettext("bytes"));
3146 if (NotTape)
3147 (void) fprintf(vfile, "0K\n");
3148 else
3149 (void) fprintf(vfile, gettext("%"
3150 FMT_blkcnt_t " tape blocks\n"),
3151 (blkcnt_t)0);
3152 }
3153 goto filedone;
3154 }
3155
3156 if (dblock.dbuf.typeflag == '6') { /* FIFO */
3157 if (rmdir(namep) < 0) {
3158 if (errno == ENOTDIR)
3159 (void) unlink(namep);
3160 }
3161 linkp = templink;
3162 if (*linkp != '\0') {
3163 if (Aflag && *linkp == '/')
3164 linkp++;
3165 if (link(linkp, namep) < 0) {
3166 (void) fprintf(stderr, gettext(
3167 "tar: %s: cannot link\n"), namep);
3168 continue;
3169 }
3170 if (vflag)
3171 (void) fprintf(vfile, gettext(
3172 "x %s linked to %s\n"), namep,
3173 linkp);
3174 xcnt++; /* increment # files extracted */
3175 continue;
3176 }
3177 if (mknod(namep, (int)(Gen.g_mode|S_IFIFO),
3178 (int)Gen.g_devmajor) < 0) {
3179 vperror(0, gettext("%s: mknod failed"), namep);
3180 continue;
3181 }
3182 bytes = stbuf.st_size;
3183 blocks = TBLOCKS(bytes);
3184 if (vflag) {
3185 (void) fprintf(vfile, "x %s, %" FMT_off_t
3186 " %s, ", namep, bytes, gettext("bytes"));
3187 if (NotTape)
3188 (void) fprintf(vfile, "%" FMT_blkcnt_t
3189 "K\n", K(blocks));
3190 else
3191 (void) fprintf(vfile, gettext("%"
3192 FMT_blkcnt_t " tape blocks\n"),
3193 blocks);
3194 }
3195 goto filedone;
3196 }
3197 if (dblock.dbuf.typeflag == '3' && !Uid) { /* CHAR SPECIAL */
3198 if (rmdir(namep) < 0) {
3199 if (errno == ENOTDIR)
3200 (void) unlink(namep);
3201 }
3202 linkp = templink;
3203 if (*linkp != '\0') {
3204 if (Aflag && *linkp == '/')
3205 linkp++;
3206 if (link(linkp, namep) < 0) {
3207 (void) fprintf(stderr, gettext(
3208 "tar: %s: cannot link\n"), namep);
3209 continue;
3210 }
3211 if (vflag)
3212 (void) fprintf(vfile, gettext(
3213 "x %s linked to %s\n"), namep,
3214 linkp);
3215 xcnt++; /* increment # files extracted */
3216 continue;
3217 }
3218 if (mknod(namep, (int)(Gen.g_mode|S_IFCHR),
3219 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) {
3220 vperror(0, gettext(
3221 "%s: mknod failed"), namep);
3222 continue;
3223 }
3232 else
3233 (void) fprintf(vfile, gettext("%"
3234 FMT_blkcnt_t " tape blocks\n"),
3235 blocks);
3236 }
3237 goto filedone;
3238 } else if (dblock.dbuf.typeflag == '3' && Uid) {
3239 (void) fprintf(stderr, gettext(
3240 "Can't create special %s\n"), namep);
3241 continue;
3242 }
3243
3244 /* BLOCK SPECIAL */
3245
3246 if (dblock.dbuf.typeflag == '4' && !Uid) {
3247 if (rmdir(namep) < 0) {
3248 if (errno == ENOTDIR)
3249 (void) unlink(namep);
3250 }
3251 linkp = templink;
3252 if (*linkp != '\0') {
3253 if (Aflag && *linkp == '/')
3254 linkp++;
3255 if (link(linkp, namep) < 0) {
3256 (void) fprintf(stderr, gettext(
3257 "tar: %s: cannot link\n"), namep);
3258 continue;
3259 }
3260 if (vflag)
3261 (void) fprintf(vfile, gettext(
3262 "x %s linked to %s\n"), namep,
3263 linkp);
3264 xcnt++; /* increment # files extracted */
3265 continue;
3266 }
3267 if (mknod(namep, (int)(Gen.g_mode|S_IFBLK),
3268 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) {
3269 vperror(0, gettext("%s: mknod failed"), namep);
3270 continue;
3271 }
3272 bytes = stbuf.st_size;
3372 }
3373
3374 /* REGULAR FILES */
3375
3376 if (convtoreg(stbuf.st_size)) {
3377 convflag = 1;
3378 if (errflag) {
3379 (void) fprintf(stderr, gettext(
3380 "tar: %s: typeflag '%c' not recognized\n"),
3381 namep, dblock.dbuf.typeflag);
3382 done(1);
3383 } else {
3384 (void) fprintf(stderr, gettext(
3385 "tar: %s: typeflag '%c' not recognized, "
3386 "converting to regular file\n"), namep,
3387 dblock.dbuf.typeflag);
3388 Errflg = 1;
3389 }
3390 }
3391 if (dblock.dbuf.typeflag == '0' ||
3392 dblock.dbuf.typeflag == '\0' || convflag) {
3393 delete_target(dirfd, comp, namep);
3394 linkp = templink;
3395 if (*linkp != '\0') {
3396 if (Aflag && *linkp == '/')
3397 linkp++;
3398 if (link(linkp, comp) < 0) {
3399 (void) fprintf(stderr, gettext(
3400 "tar: %s: cannot link\n"), namep);
3401 continue;
3402 }
3403 if (vflag)
3404 (void) fprintf(vfile, gettext(
3405 "x %s linked to %s\n"), comp,
3406 linkp);
3407 xcnt++; /* increment # files extracted */
3408 #if defined(O_XATTR)
3409 if (xattrp != NULL) {
3410 free(xattrhead);
3411 xattrp = NULL;
3412 xattr_linkp = NULL;
3413 xattrhead = NULL;
3414 }
3415 #endif
3581 "entries\n"), namep,
3582 (xattrp == NULL) ? "" :
3583 (rw_sysattr ? gettext(
3584 " system attribute ") :
3585 gettext(" attribute ")),
3586 (xattrp == NULL) ? "" :
3587 xattrapath);
3588 }
3589 /* else: silent and continue */
3590 }
3591 acl_free(aclp);
3592 aclp = NULL;
3593 }
3594
3595 if (!oflag)
3596 /* set file ownership */
3597 resugname(dirfd, comp, symflag);
3598
3599 if (pflag && newfile == TRUE && !dir &&
3600 (dblock.dbuf.typeflag == '0' ||
3601 dblock.dbuf.typeflag == '\0' ||
3602 convflag || dblock.dbuf.typeflag == '1')) {
3603 if (fstat(ofile, &xtractbuf) == -1)
3604 (void) fprintf(stderr, gettext(
3605 "tar: cannot stat extracted file "
3606 "%s%s%s%s\n"),
3607 (xattrp == NULL) ? "" : (rw_sysattr ?
3608 gettext("system attribute ") :
3609 gettext("attribute ")),
3610 (xattrp == NULL) ? "" : xattrapath,
3611 (xattrp == NULL) ? "" :
3612 gettext(" of "), namep);
3613
3614 else if ((xtractbuf.st_mode & (MODEMASK & ~S_IFMT))
3615 != (stbuf.st_mode & (MODEMASK & ~S_IFMT))) {
3616 (void) fprintf(stderr, gettext(
3617 "tar: warning - file permissions have "
3618 "changed for %s%s%s%s (are 0%o, should be "
3619 "0%o)\n"),
3620 (xattrp == NULL) ? "" : (rw_sysattr ?
3621 gettext("system attribute ") :
5468 add_file_to_table(table, buf);
5469 }
5470 (void) fclose(fp);
5471 }
5472
5473
5474 /*
5475 * Add a file name to the the specified table, if the file name has any
5476 * trailing '/'s then delete them before inserting into the table
5477 */
5478
5479 static void
5480 add_file_to_table(file_list_t *table[], char *str)
5481 {
5482 char name[PATH_MAX + 1];
5483 unsigned int h;
5484 file_list_t *exp;
5485
5486 (void) strcpy(name, str);
5487 while (name[strlen(name) - 1] == '/') {
5488 name[strlen(name) - 1] = '\0';
5489 }
5490
5491 h = hash(name);
5492 if ((exp = (file_list_t *)calloc(sizeof (file_list_t),
5493 sizeof (char))) == NULL) {
5494 (void) fprintf(stderr, gettext(
5495 "tar: out of memory, exclude/include table(entry)\n"));
5496 exit(1);
5497 }
5498
5499 if ((exp->name = strdup(name)) == NULL) {
5500 (void) fprintf(stderr, gettext(
5501 "tar: out of memory, exclude/include table(file name)\n"));
5502 exit(1);
5503 }
5504
5505 exp->next = table[h];
5506 table[h] = exp;
5507 }
5508
5509
5510 /*
5511 * See if a file name or any of the file's parent directories is in the
5512 * specified table, if the file name has any trailing '/'s then delete
5513 * them before searching the table
5514 */
5515
5516 static int
5517 is_in_table(file_list_t *table[], char *str)
5518 {
5519 char name[PATH_MAX + 1];
5520 unsigned int h;
5521 file_list_t *exp;
5522 char *ptr;
5523
5524 (void) strcpy(name, str);
5525 while (name[strlen(name) - 1] == '/') {
5526 name[strlen(name) - 1] = '\0';
5527 }
5528
5529 /*
5530 * check for the file name in the passed list
5531 */
5532 h = hash(name);
5533 exp = table[h];
5534 while (exp != NULL) {
5535 if (strcmp(name, exp->name) == 0) {
5536 return (1);
5537 }
5538 exp = exp->next;
5539 }
5540
5541 /*
5542 * check for any parent directories in the file list
5543 */
5544 while ((ptr = strrchr(name, '/'))) {
5545 *ptr = '\0';
5546 h = hash(name);
5547 exp = table[h];
5548 while (exp != NULL) {
5549 if (strcmp(name, exp->name) == 0) {
5550 return (1);
5551 }
5552 exp = exp->next;
5553 }
5554 }
5555
5556 return (0);
5557 }
5558
5559
5560 /*
5561 * Compute a hash from a string.
5562 */
5563
5564 static unsigned int
5565 hash(char *str)
6598 * If !hflag then delete the target.
6599 */
6600
6601 static void
6602 delete_target(int fd, char *comp, char *namep)
6603 {
6604 struct stat xtractbuf;
6605 char buf[PATH_MAX + 1];
6606 int n;
6607
6608
6609 if (unlinkat(fd, comp, AT_REMOVEDIR) < 0) {
6610 if (errno == ENOTDIR && !hflag) {
6611 (void) unlinkat(fd, comp, 0);
6612 } else if (errno == ENOTDIR && hflag) {
6613 if (!lstat(namep, &xtractbuf)) {
6614 if ((xtractbuf.st_mode & S_IFMT) != S_IFLNK) {
6615 (void) unlinkat(fd, comp, 0);
6616 } else if ((n = readlink(namep, buf,
6617 PATH_MAX)) != -1) {
6618 buf[n] = '\0';
6619 (void) unlinkat(fd, buf,
6620 AT_REMOVEDIR);
6621 if (errno == ENOTDIR)
6622 (void) unlinkat(fd, buf, 0);
6623 } else {
6624 (void) unlinkat(fd, comp, 0);
6625 }
6626 } else {
6627 (void) unlinkat(fd, comp, 0);
6628 }
6629 }
6630 }
6631 }
6632
6633
6634 /*
6635 * ACL changes:
6636 * putfile():
6637 * Get acl info after stat. Write out ancillary file
6638 * before the normal file, i.e. directory, regular, FIFO,
|