tarfs.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #include "tapefs.h"
  6. /*
  7. * File system for tar tapes (read-only)
  8. */
  9. #define TBLOCK 512
  10. #define NBLOCK 40 /* maximum blocksize */
  11. #define DBLOCK 20 /* default blocksize */
  12. #define TNAMSIZ 100
  13. union hblock {
  14. char dummy[TBLOCK];
  15. char tbuf[Maxbuf];
  16. struct header {
  17. char name[TNAMSIZ];
  18. char mode[8];
  19. char uid[8];
  20. char gid[8];
  21. char size[12];
  22. char mtime[12];
  23. char chksum[8];
  24. char linkflag;
  25. char linkname[TNAMSIZ];
  26. } dbuf;
  27. } dblock;
  28. int tapefile;
  29. int checksum(void);
  30. void
  31. populate(char *name)
  32. {
  33. long blkno, isabs, chksum, linkflg;
  34. Fileinf f;
  35. tapefile = open(name, OREAD);
  36. if (tapefile<0)
  37. error("Can't open argument file");
  38. replete = 1;
  39. for (blkno = 0;;) {
  40. seek(tapefile, TBLOCK*blkno, 0);
  41. if (read(tapefile, dblock.dummy, sizeof(dblock.dummy))<sizeof(dblock.dummy))
  42. break;
  43. if (dblock.dbuf.name[0]=='\0')
  44. break;
  45. f.addr = blkno+1;
  46. f.mode = strtoul(dblock.dbuf.mode, 0, 8);
  47. f.uid = strtoul(dblock.dbuf.uid, 0, 8);
  48. f.gid = strtoul(dblock.dbuf.gid, 0, 8);
  49. if((uchar)dblock.dbuf.size[0] == 0x80)
  50. f.size = b8byte(dblock.dbuf.size+3);
  51. else
  52. f.size = strtoull(dblock.dbuf.size, 0, 8);
  53. f.mdate = strtoul(dblock.dbuf.mtime, 0, 8);
  54. chksum = strtoul(dblock.dbuf.chksum, 0, 8);
  55. /* the mode test is ugly but sometimes necessary */
  56. if (dblock.dbuf.linkflag == '5'
  57. || (f.mode&0170000) == 040000
  58. || strrchr(dblock.dbuf.name, '\0')[-1] == '/'){
  59. f.mode |= DMDIR;
  60. f.size = 0;
  61. }
  62. f.mode &= DMDIR|0777;
  63. linkflg = dblock.dbuf.linkflag=='s' || dblock.dbuf.linkflag=='1';
  64. isabs = dblock.dbuf.name[0]=='/';
  65. if (chksum != checksum()){
  66. fprint(1, "bad checksum on %.28s\n", dblock.dbuf.name);
  67. exits("checksum");
  68. }
  69. if (linkflg) {
  70. /*fprint(2, "link %s->%s skipped\n", dblock.dbuf.name,
  71. dblock.dbuf.linkname);*/
  72. f.size = 0;
  73. blkno += 1;
  74. continue;
  75. }
  76. f.name = dblock.dbuf.name+isabs;
  77. if (f.name[0]=='\0')
  78. fprint(1, "null name skipped\n");
  79. else
  80. poppath(f, 1);
  81. blkno += 1 + (f.size+TBLOCK-1)/TBLOCK;
  82. }
  83. }
  84. void
  85. dotrunc(Ram *r)
  86. {
  87. USED(r);
  88. }
  89. void
  90. docreate(Ram *r)
  91. {
  92. USED(r);
  93. }
  94. char *
  95. doread(Ram *r, vlong off, long cnt)
  96. {
  97. seek(tapefile, TBLOCK*r->addr+off, 0);
  98. if (cnt>sizeof(dblock.tbuf))
  99. error("read too big");
  100. read(tapefile, dblock.tbuf, cnt);
  101. return dblock.tbuf;
  102. }
  103. void
  104. popdir(Ram *r)
  105. {
  106. USED(r);
  107. }
  108. void
  109. dowrite(Ram *r, char *buf, long off, long cnt)
  110. {
  111. USED(r); USED(buf); USED(off); USED(cnt);
  112. }
  113. int
  114. dopermw(Ram *r)
  115. {
  116. USED(r);
  117. return 0;
  118. }
  119. int
  120. checksum()
  121. {
  122. int i;
  123. char *cp;
  124. for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
  125. *cp = ' ';
  126. i = 0;
  127. for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
  128. i += *cp&0xff;
  129. return(i);
  130. }