]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/hjfs/dump.c
ircrc: freenode -> oftc
[plan9front.git] / sys / src / cmd / hjfs / dump.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "dat.h"
5 #include "fns.h"
6
7 int
8 copydentry(Fs *fs, FLoc *a, Loc *b, char *nname)
9 {
10         Buf *ba, *bb, *bc;
11         Dentry *d;
12         int i, rc;
13         FLoc c;
14
15         if(!namevalid(nname)){
16                 werrstr(Einval);
17                 return -1;
18         }
19         ba = getbuf(fs->d, a->blk, TDENTRY, 0);
20         if(ba == nil)
21                 return -1;
22         bb = getbuf(fs->d, b->blk, TDENTRY, 0);
23         if(bb == nil){
24                 putbuf(ba);
25                 return -1;
26         }
27         rc = newentry(fs, b, bb, nname, &c, 1);
28         if(rc < 0){
29         err1:
30                 putbuf(bb);
31                 putbuf(ba);
32                 return -1;
33         }
34         bc = getbuf(fs->d, c.blk, TDENTRY, 0);
35         if(bc == nil)
36                 goto err1;
37         d = &bc->de[c.deind];
38         memcpy(d, &ba->de[a->deind], sizeof(*d));
39         strcpy(d->name, nname);
40         for(i = 0; i < NDIRECT; i++)
41                 if(d->db[i] != 0)
42                         chref(fs, d->db[i], 1);
43         for(i = 0; i < NINDIRECT; i++)
44                 if(d->ib[i] != 0)
45                         chref(fs, d->ib[i], 1);
46         bc->op |= BDELWRI;
47         putbuf(bc);
48         putbuf(bb);
49         putbuf(ba);
50         return 0;
51 }
52
53 static void
54 resetldumped(Fs *fs)
55 {
56         Loc *l;
57         
58         for(l = fs->rootloc->gnext; l != fs->rootloc; l = l->gnext)
59                 l->flags &= ~LDUMPED;
60 }
61
62 int
63 fsdump(Fs *fs)
64 {
65         char buf[20], *p, *e;
66         int n, rc;
67         Tm *tm;
68         Chan *ch, *chh;
69         Buf *b;
70
71         wlock(fs);
72         tm = localtime(time(0));
73         snprint(buf, sizeof(buf), "%.4d", tm->year + 1900);
74         ch = chanattach(fs, CHFNOLOCK|CHFDUMP);
75         ch->uid = -1;
76         if(ch == nil){
77                 wunlock(fs);
78                 return -1;
79         }
80         if(chanwalk(ch, buf) < 0){
81                 chh = chanclone(ch);
82                 rc = chancreat(chh, buf, DMDIR|0555, OREAD);
83                 chanclunk(chh);
84                 if(rc < 0)
85                         goto err;
86                 if(chanwalk(ch, buf) < 0)
87                         goto err;
88         }
89         b = getbuf(fs->d, ch->loc->blk, TDENTRY, 0);
90         if(b == nil)
91                 goto err;
92         for(n = 0; ; n++){
93                 e = buf + sizeof(buf);
94                 p = seprint(buf, e, "%.2d%.2d", tm->mon + 1, tm->mday);
95                 if(n > 0)
96                         seprint(p, e, "%d", n);
97                 rc = findentry(fs, ch->loc, b, buf, nil, 1);
98                 if(rc < 0)
99                         goto err;
100                 if(rc == 0)
101                         break;
102         }
103         putbuf(b);
104         rc = copydentry(fs, fs->rootloc, ch->loc, buf);
105         chanclunk(ch);
106         resetldumped(fs);
107         wunlock(fs);
108         return rc;
109 err:
110         chanclunk(ch);
111         wunlock(fs);
112         return -1;
113 }
114
115 static int
116 willmodify1(Fs *fs, Loc *l)
117 {
118         Buf *p;
119         Loc *m;
120         uvlong i, r;
121         Dentry *d;
122         int rc;
123
124         rc = chref(fs, l->blk, 0);
125         if(rc < 0)
126                 return -1;
127         if(rc == 0){
128                 dprint("willmodify: block %lld has refcount 0\n", l->blk);
129                 werrstr("phase error -- willmodify");
130                 return -1;
131         }
132         if(rc == 1)
133                 goto done;
134
135         p = getbuf(fs->d, l->next->blk, TDENTRY, 0);
136         if(p == nil)
137                 return -1;
138         d = getdent(l->next, p);
139         if(d != nil) for(i = 0; i < d->size; i++){
140                 rc = getblk(fs, l->next, p, i, &r, GBREAD);
141                 if(rc <= 0)
142                         continue;
143                 if(r == l->blk)
144                         goto found;
145         }       
146 phase:
147         werrstr("willmodify -- phase error");
148         putbuf(p);
149         return -1;
150 found:
151         rc = getblk(fs, l->next, p, i, &r, GBWRITE);
152         if(rc < 0){
153                 putbuf(p);
154                 return -1;
155         }
156         if(rc == 0)
157                 goto phase;
158         putbuf(p);
159
160         if(r != l->blk){
161                 /*
162                  * block got dumped, update the loctree so locs
163                  * point to the new block.
164                  */
165                 qlock(&fs->loctree);
166                 for(m = l->cnext; m != l; m = m->cnext)
167                         if(m->blk == l->blk)
168                                 m->blk = r;
169                 l->blk = r;
170                 qunlock(&fs->loctree);
171         }
172 done:
173         l->flags |= LDUMPED;
174         return 0;
175 }
176
177 int
178 willmodify(Fs *fs, Loc *l, int nolock)
179 {
180         Loc **st;
181         int sti, rc;
182         
183         if((l->flags & LDUMPED) != 0)
184                 return 1;
185         if(!nolock){
186 again:
187                 runlock(fs);
188                 wlock(fs);
189         }
190         st = emalloc(sizeof(Loc *));
191         *st = l;
192         sti = 0;
193         for(;;){
194                 if((st[sti]->flags & LDUMPED) != 0 || st[sti]->next == nil)
195                         break;
196                 st = erealloc(st, (sti + 2) * sizeof(Loc *));
197                 st[sti + 1] = st[sti]->next;
198                 sti++;
199         }
200         rc = 0;
201         for(; sti >= 0; sti--){
202                 rc = willmodify1(fs, st[sti]);
203                 if(rc < 0){
204                         free(st);
205                         if(!nolock){
206                                 wunlock(fs);
207                                 rlock(fs);
208                         }
209                         return -1;
210                 }
211         }
212         if(!nolock){
213                 wunlock(fs);
214                 rlock(fs);
215                 if(chref(fs, l->blk, 0) != 1)
216                         goto again;
217         }
218         free(st);
219         return rc;
220 }