2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #define VICE /* control whether AFS changes are present */
19 #include <sys/mount.h>
20 #include <sys/vnode.h>
21 #include <ufs/inode.h>
22 #include <ufs/dinode.h>
23 #include <sys/proplist.h>
31 #include <afs/osi_inode.h>
35 struct prop_entry_desc {
36 struct prop_entry_desc *next;
38 #define PROP_ENTRY_BAD 0x1
39 #define PROP_ENTRY_DUP 0x2
44 char name[PROPLIST_NAME_MAX];
48 proplist_scan(dp, idesc)
50 struct inodesc *idesc;
52 struct proplist_desc1 *pl_descp;
56 int offsetinbuf, blksize;
57 struct prop_entry_desc *entry_list, *next;
59 code = proplist_blkscan(dp, idesc, &entry_list);
63 proplist_markdup(entry_list);
65 code = proplist_updateblks(dp, idesc, entry_list);
69 ndp = ginode(idesc->id_number);
70 if ((ndp->di_flags & IC_PROPLIST) == 0) {
74 if ((ndp->di_flags & (IC_PROPLIST_BLOCK | IC_PROPLIST_FRAG)) ==
75 (IC_PROPLIST_BLOCK | IC_PROPLIST_FRAG)) {
79 if (ndp->di_flags & IC_PROPLIST_FRAG) {
80 idesc->id_numfrags = 1;
81 blksize = sblock.fs_fsize;
83 idesc->id_numfrags = sblock.fs_frag;
84 blksize = sblock.fs_bsize;
86 idesc->id_blkno = ndp->di_proplb;
88 code = (*idesc->id_func) (idesc);
92 bp = getdatablk(idesc->id_blkno, blksize);
93 for (offsetinbuf = 0; offsetinbuf < blksize;) {
95 (struct proplist_desc1 *)(bp->b_un.b_buf + offsetinbuf);
96 offsetinbuf += pl_descp->pl_nextentry;
98 if (pl_descp->pl_nextfsb > 0) {
101 save_blkno = pl_descp->pl_nextfsb;
102 bp->b_flags &= ~B_INUSE;
103 idesc->id_blkno = save_blkno;
104 blksize = sblock.fs_bsize;
105 idesc->id_numfrags = sblock.fs_frag;
108 bp->b_flags &= ~B_INUSE;
112 for (next = entry_list; entry_list != NULL;) {
113 next = entry_list->next;
121 proplist_blkscan(dp, idesc, entry_list)
123 struct inodesc *idesc;
124 struct prop_entry_desc **entry_list;
126 struct proplist_desc1 *pl_descp;
128 struct prop_entry_desc *entry, *lastentry;
130 long code, valueresid;
133 idesc->id_blkno = dp->di_proplb;
134 if (dp->di_flags & IC_PROPLIST_FRAG) {
135 blksize = sblock.fs_fsize;
136 idesc->id_numfrags = 1;
138 blksize = sblock.fs_bsize;
139 idesc->id_numfrags = sblock.fs_frag;
144 if (idesc->id_loc == 0) {
145 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) {
146 code = proplist_blkdel(dp, idesc, 0);
149 bp = getdatablk(idesc->id_blkno, blksize);
150 if (proplist_chkblock(bp, blksize)) {
151 bp->b_flags &= ~B_INUSE;
152 pwarn("PROPERTY LIST BLOCK CORRUPTED I=%u", idesc->id_number);
154 printf(" (CLEARED)\n");
155 else if (reply("CLEAR") == 0)
157 code = proplist_blkdel(dp, idesc, 0);
161 pl_descp = (struct proplist_desc1 *)(bp->b_un.b_buf + idesc->id_loc);
162 if (pl_descp->pl_entrysize) {
165 && strcmp((char *)&pl_descp[1], entry->name))) {
166 entry->flags |= PROP_ENTRY_BAD;
169 if (valueresid == 0) {
170 entry = (struct prop_entry_desc *)
171 malloc(sizeof(struct prop_entry_desc));
176 memcpy(entry->name, (char *)&pl_descp[1],
177 pl_descp->pl_namelen);
178 entry->blkno = idesc->id_blkno;
179 entry->blksize = blksize;
180 entry->offset = idesc->id_loc;
182 if (*entry_list != NULL)
183 lastentry->next = entry;
187 valueresid = pl_descp->pl_valuelen;
189 entry->size += pl_descp->pl_entrysize;
190 valueresid -= pl_descp->pl_valuelen_entry;
192 if (pl_descp->pl_nextfsb > 0) {
195 save_blkno = pl_descp->pl_nextfsb;
196 bp->b_flags &= ~B_INUSE;
197 idesc->id_blkno = save_blkno;
198 idesc->id_numfrags = sblock.fs_frag;
199 blksize = sblock.fs_bsize;
203 idesc->id_loc += pl_descp->pl_nextentry;
204 if (idesc->id_loc == blksize) {
205 bp->b_flags &= ~B_INUSE;
207 entry->flags |= PROP_ENTRY_BAD;
216 proplist_markdup(entry_list)
217 struct prop_entry_desc *entry_list;
219 struct prop_entry_desc *start, *cur;
220 int bad_entries, dup_entries;
222 for (start = entry_list; start != NULL; start = start->next) {
223 if (start->flags & (PROP_ENTRY_BAD | PROP_ENTRY_DUP))
225 for (cur = start->next; cur != NULL; cur = cur->next) {
226 if (!strcmp(start->name, cur->name))
227 cur->flags |= PROP_ENTRY_DUP;
234 proplist_updateblks(dp, idesc, entry_list)
236 struct inodesc *idesc;
237 struct prop_entry_desc *entry_list;
239 struct proplist_desc1 *pl_descp, *prev_pl_descp;
241 struct prop_entry_desc *cur;
244 int resid, offset, free, blksize;
246 for (cur = entry_list; cur != NULL; cur = cur->next) {
249 idesc->id_blkno = cur->blkno;
250 idesc->id_loc = cur->offset;
251 blksize = cur->blksize;
253 if (cur->flags & PROP_ENTRY_BAD)
254 pwarn("BAD PROPERTY LIST ENTRY FOUND I=%u NAME %0.10s",
255 idesc->id_number, cur->name);
257 pwarn("DUP PROPERTY LIST ENTRY FOUND I=%u NAME %0.10s",
258 idesc->id_number, cur->name);
260 printf(" (FIXED)\n");
261 else if (reply("FIX") == 0)
263 for (resid = cur->size; resid > 0;) {
264 bp = getdatablk(idesc->id_blkno, blksize);
266 (struct proplist_desc1 *)(bp->b_un.b_buf + idesc->id_loc);
267 if (strcmp((char *)&pl_descp[1], cur->name)) {
268 bp->b_flags &= ~B_INUSE;
272 prev_pl_descp = (struct proplist_desc1 *)bp->b_un.b_buf;
273 for (offset = 0; offset < cur->offset;) {
275 (struct proplist_desc1 *)(bp->b_un.b_buf + offset);
276 offset += prev_pl_descp->pl_nextentry;
279 * prev_pl_descp now points to the entry
280 * before the one we need to delete
282 * Coalesce into previous entry
284 prev_pl_descp->pl_nextentry += pl_descp->pl_nextentry;
285 prev_pl_descp->pl_nextfsb = pl_descp->pl_nextfsb;
287 resid -= pl_descp->pl_entrysize;
288 pl_descp->pl_entrysize = 0;
289 pl_descp->pl_namelen = 0;
290 pl_descp->pl_valuelen = 0;
292 next_blkno = pl_descp->pl_nextfsb;
293 free = prop_avail(bp, blksize);
296 proplist_blkdel(dp, idesc, next_blkno);
298 if (next_blkno && resid > 0) {
299 idesc->id_blkno = next_blkno;
300 blksize = sblock.fs_bsize;
311 prop_avail(bp, blksize)
315 struct proplist_desc1 *pl_descp;
316 int offsetinbuf, total_avail;
319 for (offsetinbuf = 0; offsetinbuf < blksize;) {
320 pl_descp = (struct proplist_desc1 *)(bp->b_un.b_buf + offsetinbuf);
321 total_avail += (pl_descp->pl_nextentry - pl_descp->pl_entrysize);
322 offsetinbuf += pl_descp->pl_nextentry;
324 return (total_avail);
328 proplist_chkblock(bp, blksize)
332 struct proplist_desc1 *pl_descp;
335 for (offsetinbuf = 0; offsetinbuf < blksize;) {
336 pl_descp = (struct proplist_desc1 *)(bp->b_un.b_buf + offsetinbuf);
337 if (pl_descp->pl_magic != PROP_LIST_MAGIC_VERS1) {
340 if (pl_descp->pl_entrysize % 8 || pl_descp->pl_nextentry % 8
341 || pl_descp->pl_nextentry < UFSPROPLIST_STRUCT
342 || pl_descp->pl_nextentry + offsetinbuf > blksize) {
345 if (pl_descp->pl_entrysize
346 && (pl_descp->pl_namelen > PROPLIST_NAME_MAX
347 || pl_descp->pl_valuelen_entry > pl_descp->pl_valuelen
348 || pl_descp->pl_entrysize > pl_descp->pl_nextentry
349 || pl_descp->pl_entrysize !=
350 UFSPROPLIST_SIZE(pl_descp->pl_namelen,
351 pl_descp->pl_valuelen_entry)
352 || strlen((char *)&pl_descp[1]) > pl_descp->pl_namelen)) {
355 offsetinbuf += pl_descp->pl_nextentry;
356 if (offsetinbuf == blksize) {
357 bp->b_flags &= ~B_INUSE;
361 if (offsetinbuf != blksize) {
369 proplist_blkdel(dp, idesc, nextblk)
371 struct inodesc *idesc;
374 struct proplist_desc1 *pl_descp;
379 badblkno = idesc->id_blkno;
380 if (dp->di_proplb == badblkno) {
381 dp = ginode(idesc->id_number);
382 dp->di_proplb = nextblk;
383 dp->di_flags &= ~IC_PROPLIST;
385 dp->di_flags |= IC_PROPLIST_BLOCK;
389 idesc->id_blkno = dp->di_proplb;
390 if (dp->di_flags & IC_PROPLIST_FRAG) {
391 blksize = sblock.fs_fsize;
392 idesc->id_numfrags = 1;
394 blksize = sblock.fs_bsize;
395 idesc->id_numfrags = sblock.fs_frag;
397 bp = getdatablk(idesc->id_blkno, blksize);
400 pl_descp = (struct proplist_desc1 *)(bp->b_un.b_buf + idesc->id_loc);
401 if (pl_descp->pl_nextfsb > 0) {
404 if (pl_descp->pl_nextfsb == badblkno) {
405 pl_descp->pl_nextfsb = nextblk;
409 save_blkno = pl_descp->pl_nextfsb;
410 bp->b_flags &= ~B_INUSE;
411 idesc->id_blkno = save_blkno;
412 idesc->id_numfrags = sblock.fs_frag;
413 blksize = sblock.fs_bsize;
414 bp = getdatablk(save_blkno, blksize);
418 idesc->id_loc += pl_descp->pl_nextentry;
419 if (idesc->id_loc == blksize) {
420 bp->b_flags &= ~B_INUSE;
427 #endif /* AFS_OSF_ENV */