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>
14 #define VICE /* control whether AFS changes are present */
20 #include <sys/param.h>
21 #include <sys/mount.h>
22 #include <sys/vnode.h>
23 #include <ufs/inode.h>
24 #include <ufs/dinode.h>
25 #include <sys/proplist.h>
33 #include <afs/osi_inode.h>
37 struct prop_entry_desc {
38 struct prop_entry_desc *next;
40 #define PROP_ENTRY_BAD 0x1
41 #define PROP_ENTRY_DUP 0x2
46 char name[PROPLIST_NAME_MAX];
50 proplist_scan(dp, idesc)
52 struct inodesc *idesc;
54 struct proplist_desc1 *pl_descp;
58 int offsetinbuf, blksize;
59 struct prop_entry_desc *entry_list, *next;
61 code = proplist_blkscan(dp, idesc, &entry_list);
65 proplist_markdup(entry_list);
67 code = proplist_updateblks(dp, idesc, entry_list);
71 ndp = ginode(idesc->id_number);
72 if ((ndp->di_flags & IC_PROPLIST) == 0) {
76 if ((ndp->di_flags & (IC_PROPLIST_BLOCK | IC_PROPLIST_FRAG)) ==
77 (IC_PROPLIST_BLOCK | IC_PROPLIST_FRAG)) {
81 if (ndp->di_flags & IC_PROPLIST_FRAG) {
82 idesc->id_numfrags = 1;
83 blksize = sblock.fs_fsize;
85 idesc->id_numfrags = sblock.fs_frag;
86 blksize = sblock.fs_bsize;
88 idesc->id_blkno = ndp->di_proplb;
90 code = (*idesc->id_func) (idesc);
94 bp = getdatablk(idesc->id_blkno, blksize);
95 for (offsetinbuf = 0; offsetinbuf < blksize;) {
97 (struct proplist_desc1 *)(bp->b_un.b_buf + offsetinbuf);
98 offsetinbuf += pl_descp->pl_nextentry;
100 if (pl_descp->pl_nextfsb > 0) {
103 save_blkno = pl_descp->pl_nextfsb;
104 bp->b_flags &= ~B_INUSE;
105 idesc->id_blkno = save_blkno;
106 blksize = sblock.fs_bsize;
107 idesc->id_numfrags = sblock.fs_frag;
110 bp->b_flags &= ~B_INUSE;
114 for (next = entry_list; entry_list != NULL;) {
115 next = entry_list->next;
123 proplist_blkscan(dp, idesc, entry_list)
125 struct inodesc *idesc;
126 struct prop_entry_desc **entry_list;
128 struct proplist_desc1 *pl_descp;
130 struct prop_entry_desc *entry, *lastentry;
132 long code, valueresid;
135 idesc->id_blkno = dp->di_proplb;
136 if (dp->di_flags & IC_PROPLIST_FRAG) {
137 blksize = sblock.fs_fsize;
138 idesc->id_numfrags = 1;
140 blksize = sblock.fs_bsize;
141 idesc->id_numfrags = sblock.fs_frag;
146 if (idesc->id_loc == 0) {
147 if (chkrange(idesc->id_blkno, idesc->id_numfrags)) {
148 code = proplist_blkdel(dp, idesc, 0);
151 bp = getdatablk(idesc->id_blkno, blksize);
152 if (proplist_chkblock(bp, blksize)) {
153 bp->b_flags &= ~B_INUSE;
154 pwarn("PROPERTY LIST BLOCK CORRUPTED I=%u", idesc->id_number);
156 printf(" (CLEARED)\n");
157 else if (reply("CLEAR") == 0)
159 code = proplist_blkdel(dp, idesc, 0);
163 pl_descp = (struct proplist_desc1 *)(bp->b_un.b_buf + idesc->id_loc);
164 if (pl_descp->pl_entrysize) {
167 && strcmp((char *)&pl_descp[1], entry->name))) {
168 entry->flags |= PROP_ENTRY_BAD;
171 if (valueresid == 0) {
172 entry = (struct prop_entry_desc *)
173 malloc(sizeof(struct prop_entry_desc));
178 memcpy(entry->name, (char *)&pl_descp[1],
179 pl_descp->pl_namelen);
180 entry->blkno = idesc->id_blkno;
181 entry->blksize = blksize;
182 entry->offset = idesc->id_loc;
184 if (*entry_list != NULL)
185 lastentry->next = entry;
189 valueresid = pl_descp->pl_valuelen;
191 entry->size += pl_descp->pl_entrysize;
192 valueresid -= pl_descp->pl_valuelen_entry;
194 if (pl_descp->pl_nextfsb > 0) {
197 save_blkno = pl_descp->pl_nextfsb;
198 bp->b_flags &= ~B_INUSE;
199 idesc->id_blkno = save_blkno;
200 idesc->id_numfrags = sblock.fs_frag;
201 blksize = sblock.fs_bsize;
205 idesc->id_loc += pl_descp->pl_nextentry;
206 if (idesc->id_loc == blksize) {
207 bp->b_flags &= ~B_INUSE;
209 entry->flags |= PROP_ENTRY_BAD;
218 proplist_markdup(entry_list)
219 struct prop_entry_desc *entry_list;
221 struct prop_entry_desc *start, *cur;
222 int bad_entries, dup_entries;
224 for (start = entry_list; start != NULL; start = start->next) {
225 if (start->flags & (PROP_ENTRY_BAD | PROP_ENTRY_DUP))
227 for (cur = start->next; cur != NULL; cur = cur->next) {
228 if (!strcmp(start->name, cur->name))
229 cur->flags |= PROP_ENTRY_DUP;
236 proplist_updateblks(dp, idesc, entry_list)
238 struct inodesc *idesc;
239 struct prop_entry_desc *entry_list;
241 struct proplist_desc1 *pl_descp, *prev_pl_descp;
243 struct prop_entry_desc *cur;
246 int resid, offset, free, blksize;
248 for (cur = entry_list; cur != NULL; cur = cur->next) {
251 idesc->id_blkno = cur->blkno;
252 idesc->id_loc = cur->offset;
253 blksize = cur->blksize;
255 if (cur->flags & PROP_ENTRY_BAD)
256 pwarn("BAD PROPERTY LIST ENTRY FOUND I=%u NAME %0.10s",
257 idesc->id_number, cur->name);
259 pwarn("DUP PROPERTY LIST ENTRY FOUND I=%u NAME %0.10s",
260 idesc->id_number, cur->name);
262 printf(" (FIXED)\n");
263 else if (reply("FIX") == 0)
265 for (resid = cur->size; resid > 0;) {
266 bp = getdatablk(idesc->id_blkno, blksize);
268 (struct proplist_desc1 *)(bp->b_un.b_buf + idesc->id_loc);
269 if (strcmp((char *)&pl_descp[1], cur->name)) {
270 bp->b_flags &= ~B_INUSE;
274 prev_pl_descp = (struct proplist_desc1 *)bp->b_un.b_buf;
275 for (offset = 0; offset < cur->offset;) {
277 (struct proplist_desc1 *)(bp->b_un.b_buf + offset);
278 offset += prev_pl_descp->pl_nextentry;
281 * prev_pl_descp now points to the entry
282 * before the one we need to delete
284 * Coalesce into previous entry
286 prev_pl_descp->pl_nextentry += pl_descp->pl_nextentry;
287 prev_pl_descp->pl_nextfsb = pl_descp->pl_nextfsb;
289 resid -= pl_descp->pl_entrysize;
290 pl_descp->pl_entrysize = 0;
291 pl_descp->pl_namelen = 0;
292 pl_descp->pl_valuelen = 0;
294 next_blkno = pl_descp->pl_nextfsb;
295 free = prop_avail(bp, blksize);
298 proplist_blkdel(dp, idesc, next_blkno);
300 if (next_blkno && resid > 0) {
301 idesc->id_blkno = next_blkno;
302 blksize = sblock.fs_bsize;
313 prop_avail(bp, blksize)
317 struct proplist_desc1 *pl_descp;
318 int offsetinbuf, total_avail;
321 for (offsetinbuf = 0; offsetinbuf < blksize;) {
322 pl_descp = (struct proplist_desc1 *)(bp->b_un.b_buf + offsetinbuf);
323 total_avail += (pl_descp->pl_nextentry - pl_descp->pl_entrysize);
324 offsetinbuf += pl_descp->pl_nextentry;
326 return (total_avail);
330 proplist_chkblock(bp, blksize)
334 struct proplist_desc1 *pl_descp;
337 for (offsetinbuf = 0; offsetinbuf < blksize;) {
338 pl_descp = (struct proplist_desc1 *)(bp->b_un.b_buf + offsetinbuf);
339 if (pl_descp->pl_magic != PROP_LIST_MAGIC_VERS1) {
342 if (pl_descp->pl_entrysize % 8 || pl_descp->pl_nextentry % 8
343 || pl_descp->pl_nextentry < UFSPROPLIST_STRUCT
344 || pl_descp->pl_nextentry + offsetinbuf > blksize) {
347 if (pl_descp->pl_entrysize
348 && (pl_descp->pl_namelen > PROPLIST_NAME_MAX
349 || pl_descp->pl_valuelen_entry > pl_descp->pl_valuelen
350 || pl_descp->pl_entrysize > pl_descp->pl_nextentry
351 || pl_descp->pl_entrysize !=
352 UFSPROPLIST_SIZE(pl_descp->pl_namelen,
353 pl_descp->pl_valuelen_entry)
354 || strlen((char *)&pl_descp[1]) > pl_descp->pl_namelen)) {
357 offsetinbuf += pl_descp->pl_nextentry;
358 if (offsetinbuf == blksize) {
359 bp->b_flags &= ~B_INUSE;
363 if (offsetinbuf != blksize) {
371 proplist_blkdel(dp, idesc, nextblk)
373 struct inodesc *idesc;
376 struct proplist_desc1 *pl_descp;
381 badblkno = idesc->id_blkno;
382 if (dp->di_proplb == badblkno) {
383 dp = ginode(idesc->id_number);
384 dp->di_proplb = nextblk;
385 dp->di_flags &= ~IC_PROPLIST;
387 dp->di_flags |= IC_PROPLIST_BLOCK;
391 idesc->id_blkno = dp->di_proplb;
392 if (dp->di_flags & IC_PROPLIST_FRAG) {
393 blksize = sblock.fs_fsize;
394 idesc->id_numfrags = 1;
396 blksize = sblock.fs_bsize;
397 idesc->id_numfrags = sblock.fs_frag;
399 bp = getdatablk(idesc->id_blkno, blksize);
402 pl_descp = (struct proplist_desc1 *)(bp->b_un.b_buf + idesc->id_loc);
403 if (pl_descp->pl_nextfsb > 0) {
406 if (pl_descp->pl_nextfsb == badblkno) {
407 pl_descp->pl_nextfsb = nextblk;
411 save_blkno = pl_descp->pl_nextfsb;
412 bp->b_flags &= ~B_INUSE;
413 idesc->id_blkno = save_blkno;
414 idesc->id_numfrags = sblock.fs_frag;
415 blksize = sblock.fs_bsize;
416 bp = getdatablk(save_blkno, blksize);
420 idesc->id_loc += pl_descp->pl_nextentry;
421 if (idesc->id_loc == blksize) {
422 bp->b_flags &= ~B_INUSE;
429 #endif /* AFS_OSF_ENV */