1
0

tar.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. /*
  2. * tar - `tape archiver', actually usable on any medium.
  3. * POSIX "ustar" compliant when extracting, and by default when creating.
  4. * this tar attempts to read and write multiple Tblock-byte blocks
  5. * at once to and from the filesystem, and does not copy blocks
  6. * around internally.
  7. */
  8. #include <u.h>
  9. #include <libc.h>
  10. #include <fcall.h> /* for %M */
  11. #include <String.h>
  12. /*
  13. * modified versions of those in libc.h; scans only the first arg for
  14. * keyletters and options.
  15. */
  16. #define TARGBEGIN {\
  17. (argv0 || (argv0 = *argv)), argv++, argc--;\
  18. if (argv[0]) {\
  19. char *_args, *_argt;\
  20. Rune _argc;\
  21. _args = &argv[0][0];\
  22. _argc = 0;\
  23. while(*_args && (_args += chartorune(&_argc, _args)))\
  24. switch(_argc)
  25. #define TARGEND SET(_argt); USED(_argt);USED(_argc);USED(_args); \
  26. argc--, argv++; } \
  27. USED(argv); USED(argc); }
  28. #define TARGC() (_argc)
  29. #define ROUNDUP(a, b) (((a) + (b) - 1)/(b))
  30. #define BYTES2TBLKS(bytes) ROUNDUP(bytes, Tblock)
  31. typedef vlong Off;
  32. typedef char *(*Refill)(int ar, char *bufs);
  33. enum { Stdin, Stdout, Stderr };
  34. enum { Rd, Wr }; /* pipe fd-array indices */
  35. enum { Output, Input };
  36. enum { None, Toc, Xtract, Replace };
  37. enum {
  38. Tblock = 512,
  39. Nblock = 40, /* maximum blocksize */
  40. Dblock = 20, /* default blocksize */
  41. Namsiz = 100,
  42. Maxpfx = 155, /* from POSIX */
  43. Maxname = Namsiz + 1 + Maxpfx,
  44. DEBUG = 0,
  45. };
  46. /* POSIX link flags */
  47. enum {
  48. LF_PLAIN1 = '\0',
  49. LF_PLAIN2 = '0',
  50. LF_LINK = '1',
  51. LF_SYMLINK1 = '2',
  52. LF_SYMLINK2 = 's',
  53. LF_CHR = '3',
  54. LF_BLK = '4',
  55. LF_DIR = '5',
  56. LF_FIFO = '6',
  57. LF_CONTIG = '7',
  58. /* 'A' - 'Z' are reserved for custom implementations */
  59. };
  60. #define islink(lf) (isreallink(lf) || issymlink(lf))
  61. #define isreallink(lf) ((lf) == LF_LINK)
  62. #define issymlink(lf) ((lf) == LF_SYMLINK1 || (lf) == LF_SYMLINK2)
  63. typedef union {
  64. uchar data[Tblock];
  65. struct {
  66. char name[Namsiz];
  67. char mode[8];
  68. char uid[8];
  69. char gid[8];
  70. char size[12];
  71. char mtime[12];
  72. char chksum[8];
  73. char linkflag;
  74. char linkname[Namsiz];
  75. /* rest are defined by POSIX's ustar format; see p1003.2b */
  76. char magic[6]; /* "ustar" */
  77. char version[2];
  78. char uname[32];
  79. char gname[32];
  80. char devmajor[8];
  81. char devminor[8];
  82. char prefix[Maxpfx]; /* if non-null, path= prefix "/" name */
  83. };
  84. } Hdr;
  85. typedef struct {
  86. char *comp;
  87. char *decomp;
  88. char *sfx[4];
  89. } Compress;
  90. static Compress comps[] = {
  91. "gzip", "gunzip", { ".tar.gz", ".tgz" }, /* default */
  92. "compress", "uncompress", { ".tar.Z", ".tz" },
  93. "bzip2", "bunzip2", { ".tar.bz", ".tbz",
  94. ".tar.bz2",".tbz2" },
  95. };
  96. typedef struct {
  97. int kid;
  98. int fd; /* original fd */
  99. int rfd; /* replacement fd */
  100. int input;
  101. int open;
  102. } Pushstate;
  103. #define OTHER(rdwr) (rdwr == Rd? Wr: Rd)
  104. static int debug;
  105. static int verb;
  106. static int posix = 1;
  107. static int docreate;
  108. static int aruid;
  109. static int argid;
  110. static int relative = 1;
  111. static int settime;
  112. static int verbose;
  113. static int docompress;
  114. static int keepexisting;
  115. static int nblock = Dblock;
  116. static char *usefile;
  117. static char origdir[Maxname*2];
  118. static Hdr *tpblk, *endblk;
  119. static Hdr *curblk;
  120. static void
  121. usage(void)
  122. {
  123. fprint(2, "usage: %s {crtx}[PRTfgkmpuvz] [archive] file1 file2...\n",
  124. argv0);
  125. exits("usage");
  126. }
  127. /* compression */
  128. static Compress *
  129. compmethod(char *name)
  130. {
  131. int i, nmlen = strlen(name), sfxlen;
  132. Compress *cp;
  133. for (cp = comps; cp < comps + nelem(comps); cp++)
  134. for (i = 0; i < nelem(cp->sfx) && cp->sfx[i]; i++) {
  135. sfxlen = strlen(cp->sfx[i]);
  136. if (nmlen > sfxlen &&
  137. strcmp(cp->sfx[i], name + nmlen - sfxlen) == 0)
  138. return cp;
  139. }
  140. return docompress? comps: nil;
  141. }
  142. /*
  143. * push a filter, cmd, onto fd. if input, it's an input descriptor.
  144. * returns a descriptor to replace fd, or -1 on error.
  145. */
  146. static int
  147. push(int fd, char *cmd, int input, Pushstate *ps)
  148. {
  149. int nfd, pifds[2];
  150. String *s;
  151. ps->open = 0;
  152. ps->fd = fd;
  153. ps->input = input;
  154. if (fd < 0 || pipe(pifds) < 0)
  155. return -1;
  156. ps->kid = fork();
  157. switch (ps->kid) {
  158. case -1:
  159. return -1;
  160. case 0:
  161. if (input)
  162. dup(pifds[Wr], Stdout);
  163. else
  164. dup(pifds[Rd], Stdin);
  165. close(pifds[input? Rd: Wr]);
  166. dup(fd, (input? Stdin: Stdout));
  167. s = s_new();
  168. if (cmd[0] != '/')
  169. s_append(s, "/bin/");
  170. s_append(s, cmd);
  171. execl(s_to_c(s), cmd, nil);
  172. sysfatal("can't exec %s: %r", cmd);
  173. default:
  174. nfd = pifds[input? Rd: Wr];
  175. close(pifds[input? Wr: Rd]);
  176. break;
  177. }
  178. ps->rfd = nfd;
  179. ps->open = 1;
  180. return nfd;
  181. }
  182. static char *
  183. pushclose(Pushstate *ps)
  184. {
  185. Waitmsg *wm;
  186. if (ps->fd < 0 || ps->rfd < 0 || !ps->open)
  187. return "not open";
  188. close(ps->rfd);
  189. ps->rfd = -1;
  190. ps->open = 0;
  191. while ((wm = wait()) != nil && wm->pid != ps->kid)
  192. continue;
  193. return wm? wm->msg: nil;
  194. }
  195. /*
  196. * block-buffer management
  197. */
  198. static void
  199. initblks(void)
  200. {
  201. free(tpblk);
  202. tpblk = malloc(Tblock * nblock);
  203. assert(tpblk != nil);
  204. endblk = tpblk + nblock;
  205. }
  206. /* (re)fill block buffers from archive */
  207. static char *
  208. refill(int ar, char *bufs)
  209. {
  210. int i, n;
  211. unsigned bytes = Tblock * nblock;
  212. static int done, first = 1;
  213. if (done)
  214. return nil;
  215. /* try to size non-pipe input at first read */
  216. if (first && usefile) {
  217. first = 0;
  218. n = read(ar, bufs, bytes);
  219. if (n <= 0)
  220. sysfatal("error reading archive: %r");
  221. i = n;
  222. if (i % Tblock != 0) {
  223. fprint(2, "%s: archive block size (%d) error\n",
  224. argv0, i);
  225. exits("blocksize");
  226. }
  227. i /= Tblock;
  228. if (i != nblock) {
  229. nblock = i;
  230. fprint(2, "%s: blocking = %d\n", argv0, nblock);
  231. endblk = (Hdr *)bufs + nblock;
  232. bytes = n;
  233. }
  234. } else
  235. n = readn(ar, bufs, bytes);
  236. if (n == 0)
  237. sysfatal("unexpected EOF reading archive");
  238. else if (n < 0)
  239. sysfatal("error reading archive: %r");
  240. else if (n%Tblock != 0)
  241. sysfatal("partial block read from archive");
  242. if (n != bytes) {
  243. done = 1;
  244. memset(bufs + n, 0, bytes - n);
  245. }
  246. return bufs;
  247. }
  248. static Hdr *
  249. getblk(int ar, Refill rfp)
  250. {
  251. if (curblk == nil || curblk >= endblk) { /* input block exhausted? */
  252. if (rfp != nil && (*rfp)(ar, (char *)tpblk) == nil)
  253. return nil;
  254. curblk = tpblk;
  255. }
  256. return curblk++;
  257. }
  258. static Hdr *
  259. getblkrd(int ar)
  260. {
  261. return getblk(ar, refill);
  262. }
  263. static Hdr *
  264. getblke(int ar)
  265. {
  266. return getblk(ar, nil);
  267. }
  268. static Hdr *
  269. getblkz(int ar)
  270. {
  271. Hdr *hp = getblke(ar);
  272. if (hp != nil)
  273. memset(hp->data, 0, Tblock);
  274. return hp;
  275. }
  276. /*
  277. * how many block buffers are available, starting at the address
  278. * just returned by getblk*?
  279. */
  280. static int
  281. gothowmany(int max)
  282. {
  283. int n = endblk - (curblk - 1);
  284. return n > max? max: n;
  285. }
  286. /*
  287. * indicate that one is done with the last block obtained from getblke
  288. * and it is now available to be written into the archive.
  289. */
  290. static void
  291. putlastblk(int ar)
  292. {
  293. unsigned bytes = Tblock * nblock;
  294. /* if writing end-of-archive, aid compression (good hygiene too) */
  295. if (curblk < endblk)
  296. memset(curblk, 0, (char *)endblk - (char *)curblk);
  297. if (write(ar, tpblk, bytes) != bytes)
  298. sysfatal("error writing archive: %r");
  299. }
  300. static void
  301. putblk(int ar)
  302. {
  303. if (curblk >= endblk)
  304. putlastblk(ar);
  305. }
  306. static void
  307. putbackblk(int ar)
  308. {
  309. curblk--;
  310. USED(ar);
  311. }
  312. static void
  313. putreadblks(int ar, int blks)
  314. {
  315. curblk += blks - 1;
  316. USED(ar);
  317. }
  318. static void
  319. putblkmany(int ar, int blks)
  320. {
  321. curblk += blks - 1;
  322. putblk(ar);
  323. }
  324. /*
  325. * common routines
  326. */
  327. /* modifies hp->chksum */
  328. long
  329. chksum(Hdr *hp)
  330. {
  331. int n = Tblock;
  332. long i = 0;
  333. uchar *cp = hp->data;
  334. memset(hp->chksum, ' ', sizeof hp->chksum);
  335. while (n-- > 0)
  336. i += *cp++;
  337. return i;
  338. }
  339. static int
  340. isustar(Hdr *hp)
  341. {
  342. return strcmp(hp->magic, "ustar") == 0;
  343. }
  344. /*
  345. * s is at most n bytes long, but need not be NUL-terminated.
  346. * if shorter than n bytes, all bytes after the first NUL must also
  347. * be NUL.
  348. */
  349. static int
  350. strnlen(char *s, int n)
  351. {
  352. return s[n - 1] != '\0'? n: strlen(s);
  353. }
  354. /* set fullname from header */
  355. static char *
  356. name(Hdr *hp)
  357. {
  358. int pfxlen, namlen;
  359. static char fullnamebuf[2 + Maxname + 1]; /* 2 at beginning for ./ on relative names */
  360. char *fullname;
  361. fullname = fullnamebuf+2;
  362. namlen = strnlen(hp->name, sizeof hp->name);
  363. if (hp->prefix[0] == '\0' || !isustar(hp)) { /* old-style name? */
  364. memmove(fullname, hp->name, namlen);
  365. fullname[namlen] = '\0';
  366. return fullname;
  367. }
  368. /* name is in two pieces */
  369. pfxlen = strnlen(hp->prefix, sizeof hp->prefix);
  370. memmove(fullname, hp->prefix, pfxlen);
  371. fullname[pfxlen] = '/';
  372. memmove(fullname + pfxlen + 1, hp->name, namlen);
  373. fullname[pfxlen + 1 + namlen] = '\0';
  374. return fullname;
  375. }
  376. static int
  377. isdir(Hdr *hp)
  378. {
  379. /* the mode test is ugly but sometimes necessary */
  380. return hp->linkflag == LF_DIR ||
  381. strrchr(name(hp), '\0')[-1] == '/' ||
  382. (strtoul(hp->mode, nil, 8)&0170000) == 040000;
  383. }
  384. static int
  385. eotar(Hdr *hp)
  386. {
  387. return name(hp)[0] == '\0';
  388. }
  389. static Hdr *
  390. readhdr(int ar)
  391. {
  392. long hdrcksum;
  393. Hdr *hp;
  394. hp = getblkrd(ar);
  395. if (hp == nil)
  396. sysfatal("unexpected EOF instead of archive header");
  397. if (eotar(hp)) /* end-of-archive block? */
  398. return nil;
  399. hdrcksum = strtoul(hp->chksum, nil, 8);
  400. if (chksum(hp) != hdrcksum)
  401. sysfatal("bad archive header checksum: name %.64s...",
  402. hp->name);
  403. return hp;
  404. }
  405. /*
  406. * tar r[c]
  407. */
  408. /*
  409. * if name is longer than Namsiz bytes, try to split it at a slash and fit the
  410. * pieces into hp->prefix and hp->name.
  411. */
  412. static int
  413. putfullname(Hdr *hp, char *name)
  414. {
  415. int namlen, pfxlen;
  416. char *sl, *osl;
  417. String *slname = nil;
  418. if (isdir(hp)) {
  419. slname = s_new();
  420. s_append(slname, name);
  421. s_append(slname, "/"); /* posix requires this */
  422. name = s_to_c(slname);
  423. }
  424. namlen = strlen(name);
  425. if (namlen <= Namsiz) {
  426. strncpy(hp->name, name, Namsiz);
  427. hp->prefix[0] = '\0'; /* ustar paranoia */
  428. return 0;
  429. }
  430. if (!posix || namlen > Maxname) {
  431. fprint(2, "%s: name too long for tar header: %s\n",
  432. argv0, name);
  433. return -1;
  434. }
  435. /*
  436. * try various splits until one results in pieces that fit into the
  437. * appropriate fields of the header. look for slashes from right
  438. * to left, in the hopes of putting the largest part of the name into
  439. * hp->prefix, which is larger than hp->name.
  440. */
  441. sl = strrchr(name, '/');
  442. while (sl != nil) {
  443. pfxlen = sl - name;
  444. if (pfxlen <= sizeof hp->prefix && namlen-1 - pfxlen <= Namsiz)
  445. break;
  446. osl = sl;
  447. *osl = '\0';
  448. sl = strrchr(name, '/');
  449. *osl = '/';
  450. }
  451. if (sl == nil) {
  452. fprint(2, "%s: name can't be split to fit tar header: %s\n",
  453. argv0, name);
  454. return -1;
  455. }
  456. *sl = '\0';
  457. strncpy(hp->prefix, name, sizeof hp->prefix);
  458. *sl++ = '/';
  459. strncpy(hp->name, sl, sizeof hp->name);
  460. if (slname)
  461. s_free(slname);
  462. return 0;
  463. }
  464. static int
  465. mkhdr(Hdr *hp, Dir *dir, char *file)
  466. {
  467. /*
  468. * these fields run together, so we format them in order and don't use
  469. * snprint.
  470. */
  471. sprint(hp->mode, "%6lo ", dir->mode & 0777);
  472. sprint(hp->uid, "%6o ", aruid);
  473. sprint(hp->gid, "%6o ", argid);
  474. /*
  475. * files > 2⁳⁳ bytes can't be described
  476. * (unless we resort to xustar or exustar formats).
  477. */
  478. if (dir->length >= (Off)1<<33) {
  479. fprint(2, "%s: %s: too large for tar header format\n",
  480. argv0, file);
  481. return -1;
  482. }
  483. sprint(hp->size, "%11lluo ", dir->length);
  484. sprint(hp->mtime, "%11luo ", dir->mtime);
  485. hp->linkflag = (dir->mode&DMDIR? LF_DIR: LF_PLAIN1);
  486. putfullname(hp, file);
  487. if (posix) {
  488. strncpy(hp->magic, "ustar", sizeof hp->magic);
  489. strncpy(hp->version, "00", sizeof hp->version);
  490. strncpy(hp->uname, dir->uid, sizeof hp->uname);
  491. strncpy(hp->gname, dir->gid, sizeof hp->gname);
  492. }
  493. sprint(hp->chksum, "%6luo", chksum(hp));
  494. return 0;
  495. }
  496. static void addtoar(int ar, char *file, char *shortf);
  497. static void
  498. addtreetoar(int ar, char *file, char *shortf, int fd)
  499. {
  500. int n;
  501. Dir *dent, *dirents;
  502. String *name = s_new();
  503. n = dirreadall(fd, &dirents);
  504. close(fd);
  505. if (n == 0)
  506. return;
  507. if (chdir(shortf) < 0)
  508. sysfatal("chdir %s: %r", file);
  509. if (DEBUG)
  510. fprint(2, "chdir %s\t# %s\n", shortf, file);
  511. for (dent = dirents; dent < dirents + n; dent++) {
  512. s_reset(name);
  513. s_append(name, file);
  514. s_append(name, "/");
  515. s_append(name, dent->name);
  516. addtoar(ar, s_to_c(name), dent->name);
  517. }
  518. s_free(name);
  519. free(dirents);
  520. if (chdir("..") < 0)
  521. sysfatal("chdir %s/..: %r", file);
  522. if (DEBUG)
  523. fprint(2, "chdir ..\n");
  524. }
  525. static void
  526. addtoar(int ar, char *file, char *shortf)
  527. {
  528. int n, fd, isdir;
  529. long bytes;
  530. ulong blksleft, blksread;
  531. Hdr *hbp;
  532. Dir *dir;
  533. fd = open(shortf, OREAD);
  534. if (fd < 0) {
  535. fprint(2, "%s: can't open %s: %r\n", argv0, file);
  536. return;
  537. }
  538. dir = dirfstat(fd);
  539. if (dir == nil)
  540. sysfatal("can't fstat %s: %r", file);
  541. hbp = getblkz(ar);
  542. isdir = !!(dir->qid.type&QTDIR);
  543. if (mkhdr(hbp, dir, file) < 0) {
  544. putbackblk(ar);
  545. free(dir);
  546. close(fd);
  547. return;
  548. }
  549. putblk(ar);
  550. blksleft = BYTES2TBLKS(dir->length);
  551. free(dir);
  552. if (isdir)
  553. addtreetoar(ar, file, shortf, fd);
  554. else {
  555. for (; blksleft > 0; blksleft -= blksread) {
  556. hbp = getblke(ar);
  557. blksread = gothowmany(blksleft);
  558. bytes = blksread * Tblock;
  559. n = readn(fd, hbp->data, bytes);
  560. if (n < 0)
  561. sysfatal("error reading %s: %r", file);
  562. /*
  563. * ignore EOF. zero any partial block to aid
  564. * compression and emergency recovery of data.
  565. */
  566. if (n < Tblock)
  567. memset(hbp->data + n, 0, bytes - n);
  568. putblkmany(ar, blksread);
  569. }
  570. close(fd);
  571. if (verbose)
  572. fprint(2, "%s\n", file);
  573. }
  574. }
  575. static char *
  576. replace(char **argv)
  577. {
  578. int i, ar;
  579. ulong blksleft, blksread;
  580. Off bytes;
  581. Hdr *hp;
  582. Compress *comp = nil;
  583. Pushstate ps;
  584. if (usefile && docreate) {
  585. ar = create(usefile, OWRITE, 0666);
  586. if (docompress)
  587. comp = compmethod(usefile);
  588. } else if (usefile)
  589. ar = open(usefile, ORDWR);
  590. else
  591. ar = Stdout;
  592. if (comp)
  593. ar = push(ar, comp->comp, Output, &ps);
  594. if (ar < 0)
  595. sysfatal("can't open archive %s: %r", usefile);
  596. if (usefile && !docreate) {
  597. /* skip quickly to the end */
  598. while ((hp = readhdr(ar)) != nil) {
  599. bytes = strtoull(hp->size, nil, 8);
  600. if(isdir(hp))
  601. bytes = 0;
  602. for (blksleft = BYTES2TBLKS(bytes);
  603. blksleft > 0 && getblkrd(ar) != nil;
  604. blksleft -= blksread) {
  605. blksread = gothowmany(blksleft);
  606. putreadblks(ar, blksread);
  607. }
  608. }
  609. /*
  610. * we have just read the end-of-archive Tblock.
  611. * now seek back over the (big) archive block containing it,
  612. * and back up curblk ptr over end-of-archive Tblock in memory.
  613. */
  614. if (seek(ar, -Tblock*nblock, 1) < 0)
  615. sysfatal("can't seek back over end-of-archive: %r");
  616. curblk--;
  617. }
  618. for (i = 0; argv[i] != nil; i++)
  619. addtoar(ar, argv[i], argv[i]);
  620. /* write end-of-archive marker */
  621. getblkz(ar);
  622. putblk(ar);
  623. getblkz(ar);
  624. putlastblk(ar);
  625. if (comp)
  626. return pushclose(&ps);
  627. if (ar > Stderr)
  628. close(ar);
  629. return nil;
  630. }
  631. /*
  632. * tar [xt]
  633. */
  634. /* is pfx a file-name prefix of name? */
  635. static int
  636. prefix(char *name, char *pfx)
  637. {
  638. int pfxlen = strlen(pfx);
  639. char clpfx[Maxname+1];
  640. if (pfxlen > Maxname)
  641. return 0;
  642. strcpy(clpfx, pfx);
  643. cleanname(clpfx);
  644. return strncmp(pfx, name, pfxlen) == 0 &&
  645. (name[pfxlen] == '\0' || name[pfxlen] == '/');
  646. }
  647. static int
  648. match(char *name, char **argv)
  649. {
  650. int i;
  651. char clname[Maxname+1];
  652. if (argv[0] == nil)
  653. return 1;
  654. strcpy(clname, name);
  655. cleanname(clname);
  656. for (i = 0; argv[i] != nil; i++)
  657. if (prefix(clname, argv[i]))
  658. return 1;
  659. return 0;
  660. }
  661. static int
  662. makedir(char *s)
  663. {
  664. int f;
  665. if (access(s, AEXIST) == 0)
  666. return -1;
  667. f = create(s, OREAD, DMDIR | 0777);
  668. if (f >= 0)
  669. close(f);
  670. return f;
  671. }
  672. static void
  673. mkpdirs(char *s)
  674. {
  675. int done = 0;
  676. char *p = s;
  677. while (!done && (p = strchr(p + 1, '/')) != nil) {
  678. *p = '\0';
  679. done = (access(s, AEXIST) < 0 && makedir(s) < 0);
  680. *p = '/';
  681. }
  682. }
  683. /* copy a file from the archive into the filesystem */
  684. /* fname is result of name(), so has two extra bytes at beginning */
  685. static void
  686. extract1(int ar, Hdr *hp, char *fname)
  687. {
  688. int wrbytes, fd = -1, dir = 0;
  689. long mtime = strtol(hp->mtime, nil, 8);
  690. ulong mode = strtoul(hp->mode, nil, 8) & 0777;
  691. Off bytes = strtoll(hp->size, nil, 8);
  692. ulong blksread, blksleft = BYTES2TBLKS(bytes);
  693. Hdr *hbp;
  694. if (isdir(hp)) {
  695. mode |= DMDIR|0700;
  696. blksleft = 0;
  697. dir = 1;
  698. }
  699. switch (hp->linkflag) {
  700. case LF_LINK:
  701. case LF_SYMLINK1:
  702. case LF_SYMLINK2:
  703. case LF_FIFO:
  704. blksleft = 0;
  705. break;
  706. }
  707. if (relative) {
  708. if(fname[0] == '/')
  709. *--fname = '.';
  710. else if(fname[0] == '#'){
  711. *--fname = '/';
  712. *--fname = '.';
  713. }
  714. }
  715. if (verb == Xtract) {
  716. cleanname(fname);
  717. switch (hp->linkflag) {
  718. case LF_LINK:
  719. case LF_SYMLINK1:
  720. case LF_SYMLINK2:
  721. fprint(2, "%s: can't make (sym)link %s\n",
  722. argv0, fname);
  723. break;
  724. case LF_FIFO:
  725. fprint(2, "%s: can't make fifo %s\n", argv0, fname);
  726. break;
  727. default:
  728. if (!keepexisting || access(fname, AEXIST) < 0) {
  729. int rw = (dir? OREAD: OWRITE);
  730. fd = create(fname, rw, mode);
  731. if (fd < 0) {
  732. mkpdirs(fname);
  733. fd = create(fname, rw, mode);
  734. }
  735. if (fd < 0 &&
  736. (!dir || access(fname, AEXIST) < 0))
  737. fprint(2, "%s: can't create %s: %r\n",
  738. argv0, fname);
  739. }
  740. if (fd >= 0 && verbose)
  741. fprint(2, "%s\n", fname);
  742. break;
  743. }
  744. } else if (verbose) {
  745. char *cp = ctime(mtime);
  746. print("%M %8lld %-12.12s %-4.4s %s\n",
  747. mode, bytes, cp+4, cp+24, fname);
  748. } else
  749. print("%s\n", fname);
  750. for (; blksleft > 0; blksleft -= blksread) {
  751. hbp = getblkrd(ar);
  752. if (hbp == nil)
  753. sysfatal("unexpected EOF on archive extracting %s",
  754. fname);
  755. blksread = gothowmany(blksleft);
  756. wrbytes = Tblock*blksread;
  757. if(wrbytes > bytes)
  758. wrbytes = bytes;
  759. if (fd >= 0 && write(fd, hbp->data, wrbytes) != wrbytes)
  760. sysfatal("write error on %s: %r", fname);
  761. putreadblks(ar, blksread);
  762. bytes -= wrbytes;
  763. }
  764. if (fd >= 0) {
  765. /*
  766. * directories should be wstated after we're done
  767. * creating files in them.
  768. */
  769. if (settime) {
  770. Dir nd;
  771. nulldir(&nd);
  772. nd.mtime = mtime;
  773. if (isustar(hp))
  774. nd.gid = hp->gname;
  775. dirfwstat(fd, &nd);
  776. }
  777. close(fd);
  778. }
  779. }
  780. static void
  781. skip(int ar, Hdr *hp, char *fname)
  782. {
  783. Off bytes;
  784. ulong blksleft, blksread;
  785. Hdr *hbp;
  786. if (isdir(hp))
  787. return;
  788. bytes = strtoull(hp->size, nil, 8);
  789. blksleft = BYTES2TBLKS(bytes);
  790. for (; blksleft > 0; blksleft -= blksread) {
  791. hbp = getblkrd(ar);
  792. if (hbp == nil)
  793. sysfatal("unexpected EOF on archive extracting %s",
  794. fname);
  795. blksread = gothowmany(blksleft);
  796. putreadblks(ar, blksread);
  797. }
  798. }
  799. static char *
  800. extract(char **argv)
  801. {
  802. int ar;
  803. char *longname;
  804. Hdr *hp;
  805. Compress *comp = nil;
  806. Pushstate ps;
  807. if (usefile) {
  808. ar = open(usefile, OREAD);
  809. comp = compmethod(usefile);
  810. } else
  811. ar = Stdin;
  812. if (comp)
  813. ar = push(ar, comp->decomp, Input, &ps);
  814. if (ar < 0)
  815. sysfatal("can't open archive %s: %r", usefile);
  816. while ((hp = readhdr(ar)) != nil) {
  817. longname = name(hp);
  818. if (match(longname, argv))
  819. extract1(ar, hp, longname);
  820. else
  821. skip(ar, hp, longname);
  822. }
  823. if (comp)
  824. return pushclose(&ps);
  825. if (ar > Stderr)
  826. close(ar);
  827. return nil;
  828. }
  829. void
  830. main(int argc, char *argv[])
  831. {
  832. int errflg = 0;
  833. char *ret = nil;
  834. quotefmtinstall();
  835. fmtinstall('M', dirmodefmt);
  836. TARGBEGIN {
  837. case 'c':
  838. docreate++;
  839. verb = Replace;
  840. break;
  841. case 'f':
  842. usefile = EARGF(usage());
  843. break;
  844. case 'g':
  845. argid = strtoul(EARGF(usage()), 0, 0);
  846. break;
  847. case 'k':
  848. keepexisting++;
  849. break;
  850. case 'm': /* compatibility */
  851. settime = 0;
  852. break;
  853. case 'p':
  854. posix++;
  855. break;
  856. case 'P':
  857. posix = 0;
  858. break;
  859. case 'r':
  860. verb = Replace;
  861. break;
  862. case 'R':
  863. relative = 0;
  864. break;
  865. case 't':
  866. verb = Toc;
  867. break;
  868. case 'T':
  869. settime++;
  870. break;
  871. case 'u':
  872. aruid = strtoul(EARGF(usage()), 0, 0);
  873. break;
  874. case 'v':
  875. verbose++;
  876. break;
  877. case 'x':
  878. verb = Xtract;
  879. break;
  880. case 'z':
  881. docompress++;
  882. break;
  883. case '-':
  884. break;
  885. default:
  886. fprint(2, "tar: unknown letter %C\n", TARGC());
  887. errflg++;
  888. break;
  889. } TARGEND
  890. if (argc < 0 || errflg)
  891. usage();
  892. initblks();
  893. switch (verb) {
  894. case Toc:
  895. case Xtract:
  896. ret = extract(argv);
  897. break;
  898. case Replace:
  899. if (getwd(origdir, sizeof origdir) == nil)
  900. strcpy(origdir, "/tmp");
  901. ret = replace(argv);
  902. chdir(origdir); /* for profiling */
  903. break;
  904. default:
  905. usage();
  906. break;
  907. }
  908. exits(ret);
  909. }