tar.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #include <bio.h>
  6. #define TBLOCK 512
  7. #define NBLOCK 40 /* maximum blocksize */
  8. #define DBLOCK 20 /* default blocksize */
  9. #define NAMSIZ 100
  10. enum {
  11. Maxpfx = 155, /* from POSIX */
  12. Maxname = NAMSIZ + 1 + Maxpfx,
  13. };
  14. /* POSIX link flags */
  15. enum {
  16. LF_PLAIN1 = '\0',
  17. LF_PLAIN2 = '0',
  18. LF_LINK = '1',
  19. LF_SYMLINK1 = '2',
  20. LF_SYMLINK2 = 's',
  21. LF_CHR = '3',
  22. LF_BLK = '4',
  23. LF_DIR = '5',
  24. LF_FIFO = '6',
  25. LF_CONTIG = '7',
  26. /* 'A' - 'Z' are reserved for custom implementations */
  27. };
  28. #define islink(lf) (isreallink(lf) || issymlink(lf))
  29. #define isreallink(lf) ((lf) == LF_LINK)
  30. #define issymlink(lf) ((lf) == LF_SYMLINK1 || (lf) == LF_SYMLINK2)
  31. union hblock
  32. {
  33. char dummy[TBLOCK];
  34. struct header
  35. {
  36. char name[NAMSIZ];
  37. char mode[8];
  38. char uid[8];
  39. char gid[8];
  40. char size[12];
  41. char mtime[12];
  42. char chksum[8];
  43. char linkflag;
  44. char linkname[NAMSIZ];
  45. /* rest are defined by POSIX's ustar format; see p1003.2b */
  46. char magic[6]; /* "ustar" */
  47. char version[2];
  48. char uname[32];
  49. char gname[32];
  50. char devmajor[8];
  51. char devminor[8];
  52. char prefix[155]; /* if non-null, path = prefix "/" name */
  53. } dbuf;
  54. } dblock, tbuf[NBLOCK];
  55. Dir *stbuf;
  56. Biobuf bout;
  57. static int ustar; /* flag: tape block just read is ustar format */
  58. static char *fullname; /* if non-nil, prefix "/" name */
  59. int rflag, xflag, vflag, tflag, mt, cflag, fflag, Tflag, Rflag;
  60. int uflag, gflag;
  61. static int posix; /* flag: we're writing ustar format archive */
  62. int chksum, recno, first;
  63. int nblock = DBLOCK;
  64. void usage(void);
  65. void dorep(char **);
  66. int endtar(void);
  67. void getdir(void);
  68. void passtar(void);
  69. void putfile(char*, char *, char *);
  70. void doxtract(char **);
  71. void dotable(void);
  72. void putempty(void);
  73. void longt(Dir *);
  74. int checkdir(char *, int, Qid*);
  75. void tomodes(Dir *);
  76. int checksum(void);
  77. int checkupdate(char *);
  78. int prefix(char *, char *);
  79. int readtar(char *);
  80. int writetar(char *);
  81. void backtar(void);
  82. void flushtar(void);
  83. void affix(int, char *);
  84. int volprompt(void);
  85. static int
  86. isustar(struct header *hp)
  87. {
  88. return strcmp(hp->magic, "ustar") == 0;
  89. }
  90. static void
  91. setustar(struct header *hp)
  92. {
  93. strncpy(hp->magic, "ustar", sizeof hp->magic);
  94. strncpy(hp->version, "00", sizeof hp->version);
  95. }
  96. /*
  97. * s is at most n bytes long, but need not be NUL-terminated.
  98. * if shorter than n bytes, all bytes after the first NUL must also
  99. * be NUL.
  100. */
  101. static int
  102. strnlen(char *s, int n)
  103. {
  104. if (s[n - 1] != '\0')
  105. return n;
  106. else
  107. return strlen(s);
  108. }
  109. /* set fullname from header; called from getdir() */
  110. static void
  111. getfullname(struct header *hp)
  112. {
  113. int pfxlen, namlen;
  114. if (fullname != nil)
  115. free(fullname);
  116. namlen = strnlen(hp->name, sizeof hp->name);
  117. if (hp->prefix[0] == '\0' || !ustar) { /* old-style name? */
  118. fullname = malloc(namlen + 1);
  119. if (fullname == nil)
  120. sysfatal("out of memory: %r");
  121. memmove(fullname, hp->name, namlen);
  122. fullname[namlen] = '\0';
  123. return;
  124. }
  125. pfxlen = strnlen(hp->prefix, sizeof hp->prefix);
  126. fullname = malloc(pfxlen + 1 + namlen + 1);
  127. if (fullname == nil)
  128. sysfatal("out of memory: %r");
  129. memmove(fullname, hp->prefix, pfxlen);
  130. fullname[pfxlen] = '/';
  131. memmove(fullname + pfxlen + 1, hp->name, namlen);
  132. fullname[pfxlen + 1 + namlen] = '\0';
  133. }
  134. /*
  135. * if name is longer than NAMSIZ bytes, try to split it at a slash and fit the
  136. * pieces into hp->prefix and hp->name.
  137. */
  138. static int
  139. putfullname(struct header *hp, char *name)
  140. {
  141. int namlen, pfxlen;
  142. char *sl, *osl;
  143. namlen = strlen(name);
  144. if (namlen <= NAMSIZ) {
  145. strncpy(hp->name, name, NAMSIZ);
  146. hp->prefix[0] = '\0'; /* ustar paranoia */
  147. return 0;
  148. }
  149. if (!posix || namlen > NAMSIZ + 1 + sizeof hp->prefix) {
  150. fprint(2, "tar: name too long for tar header: %s\n", name);
  151. return -1;
  152. }
  153. /*
  154. * try various splits until one results in pieces that fit into the
  155. * appropriate fields of the header. look for slashes from right
  156. * to left, in the hopes of putting the largest part of the name into
  157. * hp->prefix, which is larger than hp->name.
  158. */
  159. sl = strrchr(name, '/');
  160. while (sl != nil) {
  161. pfxlen = sl - name;
  162. if (pfxlen <= sizeof hp->prefix && namlen-1 - pfxlen <= NAMSIZ)
  163. break;
  164. osl = sl;
  165. *osl = '\0';
  166. sl = strrchr(name, '/');
  167. *osl = '/';
  168. }
  169. if (sl == nil) {
  170. fprint(2, "tar: name can't be split to fit tar header: %s\n",
  171. name);
  172. return -1;
  173. }
  174. *sl = '\0';
  175. strncpy(hp->prefix, name, sizeof hp->prefix);
  176. *sl = '/';
  177. strncpy(hp->name, sl + 1, sizeof hp->name);
  178. return 0;
  179. }
  180. void
  181. main(int argc, char **argv)
  182. {
  183. char *usefile;
  184. char *cp, *ap;
  185. if (argc < 2)
  186. usage();
  187. Binit(&bout, 1, OWRITE);
  188. usefile = 0;
  189. argv[argc] = 0;
  190. argv++;
  191. for (cp = *argv++; *cp; cp++)
  192. switch(*cp) {
  193. case 'f':
  194. usefile = *argv++;
  195. if(!usefile)
  196. usage();
  197. fflag++;
  198. break;
  199. case 'u':
  200. ap = *argv++;
  201. if(!ap)
  202. usage();
  203. uflag = strtoul(ap, 0, 0);
  204. break;
  205. case 'g':
  206. ap = *argv++;
  207. if(!ap)
  208. usage();
  209. gflag = strtoul(ap, 0, 0);
  210. break;
  211. case 'c':
  212. cflag++;
  213. rflag++;
  214. break;
  215. case 'p':
  216. posix++;
  217. break;
  218. case 'r':
  219. rflag++;
  220. break;
  221. case 'v':
  222. vflag++;
  223. break;
  224. case 'x':
  225. xflag++;
  226. break;
  227. case 'T':
  228. Tflag++;
  229. break;
  230. case 't':
  231. tflag++;
  232. break;
  233. case 'R':
  234. Rflag++;
  235. break;
  236. case '-':
  237. break;
  238. default:
  239. fprint(2, "tar: %c: unknown option\n", *cp);
  240. usage();
  241. }
  242. fmtinstall('M', dirmodefmt);
  243. if (rflag) {
  244. if (!usefile) {
  245. if (cflag == 0) {
  246. fprint(2, "tar: can only create standard output archives\n");
  247. exits("arg error");
  248. }
  249. mt = dup(1, -1);
  250. nblock = 1;
  251. }
  252. else if ((mt = open(usefile, ORDWR)) < 0) {
  253. if (cflag == 0 || (mt = create(usefile, OWRITE, 0666)) < 0) {
  254. fprint(2, "tar: cannot open %s: %r\n", usefile);
  255. exits("open");
  256. }
  257. }
  258. dorep(argv);
  259. }
  260. else if (xflag) {
  261. if (!usefile) {
  262. mt = dup(0, -1);
  263. nblock = 1;
  264. }
  265. else if ((mt = open(usefile, OREAD)) < 0) {
  266. fprint(2, "tar: cannot open %s: %r\n", usefile);
  267. exits("open");
  268. }
  269. doxtract(argv);
  270. }
  271. else if (tflag) {
  272. if (!usefile) {
  273. mt = dup(0, -1);
  274. nblock = 1;
  275. }
  276. else if ((mt = open(usefile, OREAD)) < 0) {
  277. fprint(2, "tar: cannot open %s: %r\n", usefile);
  278. exits("open");
  279. }
  280. dotable();
  281. }
  282. else
  283. usage();
  284. exits(0);
  285. }
  286. void
  287. usage(void)
  288. {
  289. fprint(2, "tar: usage tar {txrc}[Rvf] [tarfile] file1 file2...\n");
  290. exits("usage");
  291. }
  292. void
  293. dorep(char **argv)
  294. {
  295. char cwdbuf[2048], *cwd, thisdir[2048];
  296. char *cp, *cp2;
  297. int cd;
  298. if (getwd(cwdbuf, sizeof(cwdbuf)) == 0) {
  299. fprint(2, "tar: can't find current directory: %r\n");
  300. exits("cwd");
  301. }
  302. cwd = cwdbuf;
  303. if (!cflag) {
  304. getdir();
  305. do {
  306. passtar();
  307. getdir();
  308. } while (!endtar());
  309. }
  310. while (*argv) {
  311. cp2 = *argv;
  312. if (!strcmp(cp2, "-C") && argv[1]) {
  313. argv++;
  314. if (chdir(*argv) < 0)
  315. perror(*argv);
  316. cwd = *argv;
  317. argv++;
  318. continue;
  319. }
  320. cd = 0;
  321. for (cp = *argv; *cp; cp++)
  322. if (*cp == '/')
  323. cp2 = cp;
  324. if (cp2 != *argv) {
  325. *cp2 = '\0';
  326. chdir(*argv);
  327. if(**argv == '/')
  328. strncpy(thisdir, *argv, sizeof(thisdir));
  329. else
  330. snprint(thisdir, sizeof(thisdir), "%s/%s", cwd, *argv);
  331. *cp2 = '/';
  332. cp2++;
  333. cd = 1;
  334. } else
  335. strncpy(thisdir, cwd, sizeof(thisdir));
  336. putfile(thisdir, *argv++, cp2);
  337. if(cd && chdir(cwd) < 0) {
  338. fprint(2, "tar: can't cd back to %s: %r\n", cwd);
  339. exits("cwd");
  340. }
  341. }
  342. putempty();
  343. putempty();
  344. flushtar();
  345. }
  346. int
  347. isendtar(void)
  348. {
  349. return fullname[0] == '\0';
  350. }
  351. int
  352. endtar(void)
  353. {
  354. if (isendtar()) {
  355. backtar();
  356. return(1);
  357. }
  358. else
  359. return(0);
  360. }
  361. void
  362. getdir(void)
  363. {
  364. Dir *sp;
  365. readtar((char*)&dblock);
  366. ustar = isustar(&dblock.dbuf);
  367. getfullname(&dblock.dbuf);
  368. if (isendtar())
  369. return;
  370. if(stbuf == nil){
  371. stbuf = malloc(sizeof(Dir));
  372. if(stbuf == nil)
  373. sysfatal("out of memory: %r");
  374. }
  375. sp = stbuf;
  376. sp->mode = strtol(dblock.dbuf.mode, 0, 8);
  377. sp->uid = "adm";
  378. sp->gid = "adm";
  379. sp->length = strtol(dblock.dbuf.size, 0, 8);
  380. sp->mtime = strtol(dblock.dbuf.mtime, 0, 8);
  381. chksum = strtol(dblock.dbuf.chksum, 0, 8);
  382. if (chksum != checksum())
  383. sysfatal("header checksum error");
  384. sp->qid.type = 0;
  385. /* the mode test is ugly but sometimes necessary */
  386. if (dblock.dbuf.linkflag == LF_DIR || (sp->mode&0170000) == 040000 ||
  387. strrchr(fullname, '\0')[-1] == '/') {
  388. sp->qid.type |= QTDIR;
  389. sp->mode |= DMDIR;
  390. }
  391. }
  392. void
  393. passtar(void)
  394. {
  395. long blocks;
  396. char buf[TBLOCK];
  397. switch (dblock.dbuf.linkflag) {
  398. case LF_LINK:
  399. case LF_SYMLINK1:
  400. case LF_SYMLINK2:
  401. case LF_FIFO:
  402. return;
  403. }
  404. blocks = stbuf->length;
  405. blocks += TBLOCK-1;
  406. blocks /= TBLOCK;
  407. while (blocks-- > 0)
  408. readtar(buf);
  409. }
  410. void
  411. putfile(char *dir, char *longname, char *sname)
  412. {
  413. int infile;
  414. long blocks;
  415. char buf[TBLOCK];
  416. char curdir[4096];
  417. char shortname[4096];
  418. char *cp;
  419. Dir *db;
  420. int i, n;
  421. if(strlen(sname) > sizeof shortname - 3){
  422. fprint(2, "tar: %s: name too long (max %d)\n", sname, sizeof shortname - 3);
  423. return;
  424. }
  425. snprint(shortname, sizeof shortname, "./%s", sname);
  426. infile = open(shortname, OREAD);
  427. if (infile < 0) {
  428. fprint(2, "tar: %s: cannot open file - %r\n", longname);
  429. return;
  430. }
  431. if(stbuf != nil)
  432. free(stbuf);
  433. stbuf = dirfstat(infile);
  434. if (stbuf->qid.type & QTDIR) {
  435. /* Directory */
  436. for (i = 0, cp = buf; *cp++ = longname[i++];)
  437. ;
  438. *--cp = '/';
  439. *++cp = 0;
  440. stbuf->length = 0;
  441. tomodes(stbuf);
  442. if (putfullname(&dblock.dbuf, buf) < 0) {
  443. close(infile);
  444. return; /* putfullname already complained */
  445. }
  446. dblock.dbuf.linkflag = LF_DIR;
  447. sprint(dblock.dbuf.chksum, "%6o", checksum());
  448. writetar( (char *) &dblock);
  449. if (chdir(shortname) < 0) {
  450. fprint(2, "tar: can't cd to %s: %r\n", shortname);
  451. snprint(curdir, sizeof(curdir), "cd %s", shortname);
  452. exits(curdir);
  453. }
  454. sprint(curdir, "%s/%s", dir, sname);
  455. while ((n = dirread(infile, &db)) > 0) {
  456. for(i = 0; i < n; i++){
  457. strncpy(cp, db[i].name, sizeof buf - (cp-buf));
  458. putfile(curdir, buf, db[i].name);
  459. }
  460. free(db);
  461. }
  462. close(infile);
  463. if (chdir(dir) < 0 && chdir("..") < 0) {
  464. fprint(2, "tar: can't cd to ..(%s): %r\n", dir);
  465. snprint(curdir, sizeof(curdir), "cd ..(%s)", dir);
  466. exits(curdir);
  467. }
  468. return;
  469. }
  470. /* plain file; write header block first */
  471. tomodes(stbuf);
  472. if (putfullname(&dblock.dbuf, longname) < 0) {
  473. close(infile);
  474. return; /* putfullname already complained */
  475. }
  476. blocks = (stbuf->length + (TBLOCK-1)) / TBLOCK;
  477. if (vflag) {
  478. fprint(2, "a %s ", longname);
  479. fprint(2, "%ld blocks\n", blocks);
  480. }
  481. dblock.dbuf.linkflag = LF_PLAIN1;
  482. sprint(dblock.dbuf.chksum, "%6o", checksum());
  483. writetar( (char *) &dblock);
  484. /* then copy contents */
  485. while ((i = readn(infile, buf, TBLOCK)) > 0 && blocks > 0) {
  486. writetar(buf);
  487. blocks--;
  488. }
  489. close(infile);
  490. if (blocks != 0 || i != 0)
  491. fprint(2, "%s: file changed size\n", longname);
  492. while (blocks-- > 0)
  493. putempty();
  494. }
  495. void
  496. doxtract(char **argv)
  497. {
  498. Dir null;
  499. int wrsize;
  500. long blocks, bytes;
  501. char buf[TBLOCK], outname[Maxname+3+1];
  502. char **cp;
  503. int ofile;
  504. for (;;) {
  505. getdir();
  506. if (endtar())
  507. break;
  508. if (*argv == 0)
  509. goto gotit;
  510. for (cp = argv; *cp; cp++)
  511. if (prefix(*cp, fullname))
  512. goto gotit;
  513. passtar();
  514. continue;
  515. gotit:
  516. if(checkdir(fullname, stbuf->mode, &stbuf->qid))
  517. continue;
  518. if (dblock.dbuf.linkflag == LF_LINK) {
  519. fprint(2, "tar: can't link %s %s\n",
  520. dblock.dbuf.linkname, fullname);
  521. remove(fullname);
  522. continue;
  523. }
  524. if (dblock.dbuf.linkflag == LF_SYMLINK1 ||
  525. dblock.dbuf.linkflag == LF_SYMLINK2) {
  526. fprint(2, "tar: %s: cannot symlink\n", fullname);
  527. continue;
  528. }
  529. if(fullname[0] != '/' || Rflag)
  530. sprint(outname, "./%s", fullname);
  531. else
  532. strcpy(outname, fullname);
  533. if ((ofile = create(outname, OWRITE, stbuf->mode & 0777)) < 0) {
  534. fprint(2, "tar: %s - cannot create: %r\n", outname);
  535. passtar();
  536. continue;
  537. }
  538. blocks = ((bytes = stbuf->length) + TBLOCK-1)/TBLOCK;
  539. if (vflag)
  540. fprint(2, "x %s, %ld bytes\n", fullname, bytes);
  541. while (blocks-- > 0) {
  542. readtar(buf);
  543. wrsize = (bytes > TBLOCK? TBLOCK: bytes);
  544. if (write(ofile, buf, wrsize) != wrsize) {
  545. fprint(2,
  546. "tar: %s: HELP - extract write error: %r\n",
  547. fullname);
  548. exits("extract write");
  549. }
  550. bytes -= TBLOCK;
  551. }
  552. if(Tflag){
  553. nulldir(&null);
  554. null.mtime = stbuf->mtime;
  555. dirfwstat(ofile, &null);
  556. }
  557. close(ofile);
  558. }
  559. }
  560. void
  561. dotable(void)
  562. {
  563. for (;;) {
  564. getdir();
  565. if (endtar())
  566. break;
  567. if (vflag)
  568. longt(stbuf);
  569. Bprint(&bout, "%s", fullname);
  570. if (dblock.dbuf.linkflag == '1')
  571. Bprint(&bout, " linked to %s", dblock.dbuf.linkname);
  572. if (dblock.dbuf.linkflag == 's')
  573. Bprint(&bout, " -> %s", dblock.dbuf.linkname);
  574. Bprint(&bout, "\n");
  575. passtar();
  576. }
  577. }
  578. void
  579. putempty(void)
  580. {
  581. char buf[TBLOCK];
  582. memset(buf, 0, TBLOCK);
  583. writetar(buf);
  584. }
  585. void
  586. longt(Dir *st)
  587. {
  588. char *cp;
  589. Bprint(&bout, "%M %4d/%1d ", st->mode, 0, 0); /* 0/0 uid/gid */
  590. Bprint(&bout, "%8lld", st->length);
  591. cp = ctime(st->mtime);
  592. Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+24);
  593. }
  594. int
  595. checkdir(char *name, int mode, Qid *qid)
  596. {
  597. char *cp;
  598. int f;
  599. Dir *d, null;
  600. if(Rflag && *name == '/')
  601. name++;
  602. cp = name;
  603. if(*cp == '/')
  604. cp++;
  605. for (; *cp; cp++) {
  606. if (*cp == '/') {
  607. *cp = '\0';
  608. if (access(name, 0) < 0) {
  609. f = create(name, OREAD, DMDIR + 0775L);
  610. if(f < 0)
  611. fprint(2, "tar: mkdir %s failed: %r\n", name);
  612. close(f);
  613. }
  614. *cp = '/';
  615. }
  616. }
  617. /* if this is a directory, chmod it to the mode in the tar plus 700 */
  618. if(cp[-1] == '/' || (qid->type&QTDIR)){
  619. if((d=dirstat(name)) != 0){
  620. nulldir(&null);
  621. null.mode = DMDIR | (mode & 0777) | 0700;
  622. dirwstat(name, &null);
  623. free(d);
  624. }
  625. return 1;
  626. } else
  627. return 0;
  628. }
  629. void
  630. tomodes(Dir *sp)
  631. {
  632. memset(dblock.dummy, 0, sizeof(dblock.dummy));
  633. sprint(dblock.dbuf.mode, "%6lo ", sp->mode & 0777);
  634. sprint(dblock.dbuf.uid, "%6o ", uflag);
  635. sprint(dblock.dbuf.gid, "%6o ", gflag);
  636. sprint(dblock.dbuf.size, "%11llo ", sp->length);
  637. sprint(dblock.dbuf.mtime, "%11lo ", sp->mtime);
  638. if (posix) {
  639. setustar(&dblock.dbuf);
  640. strncpy(dblock.dbuf.uname, sp->uid, sizeof dblock.dbuf.uname);
  641. strncpy(dblock.dbuf.gname, sp->gid, sizeof dblock.dbuf.gname);
  642. }
  643. }
  644. int
  645. checksum(void)
  646. {
  647. int i;
  648. char *cp;
  649. for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
  650. *cp = ' ';
  651. i = 0;
  652. for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
  653. i += *cp & 0xff;
  654. return(i);
  655. }
  656. int
  657. prefix(char *s1, char *s2)
  658. {
  659. while (*s1)
  660. if (*s1++ != *s2++)
  661. return(0);
  662. if (*s2)
  663. return(*s2 == '/');
  664. return(1);
  665. }
  666. int
  667. readtar(char *buffer)
  668. {
  669. int i;
  670. if (recno >= nblock || first == 0) {
  671. if ((i = readn(mt, tbuf, TBLOCK*nblock)) <= 0) {
  672. if (i == 0)
  673. werrstr("unexpected end of file");
  674. fprint(2, "tar: archive read error: %r\n");
  675. exits("archive read");
  676. }
  677. if (first == 0) {
  678. if ((i % TBLOCK) != 0) {
  679. fprint(2, "tar: archive blocksize error: %r\n");
  680. exits("blocksize");
  681. }
  682. i /= TBLOCK;
  683. if (i != nblock) {
  684. fprint(2, "tar: blocksize = %d\n", i);
  685. nblock = i;
  686. }
  687. }
  688. recno = 0;
  689. }
  690. first = 1;
  691. memmove(buffer, &tbuf[recno++], TBLOCK);
  692. return(TBLOCK);
  693. }
  694. int
  695. writetar(char *buffer)
  696. {
  697. first = 1;
  698. if (recno >= nblock) {
  699. if (write(mt, tbuf, TBLOCK*nblock) != TBLOCK*nblock) {
  700. fprint(2, "tar: archive write error: %r\n");
  701. exits("write");
  702. }
  703. recno = 0;
  704. }
  705. memmove(&tbuf[recno++], buffer, TBLOCK);
  706. if (recno >= nblock) {
  707. if (write(mt, tbuf, TBLOCK*nblock) != TBLOCK*nblock) {
  708. fprint(2, "tar: archive write error: %r\n");
  709. exits("write");
  710. }
  711. recno = 0;
  712. }
  713. return(TBLOCK);
  714. }
  715. /*
  716. * backup over last tar block
  717. */
  718. void
  719. backtar(void)
  720. {
  721. seek(mt, -TBLOCK*nblock, 1);
  722. recno--;
  723. }
  724. void
  725. flushtar(void)
  726. {
  727. write(mt, tbuf, TBLOCK*nblock);
  728. }