added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / workbench / devs / afs / filehandles3.c
blobae72318674eeb842523396f56213cdbd88456896
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #ifndef DEBUG
7 #define DEBUG 1
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 *)(((ULONG)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 ULONG *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 (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 #warning "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;
266 D(bug("[afs] examineNext(%ld,fib)\n", ah->header_block));
267 D(bug("[afs] examineNext: diskey=%ld\n", fib->fib_DiskKey));
269 error = getNextExamineBlock(afsbase, ah, &fib->fib_DiskKey, &filekey);
270 if (error != 0)
271 return error;
272 /* examine the block */
273 entryblock = getBlock(afsbase, ah->volume, fib->fib_DiskKey);
274 if (entryblock == NULL)
275 return ERROR_UNKNOWN;
276 fib->fib_DirEntryType =
277 OS_BE2LONG(entryblock->buffer[BLK_SECONDARY_TYPE(ah->volume)]);
278 string = (char *)entryblock->buffer+(BLK_FILENAME_START(ah->volume)*4);
279 CopyMem(string+1, fib->fib_FileName, string[0]);
280 fib->fib_FileName[(ULONG)string[0]] = 0;
281 fib->fib_Protection = OS_BE2LONG(entryblock->buffer[BLK_PROTECT(ah->volume)]);
282 fib->fib_EntryType = fib->fib_DirEntryType;
283 fib->fib_Size = OS_BE2LONG(entryblock->buffer[BLK_BYTE_SIZE(ah->volume)]);
284 filelistentries = ah->volume->SizeBlock-56;
285 datablocksize = BLOCK_SIZE(ah->volume);
286 if (ah->volume->dosflags == 0)
287 datablocksize = datablocksize-24;
288 datablocks = ((fib->fib_Size+datablocksize-1)/datablocksize);
289 fib->fib_NumBlocks =
290 datablocks+((datablocks+filelistentries-1)/filelistentries);
291 fib->fib_Date.ds_Days = OS_BE2LONG(entryblock->buffer[BLK_DAYS(ah->volume)]);
292 fib->fib_Date.ds_Minute = OS_BE2LONG(entryblock->buffer[BLK_MINS(ah->volume)]);
293 fib->fib_Date.ds_Tick = OS_BE2LONG(entryblock->buffer[BLK_TICKS(ah->volume)]);
294 if (fib->fib_DirEntryType != ST_ROOT)
296 string = (char *)entryblock->buffer+(BLK_COMMENT_START(ah->volume)*4);
297 CopyMem(string+1, fib->fib_Comment, string[0]);
298 fib->fib_Comment[(ULONG)string[0]] = 0;
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;