tarfs.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * File system for tar archives (read-only)
  11. */
  12. #include <u.h>
  13. #include <libc.h>
  14. #include <auth.h>
  15. #include <fcall.h>
  16. #include "tapefs.h"
  17. /* fundamental constants */
  18. enum {
  19. Tblock = 512,
  20. Namsiz = 100,
  21. Maxpfx = 155, /* from POSIX */
  22. Maxname = Namsiz + 1 + Maxpfx,
  23. Binsize = 0x80, /* flag in size[0], from gnu: positive binary size */
  24. Binnegsz = 0xff, /* flag in size[0]: negative binary size */
  25. };
  26. /* POSIX link flags */
  27. enum {
  28. LF_PLAIN1 = '\0',
  29. LF_PLAIN2 = '0',
  30. LF_LINK = '1',
  31. LF_SYMLINK1 = '2',
  32. LF_SYMLINK2 = 's', /* 4BSD used this */
  33. LF_CHR = '3',
  34. LF_BLK = '4',
  35. LF_DIR = '5',
  36. LF_FIFO = '6',
  37. LF_CONTIG = '7',
  38. /* 'A' - 'Z' are reserved for custom implementations */
  39. };
  40. typedef union {
  41. char dummy[Tblock];
  42. char tbuf[Maxbuf];
  43. struct Header {
  44. char name[Namsiz];
  45. char mode[8];
  46. char uid[8];
  47. char gid[8];
  48. char size[12];
  49. char mtime[12];
  50. char chksum[8];
  51. char linkflag;
  52. char linkname[Namsiz];
  53. /* rest are defined by POSIX's ustar format; see p1003.2b */
  54. char magic[6]; /* "ustar" */
  55. char version[2];
  56. char uname[32];
  57. char gname[32];
  58. char devmajor[8];
  59. char devminor[8];
  60. char prefix[Maxpfx]; /* if non-null, path= prefix "/" name */
  61. };
  62. } Hdr;
  63. Hdr dblock;
  64. int tapefile;
  65. int checksum(void);
  66. static int
  67. isustar(Hdr *hp)
  68. {
  69. return strcmp(hp->magic, "ustar") == 0;
  70. }
  71. /*
  72. * s is at most n bytes long, but need not be NUL-terminated.
  73. * if shorter than n bytes, all bytes after the first NUL must also
  74. * be NUL.
  75. */
  76. static int
  77. strnlen(char *s, int n)
  78. {
  79. return s[n - 1] != '\0'? n: strlen(s);
  80. }
  81. /* set fullname from header */
  82. static char *
  83. tarname(Hdr *hp)
  84. {
  85. int pfxlen, namlen;
  86. static char fullname[Maxname+1];
  87. namlen = strnlen(hp->name, sizeof hp->name);
  88. if (hp->prefix[0] == '\0' || !isustar(hp)) { /* old-style name? */
  89. memmove(fullname, hp->name, namlen);
  90. fullname[namlen] = '\0';
  91. return fullname;
  92. }
  93. /* posix name: name is in two pieces */
  94. pfxlen = strnlen(hp->prefix, sizeof hp->prefix);
  95. memmove(fullname, hp->prefix, pfxlen);
  96. fullname[pfxlen] = '/';
  97. memmove(fullname + pfxlen + 1, hp->name, namlen);
  98. fullname[pfxlen + 1 + namlen] = '\0';
  99. return fullname;
  100. }
  101. void
  102. populate(char *name)
  103. {
  104. int32_t chksum, linkflg;
  105. int64_t blkno;
  106. char *fname;
  107. Fileinf f;
  108. Hdr *hp;
  109. tapefile = open(name, OREAD);
  110. if (tapefile < 0)
  111. error("Can't open argument file");
  112. replete = 1;
  113. hp = &dblock;
  114. for (blkno = 0; ; blkno++) {
  115. seek(tapefile, Tblock*blkno, 0);
  116. if (readn(tapefile, hp->dummy, sizeof hp->dummy) < sizeof hp->dummy)
  117. break;
  118. fname = tarname(hp);
  119. if (fname[0] == '\0')
  120. break;
  121. /* crack header */
  122. f.addr = blkno + 1;
  123. f.mode = strtoul(hp->mode, 0, 8);
  124. f.uid = strtoul(hp->uid, 0, 8);
  125. f.gid = strtoul(hp->gid, 0, 8);
  126. if((uint8_t)hp->size[0] == 0x80)
  127. f.size = b8byte(hp->size+3);
  128. else
  129. f.size = strtoull(hp->size, 0, 8);
  130. f.mdate = strtoul(hp->mtime, 0, 8);
  131. chksum = strtoul(hp->chksum, 0, 8);
  132. /* the mode test is ugly but sometimes necessary */
  133. if (hp->linkflag == LF_DIR || (f.mode&0170000) == 040000 ||
  134. strrchr(fname, '\0')[-1] == '/'){
  135. f.mode |= DMDIR;
  136. f.size = 0;
  137. }
  138. f.mode &= DMDIR | 0777;
  139. /* make file name safe, canonical and free of . and .. */
  140. while (fname[0] == '/') /* don't allow absolute paths */
  141. ++fname;
  142. cleanname(fname);
  143. while (strncmp(fname, "../", 3) == 0)
  144. fname += 3;
  145. /* reject links */
  146. linkflg = hp->linkflag == LF_SYMLINK1 ||
  147. hp->linkflag == LF_SYMLINK2 || hp->linkflag == LF_LINK;
  148. if (chksum != checksum()){
  149. fprint(2, "%s: bad checksum on %.28s at offset %lld\n",
  150. argv0, fname, Tblock*blkno);
  151. exits("checksum");
  152. }
  153. if (linkflg) {
  154. /*fprint(2, "link %s->%s skipped\n", fname, hp->linkname);*/
  155. f.size = 0;
  156. } else {
  157. /* accept this file */
  158. f.name = fname;
  159. if (f.name[0] == '\0')
  160. fprint(2, "%s: null name skipped\n", argv0);
  161. else
  162. poppath(f, 1);
  163. blkno += (f.size + Tblock - 1)/Tblock;
  164. }
  165. }
  166. }
  167. void
  168. dotrunc(Ram *r)
  169. {
  170. USED(r);
  171. }
  172. void
  173. docreate(Ram *r)
  174. {
  175. USED(r);
  176. }
  177. char *
  178. doread(Ram *r, int64_t off, int32_t cnt)
  179. {
  180. int n;
  181. seek(tapefile, Tblock*r->addr + off, 0);
  182. if (cnt > sizeof dblock.tbuf)
  183. error("read too big");
  184. n = readn(tapefile, dblock.tbuf, cnt);
  185. if (n != cnt)
  186. memset(dblock.tbuf + n, 0, cnt - n);
  187. return dblock.tbuf;
  188. }
  189. void
  190. popdir(Ram *r)
  191. {
  192. USED(r);
  193. }
  194. void
  195. dowrite(Ram *r, char *buf, int32_t off, int32_t cnt)
  196. {
  197. USED(r); USED(buf); USED(off); USED(cnt);
  198. }
  199. int
  200. dopermw(Ram *r)
  201. {
  202. USED(r);
  203. return 0;
  204. }
  205. int
  206. checksum(void)
  207. {
  208. int i, n;
  209. uint8_t *cp;
  210. memset(dblock.chksum, ' ', sizeof dblock.chksum);
  211. cp = (uint8_t *)dblock.dummy;
  212. i = 0;
  213. for (n = Tblock; n-- > 0; )
  214. i += *cp++;
  215. return i;
  216. }