copy.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. static int fast;
  5. static int quiet;
  6. VtSession *zsrc, *zdst;
  7. void
  8. usage(void)
  9. {
  10. fprint(2, "usage: copy [-fq] src-host dst-host score [type]\n");
  11. exits("usage");
  12. }
  13. int
  14. parseScore(uchar *score, char *buf, int n)
  15. {
  16. int i, c;
  17. memset(score, 0, VtScoreSize);
  18. if(n < VtScoreSize*2)
  19. return 0;
  20. for(i=0; i<VtScoreSize*2; i++) {
  21. if(buf[i] >= '0' && buf[i] <= '9')
  22. c = buf[i] - '0';
  23. else if(buf[i] >= 'a' && buf[i] <= 'f')
  24. c = buf[i] - 'a' + 10;
  25. else if(buf[i] >= 'A' && buf[i] <= 'F')
  26. c = buf[i] - 'A' + 10;
  27. else {
  28. return 0;
  29. }
  30. if((i & 1) == 0)
  31. c <<= 4;
  32. score[i>>1] |= c;
  33. }
  34. return 1;
  35. }
  36. void
  37. walk(uchar score[VtScoreSize], uint type, int base)
  38. {
  39. int i, n, sub;
  40. uchar *buf;
  41. VtEntry e;
  42. VtRoot root;
  43. if(memcmp(score, vtZeroScore, VtScoreSize) == 0)
  44. return;
  45. buf = vtMemAllocZ(VtMaxLumpSize);
  46. if(fast && vtRead(zdst, score, type, buf, VtMaxLumpSize) >= 0){
  47. if(!quiet)
  48. fprint(2, "%V already exists on dst server; skipping.\n", score);
  49. free(buf);
  50. return;
  51. }
  52. n = vtRead(zsrc, score, type, buf, VtMaxLumpSize);
  53. if(n < 0){
  54. fprint(2, "warning: could not read block %V %d: %R", score, type);
  55. return;
  56. }
  57. switch(type){
  58. case VtRootType:
  59. if(!vtRootUnpack(&root, buf)){
  60. fprint(2, "warning: could not unpack root in %V %d\n", score, type);
  61. break;
  62. }
  63. walk(root.score, VtDirType, 0);
  64. walk(root.prev, VtRootType, 0);
  65. break;
  66. case VtDirType:
  67. for(i=0; i<n/VtEntrySize; i++){
  68. if(!vtEntryUnpack(&e, buf, i)){
  69. fprint(2, "warning: could not unpack entry #%d in %V %d\n", i, score, type);
  70. continue;
  71. }
  72. if(!(e.flags & VtEntryActive))
  73. continue;
  74. if(e.flags&VtEntryDir)
  75. base = VtDirType;
  76. else
  77. base = VtDataType;
  78. if(e.depth == 0)
  79. sub = base;
  80. else
  81. sub = VtPointerType0+e.depth-1;
  82. walk(e.score, sub, base);
  83. }
  84. break;
  85. case VtDataType:
  86. break;
  87. default: /* pointers */
  88. if(type == VtPointerType0)
  89. sub = base;
  90. else
  91. sub = type-1;
  92. for(i=0; i<n; i+=VtScoreSize)
  93. if(memcmp(buf+i, vtZeroScore, VtScoreSize) != 0)
  94. walk(buf+i, sub, base);
  95. break;
  96. }
  97. if(!vtWrite(zdst, score, type, buf, n))
  98. fprint(2, "warning: could not write block %V %d: %R", score, type);
  99. free(buf);
  100. }
  101. int
  102. main(int argc, char *argv[])
  103. {
  104. int type, n;
  105. uchar score[VtScoreSize];
  106. uchar *buf;
  107. ARGBEGIN{
  108. case 'f':
  109. fast = 1;
  110. break;
  111. case 'q':
  112. quiet = 1;
  113. break;
  114. default:
  115. usage();
  116. break;
  117. }ARGEND
  118. if(argc != 3 && argc != 4)
  119. usage();
  120. vtAttach();
  121. fmtinstall('V', vtScoreFmt);
  122. fmtinstall('R', vtErrFmt);
  123. if(!parseScore(score, argv[2], strlen(argv[2])))
  124. vtFatal("could not parse score: %s", vtGetError());
  125. buf = vtMemAllocZ(VtMaxLumpSize);
  126. zsrc = vtDial(argv[0], 0);
  127. if(zsrc == nil)
  128. vtFatal("could not dial src server: %R");
  129. if(!vtConnect(zsrc, 0))
  130. sysfatal("vtConnect src: %r");
  131. zdst = vtDial(argv[1], 0);
  132. if(zdst == nil)
  133. vtFatal("could not dial dst server: %R");
  134. if(!vtConnect(zdst, 0))
  135. sysfatal("vtConnect dst: %r");
  136. if(argc == 4){
  137. type = atoi(argv[3]);
  138. n = vtRead(zsrc, score, type, buf, VtMaxLumpSize);
  139. if(n < 0)
  140. vtFatal("could not read block: %R");
  141. }else{
  142. for(type=0; type<VtMaxType; type++){
  143. n = vtRead(zsrc, score, type, buf, VtMaxLumpSize);
  144. if(n >= 0)
  145. break;
  146. }
  147. if(type == VtMaxType)
  148. vtFatal("could not find block %V of any type", score);
  149. }
  150. walk(score, type, VtDirType);
  151. if(!vtSync(zdst))
  152. vtFatal("could not sync dst server: %R");
  153. vtDetach();
  154. exits(0);
  155. return 0; /* shut up compiler */
  156. }