|
|
1.1 root 1: /* write out all records pointed to by level 0 blocks,
2: * whether or not the level 0 blocks are accessible.
3: * the output is like that of bcat -R, except that many keys
4: * will be duplicated
5: * In general, the later keys are more up to date
6: * btsalvage xxx | slvg | sort | slvg2 | cbt build -R newxxx
7: * is the optimistic way of slavaging a b-tree in which the non-leaves
8: * have been clobbered
9: */
10: #include "cbt.h"
11: #include "pr.h"
12: #include "stdio.h"
13:
14: bfile *curbf;
15: extern bfile *newtran(), *xopen();
16: extern char *malloc(), *strcpy(), *realloc();
17: extern long lseek();
18: char keybuf[NDSZ];
19: char *recbuf;
20: int buflen;
21:
22: main(argc, argv)
23: char **argv;
24: { bfile *bf;
25: mbuf key, rec;
26: int n;
27: if(argc != 2) {
28: fprintf(stderr, "usage: salvage file\n");
29: exit(1);
30: }
31: bf = xopen(argv[1], 0);
32: key.mdata = keybuf;
33: if(bf == NULL) {
34: fprintf(stderr, "couldn't open %s\n", argv[1]);
35: exit(1);
36: }
37: while((n = breclen(bf)) > buflen) {
38: if(buflen == 0)
39: recbuf = malloc(buflen = 1024);
40: else
41: recbuf = realloc(recbuf, buflen += 1024);
42: if(recbuf == NULL) {
43: fprintf(stderr, "recbuf[%d] failed\n", buflen);
44: exit(1);
45: }
46: rec.mdata = recbuf;
47: }
48: for(;;) {
49: xread(bf, &key, &rec);
50: write(1, (char *)&key.mlen, 2);
51: write(1, key.mdata, key.mlen);
52: write(1, (char *)&rec.mlen, 2);
53: write(1, rec.mdata, rec.mlen);
54: }
55: }
56: bfile *xopen(s, typ) char *s; /* typ is 0 or 2 */
57: { bfile *p;
58: int n, i;
59:
60: p = alloc(bfile);
61: if(p == NULL)
62: goto nomem;
63: n = strlen(s);
64: p->fname = malloc((unsigned)n + 3);
65: if(p->fname == NULL)
66: goto nomem;
67: (void) strcpy(p->fname, s);
68: strcpy(p->fname + n, ".T");
69: if((p->tfd = open(p->fname, typ)) == -1) {
70: free(p->fname);
71: free((char *)p);
72: return(NULL);
73: }
74: p->rdwrt = typ;
75: p->fatal = p->advnc = 0;
76: p->altname = NULL;
77: for(i = 0; i <= MXHT; i++) {
78: p->path[i] = NULL;
79: p->flag[i] = 0;
80: p->loc[i] = 0;
81: }
82: p->path[0] = (hdr *)malloc(NDSZ);
83: if(p->path[0] == NULL)
84: goto nomem;
85: curbf = p;
86: if(read(p->tfd, (char *)p->path[0], NDSZ) != NDSZ) {
87: perror(" first read");
88: exit(1);
89: }
90: strcpy(p->fname + n, ".F");
91: if(!treeonly(p) && (p->dfd = open(p->fname, typ)) == -1) {
92: (void) close(p->tfd);
93: free(p->fname);
94: free(p->path[0]);
95: free((char *)p);
96: return(NULL);
97: }
98: else if(treeonly(p))
99: p->dfd = -1;
100: p->fname[n] = 0;
101: p->height = p->path[0]->hlev;
102: xfirst(p);
103: return(p);
104: nomem:
105: errno = BNOMEM;
106: return(NULL);
107: }
108:
109: breclen(bf) bfile *bf;
110: {
111: if(bf == NULL)
112: return(EOF);
113: if(notran(bf))
114: return(EOF);
115: if(bf->advnc)
116: xadvance();
117: if(bf->rdptr.rnum >= bf->path[0]->kcnt)
118: return(EOF);
119: if(treeonly(bf))
120: return(0);
121: return(lfadr(bf->path[0], bf->rdptr.rnum)->llen);
122: }
123:
124: xread(bf, key, rec) bfile *bf; mbuf *key, *rec;
125: {
126: dkey *d;
127: lfaddr *x;
128: if(bf == NULL)
129: return(NULL);
130: if(notran(bf))
131: return(EOF);
132: if(bf->advnc)
133: xadvance();
134: if(bf->rdptr.rnum >= bf->path[0]->kcnt)
135: return(EOF);
136: if(key != NULL) {
137: d = bf->rdptr.rptr;
138: key->mlen = d->dlen - DKEYSZ + d->dcom;
139: mvgbt(key->mdata, bf->rdptr.rpref, d->dcom);
140: mvgbt(key->mdata + d->dcom, d->dkey, d->dlen - DKEYSZ);
141: }
142: if(rec != NULL && !treeonly(bf)) {
143: x = lfadr(bf->path[0], bf->rdptr.rnum);
144: rec->mlen = x->llen;
145: if(rec->mlen != 0) {
146: (void) lseek(bf->dfd, x->lloc, 0);
147: (void) read(bf->dfd, rec->mdata, (int)rec->mlen);
148: }
149: /* errors on read ? */
150: }
151: bf->advnc = 1;
152: return(0);
153: }
154:
155: xstep(level)
156: /* ran off the end of node at lev-1 */
157: { hdr *b;
158: int n, i;
159: ndaddr u;
160: do {
161: n = read(curbf->tfd, (char *)curbf->path[0], NDSZ);
162: if(n == 0)
163: exit(0);
164: if(n != NDSZ) {
165: perror("xstep");
166: exit(1);
167: }
168: } while(curbf->path[0]->hlev != 0);
169: }
170:
171: xadvance()
172: { mbuf x;
173: dkey *dold, *dnew;
174: struct rdptr *y = &curbf->rdptr;
175: curbf->advnc = 0;
176: dold = y->rptr;
177: if(++y->rnum < curbf->path[0]->kcnt) {
178: dnew = (dkey *)((char *)dold + dold->dlen);
179: if(dold->dcom < dnew->dcom)
180: mvgbt(y->rpref + dold->dcom, dold->dkey, dnew->dcom - dold->dcom);
181: y->rptr = dnew;
182: return;
183: }
184: if(xstep(1) == EOF) {
185: y->rnum = curbf->path[0]->kcnt + 1;
186: y->rptr = NULL;
187: }
188: else {
189: y->rnum = 0;
190: y->rptr = (dkey *)(curbf->path[0] + 1);
191: }
192: }
193:
194: xfirst(p)
195: bfile *p;
196: { int n;
197: while(p->path[0]->hlev != 0) {
198: n = read(p->tfd, (char *)p->path[0], NDSZ);
199: if(n == 0) {
200: fprintf(stderr, "empty?\n");
201: exit(0);
202: }
203: if(n != NDSZ) {
204: perror("xfirst");
205: exit(1);
206: }
207: }
208: curbf->rdptr.rnum = 0;
209: curbf->rdptr.rptr = (dkey *)(curbf->path[0] + 1);
210: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.