3 * dumpscan - routines for scanning and manipulating AFS volume dumps
5 * Copyright (c) 1998 Carnegie Mellon University
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
29 /* pathname.c - Pathname lookup and traversal */
35 #include "dumpscan_errs.h"
37 /* Hash function for a vnode */
38 #define BUCKET_SIZE 32
39 #define vnode_hash(phi,vnode) ((vnode) & ((1 << (phi)->hash_size) - 1))
43 get_vhash_ent(path_hashinfo * phi, afs_uint32 vnode, int make)
45 int key = vnode_hash(phi, vnode);
48 for (vhe = phi->hash_table[key]; vhe && vhe->vnode != vnode;
51 vhe = (vhash_ent *) malloc(sizeof(vhash_ent));
53 memset(vhe, 0, sizeof(vhash_ent));
55 vhe->next = phi->hash_table[key];
56 phi->hash_table[key] = vhe;
64 volhdr_cb(afs_vol_header * hdr, XFILE * X, void *refcon)
66 path_hashinfo *phi = (path_hashinfo *) refcon;
69 if (hdr->field_mask & F_VOLHDR_NFILES) {
70 nfiles = phi->n_vnodes = hdr->nfiles;
71 for (phi->hash_size = 1; nfiles > BUCKET_SIZE;
72 phi->hash_size++, nfiles >>= 1);
73 hsize = (1 << phi->hash_size);
74 phi->hash_table = (vhash_ent **) malloc(hsize * sizeof(vhash_ent *));
77 memset(phi->hash_table, 0, hsize * sizeof(vhash_ent *));
81 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
82 "File count missing from volume header");
89 vnode_keep(afs_vnode * v, XFILE * X, void *refcon)
91 path_hashinfo *phi = (path_hashinfo *) refcon;
94 if (!phi->hash_table) {
96 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->refcon,
97 "No volume header in dump???");
100 vhe = get_vhash_ent(phi, v->vnode, 1);
103 cp64(vhe->v_offset, v->offset);
104 if (v->field_mask & F_VNODE_PARENT)
105 vhe->parent = v->parent;
106 if (v->field_mask & F_VNODE_DATA) {
107 cp64(vhe->d_offset, v->d_offset);
108 vhe->d_size = v->size;
110 if ((v->field_mask & F_VNODE_TYPE) && v->type == vDirectory)
119 vnode_stop(afs_vnode * v, XFILE * X, void *refcon)
121 path_hashinfo *phi = (path_hashinfo *) refcon;
124 /* If the file is seekable, try to position so we can pick up later... */
125 if (phi->p->flags && DSFLAG_SEEK)
126 if (r = xfseek(X, &v->offset))
133 dirent_cb(afs_vnode * v, afs_dir_entry * de, XFILE * X, void *refcon)
135 path_hashinfo *phi = (path_hashinfo *) refcon;
138 if (!phi->hash_table) {
139 if (phi->p->cb_error)
140 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->refcon,
141 "No volume header in dump???");
144 if (!strcmp(de->name, ".") || !strcmp(de->name, ".."))
146 vhe = get_vhash_ent(phi, de->vnode, 1);
149 vhe->parent = v->vnode;
154 /* Prescan the vnodes in a dump file, collecting information that will
155 * be useful in generating and following pathnames.
158 Path_PreScan(XFILE * X, path_hashinfo * phi, int full)
160 dump_parser my_p, *p = phi->p;
163 memset(phi, 0, sizeof(path_hashinfo));
165 memset(&my_p, 0, sizeof(my_p));
166 my_p.refcon = (void *)phi;
167 my_p.cb_volhdr = volhdr_cb;
168 my_p.cb_vnode_dir = vnode_keep;
170 my_p.cb_vnode_file = vnode_keep;
171 my_p.cb_vnode_link = vnode_keep;
172 my_p.cb_vnode_empty = vnode_keep;
173 my_p.cb_vnode_wierd = vnode_keep;
175 my_p.cb_vnode_file = vnode_stop;
176 my_p.cb_vnode_link = vnode_stop;
177 my_p.cb_vnode_empty = vnode_stop;
178 my_p.cb_vnode_wierd = vnode_stop;
180 my_p.err_refcon = p->err_refcon;
181 my_p.cb_error = p->cb_error;
182 my_p.cb_dirent = dirent_cb;
183 my_p.flags = p->flags;
184 my_p.print_flags = p->print_flags;
185 my_p.repair_flags = p->repair_flags;
187 return ParseDumpFile(X, &my_p);
191 /* Free the hash table in a path_hashinfo */
193 Path_FreeHashTable(path_hashinfo * phi)
196 vhash_ent *vhe, *next_vhe;
198 if (phi->hash_table) {
199 size = (1 << phi->hash_size);
200 for (i = 0; i < size; i++)
201 for (vhe = phi->hash_table[i]; vhe; vhe = next_vhe) {
202 next_vhe = vhe->next;
205 free(phi->hash_table);
210 /* Follow a pathname to the vnode it represents */
212 Path_Follow(XFILE * X, path_hashinfo * phi, char *path, vhash_ent * his_vhe)
216 afs_uint32 r, vnum = 1;
220 name = strtok(path, "/");
222 for (name = strtok(path, "/"); name; name = strtok(0, "/")) {
224 if (phi->p->cb_error)
225 (phi->p->cb_error) (ENOTDIR, 1, phi->p->err_refcon,
226 "Not a directory vnode");
229 vhe = get_vhash_ent(phi, vnum, 0);
231 if (phi->p->cb_error)
232 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
233 "Vnode %d not found in hash table", vnum);
236 if (zero64(vhe->d_offset)) {
237 if (phi->p->cb_error)
238 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
239 "Directory vnode %d is incomplete", vnum);
242 if (r = xfseek(X, &vhe->d_offset)) {
243 if (phi->p->cb_error)
244 (phi->p->cb_error) (r, 1, phi->p->err_refcon,
245 "Unable to seek to directory %d", vnum);
249 r = DirectoryLookup(X, phi->p, vhe->d_size, &name, &vnum, 0);
253 if (phi->p->cb_error)
254 (phi->p->cb_error) (ENOENT, 1, phi->p->err_refcon,
259 vhe = get_vhash_ent(phi, vnum, 0);
261 if (phi->p->cb_error)
262 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
263 "Vnode %d not found in hash table", vnum);
273 Path_Build(XFILE * X, path_hashinfo * phi, afs_uint32 vnode, char **his_path,
277 char *name, *path = 0, fastbuf[12];
279 afs_uint32 parent, r;
283 *his_path = (char *)malloc(2);
285 if (phi->p->cb_error)
286 (phi->p->cb_error) (ENOMEM, 1, phi->p->err_refcon,
287 "No memory for pathname of vnode 1");
290 strcpy(*his_path, "/");
295 vhe = get_vhash_ent(phi, vnode, 0);
297 if (phi->p->cb_error)
298 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
299 "Vnode %d not found in hash table", vnode);
303 /* Find the parent */
305 if (phi->p->cb_error)
306 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
307 "Vnode %d has no parent?", vnode);
312 parent = vhe->parent;
313 vhe = get_vhash_ent(phi, parent, 0);
314 if (phi->p->print_flags & DSPRINT_DEBUG)
315 fprintf(stderr, "Searching for vnode %d in parent %d\n", vnode,
318 if (phi->p->cb_error)
319 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
320 "Vnode %d not found in hash table",
328 /* Make up a path component from the vnode number */
329 sprintf(fastbuf, "%d", vnode);
332 /* Do a reverse-lookup in the parent directory */
333 if (zero64(vhe->d_offset)) {
334 if (phi->p->cb_error)
335 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
336 "Directory vnode %d is incomplete",
342 if (r = xfseek(X, &vhe->d_offset)) {
343 if (phi->p->cb_error)
344 (phi->p->cb_error) (errno, 1, phi->p->err_refcon,
345 "Unable to seek to directory %d",
353 r = DirectoryLookup(X, phi->p, vhe->d_size, &name, &vnode, 0);
357 if (phi->p->cb_error)
358 (phi->p->cb_error) (DSERR_FMT, 1, phi->p->err_refcon,
359 "No entry for vnode %d in directory %d",
369 path = (char *)realloc(path, nl + pl + 2);
371 if (phi->p->cb_error)
372 (phi->p->cb_error) (ENOMEM, 1, phi->p->err_refcon,
373 "No memory for pathname of vnode 1");
381 for (x = name, y = path + 1; *x;)
385 path = (char *)malloc(nl + 2);
387 if (phi->p->cb_error)
388 (phi->p->cb_error) (ENOMEM, 1, phi->p->err_refcon,
389 "No memory for pathname of vnode 1");
393 strcpy(path + 1, name);