updatedb.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * generate a list of files and their metadata
  3. * using a given proto file.
  4. */
  5. #include "all.h"
  6. int changesonly;
  7. char *uid;
  8. Db *db;
  9. Biobuf blog;
  10. ulong now;
  11. int n;
  12. char **x;
  13. int nx;
  14. int justlog;
  15. char *root=".";
  16. char **match;
  17. int nmatch;
  18. int
  19. ismatch(char *s)
  20. {
  21. int i, len;
  22. if(nmatch == 0)
  23. return 1;
  24. for(i=0; i<nmatch; i++){
  25. if(strcmp(s, match[i]) == 0)
  26. return 1;
  27. len = strlen(match[i]);
  28. if(strncmp(s, match[i], len) == 0 && s[len]=='/')
  29. return 1;
  30. }
  31. return 0;
  32. }
  33. void
  34. xlog(int c, char *name, Dir *d)
  35. {
  36. char *dname;
  37. dname = d->name;
  38. if(strcmp(dname, name) == 0)
  39. dname = "-";
  40. if(!justlog)
  41. Bprint(&blog, "%lud %d ", now, n++);
  42. Bprint(&blog, "%c %q %q %luo %q %q %lud %lld\n",
  43. c, name, dname, d->mode, uid ? uid : d->uid, d->gid, d->mtime, d->length);
  44. }
  45. void
  46. walk(char *new, char *old, Dir *xd, void*)
  47. {
  48. int i, change, len;
  49. Dir od, d;
  50. new = unroot(new, "/");
  51. old = unroot(old, root);
  52. if(!ismatch(new))
  53. return;
  54. for(i=0; i<nx; i++){
  55. if(strcmp(new, x[i]) == 0)
  56. return;
  57. len = strlen(x[i]);
  58. if(strncmp(new, x[i], len)==0 && new[len]=='/')
  59. return;
  60. }
  61. d = *xd;
  62. d.name = old;
  63. memset(&od, 0, sizeof od);
  64. change = 0;
  65. if(markdb(db, new, &od) < 0){
  66. if(!changesonly){
  67. xlog('a', new, &d);
  68. change = 1;
  69. }
  70. }else{
  71. if((d.mode&DMDIR)==0 && (od.mtime!=d.mtime || od.length!=d.length)){
  72. xlog('c', new, &d);
  73. change = 1;
  74. }
  75. if((!uid&&strcmp(od.uid,d.uid)!=0)
  76. || strcmp(od.gid,d.gid)!=0
  77. || od.mode!=d.mode){
  78. xlog('m', new, &d);
  79. change = 1;
  80. }
  81. }
  82. if(!justlog && change){
  83. if(uid)
  84. d.uid = uid;
  85. d.muid = "mark"; /* mark bit */
  86. insertdb(db, new, &d);
  87. }
  88. }
  89. void
  90. usage(void)
  91. {
  92. fprint(2, "usage: replica/updatedb [-c] [-p proto] [-r root] [-t now n] [-u uid] [-x path]... db [paths]\n");
  93. exits("usage");
  94. }
  95. void
  96. main(int argc, char **argv)
  97. {
  98. char *proto;
  99. Avlwalk *w;
  100. Dir d;
  101. Entry *e;
  102. quotefmtinstall();
  103. proto = "/sys/lib/sysconfig/proto/allproto";
  104. now = time(0);
  105. Binit(&blog, 1, OWRITE);
  106. ARGBEGIN{
  107. case 'c':
  108. changesonly = 1;
  109. break;
  110. case 'l':
  111. justlog = 1;
  112. break;
  113. case 'p':
  114. proto = EARGF(usage());
  115. break;
  116. case 'r':
  117. root = EARGF(usage());
  118. break;
  119. case 't':
  120. now = strtoul(EARGF(usage()), 0, 0);
  121. n = atoi(EARGF(usage()));
  122. break;
  123. case 'u':
  124. uid = EARGF(usage());
  125. break;
  126. case 'x':
  127. if(nx%16 == 0)
  128. x = erealloc(x, (nx+16)*sizeof(x[0]));
  129. x[nx++] = EARGF(usage());
  130. break;
  131. default:
  132. usage();
  133. }ARGEND
  134. if(argc <1)
  135. usage();
  136. match = argv+1;
  137. nmatch = argc-1;
  138. db = opendb(argv[0]);
  139. if(rdproto(proto, root, walk, nil, nil) < 0)
  140. sysfatal("rdproto: %r");
  141. if(!changesonly){
  142. w = avlwalk(db->avl);
  143. while(e = (Entry*)avlprev(w)){
  144. if(!ismatch(e->name))
  145. continue;
  146. if(!e->d.mark){ /* not visited during walk */
  147. memset(&d, 0, sizeof d);
  148. d.name = e->d.name;
  149. d.uid = e->d.uid;
  150. d.gid = e->d.gid;
  151. d.mtime = e->d.mtime;
  152. d.mode = e->d.mode;
  153. xlog('d', e->name, &d);
  154. if(!justlog)
  155. removedb(db, e->name);
  156. }
  157. }
  158. }
  159. if(Bterm(&blog) < 0)
  160. sysfatal("writing output: %r");
  161. exits(nil);
  162. }