2 * ADF Library. (C) 1997-1999 Laurent Clevy
16 #include "defendian.h"
21 #include "adf_cache.h"
23 extern struct Env adfEnv
;
25 void adfFileTruncate(struct Volume
*vol
, SECTNUM nParent
, char *name
)
35 void adfFlushFile(struct File
*file
)
37 struct bEntryBlock parent
;
38 struct bOFSDataBlock
*data
;
40 if (file
->currentExt
) {
42 adfWriteFileExtBlock(file
->volume
, file
->currentExt
->headerKey
,
45 if (file
->currentData
) {
46 if (file
->writeMode
) {
47 file
->fileHdr
->byteSize
= file
->pos
;
48 if (isOFS(file
->volume
->dosType
)) {
49 data
= (struct bOFSDataBlock
*)file
->currentData
;
50 data
->dataSize
= file
->posInDataBlk
;
52 if (file
->fileHdr
->byteSize
>0)
53 adfWriteDataBlock(file
->volume
, file
->curDataPtr
,
57 if (file
->writeMode
) {
58 file
->fileHdr
->byteSize
= file
->pos
;
59 //printf("pos=%ld\n",file->pos);
60 adfTime2AmigaTime(adfGiveCurrentTime(),
61 &(file
->fileHdr
->days
),&(file
->fileHdr
->mins
),&(file
->fileHdr
->ticks
) );
62 adfWriteFileHdrBlock(file
->volume
, file
->fileHdr
->headerKey
, file
->fileHdr
);
64 if (isDIRCACHE(file
->volume
->dosType
)) {
65 //printf("parent=%ld\n",file->fileHdr->parent);
66 adfReadEntryBlock(file
->volume
, file
->fileHdr
->parent
, &parent
);
67 adfUpdateCache(file
->volume
, &parent
, (struct bEntryBlock
*)file
->fileHdr
,FALSE
);
69 adfUpdateBitmap(file
->volume
);
78 RETCODE
adfGetFileBlocks(struct Volume
* vol
, struct bFileHeaderBlock
* entry
,
79 struct FileBlocks
* fileBlocks
)
83 struct bFileExtBlock extBlock
;
86 fileBlocks
->header
= entry
->headerKey
;
87 adfFileRealSize( entry
->byteSize
, vol
->datablockSize
,
88 &(fileBlocks
->nbData
), &(fileBlocks
->nbExtens
) );
90 fileBlocks
->data
=(SECTNUM
*)malloc(fileBlocks
->nbData
* sizeof(SECTNUM
));
91 if (!fileBlocks
->data
) {
92 (*adfEnv
.eFct
)("adfGetFileBlocks : malloc");
96 fileBlocks
->extens
=(SECTNUM
*)malloc(fileBlocks
->nbExtens
* sizeof(SECTNUM
));
97 if (!fileBlocks
->extens
) {
98 (*adfEnv
.eFct
)("adfGetFileBlocks : malloc");
103 /* in file header block */
104 for(i
=0; i
<entry
->highSeq
; i
++)
105 fileBlocks
->data
[n
++] = entry
->dataBlocks
[MAX_DATABLK
-1-i
];
107 /* in file extension blocks */
108 nSect
= entry
->extension
;
110 fileBlocks
->extens
[m
++] = nSect
;
111 adfReadFileExtBlock(vol
, nSect
, &extBlock
);
112 for(i
=0; i
<extBlock
.highSeq
; i
++)
113 fileBlocks
->data
[n
++] = extBlock
.dataBlocks
[MAX_DATABLK
-1-i
];
114 nSect
= extBlock
.extension
;
116 if ( (fileBlocks
->nbExtens
+fileBlocks
->nbData
) != (n
+m
) )
117 (*adfEnv
.wFct
)("adfGetFileBlocks : less blocks than expected");
126 RETCODE
adfFreeFileBlocks(struct Volume
* vol
, struct bFileHeaderBlock
*entry
)
129 struct FileBlocks fileBlocks
;
132 adfGetFileBlocks(vol
,entry
,&fileBlocks
);
134 for(i
=0; i
<fileBlocks
.nbData
; i
++) {
135 adfSetBlockFree(vol
, fileBlocks
.data
[i
]);
137 for(i
=0; i
<fileBlocks
.nbExtens
; i
++) {
138 adfSetBlockFree(vol
, fileBlocks
.extens
[i
]);
141 free(fileBlocks
.data
);
142 free(fileBlocks
.extens
);
151 * Compute and return real number of block used by one file
152 * Compute number of datablocks and file extension blocks
155 ULONG
adfFileRealSize(ULONG size
, int blockSize
, ULONG
*dataN
, ULONG
*extN
)
159 /*--- number of data blocks ---*/
160 data
= size
/ blockSize
;
161 if ( size
% blockSize
)
164 /*--- number of header extension blocks ---*/
166 if (data
>MAX_DATABLK
) {
167 ext
= (data
-MAX_DATABLK
) / MAX_DATABLK
;
168 if ( (data
-MAX_DATABLK
) % MAX_DATABLK
)
182 * adfWriteFileHdrBlock
185 RETCODE
adfWriteFileHdrBlock(struct Volume
*vol
, SECTNUM nSect
, struct bFileHeaderBlock
* fhdr
)
187 unsigned char buf
[512];
190 //printf("adfWriteFileHdrBlock %ld\n",nSect);
191 fhdr
->type
= T_HEADER
;
193 fhdr
->secType
= ST_FILE
;
195 memcpy(buf
, fhdr
, sizeof(struct bFileHeaderBlock
));
197 swapEndian(buf
, SWBL_FILE
);
199 newSum
= adfNormalSum(buf
,20,sizeof(struct bFileHeaderBlock
));
200 swLong(buf
+20, newSum
);
201 // *(ULONG*)(buf+20) = swapLong((unsigned char*)&newSum);
203 adfWriteBlock(vol
, nSect
, buf
);
213 void adfFileSeek(struct File
*file
, ULONG pos
)
215 SECTNUM extBlock
, nSect
;
219 nPos
= min(pos
, file
->fileHdr
->byteSize
);
221 extBlock
= adfPos2DataBlock(nPos
, file
->volume
->datablockSize
,
222 &(file
->posInExtBlk
), &(file
->posInDataBlk
), &(file
->curDataPtr
) );
224 adfReadDataBlock(file
->volume
,
225 file
->fileHdr
->dataBlocks
[MAX_DATABLK
-1-file
->curDataPtr
],
229 nSect
= file
->fileHdr
->extension
;
231 while( i
<extBlock
&& nSect
!=0 ) {
232 adfReadFileExtBlock(file
->volume
, nSect
, file
->currentExt
);
233 nSect
= file
->currentExt
->extension
;
236 (*adfEnv
.wFct
)("error");
237 adfReadDataBlock(file
->volume
,
238 file
->currentExt
->dataBlocks
[file
->posInExtBlk
], file
->currentData
);
247 struct File
* adfOpenFile(struct Volume
*vol
, char* name
, char *mode
)
251 struct bEntryBlock entry
, parent
;
255 write
=( strcmp("w",mode
)==0 || strcmp("a",mode
)==0 );
257 if (write
&& vol
->dev
->readOnly
) {
258 (*adfEnv
.wFct
)("adfFileOpen : device is mounted 'read only'");
262 adfReadEntryBlock(vol
, vol
->curDirPtr
, &parent
);
264 nSect
= adfNameToEntryBlk(vol
, parent
.hashTable
, name
, &entry
, NULL
);
265 if (!write
&& nSect
==-1) {
266 sprintf(filename
,"adfFileOpen : file \"%s\" not found.",name
);
267 (*adfEnv
.wFct
)(filename
);
268 //fprintf(stdout,"filename %s %d, parent =%d\n",name,strlen(name),vol->curDirPtr);
271 if (!write
&& hasR(entry
.access
)) {
272 (*adfEnv
.wFct
)("adfFileOpen : access denied"); return NULL
; }
273 /* if (entry.secType!=ST_FILE) {
274 (*adfEnv.wFct)("adfFileOpen : not a file"); return NULL; }
275 if (write && (hasE(entry.access)||hasW(entry.access))) {
276 (*adfEnv.wFct)("adfFileOpen : access denied"); return NULL; }
277 */ if (write
&& nSect
!=-1) {
278 (*adfEnv
.wFct
)("adfFileOpen : file already exists"); return NULL
; }
280 file
= (struct File
*)malloc(sizeof(struct File
));
281 if (!file
) { (*adfEnv
.wFct
)("adfFileOpen : malloc"); return NULL
; }
282 file
->fileHdr
= (struct bFileHeaderBlock
*)malloc(sizeof(struct bFileHeaderBlock
));
283 if (!file
->fileHdr
) {
284 (*adfEnv
.wFct
)("adfFileOpen : malloc");
285 free(file
); return NULL
;
287 file
->currentData
= malloc(512*sizeof(unsigned char));
288 if (!file
->currentData
) {
289 (*adfEnv
.wFct
)("adfFileOpen : malloc");
290 free(file
->fileHdr
); free(file
); return NULL
;
293 memset(file
->currentData
, 0xff, 512);
297 file
->posInExtBlk
= 0;
298 file
->posInDataBlk
= 0;
299 file
->writeMode
= write
;
300 file
->currentExt
= NULL
;
301 file
->nDataBlock
= 0;
303 if (strcmp("w",mode
)==0) {
304 memset(file
->fileHdr
,0,512);
305 adfCreateFile(vol
,vol
->curDirPtr
,name
,file
->fileHdr
);
308 else if (strcmp("a",mode
)==0) {
309 memcpy(file
->fileHdr
,&entry
,sizeof(struct bFileHeaderBlock
));
311 adfFileSeek(file
, file
->fileHdr
->byteSize
);
313 else if (strcmp("r",mode
)==0) {
314 memcpy(file
->fileHdr
,&entry
,sizeof(struct bFileHeaderBlock
));
318 //puts("adfOpenFile");
327 void adfCloseFile(struct File
*file
)
332 //puts("adfCloseFile in");
336 if (file
->currentExt
)
337 free(file
->currentExt
);
339 if (file
->currentData
)
340 free(file
->currentData
);
345 //puts("adfCloseFile out");
353 ULONG
adfReadFile(struct File
* file
, ULONG n
, unsigned char *buffer
)
356 unsigned char *dataPtr
, *bufPtr
;
360 blockSize
= file
->volume
->datablockSize
;
361 /*puts("adfReadFile");*/
362 if (file
->pos
+n
> file
->fileHdr
->byteSize
)
363 n
= file
->fileHdr
->byteSize
- file
->pos
;
365 if (isOFS(file
->volume
->dosType
))
366 dataPtr
= (unsigned char*)(file
->currentData
)+24;
368 dataPtr
= file
->currentData
;
370 if (file
->pos
==0 || file
->posInDataBlk
==blockSize
) {
371 adfReadNextFileBlock(file
);
372 file
->posInDataBlk
= 0;
375 bytesRead
= 0; bufPtr
= buffer
;
377 while ( bytesRead
< n
) {
378 size
= min(n
-bytesRead
, blockSize
-file
->posInDataBlk
);
379 memcpy(bufPtr
, dataPtr
+file
->posInDataBlk
, size
);
383 file
->posInDataBlk
+= size
;
384 if (file
->posInDataBlk
==blockSize
&& bytesRead
<n
) {
385 adfReadNextFileBlock(file
);
386 file
->posInDataBlk
= 0;
389 file
->eof
= (file
->pos
==file
->fileHdr
->byteSize
);
398 BOOL
adfEndOfFile(struct File
* file
)
405 * adfReadNextFileBlock
408 RETCODE
adfReadNextFileBlock(struct File
* file
)
411 struct bOFSDataBlock
*data
;
414 data
=(struct bOFSDataBlock
*) file
->currentData
;
416 if (file
->nDataBlock
==0) {
417 nSect
= file
->fileHdr
->firstData
;
419 else if (isOFS(file
->volume
->dosType
)) {
420 nSect
= data
->nextData
;
423 if (file
->nDataBlock
<MAX_DATABLK
)
424 nSect
= file
->fileHdr
->dataBlocks
[MAX_DATABLK
-1-file
->nDataBlock
];
426 if (file
->nDataBlock
==MAX_DATABLK
) {
427 file
->currentExt
=(struct bFileExtBlock
*)malloc(sizeof(struct bFileExtBlock
));
428 if (!file
->currentExt
) (*adfEnv
.eFct
)("adfReadNextFileBlock : malloc");
429 adfReadFileExtBlock(file
->volume
, file
->fileHdr
->extension
,
431 file
->posInExtBlk
= 0;
433 else if (file
->posInExtBlk
==MAX_DATABLK
) {
434 adfReadFileExtBlock(file
->volume
, file
->currentExt
->extension
,
436 file
->posInExtBlk
= 0;
438 nSect
= file
->currentExt
->dataBlocks
[MAX_DATABLK
-1-file
->posInExtBlk
];
442 adfReadDataBlock(file
->volume
,nSect
,file
->currentData
);
444 if (isOFS(file
->volume
->dosType
) && data
->seqNum
!=file
->nDataBlock
+1)
445 (*adfEnv
.wFct
)("adfReadNextFileBlock : seqnum incorrect");
457 ULONG
adfWriteFile(struct File
*file
, ULONG n
, unsigned char *buffer
)
460 unsigned char *dataPtr
, *bufPtr
;
462 struct bOFSDataBlock
*dataB
;
464 if (n
==0) return (n
);
465 //puts("adfWriteFile");
466 blockSize
= file
->volume
->datablockSize
;
467 if (isOFS(file
->volume
->dosType
)) {
468 dataB
=(struct bOFSDataBlock
*)file
->currentData
;
469 dataPtr
= dataB
->data
;
472 dataPtr
= file
->currentData
;
474 if (file
->pos
==0 || file
->posInDataBlk
==blockSize
) {
475 if (adfCreateNextFileBlock(file
)==-1)
476 (*adfEnv
.wFct
)("adfWritefile : no more free sector availbale");
477 file
->posInDataBlk
= 0;
480 bytesWritten
= 0; bufPtr
= buffer
;
481 while( bytesWritten
<n
) {
482 size
= min(n
-bytesWritten
, blockSize
-file
->posInDataBlk
);
483 memcpy(dataPtr
+file
->posInDataBlk
, bufPtr
, size
);
486 bytesWritten
+= size
;
487 file
->posInDataBlk
+= size
;
488 if (file
->posInDataBlk
==blockSize
&& bytesWritten
<n
) {
489 if (adfCreateNextFileBlock(file
)==-1)
490 (*adfEnv
.wFct
)("adfWritefile : no more free sector availbale");
491 file
->posInDataBlk
= 0;
494 return( bytesWritten
);
499 * adfCreateNextFileBlock
502 SECTNUM
adfCreateNextFileBlock(struct File
* file
)
504 SECTNUM nSect
, extSect
;
505 struct bOFSDataBlock
*data
;
506 unsigned int blockSize
;
508 //puts("adfCreateNextFileBlock");
509 blockSize
= file
->volume
->datablockSize
;
510 data
= file
->currentData
;
512 /* the first data blocks pointers are inside the file header block */
513 if (file
->nDataBlock
<MAX_DATABLK
) {
514 nSect
= adfGet1FreeBlock(file
->volume
);
515 if (nSect
==-1) return -1;
516 //printf("adfCreateNextFileBlock fhdr %ld\n",nSect);
517 if (file
->nDataBlock
==0)
518 file
->fileHdr
->firstData
= nSect
;
519 file
->fileHdr
->dataBlocks
[MAX_DATABLK
-1-file
->nDataBlock
] = nSect
;
520 file
->fileHdr
->highSeq
++;
523 /* one more sector is needed for one file extension block */
524 if ((file
->nDataBlock
%MAX_DATABLK
)==0) {
525 extSect
= adfGet1FreeBlock(file
->volume
);
526 //printf("extSect=%ld\n",extSect);
527 if (extSect
==-1) return -1;
529 /* the future block is the first file extension block */
530 if (file
->nDataBlock
==MAX_DATABLK
) {
531 file
->currentExt
=(struct bFileExtBlock
*)malloc(sizeof(struct bFileExtBlock
));
532 if (!file
->currentExt
) {
533 adfSetBlockFree(file
->volume
, extSect
);
534 (*adfEnv
.eFct
)("adfCreateNextFileBlock : malloc");
537 file
->fileHdr
->extension
= extSect
;
540 /* not the first : save the current one, and link it with the future */
541 if (file
->nDataBlock
>=2*MAX_DATABLK
) {
542 file
->currentExt
->extension
= extSect
;
543 //printf ("write ext=%d\n",file->currentExt->headerKey);
544 adfWriteFileExtBlock(file
->volume
, file
->currentExt
->headerKey
,
548 /* initializes a file extension block */
549 for(i
=0; i
<MAX_DATABLK
; i
++)
550 file
->currentExt
->dataBlocks
[i
] = 0L;
551 file
->currentExt
->headerKey
= extSect
;
552 file
->currentExt
->parent
= file
->fileHdr
->headerKey
;
553 file
->currentExt
->highSeq
= 0L;
554 file
->currentExt
->extension
= 0L;
555 file
->posInExtBlk
= 0L;
556 //printf("extSect=%ld\n",extSect);
558 nSect
= adfGet1FreeBlock(file
->volume
);
562 //printf("adfCreateNextFileBlock ext %ld\n",nSect);
564 file
->currentExt
->dataBlocks
[MAX_DATABLK
-1-file
->posInExtBlk
] = nSect
;
565 file
->currentExt
->highSeq
++;
569 /* builds OFS header */
570 if (isOFS(file
->volume
->dosType
)) {
571 /* writes previous data block and link it */
572 if (file
->pos
>=blockSize
) {
573 data
->nextData
= nSect
;
574 adfWriteDataBlock(file
->volume
, file
->curDataPtr
, file
->currentData
);
575 //printf ("writedata=%d\n",file->curDataPtr);
577 /* initialize a new data block */
578 for(i
=0; i
<(int)blockSize
; i
++)
580 data
->seqNum
= file
->nDataBlock
+1;
581 data
->dataSize
= blockSize
;
583 data
->headerKey
= file
->fileHdr
->headerKey
;
586 if (file
->pos
>=blockSize
) {
587 adfWriteDataBlock(file
->volume
, file
->curDataPtr
, file
->currentData
);
588 //printf ("writedata=%d\n",file->curDataPtr);
589 memset(file
->currentData
,0xff,512);
592 //printf("datablk=%d\n",nSect);
593 file
->curDataPtr
= nSect
;
604 ULONG
adfPos2DataBlock(ULONG pos
, int blockSize
,
605 int *posInExtBlk
, int *posInDataBlk
, ULONG
*curDataN
)
609 *posInDataBlk
= pos
%blockSize
;
610 *curDataN
= pos
/blockSize
;
611 if (*posInDataBlk
==0)
618 *posInExtBlk
= (pos
-72*blockSize
)%blockSize
;
619 extBlock
= (pos
-72*blockSize
)/blockSize
;
631 RETCODE
adfReadDataBlock(struct Volume
*vol
, SECTNUM nSect
, void *data
)
633 unsigned char buf
[512];
634 struct bOFSDataBlock
*dBlock
;
637 adfReadBlock(vol
, nSect
,buf
);
639 memcpy(data
,buf
,512);
641 if (isOFS(vol
->dosType
)) {
643 swapEndian(data
, SWBL_DATA
);
645 dBlock
= (struct bOFSDataBlock
*)data
;
646 //printf("adfReadDataBlock %ld\n",nSect);
648 if (dBlock
->checkSum
!=adfNormalSum(buf
,20,sizeof(struct bOFSDataBlock
)))
649 (*adfEnv
.wFct
)("adfReadDataBlock : invalid checksum");
650 if (dBlock
->type
!=T_DATA
)
651 (*adfEnv
.wFct
)("adfReadDataBlock : id T_DATA not found");
652 if (dBlock
->dataSize
<0 || dBlock
->dataSize
>488)
653 (*adfEnv
.wFct
)("adfReadDataBlock : dataSize incorrect");
654 if ( !isSectNumValid(vol
,dBlock
->headerKey
) )
655 (*adfEnv
.wFct
)("adfReadDataBlock : headerKey out of range");
656 if ( !isSectNumValid(vol
,dBlock
->nextData
) )
657 (*adfEnv
.wFct
)("adfReadDataBlock : nextData out of range");
668 RETCODE
adfWriteDataBlock(struct Volume
*vol
, SECTNUM nSect
, void *data
)
670 unsigned char buf
[512];
672 struct bOFSDataBlock
*dataB
;
676 if (isOFS(vol
->dosType
)) {
677 dataB
= (struct bOFSDataBlock
*)data
;
678 dataB
->type
= T_DATA
;
679 memcpy(buf
,dataB
,512);
681 swapEndian(buf
, SWBL_DATA
);
683 newSum
= adfNormalSum(buf
,20,512);
684 swLong(buf
+20,newSum
);
685 // *(ULONG*)(buf+20) = swapLong((unsigned char*)&newSum);
686 adfWriteBlock(vol
,nSect
,buf
);
689 adfWriteBlock(vol
,nSect
,data
);
691 //printf("adfWriteDataBlock %ld\n",nSect);
698 * adfReadFileExtBlock
701 RETCODE
adfReadFileExtBlock(struct Volume
*vol
, SECTNUM nSect
, struct bFileExtBlock
* fext
)
703 unsigned char buf
[sizeof(struct bFileExtBlock
)];
706 adfReadBlock(vol
, nSect
,buf
);
707 /*printf("read fext=%d\n",nSect);*/
708 memcpy(fext
,buf
,sizeof(struct bFileExtBlock
));
710 swapEndian((unsigned char*)fext
, SWBL_FEXT
);
712 if (fext
->checkSum
!=adfNormalSum(buf
,20,sizeof(struct bFileExtBlock
)))
713 (*adfEnv
.wFct
)("adfReadFileExtBlock : invalid checksum");
714 if (fext
->type
!=T_LIST
)
715 (*adfEnv
.wFct
)("adfReadFileExtBlock : type T_LIST not found");
716 if (fext
->secType
!=ST_FILE
)
717 (*adfEnv
.wFct
)("adfReadFileExtBlock : stype ST_FILE not found");
718 if (fext
->headerKey
!=nSect
)
719 (*adfEnv
.wFct
)("adfReadFileExtBlock : headerKey!=nSect");
720 if (fext
->highSeq
<0 || fext
->highSeq
>MAX_DATABLK
)
721 (*adfEnv
.wFct
)("adfReadFileExtBlock : highSeq out of range");
722 if ( !isSectNumValid(vol
, fext
->parent
) )
723 (*adfEnv
.wFct
)("adfReadFileExtBlock : parent out of range");
724 if ( fext
->extension
!=0 && !isSectNumValid(vol
, fext
->extension
) )
725 (*adfEnv
.wFct
)("adfReadFileExtBlock : extension out of range");
732 * adfWriteFileExtBlock
735 RETCODE
adfWriteFileExtBlock(struct Volume
*vol
, SECTNUM nSect
, struct bFileExtBlock
* fext
)
737 unsigned char buf
[512];
742 fext
->secType
= ST_FILE
;
744 fext
->firstData
= 0L;
746 memcpy(buf
,fext
,512);
748 swapEndian(buf
, SWBL_FEXT
);
750 newSum
= adfNormalSum(buf
,20,512);
751 swLong(buf
+20,newSum
);
752 // *(ULONG*)(buf+20) = swapLong((unsigned char*)&newSum);
754 adfWriteBlock(vol
,nSect
,buf
);
758 /*###########################################################################*/