]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/hjfs/dump.c
hjfs: disable hjfs check until more functionality is complete
[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 int
116 willmodify(Fs *fs, Loc *l, int nolock)
117 {
118         Buf *p;
119         Loc *m;
120         uvlong i, r;
121         Dentry *d;
122         int rc;
123
124         if((l->flags & LDUMPED) != 0)
125                 return 1;
126         if(!nolock){
127 again:
128                 runlock(fs);
129                 wlock(fs);
130         }
131         if(l->next != nil && willmodify(fs, l->next, 1) < 0)
132                 goto err;
133         rc = chref(fs, l->blk, 0);
134         if(rc < 0)
135                 goto err;
136         if(rc == 0){
137                 dprint("willmodify: block %lld has refcount 0\n", l->blk);
138                 werrstr("phase error -- willmodify");
139                 goto err;
140         }
141         if(rc == 1)
142                 goto done;
143
144         p = getbuf(fs->d, l->next->blk, TDENTRY, 0);
145         if(p == nil)
146                 goto err;
147         d = getdent(l->next, p);
148         if(d != nil) for(i = 0; i < d->size; i++){
149                 rc = getblk(fs, l->next, p, i, &r, GBREAD);
150                 if(rc <= 0)
151                         continue;
152                 if(r == l->blk)
153                         goto found;
154         }       
155 phase:
156         werrstr("willmodify -- phase error");
157         putbuf(p);
158         goto err;
159 found:
160         rc = getblk(fs, l->next, p, i, &r, GBWRITE);
161         if(rc < 0){
162                 putbuf(p);
163                 goto err;
164         }
165         if(rc == 0)
166                 goto phase;
167         putbuf(p);
168
169         if(r != l->blk){
170                 /*
171                  * block got dumped, update the loctree so locs
172                  * point to the new block.
173                  */
174                 qlock(&fs->loctree);
175                 for(m = l->cnext; m != l; m = m->cnext)
176                         if(m->blk == l->blk)
177                                 m->blk = r;
178                 l->blk = r;
179                 qunlock(&fs->loctree);
180         }
181 done:
182         l->flags |= LDUMPED;
183         if(!nolock){
184                 wunlock(fs);
185                 rlock(fs);
186                 if(chref(fs, l->blk, 0) != 1)
187                         goto again;
188         }
189         return 0;
190 err:
191         if(!nolock){
192                 wunlock(fs);
193                 rlock(fs);
194         }
195         return -1;
196 }