updatedb.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. * generate a list of files and their metadata
  11. * using a given proto file.
  12. */
  13. #include "all.h"
  14. int changesonly;
  15. char *uid;
  16. Db *db;
  17. Biobuf blog;
  18. uint32_t now;
  19. int n;
  20. char **x;
  21. int nx;
  22. int justlog;
  23. char *root=".";
  24. char **match;
  25. int nmatch;
  26. int
  27. ismatch(char *s)
  28. {
  29. int i, len;
  30. if(nmatch == 0)
  31. return 1;
  32. for(i=0; i<nmatch; i++){
  33. if(strcmp(s, match[i]) == 0)
  34. return 1;
  35. len = strlen(match[i]);
  36. if(strncmp(s, match[i], len) == 0 && s[len]=='/')
  37. return 1;
  38. }
  39. return 0;
  40. }
  41. void
  42. xlog(int c, char *name, Dir *d)
  43. {
  44. char *dname;
  45. dname = d->name;
  46. if(strcmp(dname, name) == 0)
  47. dname = "-";
  48. if(!justlog)
  49. Bprint(&blog, "%lud %d ", now, n++);
  50. Bprint(&blog, "%c %q %q %luo %q %q %lud %lld\n",
  51. c, name, dname, d->mode, uid ? uid : d->uid, d->gid, d->mtime, d->length);
  52. }
  53. void
  54. walk(char *new, char *old, Dir *xd, void*)
  55. {
  56. int i, change, len;
  57. Dir od, d;
  58. new = unroot(new, "/");
  59. old = unroot(old, root);
  60. if(!ismatch(new))
  61. return;
  62. for(i=0; i<nx; i++){
  63. if(strcmp(new, x[i]) == 0)
  64. return;
  65. len = strlen(x[i]);
  66. if(strncmp(new, x[i], len)==0 && new[len]=='/')
  67. return;
  68. }
  69. d = *xd;
  70. d.name = old;
  71. memset(&od, 0, sizeof od);
  72. change = 0;
  73. if(markdb(db, new, &od) < 0){
  74. if(!changesonly){
  75. xlog('a', new, &d);
  76. change = 1;
  77. }
  78. }else{
  79. if((d.mode&DMDIR)==0 && (od.mtime!=d.mtime || od.length!=d.length)){
  80. xlog('c', new, &d);
  81. change = 1;
  82. }
  83. if((!uid&&strcmp(od.uid,d.uid)!=0)
  84. || strcmp(od.gid,d.gid)!=0
  85. || od.mode!=d.mode){
  86. xlog('m', new, &d);
  87. change = 1;
  88. }
  89. }
  90. if(!justlog && change){
  91. if(uid)
  92. d.uid = uid;
  93. d.muid = "mark"; /* mark bit */
  94. insertdb(db, new, &d);
  95. }
  96. }
  97. void
  98. warn(char *msg, void*)
  99. {
  100. char *p;
  101. fprint(2, "warning: %s\n", msg);
  102. /* find the %r in "can't open foo: %r" */
  103. p = strstr(msg, ": ");
  104. if(p)
  105. p += 2;
  106. /*
  107. * if the error is about a remote server failing,
  108. * then there's no point in continuing to look
  109. * for changes -- we'll think everything got deleted!
  110. *
  111. * actual errors i see are:
  112. * "i/o on hungup channel" for a local hangup
  113. * "i/o on hungup channel" for a timeout (yank the network wire)
  114. * "'/n/sources/plan9' Hangup" for a remote hangup
  115. * the rest is paranoia.
  116. */
  117. if(p){
  118. if(cistrstr(p, "hungup") || cistrstr(p, "Hangup")
  119. || cistrstr(p, "rpc error")
  120. || cistrstr(p, "shut down")
  121. || cistrstr(p, "i/o")
  122. || cistrstr(p, "connection"))
  123. sysfatal("suspected network or i/o error - bailing out");
  124. }
  125. }
  126. void
  127. usage(void)
  128. {
  129. fprint(2, "usage: replica/updatedb [-c] [-p proto] [-r root] [-t now n] [-u uid] [-x path]... db [paths]\n");
  130. exits("usage");
  131. }
  132. void
  133. main(int argc, char **argv)
  134. {
  135. char *proto;
  136. Avlwalk *w;
  137. Dir d;
  138. Entry *e;
  139. quotefmtinstall();
  140. proto = "/sys/lib/sysconfig/proto/allproto";
  141. now = time(0);
  142. Binit(&blog, 1, OWRITE);
  143. ARGBEGIN{
  144. case 'c':
  145. changesonly = 1;
  146. break;
  147. case 'l':
  148. justlog = 1;
  149. break;
  150. case 'p':
  151. proto = EARGF(usage());
  152. break;
  153. case 'r':
  154. root = EARGF(usage());
  155. break;
  156. case 't':
  157. now = strtoul(EARGF(usage()), 0, 0);
  158. n = atoi(EARGF(usage()));
  159. break;
  160. case 'u':
  161. uid = EARGF(usage());
  162. break;
  163. case 'x':
  164. if(nx%16 == 0)
  165. x = erealloc(x, (nx+16)*sizeof(x[0]));
  166. x[nx++] = EARGF(usage());
  167. break;
  168. default:
  169. usage();
  170. }ARGEND
  171. if(argc <1)
  172. usage();
  173. match = argv+1;
  174. nmatch = argc-1;
  175. db = opendb(argv[0]);
  176. if(rdproto(proto, root, walk, warn, nil) < 0)
  177. sysfatal("rdproto: %r");
  178. if(!changesonly){
  179. w = avlwalk(db->avl);
  180. while(e = (Entry*)avlprev(w)){
  181. if(!ismatch(e->name))
  182. continue;
  183. if(!e->d.mark){ /* not visited during walk */
  184. memset(&d, 0, sizeof d);
  185. d.name = e->d.name;
  186. d.uid = e->d.uid;
  187. d.gid = e->d.gid;
  188. d.mtime = e->d.mtime;
  189. d.mode = e->d.mode;
  190. xlog('d', e->name, &d);
  191. if(!justlog)
  192. removedb(db, e->name);
  193. }
  194. }
  195. }
  196. if(Bterm(&blog) < 0)
  197. sysfatal("writing output: %r");
  198. exits(nil);
  199. }