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>
34 struct prop_entry_desc
{
35 struct prop_entry_desc
*next
;
37 #define PROP_ENTRY_BAD 0x1
38 #define PROP_ENTRY_DUP 0x2
43 char name
[PROPLIST_NAME_MAX
];
47 proplist_scan(dp
, idesc
)
49 struct inodesc
*idesc
;
51 struct proplist_desc1
*pl_descp
;
55 int offsetinbuf
, blksize
;
56 struct prop_entry_desc
*entry_list
, *next
;
58 code
= proplist_blkscan(dp
, idesc
, &entry_list
);
62 proplist_markdup(entry_list
);
64 code
= proplist_updateblks(dp
, idesc
, entry_list
);
68 ndp
= ginode(idesc
->id_number
);
69 if ((ndp
->di_flags
& IC_PROPLIST
) == 0) {
73 if ((ndp
->di_flags
& (IC_PROPLIST_BLOCK
| IC_PROPLIST_FRAG
)) ==
74 (IC_PROPLIST_BLOCK
| IC_PROPLIST_FRAG
)) {
78 if (ndp
->di_flags
& IC_PROPLIST_FRAG
) {
79 idesc
->id_numfrags
= 1;
80 blksize
= sblock
.fs_fsize
;
82 idesc
->id_numfrags
= sblock
.fs_frag
;
83 blksize
= sblock
.fs_bsize
;
85 idesc
->id_blkno
= ndp
->di_proplb
;
87 code
= (*idesc
->id_func
) (idesc
);
91 bp
= getdatablk(idesc
->id_blkno
, blksize
);
92 for (offsetinbuf
= 0; offsetinbuf
< blksize
;) {
94 (struct proplist_desc1
*)(bp
->b_un
.b_buf
+ offsetinbuf
);
95 offsetinbuf
+= pl_descp
->pl_nextentry
;
97 if (pl_descp
->pl_nextfsb
> 0) {
100 save_blkno
= pl_descp
->pl_nextfsb
;
101 bp
->b_flags
&= ~B_INUSE
;
102 idesc
->id_blkno
= save_blkno
;
103 blksize
= sblock
.fs_bsize
;
104 idesc
->id_numfrags
= sblock
.fs_frag
;
107 bp
->b_flags
&= ~B_INUSE
;
111 for (next
= entry_list
; entry_list
!= NULL
;) {
112 next
= entry_list
->next
;
120 proplist_blkscan(dp
, idesc
, entry_list
)
122 struct inodesc
*idesc
;
123 struct prop_entry_desc
**entry_list
;
125 struct proplist_desc1
*pl_descp
;
127 struct prop_entry_desc
*entry
, *lastentry
;
129 long code
, valueresid
;
132 idesc
->id_blkno
= dp
->di_proplb
;
133 if (dp
->di_flags
& IC_PROPLIST_FRAG
) {
134 blksize
= sblock
.fs_fsize
;
135 idesc
->id_numfrags
= 1;
137 blksize
= sblock
.fs_bsize
;
138 idesc
->id_numfrags
= sblock
.fs_frag
;
143 if (idesc
->id_loc
== 0) {
144 if (chkrange(idesc
->id_blkno
, idesc
->id_numfrags
)) {
145 code
= proplist_blkdel(dp
, idesc
, 0);
148 bp
= getdatablk(idesc
->id_blkno
, blksize
);
149 if (proplist_chkblock(bp
, blksize
)) {
150 bp
->b_flags
&= ~B_INUSE
;
151 pwarn("PROPERTY LIST BLOCK CORRUPTED I=%u", idesc
->id_number
);
153 printf(" (CLEARED)\n");
154 else if (reply("CLEAR") == 0)
156 code
= proplist_blkdel(dp
, idesc
, 0);
160 pl_descp
= (struct proplist_desc1
*)(bp
->b_un
.b_buf
+ idesc
->id_loc
);
161 if (pl_descp
->pl_entrysize
) {
164 && strcmp((char *)&pl_descp
[1], entry
->name
))) {
165 entry
->flags
|= PROP_ENTRY_BAD
;
168 if (valueresid
== 0) {
169 entry
= malloc(sizeof(struct prop_entry_desc
));
174 memcpy(entry
->name
, (char *)&pl_descp
[1],
175 pl_descp
->pl_namelen
);
176 entry
->blkno
= idesc
->id_blkno
;
177 entry
->blksize
= blksize
;
178 entry
->offset
= idesc
->id_loc
;
180 if (*entry_list
!= NULL
)
181 lastentry
->next
= entry
;
185 valueresid
= pl_descp
->pl_valuelen
;
187 entry
->size
+= pl_descp
->pl_entrysize
;
188 valueresid
-= pl_descp
->pl_valuelen_entry
;
190 if (pl_descp
->pl_nextfsb
> 0) {
193 save_blkno
= pl_descp
->pl_nextfsb
;
194 bp
->b_flags
&= ~B_INUSE
;
195 idesc
->id_blkno
= save_blkno
;
196 idesc
->id_numfrags
= sblock
.fs_frag
;
197 blksize
= sblock
.fs_bsize
;
201 idesc
->id_loc
+= pl_descp
->pl_nextentry
;
202 if (idesc
->id_loc
== blksize
) {
203 bp
->b_flags
&= ~B_INUSE
;
205 entry
->flags
|= PROP_ENTRY_BAD
;
214 proplist_markdup(entry_list
)
215 struct prop_entry_desc
*entry_list
;
217 struct prop_entry_desc
*start
, *cur
;
218 int bad_entries
, dup_entries
;
220 for (start
= entry_list
; start
!= NULL
; start
= start
->next
) {
221 if (start
->flags
& (PROP_ENTRY_BAD
| PROP_ENTRY_DUP
))
223 for (cur
= start
->next
; cur
!= NULL
; cur
= cur
->next
) {
224 if (!strcmp(start
->name
, cur
->name
))
225 cur
->flags
|= PROP_ENTRY_DUP
;
232 proplist_updateblks(dp
, idesc
, entry_list
)
234 struct inodesc
*idesc
;
235 struct prop_entry_desc
*entry_list
;
237 struct proplist_desc1
*pl_descp
, *prev_pl_descp
;
239 struct prop_entry_desc
*cur
;
242 int resid
, offset
, free
, blksize
;
244 for (cur
= entry_list
; cur
!= NULL
; cur
= cur
->next
) {
247 idesc
->id_blkno
= cur
->blkno
;
248 idesc
->id_loc
= cur
->offset
;
249 blksize
= cur
->blksize
;
251 if (cur
->flags
& PROP_ENTRY_BAD
)
252 pwarn("BAD PROPERTY LIST ENTRY FOUND I=%u NAME %0.10s",
253 idesc
->id_number
, cur
->name
);
255 pwarn("DUP PROPERTY LIST ENTRY FOUND I=%u NAME %0.10s",
256 idesc
->id_number
, cur
->name
);
258 printf(" (FIXED)\n");
259 else if (reply("FIX") == 0)
261 for (resid
= cur
->size
; resid
> 0;) {
262 bp
= getdatablk(idesc
->id_blkno
, blksize
);
264 (struct proplist_desc1
*)(bp
->b_un
.b_buf
+ idesc
->id_loc
);
265 if (strcmp((char *)&pl_descp
[1], cur
->name
)) {
266 bp
->b_flags
&= ~B_INUSE
;
270 prev_pl_descp
= (struct proplist_desc1
*)bp
->b_un
.b_buf
;
271 for (offset
= 0; offset
< cur
->offset
;) {
273 (struct proplist_desc1
*)(bp
->b_un
.b_buf
+ offset
);
274 offset
+= prev_pl_descp
->pl_nextentry
;
277 * prev_pl_descp now points to the entry
278 * before the one we need to delete
280 * Coalesce into previous entry
282 prev_pl_descp
->pl_nextentry
+= pl_descp
->pl_nextentry
;
283 prev_pl_descp
->pl_nextfsb
= pl_descp
->pl_nextfsb
;
285 resid
-= pl_descp
->pl_entrysize
;
286 pl_descp
->pl_entrysize
= 0;
287 pl_descp
->pl_namelen
= 0;
288 pl_descp
->pl_valuelen
= 0;
290 next_blkno
= pl_descp
->pl_nextfsb
;
291 free
= prop_avail(bp
, blksize
);
294 proplist_blkdel(dp
, idesc
, next_blkno
);
296 if (next_blkno
&& resid
> 0) {
297 idesc
->id_blkno
= next_blkno
;
298 blksize
= sblock
.fs_bsize
;
309 prop_avail(bp
, blksize
)
313 struct proplist_desc1
*pl_descp
;
314 int offsetinbuf
, total_avail
;
317 for (offsetinbuf
= 0; offsetinbuf
< blksize
;) {
318 pl_descp
= (struct proplist_desc1
*)(bp
->b_un
.b_buf
+ offsetinbuf
);
319 total_avail
+= (pl_descp
->pl_nextentry
- pl_descp
->pl_entrysize
);
320 offsetinbuf
+= pl_descp
->pl_nextentry
;
322 return (total_avail
);
326 proplist_chkblock(bp
, blksize
)
330 struct proplist_desc1
*pl_descp
;
333 for (offsetinbuf
= 0; offsetinbuf
< blksize
;) {
334 pl_descp
= (struct proplist_desc1
*)(bp
->b_un
.b_buf
+ offsetinbuf
);
335 if (pl_descp
->pl_magic
!= PROP_LIST_MAGIC_VERS1
) {
338 if (pl_descp
->pl_entrysize
% 8 || pl_descp
->pl_nextentry
% 8
339 || pl_descp
->pl_nextentry
< UFSPROPLIST_STRUCT
340 || pl_descp
->pl_nextentry
+ offsetinbuf
> blksize
) {
343 if (pl_descp
->pl_entrysize
344 && (pl_descp
->pl_namelen
> PROPLIST_NAME_MAX
345 || pl_descp
->pl_valuelen_entry
> pl_descp
->pl_valuelen
346 || pl_descp
->pl_entrysize
> pl_descp
->pl_nextentry
347 || pl_descp
->pl_entrysize
!=
348 UFSPROPLIST_SIZE(pl_descp
->pl_namelen
,
349 pl_descp
->pl_valuelen_entry
)
350 || strlen((char *)&pl_descp
[1]) > pl_descp
->pl_namelen
)) {
353 offsetinbuf
+= pl_descp
->pl_nextentry
;
354 if (offsetinbuf
== blksize
) {
355 bp
->b_flags
&= ~B_INUSE
;
359 if (offsetinbuf
!= blksize
) {
367 proplist_blkdel(dp
, idesc
, nextblk
)
369 struct inodesc
*idesc
;
372 struct proplist_desc1
*pl_descp
;
377 badblkno
= idesc
->id_blkno
;
378 if (dp
->di_proplb
== badblkno
) {
379 dp
= ginode(idesc
->id_number
);
380 dp
->di_proplb
= nextblk
;
381 dp
->di_flags
&= ~IC_PROPLIST
;
383 dp
->di_flags
|= IC_PROPLIST_BLOCK
;
387 idesc
->id_blkno
= dp
->di_proplb
;
388 if (dp
->di_flags
& IC_PROPLIST_FRAG
) {
389 blksize
= sblock
.fs_fsize
;
390 idesc
->id_numfrags
= 1;
392 blksize
= sblock
.fs_bsize
;
393 idesc
->id_numfrags
= sblock
.fs_frag
;
395 bp
= getdatablk(idesc
->id_blkno
, blksize
);
398 pl_descp
= (struct proplist_desc1
*)(bp
->b_un
.b_buf
+ idesc
->id_loc
);
399 if (pl_descp
->pl_nextfsb
> 0) {
402 if (pl_descp
->pl_nextfsb
== badblkno
) {
403 pl_descp
->pl_nextfsb
= nextblk
;
407 save_blkno
= pl_descp
->pl_nextfsb
;
408 bp
->b_flags
&= ~B_INUSE
;
409 idesc
->id_blkno
= save_blkno
;
410 idesc
->id_numfrags
= sblock
.fs_frag
;
411 blksize
= sblock
.fs_bsize
;
412 bp
= getdatablk(save_blkno
, blksize
);
416 idesc
->id_loc
+= pl_descp
->pl_nextentry
;
417 if (idesc
->id_loc
== blksize
) {
418 bp
->b_flags
&= ~B_INUSE
;
425 #endif /* AFS_OSF_ENV */