]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/hjfs/dump.c
renamed statw to df
[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);
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(Dentry));
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         uvlong i, r;
120         Dentry *d;
121         int rc;
122
123         if((l->flags & LDUMPED) != 0)
124                 return 1;
125         if(!nolock){
126 again:
127                 runlock(fs);
128                 wlock(fs);
129         }
130         if(l->next != nil && willmodify(fs, l->next, 1) < 0)
131                 goto err;
132         rc = chref(fs, l->blk, 0);
133         if(rc < 0)
134                 goto err;
135         if(rc == 0){
136                 dprint("hjfs: willmodify: block %lld has refcount 0\n", l->blk);
137                 werrstr("phase error -- willmodify");
138                 goto err;
139         }
140         if(rc == 1)
141                 goto done;
142
143         p = getbuf(fs->d, l->next->blk, TDENTRY, 0);
144         if(p == nil)
145                 goto err;
146         d = &p->de[l->next->deind];
147         for(i = 0; i < d->size; i++){
148                 rc = getblk(fs, l->next, p, i, &r, GBREAD);
149                 if(rc <= 0)
150                         continue;
151                 if(r == l->blk)
152                         goto found;
153         }
154 phase:
155         werrstr("willmodify -- phase error");
156         putbuf(p);
157         goto err;
158 found:
159         rc = getblk(fs, l->next, p, i, &r, GBWRITE);
160         if(rc < 0){
161                 putbuf(p);
162                 goto err;
163         }
164         if(rc == 0)
165                 goto phase;
166         putbuf(p);
167         l->blk = r;
168 done:
169         l->flags |= LDUMPED;
170         if(!nolock){
171                 wunlock(fs);
172                 rlock(fs);
173                 if(chref(fs, l->blk, 0) != 1)
174                         goto again;
175         }
176         return 0;
177 err:
178         if(!nolock){
179                 wunlock(fs);
180                 rlock(fs);
181         }
182         return -1;
183 }