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