diff options
author | aiju <aiju@phicode.de> | 2012-08-07 17:57:04 +0200 |
---|---|---|
committer | aiju <aiju@phicode.de> | 2012-08-07 17:57:04 +0200 |
commit | b21b9ba89cf66a8fac6f94efb79cfb425a2c4df2 (patch) | |
tree | 42047f997cda3eddec9faeafeb74435cc72a4786 /sys/src/cmd/hjfs/dump.c | |
parent | ef1c1863051d0530a31b291f4e334ee7601c318c (diff) |
added hjfs
Diffstat (limited to 'sys/src/cmd/hjfs/dump.c')
-rw-r--r-- | sys/src/cmd/hjfs/dump.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/sys/src/cmd/hjfs/dump.c b/sys/src/cmd/hjfs/dump.c new file mode 100644 index 000000000..06c6e2418 --- /dev/null +++ b/sys/src/cmd/hjfs/dump.c @@ -0,0 +1,169 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include "dat.h" +#include "fns.h" + +int +copydentry(Fs *fs, FLoc *a, Loc *b, char *nname) +{ + Buf *ba, *bb, *bc; + Dentry *d; + int i, rc; + FLoc c; + + if(!namevalid(nname)){ + werrstr(Einval); + return -1; + } + ba = getbuf(fs->d, a->blk, TDENTRY, 0); + if(ba == nil) + return -1; + bb = getbuf(fs->d, b->blk, TDENTRY, 0); + if(bb == nil){ + putbuf(ba); + return -1; + } + rc = newentry(fs, b, bb, nname, &c); + if(rc < 0){ + err1: + putbuf(bb); + putbuf(ba); + return -1; + } + bc = getbuf(fs->d, c.blk, TDENTRY, 0); + if(bc == nil) + goto err1; + d = &bc->de[c.deind]; + memcpy(d, &ba->de[a->deind], sizeof(Dentry)); + strcpy(d->name, nname); + for(i = 0; i < NDIRECT; i++) + if(d->db[i] != 0) + chref(fs, d->db[i], 1); + for(i = 0; i < NINDIRECT; i++) + if(d->ib[i] != 0) + chref(fs, d->ib[i], 1); + bc->op |= BDELWRI; + putbuf(bc); + putbuf(bb); + putbuf(ba); + return 0; +} + +int +fsdump(Fs *fs) +{ + char buf[20], *p, *e; + int n, rc; + Tm *tm; + Chan *ch, *chh; + Buf *b; + + wlock(fs); + tm = localtime(time(0)); + snprint(buf, sizeof(buf), "%.4d", tm->year + 1900); + ch = chanattach(fs, CHFNOLOCK|CHFDUMP); + ch->uid = -1; + if(ch == nil){ + wunlock(fs); + return -1; + } + if(chanwalk(ch, buf) < 0){ + chh = chanclone(ch); + rc = chancreat(chh, buf, DMDIR|0555, OREAD); + chanclunk(chh); + if(rc < 0) + goto err; + if(chanwalk(ch, buf) < 0) + goto err; + } + b = getbuf(fs->d, ch->loc->blk, TDENTRY, 0); + if(b == nil) + goto err; + for(n = 0; ; n++){ + e = buf + sizeof(buf); + p = seprint(buf, e, "%.2d%.2d", tm->mon + 1, tm->mday); + if(n > 0) + seprint(p, e, "%d", n); + rc = findentry(fs, ch->loc, b, buf, nil, 1); + if(rc < 0) + goto err; + if(rc == 0) + break; + } + putbuf(b); + rc = copydentry(fs, fs->rootloc, ch->loc, buf); + chanclunk(ch); + wunlock(fs); + return rc; +err: + chanclunk(ch); + wunlock(fs); + return -1; +} + +int +willmodify(Fs *fs, Loc *l, int nolock) +{ + Buf *p; + uvlong i, r; + Dentry *d; + int rc; + + if(!nolock){ +again: + runlock(fs); + wlock(fs); + } + rc = chref(fs, l->blk, 0); + if(rc < 0) + goto err; + if(rc == 0){ + dprint("hjfs: willmodify: block %lld has refcount 0\n", l->blk); + werrstr("phase error -- willmodify"); + goto err; + } + if(rc == 1) + goto done; + if(willmodify(fs, l->next, 1) < 0) + goto err; + p = getbuf(fs->d, l->next->blk, TDENTRY, 0); + if(p == nil) + goto err; + d = &p->de[l->next->deind]; + for(i = 0; i < d->size; i++){ + rc = getblk(fs, l->next, p, i, &r, GBREAD); + if(rc <= 0) + continue; + if(r == l->blk) + goto found; + } +phase: + werrstr("willmodify -- phase error"); + putbuf(p); + goto err; +found: + rc = getblk(fs, l->next, p, i, &r, GBWRITE); + if(rc < 0){ + putbuf(p); + goto err; + } + if(rc == 0) + goto phase; + putbuf(p); + l->blk = r; +done: + if(!nolock){ + wunlock(fs); + rlock(fs); + if(chref(fs, l->blk, 0) != 1) + goto again; + } + return 0; +err: + if(!nolock){ + wunlock(fs); + rlock(fs); + } + return -1; +} |