grub2: bring back build of aros-side grub2 tools
[AROS.git] / rom / filesys / afs / filehandles2.c
blob887abaccb8c81ef1c7945e8aa67e7f6efc837b8f
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
4 */
5 /*
6 * -date------ -name------------------- -description-----------------------------
7 * 02-jan-2008 [Tomasz Wiszkowski] added disk validation
8 * 04-jan-2008 [Tomasz Wiszkowski] corrected tabulation
9 */
12 #ifndef DEBUG
13 #define DEBUG 0
14 #endif
16 #include "os.h"
17 #include "filehandles2.h"
18 #include "afsblocks.h"
19 #include "bitmap.h"
20 #include "checksums.h"
21 #include "error.h"
22 #include "extstrings.h"
23 #include "filehandles1.h"
24 #include "hashing.h"
25 #include "misc.h"
26 #include "baseredef.h"
27 #include "validator.h"
29 /********************************************
30 Name : setHeaderDate
31 Descr.: set actual date for an object
32 Input : volume -
33 blockbuffer - header block of object
34 ds - datestamp to set
35 Output: 0 for success; error code otherwise
36 *********************************************/
37 ULONG setHeaderDate
39 struct AFSBase *afsbase,
40 struct Volume *volume,
41 struct BlockCache *blockbuffer,
42 struct DateStamp *ds
46 D(bug
48 "[afs] setHeaderDate: for headerblock %lu\n",
49 blockbuffer->blocknum)
51 blockbuffer->buffer[BLK_DAYS(volume)] = OS_LONG2BE(ds->ds_Days);
52 blockbuffer->buffer[BLK_MINS(volume)] = OS_LONG2BE(ds->ds_Minute);
53 blockbuffer->buffer[BLK_TICKS(volume)] = OS_LONG2BE(ds->ds_Tick);
54 writeBlockDeferred(afsbase, volume, blockbuffer, BLK_CHECKSUM);
55 blockbuffer = getBlock
56 (afsbase, volume, OS_BE2LONG(blockbuffer->buffer[BLK_PARENT(volume)]));
57 if (blockbuffer == NULL)
58 return ERROR_UNKNOWN;
59 return writeHeader(afsbase, volume, blockbuffer);
63 /********************************************
64 Name : setDate
65 Descr.: set actual date for an object
66 Input : ah - filehandle name is relative to
67 name - name of object
68 ds - datestamp to set
69 Output: 0 for success; error code otherwise
70 *********************************************/
71 ULONG setDate
73 struct AFSBase *afsbase,
74 struct AfsHandle *ah,
75 CONST_STRPTR name,
76 struct DateStamp *ds
79 ULONG block;
80 struct BlockCache *blockbuffer;
81 SIPTR error;
83 D(bug("[afs] setData()\n"));
84 if (0 == checkValid(afsbase, ah->volume))
85 return ERROR_DISK_WRITE_PROTECTED;
87 blockbuffer = findBlock(afsbase, ah, name, &block, &error);
88 if (blockbuffer == NULL)
89 return error;
90 return setHeaderDate(afsbase, ah->volume, blockbuffer, ds);
93 /********************************************
94 Name : setProtect
95 Descr.: set protection bits for an object
96 Input : ah - filehandle name is relative to
97 name - name of object
98 mask - protection bit mask
99 Output: 0 for success; error code otherwise
100 *********************************************/
101 ULONG setProtect
103 struct AFSBase *afsbase,
104 struct AfsHandle *ah,
105 CONST_STRPTR name,
106 ULONG mask
109 ULONG block;
110 struct BlockCache *blockbuffer;
111 SIPTR error;
113 D(bug("[afs] setProtect(ah,%s,%ld)\n", name, mask));
114 if (0 == checkValid(afsbase, ah->volume))
115 return ERROR_DISK_WRITE_PROTECTED;
116 blockbuffer = findBlock(afsbase, ah, name, &block, &error);
117 if (blockbuffer == NULL)
118 return error;
119 blockbuffer->buffer[BLK_PROTECT(ah->volume)] = OS_LONG2BE(mask);
120 return writeHeader(afsbase, ah->volume, blockbuffer);
123 /********************************************
124 Name : setComment
125 Descr.: set comment for an object
126 Input : ah - filehandle name is relative to
127 name - name of object
128 comment - comment to set
129 Output: 0 for success; error code otherwise
130 *********************************************/
131 ULONG setComment
132 (struct AFSBase *afsbase, struct AfsHandle *ah, CONST_STRPTR name,
133 CONST_STRPTR comment)
135 ULONG block;
136 struct BlockCache *blockbuffer;
137 SIPTR error;
139 D(bug("[afs] setComment(ah,%s,%s)\n", name, comment));
140 if (0 == checkValid(afsbase, ah->volume))
141 return ERROR_DISK_WRITE_PROTECTED;
142 if (strlen(comment) >= MAXCOMMENTLENGTH)
143 return ERROR_COMMENT_TOO_BIG;
144 blockbuffer = findBlock(afsbase, ah, name, &block, &error);
145 if (blockbuffer == NULL)
146 return error;
147 StrCpyToBstr
149 comment,
150 (APTR)((char *)blockbuffer->buffer+(BLK_COMMENT_START(ah->volume)*4)),
151 MAX_COMMENT_LENGTH
153 return writeHeader(afsbase, ah->volume, blockbuffer);
156 /************************************************
157 Name : unLinkBlock
158 Descr.: unlinks an entry from the directorylist
159 Input : lastentry - node before entry to unlink
160 (directory itself (head) or last block
161 which HASHCHAIN points to the entry to unlink
162 entry - entry to unlink
163 Output: -
164 Note : unlink is only done in buffers
165 nothing is written to disk!
166 ************************************************/
167 void unLinkBlock
169 struct AFSBase *afsbase,
170 struct Volume *volume,
171 struct BlockCache *lastentry,
172 struct BlockCache *entry
175 ULONG key;
177 D(bug("[afs] unlinkBlock: unlinking %lu\n", entry->blocknum));
178 /* find the "member" where entry is linked
179 ->linked into hashchain or hashtable */
180 key = BLK_HASHCHAIN(volume);
181 if (OS_BE2LONG(lastentry->buffer[key])!=entry->blocknum)
183 for (key = BLK_TABLE_START; key<=BLK_TABLE_END(volume); key++)
185 if (OS_BE2LONG(lastentry->buffer[key]) == entry->blocknum)
186 break;
189 /* unlink block */
190 lastentry->buffer[key] = entry->buffer[BLK_HASHCHAIN(volume)];
191 lastentry->buffer[BLK_CHECKSUM] = 0;
192 lastentry->buffer[BLK_CHECKSUM] =
193 OS_LONG2BE(0-calcChkSum(volume->SizeBlock, lastentry->buffer));
196 /********************************************
197 Name : deleteObject
198 Descr.: delete an object
199 Input : ah - filehandle name is relative to
200 name - name of object to delete
201 Output: 0 for success; error code otherwise
202 *********************************************/
203 ULONG deleteObject(struct AFSBase *afsbase, struct AfsHandle *ah,
204 CONST_STRPTR name)
206 ULONG lastblock,key;
207 struct BlockCache *blockbuffer, *priorbuffer;
208 SIPTR error;
210 D(bug("[afs] delete(ah,%s)\n", name));
212 * check disk validity *first*
213 * it may turn out, that during validation, invalid entry gets deleted either way.
215 if (0 == checkValid(afsbase, ah->volume))
216 return ERROR_DISK_WRITE_PROTECTED;
217 blockbuffer = findBlock(afsbase, ah, name, &lastblock, &error);
218 if (blockbuffer == NULL)
219 return error;
220 blockbuffer = findBlock(afsbase, ah, name, &lastblock, &error);
221 if (findHandle(ah->volume, blockbuffer->blocknum) != NULL)
222 return ERROR_OBJECT_IN_USE;
223 if (OS_BE2LONG(blockbuffer->buffer[BLK_PROTECT(ah->volume)]) & FIBF_DELETE)
224 return ERROR_DELETE_PROTECTED;
225 /* if we try to delete a directory, check if it is empty */
226 if (
227 OS_BE2LONG
228 (blockbuffer->buffer[BLK_SECONDARY_TYPE(ah->volume)]) == ST_USERDIR
231 for (key=BLK_TABLE_START; key<=BLK_TABLE_END(ah->volume); key++)
233 if (blockbuffer->buffer[key] != 0)
234 return ERROR_DIRECTORY_NOT_EMPTY;
237 blockbuffer->flags |= BCF_USED;
238 priorbuffer = getBlock(afsbase, ah->volume, lastblock);
239 if (priorbuffer == NULL)
241 blockbuffer->flags &= ~BCF_USED;
242 return ERROR_UNKNOWN;
244 if (calcChkSum(ah->volume->SizeBlock, priorbuffer->buffer) != 0)
246 blockbuffer->flags &= ~BCF_USED;
247 if (showError(afsbase, ERR_CHECKSUM, priorbuffer->blocknum))
248 launchValidator(afsbase, ah->volume);
249 return ERROR_UNKNOWN;
251 priorbuffer->flags |= BCF_USED;
252 unLinkBlock(afsbase, ah->volume, priorbuffer, blockbuffer);
253 invalidBitmap(afsbase, ah->volume);
254 writeBlock(afsbase, ah->volume, priorbuffer, -1);
255 markBlock(afsbase, ah->volume, blockbuffer->blocknum, -1);
256 if (
257 OS_BE2LONG
258 (blockbuffer->buffer[BLK_SECONDARY_TYPE(ah->volume)]) == ST_FILE
261 for (;;)
263 D(bug("[afs] extensionblock=%lu\n", blockbuffer->blocknum));
266 key = BLK_TABLE_END(ah->volume);
267 (key >= BLK_TABLE_START) && (blockbuffer->buffer[key]!=0);
268 key--
271 markBlock
272 (afsbase, ah->volume, OS_BE2LONG(blockbuffer->buffer[key]), -1);
274 if (blockbuffer->buffer[BLK_EXTENSION(ah->volume)] == 0)
275 break;
276 /* get next extensionblock */
277 blockbuffer->flags &= ~BCF_USED;
278 blockbuffer = getBlock
280 afsbase,
281 ah->volume,
282 OS_BE2LONG(blockbuffer->buffer[BLK_EXTENSION(ah->volume)])
284 if (blockbuffer == NULL)
286 priorbuffer->flags &= ~BCF_USED;
287 return ERROR_UNKNOWN;
289 if (calcChkSum(ah->volume->SizeBlock, blockbuffer->buffer))
291 priorbuffer->flags &= ~BCF_USED;
292 if (showError(afsbase, ERR_CHECKSUM))
293 launchValidator(afsbase, ah->volume);
294 return ERROR_UNKNOWN;
296 blockbuffer->flags |= BCF_USED;
297 markBlock(afsbase, ah->volume, blockbuffer->blocknum, -1);
300 validBitmap(afsbase, ah->volume);
301 blockbuffer->flags &= ~BCF_USED;
302 priorbuffer->flags &= ~BCF_USED;
303 return 0;
306 /********************************************
307 Name : deleteFileRemainder
308 Descr.: delete all data blocks in a file after the current position
309 Input : ah - filehandle to delete from
310 Output: 0 for success; error code otherwise
311 *********************************************/
312 ULONG deleteFileRemainder(struct AFSBase *afsbase, struct AfsHandle *ah)
314 ULONG key;
315 struct BlockCache *blockbuffer;
317 invalidBitmap(afsbase, ah->volume);
319 blockbuffer = getBlock(afsbase, ah->volume, ah->current.block);
320 blockbuffer->flags |= BCF_USED;
322 /* Start with the first block that will be wholly unused afterwards */
323 key = ah->current.filekey;
324 if (ah->current.byte != 0)
325 key--;
327 while (TRUE)
329 D(bug("[afs] extensionblock=%lu\n", blockbuffer->blocknum));
330 while (key >= BLK_TABLE_START && blockbuffer->buffer[key] != 0)
332 markBlock(afsbase, ah->volume,
333 OS_BE2LONG(blockbuffer->buffer[key]), -1);
334 key--;
336 if (blockbuffer->buffer[BLK_EXTENSION(ah->volume)] == 0)
337 break;
338 /* get next extensionblock */
339 blockbuffer->flags &= ~BCF_USED;
340 blockbuffer = getBlock
342 afsbase,
343 ah->volume,
344 OS_BE2LONG(blockbuffer->buffer[BLK_EXTENSION(ah->volume)])
346 if (blockbuffer == NULL)
348 return ERROR_UNKNOWN;
350 if (calcChkSum(ah->volume->SizeBlock, blockbuffer->buffer))
352 if (showError(afsbase, ERR_CHECKSUM))
353 launchValidator(afsbase, ah->volume);
354 return ERROR_UNKNOWN;
356 blockbuffer->flags |= BCF_USED;
357 markBlock(afsbase, ah->volume, blockbuffer->blocknum, -1);
358 key = BLK_TABLE_END(ah->volume);
361 validBitmap(afsbase, ah->volume);
362 blockbuffer->flags &= ~BCF_USED;
363 return 0;
366 /********************************************
367 Name : linkNewBlock
368 Descr.: links a new entry into a directorylist
369 Input : dir - directory to link in
370 file - file to link
371 Output: the block which must be written to disk
372 -> if hashtable of directory changed it's the same
373 pointer as arg1; otherwise a HASHCHAIN pointer
374 changed so we don't have to write this block but
375 another one
376 NULL if error
377 *********************************************/
378 struct BlockCache *linkNewBlock
380 struct AFSBase *afsbase,
381 struct Volume *volume,
382 struct BlockCache *dir,
383 struct BlockCache *file
386 ULONG key; /* parent; */
387 UBYTE buffer[32];
388 STRPTR name;
390 file->buffer[BLK_PARENT(volume)] = OS_LONG2BE(dir->blocknum);
391 D(bug("[afs] linkNewBlock: linking block %ld\n", file->blocknum));
392 name = (STRPTR)((char *)file->buffer+(BLK_FILENAME_START(volume)*4));
393 StrCpyFromBstr(name, buffer);
394 key = getHashKey
395 (buffer, volume->SizeBlock-56, volume->dosflags)+BLK_TABLE_START;
396 /* sort in ascending order */
397 if (
398 (dir->buffer[key] != 0) &&
399 (OS_BE2LONG(dir->buffer[key]) < file->blocknum))
401 dir = getBlock(afsbase, volume, OS_BE2LONG(dir->buffer[key]));
402 if (dir == NULL)
403 return NULL;
404 key = BLK_HASHCHAIN(volume);
405 while (
406 (dir->buffer[key] != 0) &&
407 (OS_BE2LONG(dir->buffer[key]) < file->blocknum)
410 dir = getBlock(afsbase, volume, OS_BE2LONG(dir->buffer[key]));
411 if (dir == NULL)
412 return NULL;
415 file->buffer[BLK_HASHCHAIN(volume)] = dir->buffer[key];
416 dir->buffer[key] = OS_LONG2BE(file->blocknum);
417 file->buffer[BLK_CHECKSUM] = 0;
418 file->buffer[BLK_CHECKSUM] =
419 OS_LONG2BE(0-calcChkSum(volume->SizeBlock,file->buffer));
420 dir->buffer[BLK_CHECKSUM] = 0;
421 dir->buffer[BLK_CHECKSUM] =
422 OS_LONG2BE(0-calcChkSum(volume->SizeBlock,dir->buffer));
423 return dir;
426 /********************************************
427 Name : getDirBlockBuffer
428 Descr.: returns cacheblock of the block the
429 last component before "/" or ":" of
430 name refers to or cacheblock of ah
431 if there is no such component
432 Input : ah - filehandle name is relative to
433 name - name of object
434 entryname - will be filled with a copy
435 of the last component of
436 name
437 Output: NULL for error (global error will be set);
438 pointer to a struct BlockCache otherwise
439 *********************************************/
440 struct BlockCache *getDirBlockBuffer
442 struct AFSBase *afsbase,
443 struct AfsHandle *ah,
444 CONST_STRPTR name,
445 STRPTR entryname,
446 SIPTR *error
449 ULONG block,len;
450 CONST_STRPTR end;
451 UBYTE buffer[256];
453 end = PathPart(name);
454 if (end[0] == '/')
455 end++;
456 CopyMem(name, buffer, end-name);
457 buffer[end-name] = 0;
458 len = strlen(name)+name-end;
459 CopyMem(end, entryname, len); /* skip slash or colon */
460 entryname[len] = 0;
461 return findBlock(afsbase, ah, buffer, &block, error);
464 /********************************************
465 Name : renameObject
466 Descr.: rename an object
467 Input : dirah - filehandle names are relative to
468 oname - object to rename
469 newname - new name of the object
470 Output: 0 for success; error code otherwise
471 *********************************************/
472 ULONG renameObject
474 struct AFSBase *afsbase,
475 struct AfsHandle *dirah,
476 CONST_STRPTR oname,
477 CONST_STRPTR newname
480 struct BlockCache *lastlink,*oldfile,*existingfile,*dirblock;
481 ULONG block,dirblocknum,lastblock;
482 UBYTE newentryname[34];
483 SIPTR error;
485 D(bug("[afs] rename(%ld,%s,%s)\n", dirah->header_block, oname, newname));
486 if (0 == checkValid(afsbase, dirah->volume))
487 return ERROR_DISK_WRITE_PROTECTED;
488 dirblock = getDirBlockBuffer(afsbase, dirah, newname, newentryname, &error);
489 if (dirblock == NULL)
490 return error;
491 dirblocknum = dirblock->blocknum;
492 D(bug("[afs] dir is on block %ld\n", dirblocknum));
493 oldfile = findBlock(afsbase, dirah, oname, &lastblock, &error);
494 if (oldfile == NULL)
495 return error;
496 oldfile->flags |= BCF_USED;
497 existingfile = getHeaderBlock(afsbase, dirah->volume, newentryname,
498 dirblock, &block, &error);
499 if (existingfile != NULL && existingfile->blocknum != oldfile->blocknum)
501 dirblock->flags &= ~BCF_USED;
502 return ERROR_OBJECT_EXISTS;
504 /* do we move a directory? */
505 if (OS_BE2LONG(oldfile->buffer[BLK_SECONDARY_TYPE(dirah->volume)])==ST_USERDIR)
507 /* is newdirblock child of olock/oname */
508 dirblock = getBlock(afsbase, dirah->volume, dirblocknum);
509 if (dirblock == NULL)
511 oldfile->flags &= ~BCF_USED;
512 return ERROR_UNKNOWN;
514 while ((block = OS_BE2LONG(dirblock->buffer[BLK_PARENT(dirah->volume)])))
516 if (block == oldfile->blocknum)
518 oldfile->flags &= ~BCF_USED;
519 return ERROR_OBJECT_IN_USE;
521 dirblock = getBlock(afsbase, dirah->volume, block);
522 if (dirblock == NULL)
524 oldfile->flags &= ~BCF_USED;
525 return ERROR_UNKNOWN;
529 lastlink = getBlock(afsbase, dirah->volume, lastblock);
530 if (lastlink == NULL)
532 oldfile->flags &= ~BCF_USED;
533 return ERROR_UNKNOWN;
535 lastlink->flags |= BCF_USED;
536 unLinkBlock(afsbase, dirah->volume, lastlink, oldfile);
537 /* rename in same dir ? */
538 if (lastlink->blocknum == dirblocknum)
540 /* use same buffers! */
541 dirblock = lastlink;
543 /* otherwise we use different blocks */
544 else
546 dirblock = getBlock(afsbase, dirah->volume, dirblocknum);
547 if (dirblock == NULL)
549 oldfile->flags &= ~BCF_USED;
550 lastlink->flags &= ~BCF_USED;
551 return ERROR_UNKNOWN;
554 if (
556 OS_BE2LONG
558 dirblock->buffer[BLK_SECONDARY_TYPE(dirah->volume)]
559 ) != ST_USERDIR
560 ) &&
562 OS_BE2LONG
564 dirblock->buffer[BLK_SECONDARY_TYPE(dirah->volume)]
565 ) != ST_ROOT
569 oldfile->flags &= ~BCF_USED;
570 lastlink->flags &= ~BCF_USED;
571 return ERROR_OBJECT_WRONG_TYPE;
573 StrCpyToBstr
575 newentryname,
576 (APTR)((char *)oldfile->buffer+(BLK_FILENAME_START(dirah->volume)*4)),
577 MAX_NAME_LENGTH
579 dirblock = linkNewBlock(afsbase, dirah->volume, dirblock, oldfile);
580 if (dirblock == NULL)
582 oldfile->flags &= ~BCF_USED;
583 lastlink->flags &= ~BCF_USED;
584 return ERROR_UNKNOWN;
586 /* concurrent access if newdir=rootblock! */
587 dirblock->flags |= BCF_USED;
589 mark it as used, so that this buffer isn't
590 used in invalidating volume!
592 if (!setBitmapFlag(afsbase, dirah->volume, 0))
594 oldfile->flags &= ~BCF_USED;
595 lastlink->flags &= ~BCF_USED;
596 dirblock->flags &= ~BCF_USED;
597 return ERROR_UNKNOWN;
599 /* now we can release that buffer */
600 dirblock->flags &= ~BCF_USED;
602 syscrash after this: 2 dirs pointing to the same
603 dir and one wrong linked entry->recoverable
605 writeBlock(afsbase, dirah->volume, dirblock, -1);
607 syscrash after this: directory pointing is now
608 correct but one wrong linked entry->recoverable
610 writeBlock(afsbase, dirah->volume, lastlink, -1);
611 writeBlock(afsbase, dirah->volume, oldfile, -1);
612 oldfile->flags &= ~BCF_USED;
613 lastlink->flags &= ~BCF_USED;
615 if newdir=rootblock we now write the correct
616 (changed) buffer back
618 setBitmapFlag(afsbase, dirah->volume, -1);
619 return 0;
622 /********************************************
623 Name : createNewEntry
624 Descr.: create a new object on disk
625 Input : volume -
626 entrytype - ST_USERDIR/ST_FILE/...
627 entryname - name of object
628 dirblock - pointer to struct BlockCache
629 containing a directory in which
630 name shall be created in
631 protection - protection bit mask
632 Output: NULL for error (global error set);
633 pointer to struct BlockCache of the newly
634 created object otherwise
635 *********************************************/
636 struct BlockCache *createNewEntry
638 struct AFSBase *afsbase,
639 struct Volume *volume,
640 ULONG entrytype,
641 CONST_STRPTR entryname,
642 struct BlockCache *dirblock,
643 ULONG protection,
644 SIPTR *error
647 struct BlockCache *newblock;
648 struct DateStamp ds;
649 ULONG i;
651 D(bug("[afs] createNewEntry(%ld, %s)\n", dirblock->blocknum, entryname));
652 dirblock->flags |= BCF_USED;
653 if (getHeaderBlock(afsbase, volume, entryname, dirblock, &i, error) != NULL)
655 dirblock->flags &= ~BCF_USED;
656 *error = ERROR_OBJECT_EXISTS;
657 return NULL;
659 *error = 0;
660 if (!invalidBitmap(afsbase, volume))
662 dirblock->flags &= ~BCF_USED;
663 return NULL;
665 i = allocBlock(afsbase, volume);
666 if (i == 0)
668 dirblock->flags &= ~BCF_USED;
669 validBitmap(afsbase, volume);
670 *error = ERROR_DISK_FULL;
671 return NULL;
673 newblock = getFreeCacheBlock(afsbase, volume, i);
674 if (newblock == NULL)
676 dirblock->flags &= ~BCF_USED;
677 validBitmap(afsbase, volume);
678 *error = ERROR_UNKNOWN;
679 return NULL;
681 newblock->flags |= BCF_USED;
682 newblock->buffer[BLK_PRIMARY_TYPE] = OS_LONG2BE(T_SHORT);
683 for (i=BLK_BLOCK_COUNT; i<=BLK_COMMENT_END(volume); i++)
684 newblock->buffer[i] = 0;
685 newblock->buffer[BLK_PROTECT(volume)] = OS_LONG2BE(protection);
686 DateStamp(&ds);
687 newblock->buffer[BLK_DAYS(volume)] = OS_LONG2BE(ds.ds_Days);
688 newblock->buffer[BLK_MINS(volume)] = OS_LONG2BE(ds.ds_Minute);
689 newblock->buffer[BLK_TICKS(volume)] = OS_LONG2BE(ds.ds_Tick);
690 StrCpyToBstr
692 entryname,
693 (APTR)((char *)newblock->buffer+(BLK_FILENAME_START(volume)*4)),
694 MAX_NAME_LENGTH
696 for (i=BLK_FILENAME_END(volume)+1; i<BLK_HASHCHAIN(volume); i++)
697 newblock->buffer[i] = 0;
698 newblock->buffer[BLK_PARENT(volume)] = OS_LONG2BE(dirblock->blocknum);
699 newblock->buffer[BLK_EXTENSION(volume)] = 0;
700 newblock->buffer[BLK_SECONDARY_TYPE(volume)] = OS_LONG2BE(entrytype);
701 newblock->buffer[BLK_OWN_KEY] = OS_LONG2BE(newblock->blocknum);
702 dirblock->flags &= ~BCF_USED;
703 dirblock = linkNewBlock(afsbase, volume, dirblock, newblock);
704 if (dirblock == NULL)
706 markBlock(afsbase, volume, newblock->blocknum, -1);
707 newblock->flags &= ~BCF_USED;
708 newblock->newness = 0;
709 validBitmap(afsbase, volume);
710 return NULL;
713 if crash after this block not yet linked->block
714 not written to disk, bitmap corrected
716 writeBlock(afsbase, volume, newblock, -1);
717 /* consistent after this */
718 writeBlock(afsbase, volume, dirblock, -1);
719 validBitmap(afsbase, volume);
720 newblock->flags &= ~BCF_USED;
721 return newblock;
725 /********************************************
726 Name : createDir
727 Descr.: create a directory object
728 Input : dirah - filehandle filename is relative to
729 filename - path to the new directory
730 protection - protection bit mask
731 Output: pointer to struct AfsHandle;
732 NULL otherwise (global error set)
733 *********************************************/
734 struct AfsHandle *createDir
736 struct AFSBase *afsbase,
737 struct AfsHandle *dirah,
738 CONST_STRPTR filename,
739 ULONG protection,
740 SIPTR *error
743 struct AfsHandle *ah = NULL;
744 struct BlockCache *dirblock;
745 char dirname[34];
747 D(bug("[afs] createDir(ah,%s,%ld)\n", filename, protection));
748 if (0 == checkValid(afsbase, dirah->volume))
750 *error = ERROR_DISK_WRITE_PROTECTED;
751 return NULL;
753 dirblock = getDirBlockBuffer(afsbase, dirah, filename, dirname, error);
754 if (dirblock != NULL)
756 D(bug("[afs] dir is on block %ld\n", dirblock->blocknum));
757 dirblock = createNewEntry
758 (afsbase, dirah->volume, ST_USERDIR, dirname, dirblock, protection, error);
759 if (dirblock != NULL)
760 ah = getHandle(afsbase, dirah->volume, dirblock, MODE_OLDFILE, error);
762 return ah;