dumparena.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. #include <disk.h>
  5. typedef struct Label Label;
  6. struct Label {
  7. ulong ver;
  8. ulong trailer;
  9. ulong tape;
  10. ulong slot;
  11. };
  12. static void usage(void);
  13. static void verifyArena(void);
  14. static int writeBlock(uchar *buf);
  15. static int writeLabel(Label*);
  16. static int readBlock(uchar *buf);
  17. static int readLabel(Label*);
  18. static int writeMark(void);
  19. static int rewind(int);
  20. static int space(int);
  21. int tape;
  22. int slot;
  23. int pos;
  24. Scsi *dev;
  25. enum {
  26. LabelMagic = 0x4b5474d2,
  27. BlockSize = 16*1024,
  28. Version = 1,
  29. };
  30. void
  31. main(int argc, char *argv[])
  32. {
  33. char *p;
  34. int overwrite = 0;
  35. fmtregister('V', vtScoreFmt);
  36. fmtregister('R', vtErrFmt);
  37. vtAttach();
  38. statsInit();
  39. ARGBEGIN{
  40. default:
  41. usage();
  42. break;
  43. case 's':
  44. p = ARGF();
  45. if(p == nil)
  46. usage();
  47. slot = atoi(p);
  48. break;
  49. case 't':
  50. p = ARGF();
  51. if(p == nil)
  52. usage();
  53. tape = atoi(p);
  54. break;
  55. case 'o':
  56. overwrite++;
  57. break;
  58. case '
  59. }ARGEND
  60. readonly = 1;
  61. if(argc != 1)
  62. usage();
  63. dev = openscsi(argv[0]);
  64. if(dev == nil)
  65. fatal("could not open scsi device: %r");
  66. if(!initPos() && !rewind())
  67. fatal("could not rewind: %r");
  68. fprint(2, "pos = %d\n", pos);
  69. if(pos != 0) {
  70. if(!movetoSlot(slot)) {
  71. if(!rewind())
  72. fatal("could not rewind: %r");
  73. pos = 0;
  74. }
  75. }
  76. if(pos != slot && !movetoSlot(slot))
  77. fatal("could not seek to slot: %r");
  78. if(!overwrite) {
  79. if(readLabel(&lb))
  80. fatal("tape not empty: tape=%d", lb->tape);
  81. }
  82. memset(&lb, 0, sizeof(lb));
  83. lb.ver = Version;
  84. lb.tape = tape;
  85. lb.slot = slot;
  86. if(!writeLabel(&lb))
  87. fatal("could not write header: %r");
  88. if(!writeArena(score))
  89. fatal("could not write arena: %r");
  90. lb.trailer = 1;
  91. if(!writeLabel(&lb))
  92. fatal("could not write header: %r");
  93. if(!writeArena(score))
  94. fatal("could not write arena: %r");
  95. exits(0);
  96. }
  97. static void
  98. usage(void)
  99. {
  100. fprint(2, "usage: dumparena [-o] [-t tape] [-s slot] device\n");
  101. exits("usage");
  102. }
  103. static int
  104. initPos(void)
  105. {
  106. Label lb;
  107. int i;
  108. for(i=0; i<4; i++) {
  109. slot(-2);
  110. if(space(1))
  111. if(readLabel(&lb))
  112. if(lb->tape == tape && lb->trailer) {
  113. pos = lb->slot;
  114. return 1;
  115. }
  116. }
  117. return 0;
  118. }
  119. static void
  120. readBlock(uchar *buf, int n)
  121. {
  122. int nr, m;
  123. for(nr = 0; nr < n; nr += m){
  124. m = n - nr;
  125. m = read(0, &buf[nr], m);
  126. if(m <= 0)
  127. fatal("can't read arena from standard input: %r");
  128. }
  129. }
  130. static void
  131. verifyArena(void)
  132. {
  133. Arena arena;
  134. ArenaHead head;
  135. ZBlock *b;
  136. VtSha1 *s;
  137. u64int n, e;
  138. u32int bs;
  139. u8int score[VtScoreSize];
  140. memset(&arena, 0, sizeof arena);
  141. fprint(2, "verify arena from standard input\n");
  142. s = vtSha1Alloc();
  143. if(s == nil)
  144. fatal("can't initialize sha1 state");
  145. vtSha1Init(s);
  146. /*
  147. * read the little bit, which will included the header
  148. */
  149. bs = MaxIoSize;
  150. b = allocZBlock(bs, 0);
  151. readBlock(b->data, HeadSize);
  152. vtSha1Update(s, b->data, HeadSize);
  153. if(!unpackArenaHead(&head, b->data))
  154. fatal("corrupted arena header: %R");
  155. if(head.version != ArenaVersion)
  156. fatal("unknown arena version %d", head.version);
  157. /*
  158. * now we know how much to read
  159. * read everything but the last block, which is special
  160. */
  161. e = head.size - head.blockSize;
  162. for(n = HeadSize; n < e; n += bs){
  163. if(n + bs > e)
  164. bs = e - n;
  165. readBlock(b->data, bs);
  166. vtSha1Update(s, b->data, bs);
  167. }
  168. /*
  169. * read the last block update the sum.
  170. * the sum is calculated assuming the slot for the sum is zero.
  171. */
  172. bs = head.blockSize;
  173. readBlock(b->data, bs);
  174. vtSha1Update(s, b->data, bs - VtScoreSize);
  175. vtSha1Update(s, zeroScore, VtScoreSize);
  176. vtSha1Final(s, score);
  177. vtSha1Free(s);
  178. /*
  179. * validity check on the trailer
  180. */
  181. arena.blockSize = head.blockSize;
  182. if(!unpackArena(&arena, b->data))
  183. fatal("corrupted arena trailer: %R");
  184. scoreCp(arena.score, &b->data[arena.blockSize - VtScoreSize]);
  185. if(!nameEq(arena.name, head.name))
  186. fatal("arena header and trailer names clash: %s vs. %s\n", head.name, arena.name);
  187. if(arena.version != head.version)
  188. fatal("arena header and trailer versions clash: %d vs. %d\n", head.version, arena.version);
  189. arena.size = head.size - 2 * head.blockSize;
  190. /*
  191. * check for no checksum or the same
  192. */
  193. if(!scoreEq(score, arena.score)){
  194. if(!scoreEq(zeroScore, arena.score))
  195. fprint(2, "warning: mismatched checksums for arena=%s, found=%V calculated=%V",
  196. arena.name, arena.score, score);
  197. scoreCp(arena.score, score);
  198. }else
  199. fprint(2, "matched score\n");
  200. printArena(2, &arena);
  201. }
  202. static int
  203. writeBlock(uchar *buf)
  204. {
  205. uchar cmd[6];
  206. memset(cmd, 0, sizeof(cmd));
  207. cmd[0] = 0x0a;
  208. cmd[2] = BlockSize>>16;
  209. cmd[3] = BlockSize>>8;
  210. cmd[4] = BlockSize;
  211. if(scsi(dev, cmd, 6, buf, BlockSize, Swrite) < 0)
  212. return 0;
  213. return 1;
  214. }
  215. static int
  216. readBlock(uchar *buf)
  217. {
  218. uchar cmd[6];
  219. memset(cmd, 0, sizeof(cmd));
  220. cmd[0] = 0x08;
  221. cmd[2] = BlockSize>>16;
  222. cmd[3] = BlockSize>>8;
  223. cmd[4] = BlockSize;
  224. if(scsi(dev, cmd, 6, buf, BlockSize, Sread) < 0)
  225. return 0;
  226. return 1;
  227. }
  228. static int
  229. writeMark(void)
  230. {
  231. uchar cmd[6];
  232. memset(cmd, 0, sizeof(cmd));
  233. cmd[0] = 0x10;
  234. if(scsi(dev, cmd, 6, buf, BlockSize, Sread) < 0)
  235. return 0;
  236. return 1;
  237. }
  238. static int
  239. rewind(int n)
  240. {
  241. uchar cmd[6];
  242. if(n > 225)
  243. n = 255;
  244. memset(cmd, 0, sizeof(cmd));
  245. cmd[0] = 0x01;
  246. cmd[4] = n;
  247. if(scsi(dev, cmd, 6, buf, BlockSize, Sread) < 0)
  248. return 0;
  249. return 1;
  250. }
  251. static int
  252. space(int off)
  253. {
  254. uchar cmd[6];
  255. memset(cmd, 0, sizeof(cmd));
  256. cmd[0] = 0x11;
  257. cmd[1] = 0x01; /* file marks */
  258. cmd[2] = off>>16;
  259. cmd[3] = off>>8;
  260. cmd[4] = off;
  261. if(scsi(dev, cmd, 6, buf, BlockSize, Sread) < 0)
  262. return 0;
  263. return 1;
  264. }
  265. static int
  266. writeLabel(Label *lb)
  267. {
  268. uchar block[BlockSize];
  269. if(lb->ver != Version) {
  270. vtSerError("unknown header version");
  271. return 0;
  272. }
  273. memset(block, 0, blockSize);
  274. vtPutUint32(block+0, Magic);
  275. vtPutUint32(block+4, lb->ver);
  276. vtPutUint32(block+8, lb->trailer);
  277. vtPutUint32(block+12, lb->tape);
  278. vtPutUint32(block+16, lb->slot);
  279. if(!writeBlock(block))
  280. return 0;
  281. if(!writeMark(1))
  282. return 0;
  283. return 1;
  284. }
  285. static int
  286. readLabel(Label *lb)
  287. {
  288. uchar block[BlockSize];
  289. if(!readBlock(block))
  290. return 0;
  291. if(vtGetUint32(block+0) != Magic) {
  292. vtSetError("bad magic in header");
  293. return 0;
  294. }
  295. lb->ver = vtGetUint32(block+4);
  296. if(lb->ver != Version) {
  297. vtSerError("unknown header version");
  298. return 0;
  299. }
  300. lb->trailer = vtPutUint32(block+8);
  301. lb->tape = vtGetUint32(block+12);
  302. lb->slot = vtGetUint32(block+16);
  303. return 1;
  304. }