2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
7 * -date------ -name------------------- -description-----------------------------
8 * 02-jan-2008 [Tomasz Wiszkowski] added disk validation
9 * 03-jan-2008 [Tomasz Wiszkowski] fixed procedures to allow validation prior to disk write
10 * 04-jan-2008 [Tomasz Wiszkowski] corrected tabulation
17 #include "filehandles1.h"
18 #include "filehandles2.h"
20 #include "extstrings.h"
21 #include "checksums.h"
24 #include "afsblocks.h"
25 #include "baseredef.h"
26 #include "validator.h"
30 /***********************************************
32 Descr.: search through blocks until header block found
33 Input : name - object we are searching for
34 blockbuffer - dirblock we are searching in
35 block - will be filled with the block number
36 prior to the entry we are using
37 Output: cache block of last object
38 See : locateObject, setDate, setComment, deleteObject
39 ************************************************/
40 struct BlockCache
*getHeaderBlock
42 struct AFSBase
*afsbase
,
43 struct Volume
*volume
,
45 struct BlockCache
*blockbuffer
,
51 D(bug("[afs] getHeaderBlock: searching for block of '%s'\n",name
));
52 key
= getHashKey(name
,volume
->SizeBlock
-56,volume
->dosflags
)+BLK_TABLE_START
;
53 *block
= blockbuffer
->blocknum
;
54 if (blockbuffer
->buffer
[key
] == 0)
56 error
= ERROR_OBJECT_NOT_FOUND
;
59 blockbuffer
=getBlock(afsbase
, volume
,OS_BE2LONG(blockbuffer
->buffer
[key
]));
60 if (blockbuffer
== NULL
)
62 error
= ERROR_UNKNOWN
;
69 name
= (char *)blockbuffer
->buffer
+(BLK_DIRECTORYNAME_START(volume
)*4);
70 kprintf("[afs] %.*s\n", name
[0], name
+1);
73 if (calcChkSum(volume
->SizeBlock
, blockbuffer
->buffer
) != 0)
76 * since we will not work on blockbuffer here any more,
77 * we don't have to preserve it.
79 if (showError(afsbase
, ERR_CHECKSUM
, blockbuffer
->blocknum
))
80 launchValidator(afsbase
, volume
);
82 error
= ERROR_UNKNOWN
;
85 if (OS_BE2LONG(blockbuffer
->buffer
[BLK_PRIMARY_TYPE
]) != T_SHORT
)
88 * again, we don't work on blockbuffer any more
89 * no need to preserve BlockCache structure.
91 if (showError(afsbase
, ERR_BLOCKTYPE
, blockbuffer
->blocknum
))
92 launchValidator(afsbase
, volume
);
94 error
= ERROR_OBJECT_WRONG_TYPE
;
103 (ULONG
)blockbuffer
->buffer
+
104 (BLK_DIRECTORYNAME_START(volume
)*4)
111 *block
= blockbuffer
->blocknum
;
112 if (blockbuffer
->buffer
[BLK_HASHCHAIN(volume
)] == 0)
114 error
=ERROR_OBJECT_NOT_FOUND
;
121 OS_BE2LONG(blockbuffer
->buffer
[BLK_HASHCHAIN(volume
)])
123 if (blockbuffer
== NULL
)
125 error
= ERROR_UNKNOWN
;
128 if (calcChkSum(volume
->SizeBlock
, blockbuffer
->buffer
) != 0)
131 * we won't work on blockbuffer any more
132 * don't preserve the buffer.
134 if (showError(afsbase
, ERR_CHECKSUM
,blockbuffer
->blocknum
))
135 launchValidator(afsbase
, volume
);
140 if (OS_BE2LONG(blockbuffer
->buffer
[BLK_PRIMARY_TYPE
]) != T_SHORT
)
143 * not working with blockbuffer :)
145 if (showError(afsbase
, ERR_BLOCKTYPE
, blockbuffer
->blocknum
))
146 launchValidator(afsbase
, volume
);
148 error
= ERROR_OBJECT_WRONG_TYPE
;
155 /*******************************************
157 Descr.: find the header block of a file/dir
158 Input : dirah - directory lock as starting point
159 if NULL, start in root dir
160 name - path of file/dir
161 block - will be filled with the block number
162 prior the entry we are using; rootblock
163 if we are searching for the root
164 Output: NULL=error (evtl. error=ERROR_...)
165 blockcache structure of found block otherwise
166 ********************************************/
167 struct BlockCache
*findBlock
169 struct AFSBase
*afsbase
,
170 struct AfsHandle
*dirah
,
176 struct BlockCache
*blockbuffer
;
179 if (dirah
->volume
->dostype
!= 0x444F5300)
181 error
= ERROR_NOT_A_DOS_DISK
;
184 *block
= dirah
->header_block
;
186 D(bug("[afs] findBlock: startblock=%ld\n",*block
));
187 /* get first entry (root or filelock refers to) */
188 blockbuffer
= getBlock(afsbase
, dirah
->volume
, *block
);
189 if (blockbuffer
== NULL
)
191 error
= ERROR_UNKNOWN
;
192 D(bug("[afs] error blockbuffer\n"));
195 if (calcChkSum(dirah
->volume
->SizeBlock
, blockbuffer
->buffer
) != 0)
198 * not working with blockbuffer any more.
199 * otherwise we would need to preserve it (BCF_USED or one more time getBlock)
201 if (showError(afsbase
, ERR_CHECKSUM
, *block
))
202 launchValidator(afsbase
, dirah
->volume
);
204 error
= ERROR_UNKNOWN
;
205 D(bug("[afs] error checksum\n"));
208 if (OS_BE2LONG(blockbuffer
->buffer
[BLK_PRIMARY_TYPE
]) != T_SHORT
)
213 if (showError(afsbase
, ERR_BLOCKTYPE
, *block
))
214 launchValidator(afsbase
, dirah
->volume
);
216 error
= ERROR_OBJECT_WRONG_TYPE
;
217 D(bug("[afs] error wrong type\n"));
222 if (*name
== '/') /* get parent entry ? */
224 if (blockbuffer
->buffer
[BLK_PARENT(dirah
->volume
)] == 0)
226 error
= ERROR_OBJECT_NOT_FOUND
;
227 D(bug("[afs] object not found\n"));
230 D(bug("[afs] findBlock: getting parent\n"));
231 blockbuffer
= getBlock
235 OS_BE2LONG(blockbuffer
->buffer
[BLK_PARENT(dirah
->volume
)])
237 if (blockbuffer
== NULL
)
239 error
= ERROR_UNKNOWN
;
240 D(bug("[afs] error no blockbuffer\n"));
250 blockbuffer
->buffer
[BLK_SECONDARY_TYPE(dirah
->volume
)]
254 blockbuffer
->buffer
[BLK_SECONDARY_TYPE(dirah
->volume
)]
258 blockbuffer
->buffer
[BLK_SECONDARY_TYPE(dirah
->volume
)]
261 error
= ERROR_OBJECT_WRONG_TYPE
;
262 D(bug("[afs] error wrong type\n"));
266 while ((*name
!= 0) && (*name
!= '/'))
275 "[afs] findBlock: searching for header block of %s\n",
279 getHeaderBlock(afsbase
, dirah
->volume
, buffer
, blockbuffer
, block
);
280 if (blockbuffer
== NULL
)
281 break; /* object not found or other error */
285 if (blockbuffer
!= NULL
)
286 bug("[afs] findBlock: block=%ld\n",blockbuffer
->blocknum
);
288 bug("[afs] findBlock: error\n");
293 /* add handle to locklist */
294 void addHandle(struct AfsHandle
*ah
) {
296 ah
->next
=ah
->volume
->locklist
;
297 ah
->volume
->locklist
=ah
;
300 /* remove handle from locklist */
301 void remHandle(struct AfsHandle
*ah
) {
302 struct AfsHandle
*old
;
304 if (ah
->volume
->locklist
==ah
)
305 ah
->volume
->locklist
=ah
->next
;
308 old
=ah
->volume
->locklist
;
321 /* find handle in locklist */
322 struct AfsHandle
*findHandle(struct Volume
*volume
, ULONG block
) {
323 struct AfsHandle
*ah
;
328 if (ah
->header_block
==block
)
335 /****************************************
337 Descr.: allocate a new handle
339 fileblock - block of the entry
341 hashtable - ptr to the (hash)table
342 Output: AfsHandle for success; NULL otherwise
343 ****************************************/
344 struct AfsHandle
*allocHandle
346 struct AFSBase
*afsbase
,
347 struct Volume
*volume
,
348 struct BlockCache
*fileblock
,
353 struct AfsHandle
*ah
;
355 ah
=(struct AfsHandle
*)AllocMem
356 (sizeof(struct AfsHandle
), MEMF_PUBLIC
| MEMF_CLEAR
);
359 ah
->header_block
= fileblock
->blocknum
;
360 ah
->dirpos
= fileblock
->blocknum
;
362 ah
->current
.block
= fileblock
->blocknum
;
363 ah
->current
.filekey
= BLK_TABLE_END(volume
);
364 ah
->current
.byte
= 0;
365 ah
->current
.offset
= 0;
366 ah
->filesize
= OS_BE2LONG(fileblock
->buffer
[BLK_BYTE_SIZE(volume
)]);
371 error
= ERROR_NO_FREE_STORE
;
375 /****************************************
377 Descr.: check if a new handle can be
378 allocated and allocate one if
381 fileblock - block of the entry
383 Output: AfsHandle for success; NULL otherwise
384 ****************************************/
385 struct AfsHandle
*getHandle
387 struct AFSBase
*afsbase
,
388 struct Volume
*volume
,
389 struct BlockCache
*fileblock
,
393 struct AfsHandle
*ah
;
397 "[afs] getHandle: trying to get handle for block %lu\n",
403 ah
= findHandle(volume
, fileblock
->blocknum
);
406 if (ah
->mode
& FMF_LOCK
)
408 error
= ERROR_OBJECT_IN_USE
;
421 (ULONG
*)((char *)fileblock
->buffer
+(BLK_TABLE_START
*4))
428 /*****************************************
430 Descr.: open (lock) a file
431 Input : dirah - a handle filename is
433 filename - filename to lock
435 Output: AfsHandle for success; NULL otherwise
436 ******************************************/
437 struct AfsHandle
*openf
439 struct AFSBase
*afsbase
,
440 struct AfsHandle
*dirah
,
445 struct AfsHandle
*ah
= NULL
;
446 struct BlockCache
*fileblock
;
449 D(bug("[afs] openf(%ld,%s,%ld)\n",dirah
->header_block
,filename
,mode
));
450 fileblock
= findBlock(afsbase
, dirah
, filename
, &block
);
451 if (fileblock
!= NULL
)
452 ah
= getHandle(afsbase
, dirah
->volume
, fileblock
, mode
);
456 /*****************************************
458 Descr.: open (lock) a file
459 Input : dirah - a handle filename is
461 filename - filename to lock
463 protection - bits for new files
464 Output: AfsHandle for success; NULL otherwise
465 ******************************************/
466 struct AfsHandle
*openfile
468 struct AFSBase
*afsbase
,
469 struct AfsHandle
*dirah
,
475 struct AfsHandle
*ah
= NULL
;
476 struct BlockCache
*fileblock
, *dirblock
;
480 ULONG fileblocknum
= -1;
483 * nicely say what's going on
485 D(bug("[afs] openfile(%lu,%s,0x%lx,%lu)\n", dirah
->header_block
,name
,mode
,protection
));
489 * if user wants to delete or create a new file - make sure we can do that.
491 if (((mode
& FMF_CLEAR
) || (mode
& FMF_CREATE
)) && (0 == checkValid(afsbase
, dirah
->volume
)))
492 error
= ERROR_DISK_WRITE_PROTECTED
;
495 * get the directory the last component of "name" is in
497 dirblock
= getDirBlockBuffer(afsbase
, dirah
, name
, filename
);
500 * if no error so far and directory block is found, move on.
502 if (error
== 0 && dirblock
!= NULL
)
505 * only if the directory is of DIR or ROOT type
507 if ((OS_BE2LONG(dirblock
->buffer
[BLK_SECONDARY_TYPE(dirah
->volume
)]) == ST_USERDIR
) ||
508 (OS_BE2LONG(dirblock
->buffer
[BLK_SECONDARY_TYPE(dirah
->volume
)]) == ST_ROOT
))
510 D(bug("[afs] parent of %s is on block %lu\n", name
, dirblock
->blocknum
));
511 dirblocknum
= dirblock
->blocknum
;
514 * get the header block of the file to open
516 fileblock
= getHeaderBlock(afsbase
, dirah
->volume
, filename
, dirblock
, &block
);
519 * check if 'file' is really a FILE
521 if ((fileblock
!= NULL
) && (OS_BE2LONG(fileblock
->buffer
[BLK_SECONDARY_TYPE(dirah
->volume
)])!=ST_FILE
))
523 error
= ERROR_OBJECT_WRONG_TYPE
;
528 * get file block, if there was (is) a file
530 if (fileblock
!= NULL
)
531 fileblocknum
= fileblock
->blocknum
;
534 * remove existing file if we are asked to clear its contents
536 if (mode
& FMF_CLEAR
)
537 error
= deleteObject(afsbase
, dirah
, name
);
540 * if we cleared the file or there was no file at all, move on
542 if ((error
== 0) || (error
== ERROR_OBJECT_NOT_FOUND
))
545 * in case we could not find existing file, or if we deleted this file previously,
548 if ((mode
& FMF_CREATE
) && ((fileblock
== NULL
) || (mode
& FMF_CLEAR
)))
551 * please note that dirblock may become invalid here
553 fileblock
= createNewEntry(afsbase
, dirah
->volume
, ST_FILE
, filename
, dirblock
, protection
);
558 * we should already have fileblock here
559 * again, dirblock may become invalid here
561 if (fileblock
!= NULL
)
562 fileblock
= getBlock(afsbase
, dirah
->volume
, fileblocknum
);
566 * create a handle for the file
568 if (fileblock
!= NULL
)
571 ah
= getHandle(afsbase
, dirah
->volume
, fileblock
, mode
);
577 error
= ERROR_OBJECT_WRONG_TYPE
;
582 /***********************************
584 Descr.: close a file/free a lock
585 Input : ah - the handle to close
587 ************************************/
588 void closef(struct AFSBase
*afsbase
, struct AfsHandle
*ah
) {
590 D(bug("[afs] closef(%lu)\n",ah
->header_block
));
592 FreeMem(ah
,sizeof(struct AfsHandle
));
595 /******************************************
597 Descr.: read data from file
598 Input : ah - handle (file) to read from
599 buffer - buffer to store data into
600 length - size of data to read
602 *******************************************/
605 struct AFSBase
*afsbase
,
606 struct AfsHandle
*ah
,
611 struct BlockCache
*extensionbuffer
;
612 struct BlockCache
*databuffer
;
617 if (ah
->current
.block
== 0)
618 return 0; /* we can't read beyond EOF so return EOF */
619 if (length
> (ah
->filesize
-ah
->current
.offset
))
621 length
= ah
->filesize
-ah
->current
.offset
; /* we can't read more bytes than left in file! */
623 D(bug("[afs] readData: offset=%ld\n", ah
->current
.offset
));
624 extensionbuffer
= getBlock(afsbase
, ah
->volume
, ah
->current
.block
);
625 if (extensionbuffer
== NULL
)
627 error
= ERROR_UNKNOWN
;
630 extensionbuffer
->flags
|= BCF_USED
; /* don't overwrite that cache block! */
633 D(bug("[afs] readData: bytes left=%ld\n",length
));
635 block, filekey always point to the next block
636 so update them if we have read a whole block
638 /* do we have to read next extension block? */
639 if (ah
->current
.filekey
<BLK_TABLE_START
)
642 OS_BE2LONG(extensionbuffer
->buffer
[BLK_EXTENSION(ah
->volume
)]);
643 ah
->current
.filekey
= BLK_TABLE_END(ah
->volume
);
644 extensionbuffer
->flags
&= ~BCF_USED
; //we can now overwrite that cache block
645 D(bug("[afs] readData: reading extensionblock=%ld\n",ah
->current
.block
));
646 if (ah
->current
.block
!= 0)
648 extensionbuffer
= getBlock(afsbase
, ah
->volume
,ah
->current
.block
);
649 if (extensionbuffer
== 0)
651 error
= ERROR_UNKNOWN
;
652 return ENDSTREAMCH
; //was readbytes;
654 extensionbuffer
->flags
|= BCF_USED
; //don't overwrite this cache block
661 "Shit, out of extensionblocks!\n"
663 "Last extensionblock: %ld\n",
664 length
,extensionbuffer
->blocknum
670 "[afs] readData: reading datablock %ld\n",
671 OS_BE2LONG(extensionbuffer
->buffer
[ah
->current
.filekey
]))
673 databuffer
= getBlock
677 OS_BE2LONG(extensionbuffer
->buffer
[ah
->current
.filekey
])
681 extensionbuffer
->flags
&= ~BCF_USED
; //free that block
682 error
= ERROR_UNKNOWN
;
683 return ENDSTREAMCH
; //was readbytes;
685 source
= (char *)databuffer
->buffer
+ah
->current
.byte
;
686 if (ah
->volume
->dosflags
== 0)
688 size
= OS_BE2LONG(databuffer
->buffer
[BLK_DATA_SIZE
]);
689 source
+= (BLK_DATA_START
*4);
693 size
= BLOCK_SIZE(ah
->volume
);
695 size
-= ah
->current
.byte
;
699 ah
->current
.byte
+= size
;
703 ah
->current
.byte
= 0;
704 ah
->current
.filekey
--;
706 CopyMem((APTR
)source
, (APTR
)((char *)buffer
+readbytes
),size
);
710 extensionbuffer
->flags
&= ~BCF_USED
;
715 (struct AFSBase
*afsbase
, struct AfsHandle
*ah
, void *buffer
, ULONG length
)
719 D(bug("[afs] read(%ld,buffer,%ld)\n", ah
->header_block
, length
));
720 readbytes
= readData(afsbase
, ah
,buffer
,length
);
721 if (readbytes
!= ENDSTREAMCH
)
722 ah
->current
.offset
= ah
->current
.offset
+readbytes
;
726 void newFileExtensionBlock
728 struct Volume
*volume
,
729 struct BlockCache
*extension
,
734 extension
->buffer
[BLK_PRIMARY_TYPE
] = OS_LONG2BE(T_LIST
);
735 extension
->buffer
[BLK_OWN_KEY
] = OS_LONG2BE(extension
->blocknum
);
736 for (i
=2; i
<BLK_PARENT(volume
); i
++)
737 extension
->buffer
[i
] = 0;
738 extension
->buffer
[BLK_PARENT(volume
)] = OS_LONG2BE(parent
);
739 extension
->buffer
[BLK_EXTENSION(volume
)] = 0;
740 extension
->buffer
[BLK_SECONDARY_TYPE(volume
)] = OS_LONG2BE(ST_FILE
);
743 void writeExtensionBlock
745 struct AFSBase
*afsbase
,
746 struct Volume
*volume
,
747 struct BlockCache
*extension
,
752 ULONG newcount
= BLK_TABLE_END(volume
)-(filekey
-1);
754 if (OS_BE2LONG(extension
->buffer
[BLK_BLOCK_COUNT
]) < newcount
)
755 extension
->buffer
[BLK_BLOCK_COUNT
] = OS_LONG2BE(newcount
);
757 extension
->buffer
[BLK_EXTENSION(volume
)] = OS_LONG2BE(next
);
758 writeBlockDeferred(afsbase
, volume
, extension
, BLK_CHECKSUM
);
763 struct AFSBase
*afsbase
,
764 struct AfsHandle
*ah
,
770 ULONG lastblock
= 0; /* 0 means: don't update BLK_NEXT_DATA */
771 struct BlockCache
*extensionbuffer
= NULL
;
772 struct BlockCache
*databuffer
= NULL
;
773 UWORD size
, blockCapacity
;
774 LONG writtenbytes
= 0, sumoffset
;
776 BOOL extensionModified
= FALSE
;
778 D(bug("[afs] writeData: offset=%ld\n", ah
->current
.offset
));
779 extensionbuffer
= getBlock(afsbase
, ah
->volume
, ah
->current
.block
);
780 if (extensionbuffer
== NULL
)
782 error
= ERROR_UNKNOWN
;
785 extensionbuffer
->flags
|=BCF_USED
; /* don't overwrite that cache block! */
788 /* save last data block for OFS data */
790 (ah
->current
.byte
==0) && /* last block fully written */
791 (ah
->current
.filekey
!=BLK_TABLE_END(ah
->volume
)) /* this is not the first block of the file */
794 lastblock
= OS_BE2LONG(extensionbuffer
->buffer
[ah
->current
.filekey
+1]);
796 ("[afs] writeData: for OFS last datablock was %lu\n", lastblock
));
799 block, filekey always point to the last block
800 so update them if we have read a whole block
802 /* read next extension block? */
803 if (ah
->current
.filekey
< BLK_TABLE_START
)
805 extensionModified
= FALSE
;
806 if (extensionbuffer
->buffer
[BLK_EXTENSION(ah
->volume
)] != 0)
808 block
= OS_BE2LONG(extensionbuffer
->buffer
[BLK_EXTENSION(ah
->volume
)]);
809 extensionbuffer
->flags
&= ~BCF_USED
;
810 extensionbuffer
= getBlock(afsbase
, ah
->volume
, block
);
811 if (extensionbuffer
== NULL
)
813 error
= ERROR_UNKNOWN
;
814 return ENDSTREAMCH
; // was writtenbytes;
819 D(bug("[afs] writeData: need new extensionblock\n"));
820 block
= allocBlock(afsbase
, ah
->volume
);
826 ah
->current
.filekey
+1,
829 extensionbuffer
->flags
&= ~BCF_USED
;
832 error
= ERROR_NO_FREE_STORE
;
833 return ENDSTREAMCH
; /* was writtenbytes; */
835 extensionbuffer
= getFreeCacheBlock(afsbase
, ah
->volume
,block
);
836 if (extensionbuffer
== NULL
)
838 error
= ERROR_UNKNOWN
;
839 return ENDSTREAMCH
; /* was writtenbytes; */
841 newFileExtensionBlock(ah
->volume
,extensionbuffer
, ah
->header_block
);
843 ah
->current
.filekey
= BLK_TABLE_END(ah
->volume
);
844 extensionbuffer
->flags
|= BCF_USED
; /* don't overwrite this cache block */
845 ah
->current
.block
= block
;
847 /* find a block to write data into */
848 if (extensionbuffer
->buffer
[ah
->current
.filekey
] != 0) /* do we already have that block? */
852 "[afs] writeData: using old datablock %lu\n",
853 OS_BE2LONG(extensionbuffer
->buffer
[ah
->current
.filekey
]))
855 /* Only get the block's old contents if some of it won't be overwritten
856 (except for OFS or a final, partially-used block) */
857 block
= OS_BE2LONG(extensionbuffer
->buffer
[ah
->current
.filekey
]);
858 if ((ah
->current
.byte
== 0) && (length
>= BLOCK_SIZE(ah
->volume
))
859 && (ah
->volume
->dosflags
!= 0))
860 databuffer
= getFreeCacheBlock(afsbase
, ah
->volume
, block
);
862 databuffer
= getBlock(afsbase
, ah
->volume
, block
);
863 if (databuffer
== NULL
)
873 extensionbuffer
->flags
&= ~BCF_USED
; //free that block
874 error
= ERROR_UNKNOWN
;
875 return ENDSTREAMCH
; //was writtenbytes;
880 extensionModified
= TRUE
;
881 D(bug("[afs] writeData: need a new datablock\n"));
882 block
=allocBlock(afsbase
, ah
->volume
);
893 extensionbuffer
->flags
&= ~BCF_USED
;
894 error
= ERROR_NO_FREE_STORE
;
895 return ENDSTREAMCH
; //was writtenbytes;
897 extensionbuffer
->buffer
[ah
->current
.filekey
] = OS_LONG2BE(block
);
898 if ((ah
->volume
->dosflags
==0) && (lastblock
!= 0))
900 D(bug("[afs] writeData: OFS->fill in %ld BLK_NEXT_DATA\n",lastblock
));
902 we allocated a new block
903 so there MUST be an initialized lastblock
905 databuffer
= getBlock(afsbase
, ah
->volume
,lastblock
);
906 if (databuffer
== NULL
)
916 extensionbuffer
->flags
&= ~BCF_USED
; //free that block
917 error
= ERROR_UNKNOWN
;
918 return ENDSTREAMCH
; //was writtenbytes;
920 databuffer
->buffer
[BLK_NEXT_DATA
] = OS_LONG2BE(block
);
921 writeBlock(afsbase
, ah
->volume
,databuffer
, BLK_CHECKSUM
);
923 databuffer
= getFreeCacheBlock(afsbase
, ah
->volume
,block
);
924 if (databuffer
== NULL
)
927 (afsbase
, ah
->volume
, extensionbuffer
, ah
->current
.filekey
, 0);
928 extensionbuffer
->flags
&= ~BCF_USED
; //free that block
929 error
= ERROR_UNKNOWN
;
930 return ENDSTREAMCH
; //was writtenbytes;
932 if (ah
->volume
->dosflags
== 0)
934 databuffer
->buffer
[BLK_PRIMARY_TYPE
] = OS_LONG2BE(T_DATA
);
935 databuffer
->buffer
[BLK_HEADER_KEY
] = OS_LONG2BE(ah
->header_block
);
936 blockCapacity
= (ah
->volume
->SizeBlock
-BLK_DATA_START
)*sizeof(ULONG
);
937 databuffer
->buffer
[BLK_SEQUENCE_NUMBER
] =
939 (((ah
->current
.offset
+writtenbytes
)/blockCapacity
)+1);
940 databuffer
->buffer
[BLK_DATA_SIZE
] = 0;
941 databuffer
->buffer
[BLK_NEXT_DATA
] = 0;
944 destination
= (char *)databuffer
->buffer
+ah
->current
.byte
;
945 size
= BLOCK_SIZE(ah
->volume
);
946 if (ah
->volume
->dosflags
== 0)
949 destination
+= (BLK_DATA_START
*4);
951 size
-= ah
->current
.byte
;
955 ah
->current
.byte
+= size
;
959 ah
->current
.byte
= 0;
960 ah
->current
.filekey
--;
962 CopyMem((APTR
)((char *)buffer
+writtenbytes
),(APTR
)destination
,size
);
963 if (ah
->volume
->dosflags
== 0)
965 if (ah
->current
.byte
== 0)
967 databuffer
->buffer
[BLK_DATA_SIZE
] =
968 OS_LONG2BE(BLOCK_SIZE(ah
->volume
)-(6*4));
970 else if (OS_BE2LONG(databuffer
->buffer
[BLK_DATA_SIZE
]) < ah
->current
.byte
)
972 databuffer
->buffer
[BLK_DATA_SIZE
] = OS_LONG2BE(ah
->current
.byte
);
974 sumoffset
= BLK_CHECKSUM
;
978 writeBlock(afsbase
, ah
->volume
, databuffer
, sumoffset
);
980 writtenbytes
+= size
;
982 if (extensionModified
)
989 ah
->current
.byte
==0 ? ah
->current
.filekey
+1 : ah
->current
.filekey
,
993 extensionbuffer
->flags
&= ~BCF_USED
;
994 D(bug("[afs] writeData=%ld\n", writtenbytes
));
999 (struct AFSBase
*afsbase
, struct AfsHandle
*ah
, void *buffer
, ULONG length
)
1001 struct BlockCache
*headerblock
;
1003 struct DateStamp ds
;
1005 D(bug("[afs] write(ah,buffer,%ld)\n", length
));
1006 if (0 == checkValid(afsbase
, ah
->volume
))
1008 error
= ERROR_DISK_WRITE_PROTECTED
;
1012 invalidBitmap(afsbase
, ah
->volume
);
1013 writtenbytes
= writeData(afsbase
, ah
, buffer
, length
);
1014 if (writtenbytes
!= ENDSTREAMCH
)
1016 ah
->current
.offset
+= writtenbytes
;
1017 headerblock
= getBlock(afsbase
, ah
->volume
,ah
->header_block
);
1018 if (headerblock
!= NULL
)
1020 headerblock
->buffer
[BLK_FIRST_DATA
] =
1021 headerblock
->buffer
[BLK_TABLE_END(ah
->volume
)];
1022 if (ah
->current
.offset
> ah
->filesize
)
1024 ah
->filesize
= ah
->current
.offset
;
1025 headerblock
->buffer
[BLK_BYTE_SIZE(ah
->volume
)] =
1026 OS_LONG2BE(ah
->filesize
);
1029 setHeaderDate(afsbase
, ah
->volume
, headerblock
, &ds
);
1032 validBitmap(afsbase
, ah
->volume
);
1033 return writtenbytes
;
1037 (struct AFSBase
* afsbase
, struct AfsHandle
*ah
, LONG offset
, LONG mode
)
1040 UWORD filekey
, byte
;
1041 ULONG block
, extblockindex
, newextblockindex
;
1042 UWORD blocksize
, tablesize
;
1044 struct BlockCache
*blockbuffer
;
1046 D(bug("[afs] seek(%ld,%ld,%ld)\n", ah
->header_block
, offset
, mode
));
1047 error
= ERROR_SEEK_ERROR
;
1048 if (mode
== OFFSET_BEGINNING
)
1050 newoffset
= (ULONG
)offset
;
1052 else if (mode
== OFFSET_CURRENT
)
1057 return ah
->current
.offset
;
1059 newoffset
= ah
->current
.offset
+offset
;
1061 else if (mode
== OFFSET_END
)
1063 newoffset
= ah
->filesize
+offset
;
1069 blocksize
= BLOCK_SIZE(ah
->volume
);
1070 if (ah
->volume
->dosflags
== 0)
1071 blocksize
-= (BLK_DATA_START
*4);
1072 newextblockindex
= newoffset
/ blocksize
;
1073 tablesize
= BLK_TABLE_END(ah
->volume
)-BLK_TABLE_START
+1; /* hashtable size */
1074 filekey
= BLK_TABLE_END(ah
->volume
)-(newextblockindex
% tablesize
);
1075 newextblockindex
/= tablesize
; /* # of extensionblock we need */
1076 byte
= newoffset
% blocksize
;
1078 /* Get index of current extension block */
1079 extblockindex
= (ah
->current
.offset
/ blocksize
) / tablesize
;
1080 if (ah
->current
.filekey
<BLK_TABLE_START
)
1083 /* Start at current extension block, unless we have to go back to
1084 a previous extension block */
1085 if (newextblockindex
>= extblockindex
)
1086 block
= ah
->current
.block
;
1089 block
= ah
->header_block
;
1093 while ((extblockindex
!= newextblockindex
) && (block
!= 0))
1095 blockbuffer
= getBlock(afsbase
, ah
->volume
, block
);
1096 if (blockbuffer
== NULL
)
1098 block
= OS_BE2LONG(blockbuffer
->buffer
[BLK_EXTENSION(ah
->volume
)]);
1104 old
= ah
->current
.offset
;
1105 ah
->current
.block
= block
;
1106 ah
->current
.filekey
= filekey
;
1107 ah
->current
.byte
= byte
;
1108 ah
->current
.offset
= newoffset
;
1114 /* vim: set noet ts=3 ai fdm=marker fmr={,} :*/