1 #include "all.h"
2
3 static Entry *fe;
4
5 static Entry*
allocentry(void)6 allocentry(void)
7 {
8 int i;
9 Entry *e;
10
11 if(fe == nil){
12 fe = emalloc(128*sizeof(Entry));
13 for(i=0; i<128-1; i++)
14 fe[i].name = (char*)&fe[i+1];
15 fe[i].name = nil;
16 }
17
18 e = fe;
19 fe = (Entry*)e->name;
20 memset(e, 0, sizeof *e);
21 return e;
22 }
23
24 static void
freeentry(Entry * e)25 freeentry(Entry *e)
26 {
27 e->name = (char*)fe;
28 fe = e;
29 }
30
31 static void
_removedb(Db * db,char * name)32 _removedb(Db *db, char *name)
33 {
34 Entry *e, k;
35
36 memset(&k, 0, sizeof k);
37 k.name = name;
38 e = nil;
39 deleteavl(db->avl, (Avl*)&k, (Avl**)&e);
40 if(e)
41 freeentry(e);
42 }
43
44 static void
_insertdb(Db * db,Entry * e)45 _insertdb(Db *db, Entry *e)
46 {
47 Entry *o, *ne;
48
49 ne = allocentry();
50 *ne = *e;
51 o = nil;
52 insertavl(db->avl, (Avl*)ne, (Avl**)&o);
53 if(o)
54 freeentry(o);
55 }
56
57 static int
entrycmp(Avl * a,Avl * b)58 entrycmp(Avl *a, Avl *b)
59 {
60 Entry *ea, *eb;
61 int r;
62
63 ea = (Entry*)a;
64 eb = (Entry*)b;
65 r = strcmp(ea->name, eb->name);
66 return r > 0 ? 1 : r < 0 ? -1 : 0;
67 }
68
69 Db*
opendb(char * file)70 opendb(char *file)
71 {
72 char *f[10], *s, *t;
73 int i, fd, nf;
74 Biobuf b;
75 Db *db;
76 Entry e;
77
78 if(file == nil)
79 fd = -1;
80 else if((fd = open(file, ORDWR)) < 0)
81 sysfatal("opendb %s: %r", file);
82 db = emalloc(sizeof(Db));
83 db->avl = mkavltree(entrycmp);
84 db->fd = fd;
85 if(fd < 0)
86 return db;
87 Binit(&b, fd, OREAD);
88 i = 0;
89 for(; s=Brdstr(&b, '\n', 1); free(s)){
90 t = estrdup(s);
91 nf = tokenize(s, f, nelem(f));
92 if(nf != 7)
93 sysfatal("bad database entry '%s'", t);
94 free(t);
95 if(strcmp(f[2], "REMOVED") == 0)
96 _removedb(db, f[0]);
97 else{
98 memset(&e, 0, sizeof e);
99 e.name = atom(f[0]);
100 e.d.name = atom(f[1]);
101 if(strcmp(e.d.name, "-")==0)
102 e.d.name = e.name;
103 e.d.mode = strtoul(f[2], 0, 8);
104 e.d.uid = atom(f[3]);
105 e.d.gid = atom(f[4]);
106 e.d.mtime = strtoul(f[5], 0, 10);
107 e.d.length = strtoll(f[6], 0, 10);
108 _insertdb(db, &e);
109 i++;
110 }
111 }
112 return db;
113 }
114
115 static int
_finddb(Db * db,char * name,Dir * d,int domark)116 _finddb(Db *db, char *name, Dir *d, int domark)
117 {
118 Entry *e, k;
119
120 memset(&k, 0, sizeof k);
121 k.name = name;
122
123 e = (Entry*)lookupavl(db->avl, (Avl*)&k);
124 if(e == nil)
125 return -1;
126 memset(d, 0, sizeof *d);
127 d->name = e->d.name;
128 d->uid = e->d.uid;
129 d->gid = e->d.gid;
130 d->mtime = e->d.mtime;
131 d->mode = e->d.mode;
132 d->length = e->d.length;
133 if(domark)
134 e->d.mark = 1;
135 return 0;
136 }
137
138 int
finddb(Db * db,char * name,Dir * d)139 finddb(Db *db, char *name, Dir *d)
140 {
141 return _finddb(db, name, d, 0);
142 }
143
144 int
markdb(Db * db,char * name,Dir * d)145 markdb(Db *db, char *name, Dir *d)
146 {
147 return _finddb(db, name, d, 1);
148 }
149
150 void
removedb(Db * db,char * name)151 removedb(Db *db, char *name)
152 {
153 if(db->fd>=0 && fprint(db->fd, "%q xxx REMOVED xxx xxx 0 0\n", name) < 0)
154 sysfatal("appending to db: %r");
155 _removedb(db, name);
156 }
157
158 void
insertdb(Db * db,char * name,Dir * d)159 insertdb(Db *db, char *name, Dir *d)
160 {
161 char *dname;
162 Entry e;
163
164 memset(&e, 0, sizeof e);
165 e.name = atom(name);
166 e.d.name = atom(d->name);
167 e.d.uid = atom(d->uid);
168 e.d.gid = atom(d->gid);
169 e.d.mtime = d->mtime;
170 e.d.mode = d->mode;
171 e.d.length = d->length;
172 e.d.mark = d->muid!=0;
173
174 dname = d->name;
175 if(strcmp(name, dname) == 0)
176 dname = "-";
177 if(db->fd>=0 && fprint(db->fd, "%q %q %luo %q %q %lud %lld\n", name, dname, d->mode, d->uid, d->gid, d->mtime, d->length) < 0)
178 sysfatal("appending to db: %r");
179 _insertdb(db, &e);
180 }
181
182