]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/hgfs/tree.c
upas/fs: fix more locking bugs, remove debugging clutter, remove planb mbox code
[plan9front.git] / sys / src / cmd / hgfs / tree.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "dat.h"
5 #include "fns.h"
6
7 char*
8 nodepath(char *s, char *e, Revnode *nd, int mangle)
9 {
10         static char *frogs[] = {
11                 "con", "prn", "aux", "nul",
12                 "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
13                 "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
14         };
15         char *p;
16         int i, l;
17
18         if(nd == nil || nd->name == nil)
19                 return s;
20
21         s = seprint(nodepath(s, e, nd->up, mangle), e, "/");
22         p = nd->name;
23         if(!mangle)
24                 return seprint(s, e, "%s", p);
25
26         for(i=0; i<nelem(frogs); i++){
27                 l = strlen(frogs[i]);
28                 if((strncmp(frogs[i], p, l) == 0) && (p[l] == 0 || p[l] == '.'))
29                         return seprint(s, e, "%.2s~%.2x%s", p, (uchar)p[2], p+3);
30         }
31         for(; s+4 < e && *p; p++){
32                 if(*p == '_'){
33                         *s++ = '_';
34                         *s++ = '_';
35                 } else if(*p >= 'A' && *p <= 'Z'){
36                         *s++ = '_';
37                         *s++ = 'a' + (*p - 'A');
38                 } else if((uchar)*p >= 126 || strchr("\\:*?\"<>|", *p)){
39                         *s++ = '~';
40                         s = seprint(s, e, "%.2x", (uchar)*p);
41                 } else
42                         *s++ = *p;
43         }
44         *s = 0;
45
46         return s;
47 }
48
49 Revnode*
50 mknode(char *name, uchar *hash, char mode)
51 {
52         Revnode *d;
53         char *s;
54
55         d = malloc(sizeof(*d) + (hash ? HASHSZ : 0) + (name ? strlen(name)+1 : 0));
56         memset(d, 0, sizeof(*d));
57         s = (char*)&d[1];
58         if(hash){
59                 d->path = hash2qid(hash);
60                 memmove(d->hash = (uchar*)s, hash, HASHSZ);
61                 s += HASHSZ;
62         }else
63                 d->path = 1;
64         if(name)
65                 strcpy(d->name = s, name);
66         d->mode = mode;
67         return d;
68 }
69
70 static void
71 addnode(Revnode *d, char *path, uchar *hash, char mode)
72 {
73         char *slash;
74         Revnode *c, *p;
75
76         while(path && *path){
77                 if(slash = strchr(path, '/'))
78                         *slash++ = 0;
79                 p = nil;
80                 for(c = d->down; c; p = c, c = c->next)
81                         if(strcmp(c->name, path) == 0)
82                                 break;
83                 if(c == nil){
84                         c = mknode(path, slash ? nil : hash, slash ? 0 : mode);
85                         c->up = d;
86                         if(p){
87                                 c->next = p->next;
88                                 p->next = c;
89                         } else {
90                                 c->next = d->down;
91                                 d->down = c;
92                         }
93                         if(!slash){
94                                 p = c;
95                                 while(d){
96                                         d->path += p->path;
97                                         p = d;
98                                         d = d->up;
99                                 }
100                         }
101                 }
102                 d = c;
103                 path = slash;
104         }
105 }
106
107 typedef struct Hashstr Hashstr;
108 struct Hashstr
109 {
110         Hashstr *next;
111         char    str[];
112 };
113
114 static int
115 loadmanifest(Revnode *root, int fd, Hashstr **ht, int nh)
116 {
117         char buf[BUFSZ], *p, *e, *x;
118         uchar hash[HASHSZ];
119         int n;
120
121         p = buf;
122         e = buf + BUFSZ;
123         while((n = read(fd, p, e - p)) > 0){
124                 p += n;
125                 while((p > buf) && (e = memchr(buf, '\n', p - buf))){
126                         *e++ = 0;
127
128                         x = buf;
129                         x += strlen(x) + 1;
130                         hex2hash(x, hash);
131                         x += HASHSZ*2;
132
133                         if(ht == nil)
134                                 addnode(root, buf, hash, *x);
135                         else {
136                                 Hashstr *he;
137
138                                 for(he = ht[hashstr(buf) % nh]; he; he = he->next){
139                                         if(strcmp(he->str, buf) == 0){
140                                                 addnode(root, buf, hash, *x);
141                                                 break;
142                                         }
143                                 }
144                         }
145
146                         p -= e - buf;
147                         if(p > buf)
148                                 memmove(buf, e, p - buf);
149                 }
150                 e = buf + BUFSZ;
151         }
152         return 0;
153 }
154
155 static Revtree*
156 loadtree(Revlog *manifest, Revinfo *ri, Hashstr **ht, int nh)
157 {
158         Revtree *t;
159         int fd;
160
161         if((fd = revlogopentemp(manifest, hashrev(manifest, ri->mhash))) < 0)
162                 return nil;
163
164         t = malloc(sizeof(*t));
165         memset(t, 0, sizeof(*t));
166         incref(t);
167         t->root = mknode(nil, nil, 0);
168         if(loadmanifest(t->root, fd, ht, nh) < 0){
169                 close(fd);
170                 closerevtree(t);
171                 return nil;
172         }
173         close(fd);
174
175         return t;
176 }
177
178 Revtree*
179 loadfilestree(Revlog *, Revlog *manifest, Revinfo *ri)
180 {
181         return loadtree(manifest, ri, nil, 0);
182 }
183
184 Revtree*
185 loadchangestree(Revlog *changelog, Revlog *manifest, Revinfo *ri)
186 {
187         char buf[BUFSZ], *p, *e;
188         Hashstr *ht[256], *he, **hp;
189         int fd, n;
190         Revtree *t;
191         vlong off;
192
193         if((fd = revlogopentemp(changelog, hashrev(changelog, ri->chash))) < 0)
194                 return nil;
195
196         off = seek(fd, ri->logoff, 0);
197         if(off < 0){
198                 close(fd);
199                 return nil;
200         }
201
202         memset(ht, 0, sizeof(ht));
203
204         p = buf;
205         e = buf + BUFSZ;
206         while((off - ri->logoff) < ri->loglen){
207                 if((n = read(fd, p, e - p)) <= 0)
208                         break;
209                 p += n;
210                 while((p > buf) && (e = memchr(buf, '\n', p - buf))){
211                         *e++ = 0;
212
213                         he = malloc(sizeof(*he) + strlen(buf)+1);
214                         hp = &ht[hashstr(strcpy(he->str, buf)) % nelem(ht)];
215                         he->next = *hp;
216                         *hp = he;
217
218                         n = e - buf;
219                         p -= n;
220                         if(p > buf)
221                                 memmove(buf, e, p - buf);
222                         off += n;
223                 }
224                 e = buf + BUFSZ;
225         }
226         close(fd);
227
228         t = loadtree(manifest, ri, ht, nelem(ht));
229
230         for(hp = ht; hp != &ht[nelem(ht)]; hp++){
231                 while(he = *hp){
232                         *hp = he->next;
233                         free(he);
234                 }
235         }
236
237         return t;
238 }
239
240 static void
241 freenode(Revnode *nd)
242 {
243         if(nd == nil)
244                 return;
245         freenode(nd->down);
246         freenode(nd->next);
247         freenode(nd->before);
248         free(nd);
249 }
250
251 void
252 closerevtree(Revtree *t)
253 {
254         if(t == nil || decref(t))
255                 return;
256         freenode(t->root);
257         free(t);
258 }