Print this page
5218 posix definition of NULL
correct unistd.h and iso/stddef_iso.h
update gate source affected


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,