revert between 56095 -> 55830 in arch
[AROS.git] / rom / filesys / afs / filehandles3.c
blobb35ecf4a41ab114f9571fcbeeaba7187918e242d
1 /*
2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #ifndef DEBUG
7 #define DEBUG 0
8 #endif
10 #include <stddef.h>
11 #include "os.h"
12 #include "filehandles3.h"
13 #include "afsblocks.h"
14 #include "cache.h"
15 #include "hashing.h"
16 #include "baseredef.h"
18 LONG sameLock(struct AfsHandle *ah1, struct AfsHandle *ah2) {
20 return (ah1->header_block == ah2->header_block) ? LOCK_SAME : LOCK_DIFFERENT;
23 static const ULONG sizes[]=
26 offsetof(struct ExAllData,ed_Type),
27 offsetof(struct ExAllData,ed_Size),
28 offsetof(struct ExAllData,ed_Prot),
29 offsetof(struct ExAllData,ed_Days),
30 offsetof(struct ExAllData,ed_Comment),
31 offsetof(struct ExAllData,ed_OwnerUID),
32 sizeof(struct ExAllData)
35 ULONG examineEAD
37 struct AFSBase *afsbase,
38 struct Volume *volume,
39 struct ExAllData *ead,
40 struct BlockCache *entryblock,
41 ULONG size,
42 ULONG mode
45 STRPTR next,end,name;
46 ULONG owner;
48 next = (STRPTR)ead+sizes[mode];
49 end = (STRPTR)ead+size;
51 if (next > end) /* > is correct. Not >= */
52 return ERROR_BUFFER_OVERFLOW;
54 switch (mode)
56 case ED_OWNER :
57 owner = OS_BE2LONG(entryblock->buffer[BLK_OWNER(volume)]);
58 ead->ed_OwnerUID = owner>>16;
59 ead->ed_OwnerGID = owner & 0xFFFF;
60 case ED_COMMENT :
61 if (OS_BE2LONG(entryblock->buffer[BLK_SECONDARY_TYPE(volume)]) != ST_ROOT)
63 name = (STRPTR)((char *)entryblock->buffer+(BLK_COMMENT_START(volume)*4));
64 if ((next+name[0]+1) > end)
65 return ERROR_BUFFER_OVERFLOW;
66 ead->ed_Comment = next;
67 CopyMem(name+1, ead->ed_Comment, name[0]);
68 ead->ed_Comment[(ULONG)name[0]] = 0;
69 next += name[0]+1; /* NULL-Byte */
71 else
72 ead->ed_Comment = 0;
73 case ED_DATE :
74 ead->ed_Days = OS_BE2LONG(entryblock->buffer[BLK_DAYS(volume)]);
75 ead->ed_Mins = OS_BE2LONG(entryblock->buffer[BLK_MINS(volume)]);
76 ead->ed_Ticks = OS_BE2LONG(entryblock->buffer[BLK_TICKS(volume)]);
77 case ED_PROTECTION :
78 ead->ed_Prot = OS_BE2LONG(entryblock->buffer[BLK_PROTECT(volume)]);
79 case ED_SIZE :
80 ead->ed_Size = OS_BE2LONG(entryblock->buffer[BLK_BYTE_SIZE(volume)]);
81 case ED_TYPE :
82 ead->ed_Type = OS_BE2LONG(entryblock->buffer[BLK_SECONDARY_TYPE(volume)]);
83 case ED_NAME :
84 name = (STRPTR)((char *)entryblock->buffer+(BLK_FILENAME_START(volume)*4));
85 if ((next+name[0]+1) > end)
86 return ERROR_BUFFER_OVERFLOW;
87 ead->ed_Name = next;
88 CopyMem(name+1, ead->ed_Name, name[0]);
89 ead->ed_Name[(ULONG)name[0]] = 0;
90 next += name[0]+1; /* NULL-Byte */
91 case 0 :
92 ead->ed_Next = (struct ExAllData *)(((IPTR)next + OS_PTRALIGN - 1) & ~(OS_PTRALIGN - 1));
94 return 0;
97 ULONG examine
99 struct AFSBase *afsbase,
100 struct AfsHandle *ah,
101 struct ExAllData *ead,
102 ULONG size,
103 ULONG mode,
104 IPTR *dirpos
107 struct BlockCache *entryblock;
109 D(bug("[afs] examine(%ld,ead,%ld,%ld)\n",ah->header_block,size,mode));
110 if (mode > ED_OWNER)
111 return ERROR_BAD_NUMBER;
112 entryblock = getBlock(afsbase, ah->volume, ah->header_block);
113 if (entryblock == NULL)
114 return ERROR_UNKNOWN;
115 examineEAD(afsbase, ah->volume, ead, entryblock, size, mode);
116 *dirpos = ah->header_block;
117 return 0;
120 ULONG getNextExamineBlock
121 (struct AFSBase *afsbase, struct AfsHandle *ah, ULONG *key, ULONG *pos)
123 struct BlockCache *entryblock;
124 UBYTE cstr[34];
125 STRPTR string;
127 entryblock = getBlock(afsbase, ah->volume, *key);
128 if (entryblock == NULL)
129 return ERROR_UNKNOWN;
130 if (*key == ah->header_block) /* start examining entries in ah */
132 *pos = BLK_TABLE_START;
134 else
136 if (entryblock->buffer[BLK_HASHCHAIN(ah->volume)] != 0)
138 /* chained entry */
139 *pos = BLK_HASHCHAIN(ah->volume);
141 else
143 string = (char *)entryblock->buffer+(BLK_FILENAME_START(ah->volume)*4);
144 CopyMem(string+1, cstr, string[0]);
145 cstr[(ULONG)string[0]] = 0;
146 *pos = BLK_TABLE_START+getHashKey(cstr, ah->volume->SizeBlock-56, ah->volume->dosflags)+1;
147 if (*pos > BLK_TABLE_END(ah->volume))
148 return ERROR_NO_MORE_ENTRIES;
149 entryblock = getBlock(afsbase, ah->volume, ah->header_block);
150 if (entryblock == NULL)
151 return ERROR_UNKNOWN;
154 /* in one case entryblock->buffer[i] points to a block
155 which should be examined next
156 in the other cases it may point to NULL */
157 while (entryblock->buffer[*pos] == 0)
159 if (*pos == BLK_TABLE_END(ah->volume))
160 return ERROR_NO_MORE_ENTRIES;
161 *pos += 1;
163 /* now i is on a valid position */
164 *key = OS_BE2LONG(entryblock->buffer[*pos]);
165 return 0;
169 ULONG examineAll
171 struct AFSBase *afsbase,
172 struct AfsHandle *ah,
173 struct ExAllData *ead,
174 struct ExAllControl *eac,
175 ULONG size,
176 ULONG mode
179 struct BlockCache *headerblock;
180 struct BlockCache *entryblock;
181 struct ExAllData *last;
182 ULONG error,i,block;
184 D(bug("[afs] examineAll(%ld,ead,%ld,%ld)\n",ah->header_block,size,mode));
185 eac->eac_Entries = 0;
186 if (mode > ED_OWNER)
187 return ERROR_BAD_NUMBER;
188 headerblock = getBlock(afsbase, ah->volume, ah->header_block);
189 if (headerblock == NULL)
190 return ERROR_UNKNOWN;
191 /* is it a file? */
192 if ((LONG)(OS_BE2LONG(headerblock->buffer[BLK_SECONDARY_TYPE(ah->volume)])) < 0)
194 error = examineEAD(afsbase, ah->volume, ead, headerblock, size, mode);
195 if (error == 0)
196 eac->eac_Entries = 1;
197 return error;
199 error = getNextExamineBlock(afsbase, ah, &ah->dirpos, &i);
200 /* FIXME: if ah->dirpos is an entry stored in a hashchain we return entries twice */
201 if (error != 0)
202 return error;
203 last = ead;
205 the contents of headerblock may have changed
206 by getNextExamineBlock
208 if (headerblock->blocknum != ah->header_block)
210 headerblock = getBlock(afsbase, ah->volume, ah->header_block);
211 if (headerblock == NULL)
212 return ERROR_UNKNOWN;
214 headerblock->flags |= BCF_USED;
215 for (; i<=BLK_TABLE_END(ah->volume); i++)
217 if (headerblock->buffer[i] != 0)
219 block = OS_BE2LONG(headerblock->buffer[i]);
222 entryblock = getBlock(afsbase, ah->volume, block);
223 if (entryblock == NULL)
225 headerblock->flags &= ~BCF_USED;
226 return ERROR_UNKNOWN;
228 error = examineEAD(afsbase, ah->volume, ead, entryblock, size, mode);
229 if (error != 0)
231 /* stegerg: CHECK CHECK CHECK CHECK CHECK */
232 if (error == ERROR_BUFFER_OVERFLOW)
234 ah->dirpos = OS_BE2LONG(headerblock->buffer[i]);
235 error = 0;
237 /* stegerg: END CHECK CHECK CHECK CHECK CHECK */
239 ead->ed_Next = NULL;
240 headerblock->flags &= ~BCF_USED;
241 return error;
243 size -= (ULONG)((char *)ead->ed_Next-(char *)ead);
244 last = ead;
245 ead = ead->ed_Next;
246 ah->dirpos = OS_BE2LONG(headerblock->buffer[i]);
247 block = OS_BE2LONG(entryblock->buffer[BLK_HASHCHAIN(ah->volume)]);
248 eac->eac_Entries++;
249 } while (block != 0);
252 last->ed_Next = NULL;
253 headerblock->flags &= ~BCF_USED;
254 return ERROR_NO_MORE_ENTRIES;
257 ULONG examineNext
258 (struct AFSBase *afsbase, struct AfsHandle *ah, struct FileInfoBlock *fib)
260 struct BlockCache *entryblock;
261 STRPTR string;
262 ULONG filelistentries,datablocksize,datablocks;
263 ULONG owner;
264 ULONG error,filekey;
265 ULONG dirkey = fib->fib_DiskKey; /* fib_DiskKey is an IPTR, so we need this conversion */
267 D(bug("[afs] examineNext(%ld,fib)\n", ah->header_block));
268 D(bug("[afs] examineNext: diskey=%ld\n", dirkey));
270 error = getNextExamineBlock(afsbase, ah, &dirkey, &filekey);
271 fib->fib_DiskKey = dirkey;
272 if (error != 0)
273 return error;
274 /* examine the block */
275 entryblock = getBlock(afsbase, ah->volume, dirkey);
276 if (entryblock == NULL)
277 return ERROR_UNKNOWN;
278 fib->fib_DirEntryType =
279 OS_BE2LONG(entryblock->buffer[BLK_SECONDARY_TYPE(ah->volume)]);
280 string = (char *)entryblock->buffer+(BLK_FILENAME_START(ah->volume)*4);
281 CopyMem(string, fib->fib_FileName, string[0]+1);
282 fib->fib_Protection = OS_BE2LONG(entryblock->buffer[BLK_PROTECT(ah->volume)]);
283 fib->fib_EntryType = fib->fib_DirEntryType;
284 fib->fib_Size = OS_BE2LONG(entryblock->buffer[BLK_BYTE_SIZE(ah->volume)]);
285 filelistentries = ah->volume->SizeBlock-56;
286 datablocksize = BLOCK_SIZE(ah->volume);
287 if (ah->volume->dosflags == 0)
288 datablocksize = datablocksize-24;
289 datablocks = ((fib->fib_Size+datablocksize-1)/datablocksize);
290 fib->fib_NumBlocks =
291 datablocks+((datablocks+filelistentries-1)/filelistentries);
292 fib->fib_Date.ds_Days = OS_BE2LONG(entryblock->buffer[BLK_DAYS(ah->volume)]);
293 fib->fib_Date.ds_Minute = OS_BE2LONG(entryblock->buffer[BLK_MINS(ah->volume)]);
294 fib->fib_Date.ds_Tick = OS_BE2LONG(entryblock->buffer[BLK_TICKS(ah->volume)]);
295 if (fib->fib_DirEntryType != ST_ROOT)
297 string = (char *)entryblock->buffer+(BLK_COMMENT_START(ah->volume)*4);
298 CopyMem(string, fib->fib_Comment, string[0] + 1);
300 owner = OS_BE2LONG(entryblock->buffer[BLK_OWNER(ah->volume)]);
301 fib->fib_OwnerUID = owner>>16;
302 fib->fib_OwnerGID = owner & 0xFFFF;
303 return 0;