00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef lint
00035 #if 0
00036 static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
00037 #endif
00038 #endif
00039
00040 #include <sys/types.h>
00041 #include <sys/time.h>
00042 #include <sys/stat.h>
00043 #include <string.h>
00044 #include <stdio.h>
00045 #include <unistd.h>
00046 #include <stdlib.h>
00047 #include "pax.h"
00048 #include "extern.h"
00049 #include "tar.h"
00050
00051
00052
00053
00054
00055 static u_long tar_chksm(char *, int);
00056 static char *name_split(char *, int);
00057 static int ul_oct(u_long, char *, int, int);
00058 #ifndef NET2_STAT
00059 static int uqd_oct(u_quad_t, char *, int, int);
00060 #endif
00061
00062
00063
00064
00065
00066 static int tar_nodir;
00067
00068
00069
00070
00071
00072
00073
00074
00075 int
00076 tar_endwr(void)
00077 {
00078 return(wr_skip((off_t)(NULLCNT*BLKMULT)));
00079 }
00080
00081
00082
00083
00084
00085
00086
00087
00088 off_t
00089 tar_endrd(void)
00090 {
00091 return((off_t)(NULLCNT*BLKMULT));
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 int
00106 tar_trail(char *buf, int in_resync, int *cnt)
00107 {
00108 int i;
00109
00110
00111
00112
00113 for (i = 0; i < BLKMULT; ++i) {
00114 if (buf[i] != '\0')
00115 break;
00116 }
00117
00118
00119
00120
00121 if (i != BLKMULT)
00122 return(-1);
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 if (!in_resync && (++*cnt >= NULLCNT))
00133 return(0);
00134 return(1);
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 static int
00149 ul_oct(u_long val, char *str, int len, int term)
00150 {
00151 char *pt;
00152
00153
00154
00155
00156 pt = str + len - 1;
00157 switch(term) {
00158 case 3:
00159 *pt-- = '\0';
00160 break;
00161 case 2:
00162 *pt-- = ' ';
00163 *pt-- = '\0';
00164 break;
00165 case 1:
00166 *pt-- = ' ';
00167 break;
00168 case 0:
00169 default:
00170 *pt-- = '\0';
00171 *pt-- = ' ';
00172 break;
00173 }
00174
00175
00176
00177
00178 while (pt >= str) {
00179 *pt-- = '0' + (char)(val & 0x7);
00180 if ((val = val >> 3) == (u_long)0)
00181 break;
00182 }
00183
00184 while (pt >= str)
00185 *pt-- = '0';
00186 if (val != (u_long)0)
00187 return(-1);
00188 return(0);
00189 }
00190
00191 #ifndef NET2_STAT
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 static int
00204 uqd_oct(u_quad_t val, char *str, int len, int term)
00205 {
00206 char *pt;
00207
00208
00209
00210
00211 pt = str + len - 1;
00212 switch(term) {
00213 case 3:
00214 *pt-- = '\0';
00215 break;
00216 case 2:
00217 *pt-- = ' ';
00218 *pt-- = '\0';
00219 break;
00220 case 1:
00221 *pt-- = ' ';
00222 break;
00223 case 0:
00224 default:
00225 *pt-- = '\0';
00226 *pt-- = ' ';
00227 break;
00228 }
00229
00230
00231
00232
00233 while (pt >= str) {
00234 *pt-- = '0' + (char)(val & 0x7);
00235 if ((val = val >> 3) == 0)
00236 break;
00237 }
00238
00239 while (pt >= str)
00240 *pt-- = '0';
00241 if (val != (u_quad_t)0)
00242 return(-1);
00243 return(0);
00244 }
00245 #endif
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 static u_long
00258 tar_chksm(char *blk, int len)
00259 {
00260 char *stop;
00261 char *pt;
00262 u_long chksm = BLNKSUM;
00263
00264
00265
00266
00267 pt = blk;
00268 stop = blk + CHK_OFFSET;
00269 while (pt < stop)
00270 chksm += (u_long)(*pt++ & 0xff);
00271
00272
00273
00274
00275
00276
00277
00278 pt += CHK_LEN;
00279 stop = blk + len;
00280 while (pt < stop)
00281 chksm += (u_long)(*pt++ & 0xff);
00282 return(chksm);
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 int
00299 tar_id(char *blk, int size)
00300 {
00301 HD_TAR *hd;
00302 HD_USTAR *uhd;
00303
00304 if (size < BLKMULT)
00305 return(-1);
00306 hd = (HD_TAR *)blk;
00307 uhd = (HD_USTAR *)blk;
00308
00309
00310
00311
00312
00313
00314
00315
00316 if (hd->name[0] == '\0')
00317 return(-1);
00318 if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0)
00319 return(-1);
00320 if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
00321 return(-1);
00322 return(0);
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332 int
00333 tar_opt(void)
00334 {
00335 OPLIST *opt;
00336
00337 while ((opt = opt_next()) != NULL) {
00338 if (strcmp(opt->name, TAR_OPTION) ||
00339 strcmp(opt->value, TAR_NODIR)) {
00340 paxwarn(1, "Unknown tar format -o option/value pair %s=%s",
00341 opt->name, opt->value);
00342 paxwarn(1,"%s=%s is the only supported tar format option",
00343 TAR_OPTION, TAR_NODIR);
00344 return(-1);
00345 }
00346
00347
00348
00349
00350 if ((act != APPND) && (act != ARCHIVE)) {
00351 paxwarn(1, "%s=%s is only supported when writing.",
00352 opt->name, opt->value);
00353 return(-1);
00354 }
00355 tar_nodir = 1;
00356 }
00357 return(0);
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 int
00370 tar_rd(ARCHD *arcn, char *buf)
00371 {
00372 HD_TAR *hd;
00373 char *pt;
00374
00375
00376
00377
00378 if (tar_id(buf, BLKMULT) < 0)
00379 return(-1);
00380 arcn->org_name = arcn->name;
00381 arcn->sb.st_nlink = 1;
00382 arcn->pat = NULL;
00383
00384
00385
00386
00387 hd = (HD_TAR *)buf;
00388
00389
00390
00391
00392
00393 arcn->nlen = l_strncpy(arcn->name, hd->name,
00394 MIN(sizeof(hd->name), sizeof(arcn->name)) - 1);
00395 arcn->name[arcn->nlen] = '\0';
00396 arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
00397 0xfff);
00398 arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
00399 arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
00400 #ifdef NET2_STAT
00401 arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
00402 arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
00403 #else
00404 arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
00405 arcn->sb.st_mtime = (time_t)asc_uqd(hd->mtime, sizeof(hd->mtime), OCT);
00406 #endif
00407 arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
00408
00409
00410
00411
00412
00413 pt = &(arcn->name[arcn->nlen - 1]);
00414 arcn->pad = 0;
00415 arcn->skip = 0;
00416 switch(hd->linkflag) {
00417 case SYMTYPE:
00418
00419
00420
00421
00422 arcn->type = PAX_SLK;
00423 arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
00424 MIN(sizeof(hd->linkname), sizeof(arcn->ln_name)) - 1);
00425 arcn->ln_name[arcn->ln_nlen] = '\0';
00426 arcn->sb.st_mode |= S_IFLNK;
00427 break;
00428 case LNKTYPE:
00429
00430
00431
00432
00433 arcn->type = PAX_HLK;
00434 arcn->sb.st_nlink = 2;
00435 arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
00436 MIN(sizeof(hd->linkname), sizeof(arcn->ln_name)) - 1);
00437 arcn->ln_name[arcn->ln_nlen] = '\0';
00438
00439
00440
00441
00442
00443 arcn->sb.st_mode |= S_IFREG;
00444 break;
00445 case DIRTYPE:
00446
00447
00448
00449 arcn->type = PAX_DIR;
00450 arcn->sb.st_mode |= S_IFDIR;
00451 arcn->sb.st_nlink = 2;
00452 arcn->ln_name[0] = '\0';
00453 arcn->ln_nlen = 0;
00454 break;
00455 case AREGTYPE:
00456 case REGTYPE:
00457 default:
00458
00459
00460
00461 arcn->ln_name[0] = '\0';
00462 arcn->ln_nlen = 0;
00463 if (*pt == '/') {
00464
00465
00466
00467 arcn->type = PAX_DIR;
00468 arcn->sb.st_mode |= S_IFDIR;
00469 arcn->sb.st_nlink = 2;
00470 } else {
00471
00472
00473
00474
00475
00476 arcn->type = PAX_REG;
00477 arcn->sb.st_mode |= S_IFREG;
00478 arcn->pad = TAR_PAD(arcn->sb.st_size);
00479 arcn->skip = arcn->sb.st_size;
00480 }
00481 break;
00482 }
00483
00484
00485
00486
00487 if (*pt == '/') {
00488 *pt = '\0';
00489 --arcn->nlen;
00490 }
00491 return(0);
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 int
00507 tar_wr(ARCHD *arcn)
00508 {
00509 HD_TAR *hd;
00510 int len;
00511 char hdblk[sizeof(HD_TAR)];
00512
00513
00514
00515
00516 switch(arcn->type) {
00517 case PAX_DIR:
00518
00519
00520
00521 if (tar_nodir)
00522 return(1);
00523 break;
00524 case PAX_CHR:
00525 paxwarn(1, "Tar cannot archive a character device %s",
00526 arcn->org_name);
00527 return(1);
00528 case PAX_BLK:
00529 paxwarn(1, "Tar cannot archive a block device %s", arcn->org_name);
00530 return(1);
00531 case PAX_SCK:
00532 paxwarn(1, "Tar cannot archive a socket %s", arcn->org_name);
00533 return(1);
00534 case PAX_FIF:
00535 paxwarn(1, "Tar cannot archive a fifo %s", arcn->org_name);
00536 return(1);
00537 case PAX_SLK:
00538 case PAX_HLK:
00539 case PAX_HRG:
00540 if (arcn->ln_nlen >= (int)sizeof(hd->linkname)) {
00541 paxwarn(1,"Link name too long for tar %s", arcn->ln_name);
00542 return(1);
00543 }
00544 break;
00545 case PAX_REG:
00546 case PAX_CTG:
00547 default:
00548 break;
00549 }
00550
00551
00552
00553
00554 len = arcn->nlen;
00555 if (arcn->type == PAX_DIR)
00556 ++len;
00557 if (len >= (int)sizeof(hd->name)) {
00558 paxwarn(1, "File name too long for tar %s", arcn->name);
00559 return(1);
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 hd = (HD_TAR *)hdblk;
00571 l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1);
00572 hd->name[sizeof(hd->name) - 1] = '\0';
00573 arcn->pad = 0;
00574
00575 if (arcn->type == PAX_DIR) {
00576
00577
00578
00579
00580
00581 hd->linkflag = AREGTYPE;
00582 memset(hd->linkname, 0, sizeof(hd->linkname));
00583 hd->name[len-1] = '/';
00584 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
00585 goto out;
00586 } else if (arcn->type == PAX_SLK) {
00587
00588
00589
00590 hd->linkflag = SYMTYPE;
00591 l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
00592 hd->linkname[sizeof(hd->linkname) - 1] = '\0';
00593 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
00594 goto out;
00595 } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
00596
00597
00598
00599 hd->linkflag = LNKTYPE;
00600 l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
00601 hd->linkname[sizeof(hd->linkname) - 1] = '\0';
00602 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
00603 goto out;
00604 } else {
00605
00606
00607
00608 hd->linkflag = AREGTYPE;
00609 memset(hd->linkname, 0, sizeof(hd->linkname));
00610 # ifdef NET2_STAT
00611 if (ul_oct((u_long)arcn->sb.st_size, hd->size,
00612 sizeof(hd->size), 1)) {
00613 # else
00614 if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
00615 sizeof(hd->size), 1)) {
00616 # endif
00617 paxwarn(1,"File is too large for tar %s", arcn->org_name);
00618 return(1);
00619 }
00620 arcn->pad = TAR_PAD(arcn->sb.st_size);
00621 }
00622
00623
00624
00625
00626 if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
00627 ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
00628 ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
00629 ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
00630 goto out;
00631
00632
00633
00634
00635
00636
00637 if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
00638 sizeof(hd->chksum), 3))
00639 goto out;
00640 if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
00641 return(-1);
00642 if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0)
00643 return(-1);
00644 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
00645 return(0);
00646 return(1);
00647
00648 out:
00649
00650
00651
00652 paxwarn(1, "Tar header field is too small for %s", arcn->org_name);
00653 return(1);
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 int
00668 ustar_strd(void)
00669 {
00670 if ((usrtb_start() < 0) || (grptb_start() < 0))
00671 return(-1);
00672 return(0);
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682 int
00683 ustar_stwr(void)
00684 {
00685 if ((uidtb_start() < 0) || (gidtb_start() < 0))
00686 return(-1);
00687 return(0);
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698 int
00699 ustar_id(char *blk, int size)
00700 {
00701 HD_USTAR *hd;
00702
00703 if (size < BLKMULT)
00704 return(-1);
00705 hd = (HD_USTAR *)blk;
00706
00707
00708
00709
00710
00711
00712
00713 if (hd->name[0] == '\0')
00714 return(-1);
00715 if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
00716 return(-1);
00717 if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
00718 return(-1);
00719 return(0);
00720 }
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 int
00731 ustar_rd(ARCHD *arcn, char *buf)
00732 {
00733 HD_USTAR *hd;
00734 char *dest;
00735 int cnt = 0;
00736 dev_t devmajor;
00737 dev_t devminor;
00738
00739
00740
00741
00742 if (ustar_id(buf, BLKMULT) < 0)
00743 return(-1);
00744 arcn->org_name = arcn->name;
00745 arcn->sb.st_nlink = 1;
00746 arcn->pat = NULL;
00747 arcn->nlen = 0;
00748 hd = (HD_USTAR *)buf;
00749
00750
00751
00752
00753
00754 dest = arcn->name;
00755 if (*(hd->prefix) != '\0') {
00756 cnt = l_strncpy(dest, hd->prefix,
00757 MIN(sizeof(hd->prefix), sizeof(arcn->name) - 2));
00758 dest += cnt;
00759 *dest++ = '/';
00760 cnt++;
00761 }
00762
00763
00764
00765
00766
00767 arcn->nlen = cnt + l_strncpy(dest, hd->name,
00768 MIN(sizeof(hd->name), sizeof(arcn->name) - cnt - 1));
00769 arcn->name[arcn->nlen] = '\0';
00770
00771
00772
00773
00774
00775 arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
00776 0xfff);
00777 #ifdef NET2_STAT
00778 arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
00779 arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
00780 #else
00781 arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
00782 arcn->sb.st_mtime = (time_t)asc_uqd(hd->mtime, sizeof(hd->mtime), OCT);
00783 #endif
00784 arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
00785
00786
00787
00788
00789
00790
00791
00792 hd->gname[sizeof(hd->gname) - 1] = '\0';
00793 if (gid_name((char *) hd->gname, (gid_t *) &(arcn->sb.st_gid)) < 0)
00794 arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
00795 hd->uname[sizeof(hd->uname) - 1] = '\0';
00796 if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0)
00797 arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
00798
00799
00800
00801
00802 arcn->ln_name[0] = '\0';
00803 arcn->ln_nlen = 0;
00804 arcn->pad = 0;
00805 arcn->skip = 0;
00806 arcn->sb.st_rdev = (dev_t)0;
00807
00808
00809
00810
00811 switch(hd->typeflag) {
00812 case FIFOTYPE:
00813 arcn->type = PAX_FIF;
00814 arcn->sb.st_mode |= S_IFIFO;
00815 break;
00816 case DIRTYPE:
00817 arcn->type = PAX_DIR;
00818 arcn->sb.st_mode |= S_IFDIR;
00819 arcn->sb.st_nlink = 2;
00820
00821
00822
00823
00824
00825
00826 if (arcn->name[arcn->nlen - 1] == '/')
00827 arcn->name[--arcn->nlen] = '\0';
00828 break;
00829 case BLKTYPE:
00830 case CHRTYPE:
00831
00832
00833
00834 if (hd->typeflag == BLKTYPE) {
00835 arcn->type = PAX_BLK;
00836 arcn->sb.st_mode |= S_IFBLK;
00837 } else {
00838 arcn->type = PAX_CHR;
00839 arcn->sb.st_mode |= S_IFCHR;
00840 }
00841 devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT);
00842 devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT);
00843 arcn->sb.st_rdev = TODEV(devmajor, devminor);
00844 break;
00845 case SYMTYPE:
00846 case LNKTYPE:
00847 if (hd->typeflag == SYMTYPE) {
00848 arcn->type = PAX_SLK;
00849 arcn->sb.st_mode |= S_IFLNK;
00850 } else {
00851 arcn->type = PAX_HLK;
00852
00853
00854
00855 arcn->sb.st_mode |= S_IFREG;
00856 arcn->sb.st_nlink = 2;
00857 }
00858
00859
00860
00861 arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
00862 MIN(sizeof(hd->linkname), sizeof(arcn->ln_name) - 1));
00863 arcn->ln_name[arcn->ln_nlen] = '\0';
00864 break;
00865 case CONTTYPE:
00866 case AREGTYPE:
00867 case REGTYPE:
00868 default:
00869
00870
00871
00872
00873 arcn->type = PAX_REG;
00874 arcn->pad = TAR_PAD(arcn->sb.st_size);
00875 arcn->skip = arcn->sb.st_size;
00876 arcn->sb.st_mode |= S_IFREG;
00877 break;
00878 }
00879 return(0);
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 int
00895 ustar_wr(ARCHD *arcn)
00896 {
00897 HD_USTAR *hd;
00898 char *pt;
00899 char hdblk[sizeof(HD_USTAR)];
00900
00901
00902
00903
00904 if (arcn->type == PAX_SCK) {
00905 paxwarn(1, "Ustar cannot archive a socket %s", arcn->org_name);
00906 return(1);
00907 }
00908
00909
00910
00911
00912 if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
00913 (arcn->type == PAX_HRG)) &&
00914 (arcn->ln_nlen > (int)sizeof(hd->linkname))) {
00915 paxwarn(1, "Link name too long for ustar %s", arcn->ln_name);
00916 return(1);
00917 }
00918
00919
00920
00921
00922
00923 if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) {
00924 paxwarn(1, "File name too long for ustar %s", arcn->name);
00925 return(1);
00926 }
00927 hd = (HD_USTAR *)hdblk;
00928 arcn->pad = 0L;
00929
00930
00931
00932
00933 if (pt != arcn->name) {
00934
00935
00936
00937
00938 *pt = '\0';
00939 l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix));
00940 *pt++ = '/';
00941 } else
00942 memset(hd->prefix, 0, sizeof(hd->prefix));
00943
00944
00945
00946
00947
00948 l_strncpy(hd->name, pt, sizeof(hd->name));
00949
00950
00951
00952
00953 switch(arcn->type) {
00954 case PAX_DIR:
00955 hd->typeflag = DIRTYPE;
00956 memset(hd->linkname, 0, sizeof(hd->linkname));
00957 memset(hd->devmajor, 0, sizeof(hd->devmajor));
00958 memset(hd->devminor, 0, sizeof(hd->devminor));
00959 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
00960 goto out;
00961 break;
00962 case PAX_CHR:
00963 case PAX_BLK:
00964 if (arcn->type == PAX_CHR)
00965 hd->typeflag = CHRTYPE;
00966 else
00967 hd->typeflag = BLKTYPE;
00968 memset(hd->linkname, 0, sizeof(hd->linkname));
00969 if (ul_oct((u_long)major(arcn->sb.st_rdev), hd->devmajor,
00970 sizeof(hd->devmajor), 3) ||
00971 ul_oct((u_long)minor(arcn->sb.st_rdev), hd->devminor,
00972 sizeof(hd->devminor), 3) ||
00973 ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
00974 goto out;
00975 break;
00976 case PAX_FIF:
00977 hd->typeflag = FIFOTYPE;
00978 memset(hd->linkname, 0, sizeof(hd->linkname));
00979 memset(hd->devmajor, 0, sizeof(hd->devmajor));
00980 memset(hd->devminor, 0, sizeof(hd->devminor));
00981 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
00982 goto out;
00983 break;
00984 case PAX_SLK:
00985 case PAX_HLK:
00986 case PAX_HRG:
00987 if (arcn->type == PAX_SLK)
00988 hd->typeflag = SYMTYPE;
00989 else
00990 hd->typeflag = LNKTYPE;
00991
00992 l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname));
00993 memset(hd->devmajor, 0, sizeof(hd->devmajor));
00994 memset(hd->devminor, 0, sizeof(hd->devminor));
00995 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
00996 goto out;
00997 break;
00998 case PAX_REG:
00999 case PAX_CTG:
01000 default:
01001
01002
01003
01004 if (arcn->type == PAX_CTG)
01005 hd->typeflag = CONTTYPE;
01006 else
01007 hd->typeflag = REGTYPE;
01008 memset(hd->linkname, 0, sizeof(hd->linkname));
01009 memset(hd->devmajor, 0, sizeof(hd->devmajor));
01010 memset(hd->devminor, 0, sizeof(hd->devminor));
01011 arcn->pad = TAR_PAD(arcn->sb.st_size);
01012 # ifdef NET2_STAT
01013 if (ul_oct((u_long)arcn->sb.st_size, hd->size,
01014 sizeof(hd->size), 3)) {
01015 # else
01016 if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
01017 sizeof(hd->size), 3)) {
01018 # endif
01019 paxwarn(1,"File is too long for ustar %s",arcn->org_name);
01020 return(1);
01021 }
01022 break;
01023 }
01024
01025 l_strncpy(hd->magic, TMAGIC, TMAGLEN);
01026 l_strncpy(hd->version, TVERSION, TVERSLEN);
01027
01028
01029
01030
01031
01032 if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
01033 ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) ||
01034 ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
01035 ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
01036 goto out;
01037 l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
01038 l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
01039
01040
01041
01042
01043
01044
01045 if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
01046 sizeof(hd->chksum), 3))
01047 goto out;
01048 if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
01049 return(-1);
01050 if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
01051 return(-1);
01052 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
01053 return(0);
01054 return(1);
01055
01056 out:
01057
01058
01059
01060 paxwarn(1, "Ustar header field is too small for %s", arcn->org_name);
01061 return(1);
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076 static char *
01077 name_split(char *name, int len)
01078 {
01079 char *start;
01080
01081
01082
01083
01084
01085 if (len <= TNMSZ)
01086 return(name);
01087 if (len > (TPFSZ + TNMSZ + 1))
01088 return(NULL);
01089
01090
01091
01092
01093
01094
01095
01096 start = name + len - TNMSZ - 1;
01097 while ((*start != '\0') && (*start != '/'))
01098 ++start;
01099
01100
01101
01102
01103
01104 if (*start == '\0')
01105 return(NULL);
01106 len = start - name;
01107
01108
01109
01110
01111
01112
01113
01114 if ((len > TPFSZ) || (len == 0))
01115 return(NULL);
01116
01117
01118
01119
01120 return(start);
01121 }