tar.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  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) {
  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. endtar(void)
  348. {
  349. if (dblock.dbuf.name[0] == '\0') {
  350. backtar();
  351. return(1);
  352. }
  353. else
  354. return(0);
  355. }
  356. void
  357. getdir(void)
  358. {
  359. Dir *sp;
  360. readtar((char*)&dblock);
  361. if (dblock.dbuf.name[0] == '\0')
  362. return;
  363. if(stbuf == nil){
  364. stbuf = malloc(sizeof(Dir));
  365. if(stbuf == nil)
  366. sysfatal("out of memory: %r");
  367. }
  368. sp = stbuf;
  369. sp->mode = strtol(dblock.dbuf.mode, 0, 8);
  370. sp->uid = "adm";
  371. sp->gid = "adm";
  372. sp->length = strtol(dblock.dbuf.size, 0, 8);
  373. sp->mtime = strtol(dblock.dbuf.mtime, 0, 8);
  374. chksum = strtol(dblock.dbuf.chksum, 0, 8);
  375. if (chksum != checksum())
  376. sysfatal("header checksum error");
  377. sp->qid.type = 0;
  378. ustar = isustar(&dblock.dbuf);
  379. getfullname(&dblock.dbuf);
  380. /* the mode test is ugly but sometimes necessary */
  381. if (dblock.dbuf.linkflag == LF_DIR || (sp->mode&0170000) == 040000 ||
  382. strrchr(fullname, '\0')[-1] == '/') {
  383. sp->qid.type |= QTDIR;
  384. sp->mode |= DMDIR;
  385. }
  386. }
  387. void
  388. passtar(void)
  389. {
  390. long blocks;
  391. char buf[TBLOCK];
  392. switch (dblock.dbuf.linkflag) {
  393. case LF_LINK:
  394. case LF_SYMLINK1:
  395. case LF_SYMLINK2:
  396. case LF_FIFO:
  397. return;
  398. }
  399. blocks = stbuf->length;
  400. blocks += TBLOCK-1;
  401. blocks /= TBLOCK;
  402. while (blocks-- > 0)
  403. readtar(buf);
  404. }
  405. void
  406. putfile(char *dir, char *longname, char *sname)
  407. {
  408. int infile;
  409. long blocks;
  410. char buf[TBLOCK];
  411. char curdir[4096];
  412. char shortname[4096];
  413. char *cp;
  414. Dir *db;
  415. int i, n;
  416. if(strlen(sname) > sizeof shortname - 3){
  417. fprint(2, "tar: %s: name too long (max %d)\n", sname, sizeof shortname - 3);
  418. return;
  419. }
  420. snprint(shortname, sizeof shortname, "./%s", sname);
  421. infile = open(shortname, OREAD);
  422. if (infile < 0) {
  423. fprint(2, "tar: %s: cannot open file - %r\n", longname);
  424. return;
  425. }
  426. if(stbuf != nil)
  427. free(stbuf);
  428. stbuf = dirfstat(infile);
  429. if (stbuf->qid.type & QTDIR) {
  430. /* Directory */
  431. for (i = 0, cp = buf; *cp++ = longname[i++];);
  432. *--cp = '/';
  433. *++cp = 0;
  434. stbuf->length = 0;
  435. tomodes(stbuf);
  436. if (putfullname(&dblock.dbuf, buf) < 0) {
  437. close(infile);
  438. return; /* putfullname already complained */
  439. }
  440. dblock.dbuf.linkflag = LF_DIR;
  441. sprint(dblock.dbuf.chksum, "%6o", checksum());
  442. writetar( (char *) &dblock);
  443. if (chdir(shortname) < 0) {
  444. fprint(2, "tar: can't cd to %s: %r\n", shortname);
  445. snprint(curdir, sizeof(curdir), "cd %s", shortname);
  446. exits(curdir);
  447. }
  448. sprint(curdir, "%s/%s", dir, sname);
  449. while ((n = dirread(infile, &db)) > 0) {
  450. for(i = 0; i < n; i++){
  451. strncpy(cp, db[i].name, sizeof buf - (cp-buf));
  452. putfile(curdir, buf, db[i].name);
  453. }
  454. free(db);
  455. }
  456. close(infile);
  457. if (chdir(dir) < 0 && chdir("..") < 0) {
  458. fprint(2, "tar: can't cd to ..(%s): %r\n", dir);
  459. snprint(curdir, sizeof(curdir), "cd ..(%s)", dir);
  460. exits(curdir);
  461. }
  462. return;
  463. }
  464. /* plain file; write header block first */
  465. tomodes(stbuf);
  466. if (putfullname(&dblock.dbuf, longname) < 0) {
  467. close(infile);
  468. return; /* putfullname already complained */
  469. }
  470. blocks = (stbuf->length + (TBLOCK-1)) / TBLOCK;
  471. if (vflag) {
  472. fprint(2, "a %s ", longname);
  473. fprint(2, "%ld blocks\n", blocks);
  474. }
  475. dblock.dbuf.linkflag = LF_PLAIN1;
  476. sprint(dblock.dbuf.chksum, "%6o", checksum());
  477. writetar( (char *) &dblock);
  478. /* then copy contents */
  479. while ((i = readn(infile, buf, TBLOCK)) > 0 && blocks > 0) {
  480. writetar(buf);
  481. blocks--;
  482. }
  483. close(infile);
  484. if (blocks != 0 || i != 0)
  485. fprint(2, "%s: file changed size\n", longname);
  486. while (blocks-- > 0)
  487. putempty();
  488. }
  489. void
  490. doxtract(char **argv)
  491. {
  492. Dir null;
  493. int wrsize;
  494. long blocks, bytes;
  495. char buf[TBLOCK], outname[Maxname+3+1];
  496. char **cp;
  497. int ofile;
  498. for (;;) {
  499. getdir();
  500. if (endtar())
  501. break;
  502. if (*argv == 0)
  503. goto gotit;
  504. for (cp = argv; *cp; cp++)
  505. if (prefix(*cp, fullname))
  506. goto gotit;
  507. passtar();
  508. continue;
  509. gotit:
  510. if(checkdir(fullname, stbuf->mode, &stbuf->qid))
  511. continue;
  512. if (dblock.dbuf.linkflag == LF_LINK) {
  513. fprint(2, "tar: can't link %s %s\n",
  514. dblock.dbuf.linkname, fullname);
  515. remove(fullname);
  516. continue;
  517. }
  518. if (dblock.dbuf.linkflag == LF_SYMLINK1 ||
  519. dblock.dbuf.linkflag == LF_SYMLINK2) {
  520. fprint(2, "tar: %s: cannot symlink\n", fullname);
  521. continue;
  522. }
  523. if(fullname[0] != '/' || Rflag)
  524. sprint(outname, "./%s", fullname);
  525. else
  526. strcpy(outname, fullname);
  527. if ((ofile = create(outname, OWRITE, stbuf->mode & 0777)) < 0) {
  528. fprint(2, "tar: %s - cannot create: %r\n", outname);
  529. passtar();
  530. continue;
  531. }
  532. blocks = ((bytes = stbuf->length) + TBLOCK-1)/TBLOCK;
  533. if (vflag)
  534. fprint(2, "x %s, %ld bytes\n", fullname, bytes);
  535. while (blocks-- > 0) {
  536. readtar(buf);
  537. wrsize = (bytes > TBLOCK? TBLOCK: bytes);
  538. if (write(ofile, buf, wrsize) != wrsize) {
  539. fprint(2,
  540. "tar: %s: HELP - extract write error: %r\n",
  541. fullname);
  542. exits("extract write");
  543. }
  544. bytes -= TBLOCK;
  545. }
  546. if(Tflag){
  547. nulldir(&null);
  548. null.mtime = stbuf->mtime;
  549. dirfwstat(ofile, &null);
  550. }
  551. close(ofile);
  552. }
  553. }
  554. void
  555. dotable(void)
  556. {
  557. for (;;) {
  558. getdir();
  559. if (endtar())
  560. break;
  561. if (vflag)
  562. longt(stbuf);
  563. Bprint(&bout, "%s", fullname);
  564. if (dblock.dbuf.linkflag == '1')
  565. Bprint(&bout, " linked to %s", dblock.dbuf.linkname);
  566. if (dblock.dbuf.linkflag == 's')
  567. Bprint(&bout, " -> %s", dblock.dbuf.linkname);
  568. Bprint(&bout, "\n");
  569. passtar();
  570. }
  571. }
  572. void
  573. putempty(void)
  574. {
  575. char buf[TBLOCK];
  576. memset(buf, 0, TBLOCK);
  577. writetar(buf);
  578. }
  579. void
  580. longt(Dir *st)
  581. {
  582. char *cp;
  583. Bprint(&bout, "%M %4d/%1d ", st->mode, 0, 0); /* 0/0 uid/gid */
  584. Bprint(&bout, "%8lld", st->length);
  585. cp = ctime(st->mtime);
  586. Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+24);
  587. }
  588. int
  589. checkdir(char *name, int mode, Qid *qid)
  590. {
  591. char *cp;
  592. int f;
  593. Dir *d, null;
  594. if(Rflag && *name == '/')
  595. name++;
  596. cp = name;
  597. if(*cp == '/')
  598. cp++;
  599. for (; *cp; cp++) {
  600. if (*cp == '/') {
  601. *cp = '\0';
  602. if (access(name, 0) < 0) {
  603. f = create(name, OREAD, DMDIR + 0775L);
  604. if(f < 0)
  605. fprint(2, "tar: mkdir %s failed: %r\n", name);
  606. close(f);
  607. }
  608. *cp = '/';
  609. }
  610. }
  611. /* if this is a directory, chmod it to the mode in the tar plus 700 */
  612. if(cp[-1] == '/' || (qid->type&QTDIR)){
  613. if((d=dirstat(name)) != 0){
  614. nulldir(&null);
  615. null.mode = DMDIR | (mode & 0777) | 0700;
  616. dirwstat(name, &null);
  617. free(d);
  618. }
  619. return 1;
  620. } else
  621. return 0;
  622. }
  623. void
  624. tomodes(Dir *sp)
  625. {
  626. memset(dblock.dummy, 0, sizeof(dblock.dummy));
  627. sprint(dblock.dbuf.mode, "%6lo ", sp->mode & 0777);
  628. sprint(dblock.dbuf.uid, "%6o ", uflag);
  629. sprint(dblock.dbuf.gid, "%6o ", gflag);
  630. sprint(dblock.dbuf.size, "%11llo ", sp->length);
  631. sprint(dblock.dbuf.mtime, "%11lo ", sp->mtime);
  632. if (posix) {
  633. setustar(&dblock.dbuf);
  634. strncpy(dblock.dbuf.uname, sp->uid, sizeof dblock.dbuf.uname);
  635. strncpy(dblock.dbuf.gname, sp->gid, sizeof dblock.dbuf.gname);
  636. }
  637. }
  638. int
  639. checksum(void)
  640. {
  641. int i;
  642. char *cp;
  643. for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
  644. *cp = ' ';
  645. i = 0;
  646. for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
  647. i += *cp & 0xff;
  648. return(i);
  649. }
  650. int
  651. prefix(char *s1, char *s2)
  652. {
  653. while (*s1)
  654. if (*s1++ != *s2++)
  655. return(0);
  656. if (*s2)
  657. return(*s2 == '/');
  658. return(1);
  659. }
  660. int
  661. readtar(char *buffer)
  662. {
  663. int i;
  664. if (recno >= nblock || first == 0) {
  665. if ((i = readn(mt, tbuf, TBLOCK*nblock)) <= 0) {
  666. fprint(2, "tar: archive read error: %r\n");
  667. exits("archive read");
  668. }
  669. if (first == 0) {
  670. if ((i % TBLOCK) != 0) {
  671. fprint(2, "tar: archive blocksize error: %r\n");
  672. exits("blocksize");
  673. }
  674. i /= TBLOCK;
  675. if (i != nblock) {
  676. fprint(2, "tar: blocksize = %d\n", i);
  677. nblock = i;
  678. }
  679. }
  680. recno = 0;
  681. }
  682. first = 1;
  683. memmove(buffer, &tbuf[recno++], TBLOCK);
  684. return(TBLOCK);
  685. }
  686. int
  687. writetar(char *buffer)
  688. {
  689. first = 1;
  690. if (recno >= nblock) {
  691. if (write(mt, tbuf, TBLOCK*nblock) != TBLOCK*nblock) {
  692. fprint(2, "tar: archive write error: %r\n");
  693. exits("write");
  694. }
  695. recno = 0;
  696. }
  697. memmove(&tbuf[recno++], buffer, TBLOCK);
  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. return(TBLOCK);
  706. }
  707. /*
  708. * backup over last tar block
  709. */
  710. void
  711. backtar(void)
  712. {
  713. seek(mt, -TBLOCK*nblock, 1);
  714. recno--;
  715. }
  716. void
  717. flushtar(void)
  718. {
  719. write(mt, tbuf, TBLOCK*nblock);
  720. }