comparison ffstools/tiffs-rd/tree.c @ 0:e7502631a0f9

initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 11 Jun 2016 00:13:35 +0000
parents
children 1f27fc13eab7
comparison
equal deleted inserted replaced
-1:000000000000 0:e7502631a0f9
1 /*
2 * This C module implements operations on the tree level.
3 */
4
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <strings.h>
10 #include "types.h"
11 #include "struct.h"
12 #include "globals.h"
13 #include "pathname.h"
14
15 static void
16 visible_walk_dir(pathbuf_start, pathbuf_ptr, dirino, depth, callback)
17 char *pathbuf_start, *pathbuf_ptr;
18 void (*callback)();
19 {
20 int ndepth = depth + 1;
21 int child;
22 struct inode_info *inf;
23
24 if (depth > MAX_DIR_NEST) {
25 fprintf(stderr,
26 "error: max dir nesting exceeded at inode #%x\n",
27 dirino);
28 return;
29 }
30 for (child = inode_info[dirino]->descend; child; child = inf->sibling) {
31 if (!validate_inode(child)) {
32 fprintf(stderr,
33 "error: walk of visible tree hit invalid inode #%x\n",
34 child);
35 return;
36 }
37 inf = inode_info[child];
38 switch (inf->type) {
39 case 0x00:
40 /* walking the *visible* tree: skip deleted objects */
41 continue;
42 case 0xF4:
43 fprintf(stderr,
44 "warning: directory #%x has child #%x of type segment (F4), skipping\n",
45 dirino, child);
46 continue;
47 }
48 if (!validate_obj_name(child, 0)) {
49 fprintf(stderr,
50 "visible tree walk error: no valid name for inode #%x\n",
51 child);
52 continue;
53 }
54 sprintf(pathbuf_ptr, "/%s", inf->dataptr);
55 callback(pathbuf_start, child, ndepth);
56 if (inf->type == 0xF2)
57 visible_walk_dir(pathbuf_start,
58 index(pathbuf_ptr, '\0'), child,
59 ndepth, callback);
60 }
61 }
62
63 traverse_visible_tree(callback)
64 void (*callback)();
65 {
66 char pathbuf[PATHNAME_BUF_SIZE];
67
68 visible_walk_dir(pathbuf, pathbuf, root_inode, 0, callback);
69 }
70
71 /*
72 * The following function iterates through the descendants of a directory
73 * object looking for a specific directory-member filename.
74 *
75 * Arguments:
76 * - inode # of the parent directory
77 * - inode # of the first descendant (descendant pointer from the dir object)
78 * - filename to search for
79 *
80 * Returns: inode # of the sought descendant object if found, 0 otherwise.
81 */
82 find_dir_member(dirino, first_descend, srchname)
83 char *srchname;
84 {
85 int ino;
86 struct inode_info *inf;
87
88 for (ino = first_descend; ino; ino = inf->sibling) {
89 if (!validate_inode(ino)) {
90 fprintf(stderr,
91 "error: pathname search hit invalid inode #%x\n",
92 ino);
93 exit(1);
94 }
95 inf = inode_info[ino];
96 switch (inf->type) {
97 case 0x00:
98 /* walking the *visible* tree: skip deleted objects */
99 continue;
100 case 0xF4:
101 fprintf(stderr,
102 "warning: directory #%x has child #%x of type segment (F4), skipping\n",
103 dirino, ino);
104 continue;
105 }
106 if (!validate_obj_name(ino, 0)) {
107 fprintf(stderr,
108 "visible tree walk error: no valid name for inode #%x\n",
109 ino);
110 continue;
111 }
112 if (!strcmp(inf->dataptr, srchname))
113 return(ino);
114 }
115 return(0);
116 }
117
118 /*
119 * The following function searches for a pathname from the root down.
120 * Returns the inode # if found, otherwise exits with an error message
121 * indicating which step failed.
122 *
123 * Warning: the pathname in the argument buffer will be destroyed:
124 * 0s put in place of the slashes.
125 */
126 find_pathname(pathname)
127 char *pathname;
128 {
129 char *cur, *next;
130 int ino;
131 struct inode_info *inf;
132
133 cur = pathname;
134 if (*cur == '/')
135 cur++;
136 else {
137 fprintf(stderr,
138 "bad pathname \"%s\": TIFFS pathnames must be absolute\n",
139 pathname);
140 exit(1);
141 }
142 for (ino = root_inode; cur; cur = next) {
143 if (!*cur)
144 break;
145 next = index(cur, '/');
146 if (next == cur) {
147 fprintf(stderr,
148 "malformed pathname: multiple adjacent slashes\n");
149 exit(1);
150 }
151 if (next)
152 *next++ = '\0';
153 inf = inode_info[ino];
154 if (inf->type != 0xF2) {
155 fprintf(stderr,
156 "pathname search error: encountered a non-directory\n");
157 exit(1);
158 }
159 ino = find_dir_member(ino, inf->descend, cur);
160 if (!ino) {
161 fprintf(stderr,
162 "pathname search error: component name not found\n");
163 exit(1);
164 }
165 }
166 return(ino);
167 }
168
169 /*
170 * treewalk_all() walks the entire inode tree from the root down, without
171 * regard to object types, including deleted objects and even reclaimed ones.
172 * The output is the filling of the parent and nparents fields in the inode
173 * info array.
174 */
175
176 static void
177 treewalk_all_node(parent)
178 {
179 int child;
180 struct inode_info *inf;
181
182 for (child = inode_info[parent]->descend; child; child = inf->sibling) {
183 if (!validate_inode(child)) {
184 fprintf(stderr,
185 "error: walk of complete tree hit invalid inode #%x\n",
186 child);
187 return;
188 }
189 inf = inode_info[child];
190 inf->parent = parent;
191 inf->nparents++;
192 if (inf->nparents >= inode_limit) {
193 fprintf(stderr,
194 "error: detected loop in inode tree at #%x, child of #%x\n",
195 child, parent);
196 return;
197 }
198 if (inf->nparents == 1)
199 treewalk_all_node(child);
200 }
201 }
202
203 treewalk_all()
204 {
205 treewalk_all_node(root_inode);
206 }
207
208 pathname_of_inode(ino, pnbuf)
209 char *pnbuf;
210 {
211 int level;
212 char *revpath[MAX_DIR_NEST+1];
213 struct inode_info *inf;
214 char *op;
215
216 for (level = 0; ino != root_inode; ino = inf->parent) {
217 if (!validate_obj_name(ino, 0))
218 return(-1);
219 inf = inode_info[ino];
220 if (!inf->parent)
221 return(-1);
222 if (level > MAX_DIR_NEST)
223 return(-1);
224 revpath[level++] = (char *) inf->dataptr;
225 }
226 op = pnbuf;
227 if (!level)
228 *op++ = '/';
229 while (level) {
230 level--;
231 *op++ = '/';
232 strcpy(op, revpath[level]);
233 op = index(op, '\0');
234 }
235 *op = '\0';
236 return(0);
237 }