2 * ADF Library. (C) 1997-1999 Laurent Clevy
22 extern struct Env adfEnv
;
24 void adfFileTruncate(struct Volume
*vol
, SECTNUM nParent
, char *name
)
34 void adfFlushFile(struct File
*file
)
36 struct bEntryBlock parent
;
37 struct bOFSDataBlock
*data
;
39 if (file
->currentExt
) {
41 adfWriteFileExtBlock(file
->volume
, file
->currentExt
->headerKey
,
44 if (file
->currentData
) {
45 if (file
->writeMode
) {
46 file
->fileHdr
->byteSize
= file
->pos
;
47 if (isOFS(file
->volume
->dosType
)) {
48 data
= (struct bOFSDataBlock
*)file
->currentData
;
49 data
->dataSize
= file
->posInDataBlk
;
51 if (file
->fileHdr
->byteSize
>0)
52 adfWriteDataBlock(file
->volume
, file
->curDataPtr
,
56 if (file
->writeMode
) {
57 file
->fileHdr
->byteSize
= file
->pos
;
58 //printf("pos=%ld\n",file->pos);
59 adfTime2AmigaTime(adfGiveCurrentTime(),
60 &(file
->fileHdr
->days
),&(file
->fileHdr
->mins
),&(file
->fileHdr
->ticks
) );
61 adfWriteFileHdrBlock(file
->volume
, file
->fileHdr
->headerKey
, file
->fileHdr
);
63 if (isDIRCACHE(file
->volume
->dosType
)) {
64 //printf("parent=%ld\n",file->fileHdr->parent);
65 adfReadEntryBlock(file
->volume
, file
->fileHdr
->parent
, &parent
);
66 adfUpdateCache(file
->volume
, &parent
, (struct bEntryBlock
*)file
->fileHdr
,FALSE
);
68 adfUpdateBitmap(file
->volume
);
77 RETCODE
adfGetFileBlocks(struct Volume
* vol
, struct bFileHeaderBlock
* entry
,
78 struct FileBlocks
* fileBlocks
)
82 struct bFileExtBlock extBlock
;
85 fileBlocks
->header
= entry
->headerKey
;
86 adfFileRealSize( entry
->byteSize
, vol
->datablockSize
,
87 &(fileBlocks
->nbData
), &(fileBlocks
->nbExtens
) );
89 fileBlocks
->data
=(SECTNUM
*)malloc(fileBlocks
->nbData
* sizeof(SECTNUM
));
90 if (!fileBlocks
->data
) {
91 (*adfEnv
.eFct
)("adfGetFileBlocks : malloc");
95 fileBlocks
->extens
=(SECTNUM
*)malloc(fileBlocks
->nbExtens
* sizeof(SECTNUM
));
96 if (!fileBlocks
->extens
) {
97 (*adfEnv
.eFct
)("adfGetFileBlocks : malloc");
102 /* in file header block */
103 for(i
=0; i
<entry
->highSeq
; i
++)
104 fileBlocks
->data
[n
++] = entry
->dataBlocks
[MAX_DATABLK
-1-i
];
106 /* in file extension blocks */
107 nSect
= entry
->extension
;
109 fileBlocks
->extens
[m
++] = nSect
;
110 adfReadFileExtBlock(vol
, nSect
, &extBlock
);
111 for(i
=0; i
<extBlock
.highSeq
; i
++)
112 fileBlocks
->data
[n
++] = extBlock
.dataBlocks
[MAX_DATABLK
-1-i
];
113 nSect
= extBlock
.extension
;
115 if ( (fileBlocks
->nbExtens
+fileBlocks
->nbData
) != (n
+m
) )
116 (*adfEnv
.wFct
)("adfGetFileBlocks : less blocks than expected");
125 RETCODE
adfFreeFileBlocks(struct Volume
* vol
, struct bFileHeaderBlock
*entry
)
128 struct FileBlocks fileBlocks
;
131 adfGetFileBlocks(vol
,entry
,&fileBlocks
);
133 for(i
=0; i
<fileBlocks
.nbData
; i
++) {
134 adfSetBlockFree(vol
, fileBlocks
.data
[i
]);
136 for(i
=0; i
<fileBlocks
.nbExtens
; i
++) {
137 adfSetBlockFree(vol
, fileBlocks
.extens
[i
]);
140 free(fileBlocks
.data
);
141 free(fileBlocks
.extens
);
150 * Compute and return real number of block used by one file
151 * Compute number of datablocks and file extension blocks
154 long adfFileRealSize(unsigned long size
, int blockSize
, long *dataN
, long *extN
)
158 /*--- number of data blocks ---*/
159 data
= size
/ blockSize
;
160 if ( size
% blockSize
)
163 /*--- number of header extension blocks ---*/
165 if (data
>MAX_DATABLK
) {
166 ext
= (data
-MAX_DATABLK
) / MAX_DATABLK
;
167 if ( (data
-MAX_DATABLK
) % MAX_DATABLK
)
181 * adfWriteFileHdrBlock
184 RETCODE
adfWriteFileHdrBlock(struct Volume
*vol
, SECTNUM nSect
, struct bFileHeaderBlock
* fhdr
)
186 unsigned char buf
[512];
187 unsigned long newSum
;
189 //printf("adfWriteFileHdrBlock %ld\n",nSect);
190 fhdr
->type
= T_HEADER
;
192 fhdr
->secType
= ST_FILE
;
194 memcpy(buf
, fhdr
, sizeof(struct bFileHeaderBlock
));
196 swapEndian(buf
, SWBL_FILE
);
198 newSum
= adfNormalSum(buf
,20,sizeof(struct bFileHeaderBlock
));
199 swLong(buf
+20, newSum
);
200 // *(unsigned long*)(buf+20) = swapLong((unsigned char*)&newSum);
202 adfWriteBlock(vol
, nSect
, buf
);
212 void adfFileSeek(struct File
*file
, unsigned long pos
)
214 SECTNUM extBlock
, nSect
;
218 nPos
= min(pos
, file
->fileHdr
->byteSize
);
220 extBlock
= adfPos2DataBlock(nPos
, file
->volume
->datablockSize
,
221 &(file
->posInExtBlk
), &(file
->posInDataBlk
), &(file
->curDataPtr
) );
223 adfReadDataBlock(file
->volume
,
224 file
->fileHdr
->dataBlocks
[MAX_DATABLK
-1-file
->curDataPtr
],
228 nSect
= file
->fileHdr
->extension
;
230 while( i
<extBlock
&& nSect
!=0 ) {
231 adfReadFileExtBlock(file
->volume
, nSect
, file
->currentExt
);
232 nSect
= file
->currentExt
->extension
;
235 (*adfEnv
.wFct
)("error");
236 adfReadDataBlock(file
->volume
,
237 file
->currentExt
->dataBlocks
[file
->posInExtBlk
], file
->currentData
);
246 struct File
* adfOpenFile(struct Volume
*vol
, char* name
, char *mode
)
250 struct bEntryBlock entry
, parent
;
254 write
=( strcmp("w",mode
)==0 || strcmp("a",mode
)==0 );
256 if (write
&& vol
->dev
->readOnly
) {
257 (*adfEnv
.wFct
)("adfFileOpen : device is mounted 'read only'");
261 adfReadEntryBlock(vol
, vol
->curDirPtr
, &parent
);
263 nSect
= adfNameToEntryBlk(vol
, parent
.hashTable
, name
, &entry
, NULL
);
264 if (!write
&& nSect
==-1) {
265 sprintf(filename
,"adfFileOpen : file \"%s\" not found.",name
);
266 (*adfEnv
.wFct
)(filename
);
267 //fprintf(stdout,"filename %s %d, parent =%d\n",name,strlen(name),vol->curDirPtr);
270 if (!write
&& hasR(entry
.access
)) {
271 (*adfEnv
.wFct
)("adfFileOpen : access denied"); return NULL
; }
272 /* if (entry.secType!=ST_FILE) {
273 (*adfEnv.wFct)("adfFileOpen : not a file"); return NULL; }
274 if (write && (hasE(entry.access)||hasW(entry.access))) {
275 (*adfEnv.wFct)("adfFileOpen : access denied"); return NULL; }
276 */ if (write
&& nSect
!=-1) {
277 (*adfEnv
.wFct
)("adfFileOpen : file already exists"); return NULL
; }
279 file
= (struct File
*)malloc(sizeof(struct File
));
280 if (!file
) { (*adfEnv
.wFct
)("adfFileOpen : malloc"); return NULL
; }
281 file
->fileHdr
= (struct bFileHeaderBlock
*)malloc(sizeof(struct bFileHeaderBlock
));
282 if (!file
->fileHdr
) {
283 (*adfEnv
.wFct
)("adfFileOpen : malloc");
284 free(file
); return NULL
;
286 file
->currentData
= malloc(512*sizeof(unsigned char));
287 if (!file
->currentData
) {
288 (*adfEnv
.wFct
)("adfFileOpen : malloc");
289 free(file
->fileHdr
); free(file
); return NULL
;
294 file
->posInExtBlk
= 0;
295 file
->posInDataBlk
= 0;
296 file
->writeMode
= write
;
297 file
->currentExt
= NULL
;
298 file
->nDataBlock
= 0;
300 if (strcmp("w",mode
)==0) {
301 memset(file
->fileHdr
,0,512);
302 adfCreateFile(vol
,vol
->curDirPtr
,name
,file
->fileHdr
);
305 else if (strcmp("a",mode
)==0) {
306 memcpy(file
->fileHdr
,&entry
,sizeof(struct bFileHeaderBlock
));
308 adfFileSeek(file
, file
->fileHdr
->byteSize
);
310 else if (strcmp("r",mode
)==0) {
311 memcpy(file
->fileHdr
,&entry
,sizeof(struct bFileHeaderBlock
));
315 //puts("adfOpenFile");
324 void adfCloseFile(struct File
*file
)
329 //puts("adfCloseFile in");
333 if (file
->currentExt
)
334 free(file
->currentExt
);
336 if (file
->currentData
)
337 free(file
->currentData
);
342 //puts("adfCloseFile out");
350 long adfReadFile(struct File
* file
, long n
, unsigned char *buffer
)
353 unsigned char *dataPtr
, *bufPtr
;
357 blockSize
= file
->volume
->datablockSize
;
358 /*puts("adfReadFile");*/
359 if (file
->pos
+n
> file
->fileHdr
->byteSize
)
360 n
= file
->fileHdr
->byteSize
- file
->pos
;
362 if (isOFS(file
->volume
->dosType
))
363 dataPtr
= (unsigned char*)(file
->currentData
)+24;
365 dataPtr
= file
->currentData
;
367 if (file
->pos
==0 || file
->posInDataBlk
==blockSize
) {
368 adfReadNextFileBlock(file
);
369 file
->posInDataBlk
= 0;
372 bytesRead
= 0; bufPtr
= buffer
;
374 while ( bytesRead
< n
) {
375 size
= min(n
-bytesRead
, blockSize
-file
->posInDataBlk
);
376 memcpy(bufPtr
, dataPtr
+file
->posInDataBlk
, size
);
380 file
->posInDataBlk
+= size
;
381 if (file
->posInDataBlk
==blockSize
&& bytesRead
<n
) {
382 adfReadNextFileBlock(file
);
383 file
->posInDataBlk
= 0;
386 file
->eof
= (file
->pos
==file
->fileHdr
->byteSize
);
395 BOOL
adfEndOfFile(struct File
* file
)
402 * adfReadNextFileBlock
405 RETCODE
adfReadNextFileBlock(struct File
* file
)
408 struct bOFSDataBlock
*data
;
411 data
=(struct bOFSDataBlock
*) file
->currentData
;
413 if (file
->nDataBlock
==0) {
414 nSect
= file
->fileHdr
->firstData
;
416 else if (isOFS(file
->volume
->dosType
)) {
417 nSect
= data
->nextData
;
420 if (file
->nDataBlock
<MAX_DATABLK
)
421 nSect
= file
->fileHdr
->dataBlocks
[MAX_DATABLK
-1-file
->nDataBlock
];
423 if (file
->nDataBlock
==MAX_DATABLK
) {
424 file
->currentExt
=(struct bFileExtBlock
*)malloc(sizeof(struct bFileExtBlock
));
425 if (!file
->currentExt
) (*adfEnv
.eFct
)("adfReadNextFileBlock : malloc");
426 adfReadFileExtBlock(file
->volume
, file
->fileHdr
->extension
,
428 file
->posInExtBlk
= 0;
430 else if (file
->posInExtBlk
==MAX_DATABLK
) {
431 adfReadFileExtBlock(file
->volume
, file
->currentExt
->extension
,
433 file
->posInExtBlk
= 0;
435 nSect
= file
->currentExt
->dataBlocks
[MAX_DATABLK
-1-file
->posInExtBlk
];
439 adfReadDataBlock(file
->volume
,nSect
,file
->currentData
);
441 if (isOFS(file
->volume
->dosType
) && data
->seqNum
!=file
->nDataBlock
+1)
442 (*adfEnv
.wFct
)("adfReadNextFileBlock : seqnum incorrect");
454 long adfWriteFile(struct File
*file
, long n
, unsigned char *buffer
)
457 unsigned char *dataPtr
, *bufPtr
;
459 struct bOFSDataBlock
*dataB
;
461 if (n
==0) return (n
);
462 //puts("adfWriteFile");
463 blockSize
= file
->volume
->datablockSize
;
464 if (isOFS(file
->volume
->dosType
)) {
465 dataB
=(struct bOFSDataBlock
*)file
->currentData
;
466 dataPtr
= dataB
->data
;
469 dataPtr
= file
->currentData
;
471 if (file
->pos
==0 || file
->posInDataBlk
==blockSize
) {
472 if (adfCreateNextFileBlock(file
)==-1)
473 (*adfEnv
.wFct
)("adfWritefile : no more free sector availbale");
474 file
->posInDataBlk
= 0;
477 bytesWritten
= 0; bufPtr
= buffer
;
478 while( bytesWritten
<n
) {
479 size
= min(n
-bytesWritten
, blockSize
-file
->posInDataBlk
);
480 memcpy(dataPtr
+file
->posInDataBlk
, bufPtr
, size
);
483 bytesWritten
+= size
;
484 file
->posInDataBlk
+= size
;
485 if (file
->posInDataBlk
==blockSize
&& bytesWritten
<n
) {
486 if (adfCreateNextFileBlock(file
)==-1)
487 (*adfEnv
.wFct
)("adfWritefile : no more free sector availbale");
488 file
->posInDataBlk
= 0;
491 return( bytesWritten
);
496 * adfCreateNextFileBlock
499 SECTNUM
adfCreateNextFileBlock(struct File
* file
)
501 SECTNUM nSect
, extSect
;
502 struct bOFSDataBlock
*data
;
503 unsigned int blockSize
;
505 //puts("adfCreateNextFileBlock");
506 blockSize
= file
->volume
->datablockSize
;
507 data
= file
->currentData
;
509 /* the first data blocks pointers are inside the file header block */
510 if (file
->nDataBlock
<MAX_DATABLK
) {
511 nSect
= adfGet1FreeBlock(file
->volume
);
512 if (nSect
==-1) return -1;
513 //printf("adfCreateNextFileBlock fhdr %ld\n",nSect);
514 if (file
->nDataBlock
==0)
515 file
->fileHdr
->firstData
= nSect
;
516 file
->fileHdr
->dataBlocks
[MAX_DATABLK
-1-file
->nDataBlock
] = nSect
;
517 file
->fileHdr
->highSeq
++;
520 /* one more sector is needed for one file extension block */
521 if ((file
->nDataBlock
%MAX_DATABLK
)==0) {
522 extSect
= adfGet1FreeBlock(file
->volume
);
523 //printf("extSect=%ld\n",extSect);
524 if (extSect
==-1) return -1;
526 /* the future block is the first file extension block */
527 if (file
->nDataBlock
==MAX_DATABLK
) {
528 file
->currentExt
=(struct bFileExtBlock
*)malloc(sizeof(struct bFileExtBlock
));
529 if (!file
->currentExt
) {
530 adfSetBlockFree(file
->volume
, extSect
);
531 (*adfEnv
.eFct
)("adfCreateNextFileBlock : malloc");
534 file
->fileHdr
->extension
= extSect
;
537 /* not the first : save the current one, and link it with the future */
538 if (file
->nDataBlock
>=2*MAX_DATABLK
) {
539 file
->currentExt
->extension
= extSect
;
540 //printf ("write ext=%d\n",file->currentExt->headerKey);
541 adfWriteFileExtBlock(file
->volume
, file
->currentExt
->headerKey
,
545 /* initializes a file extension block */
546 for(i
=0; i
<MAX_DATABLK
; i
++)
547 file
->currentExt
->dataBlocks
[i
] = 0L;
548 file
->currentExt
->headerKey
= extSect
;
549 file
->currentExt
->parent
= file
->fileHdr
->headerKey
;
550 file
->currentExt
->highSeq
= 0L;
551 file
->currentExt
->extension
= 0L;
552 file
->posInExtBlk
= 0L;
553 //printf("extSect=%ld\n",extSect);
555 nSect
= adfGet1FreeBlock(file
->volume
);
559 //printf("adfCreateNextFileBlock ext %ld\n",nSect);
561 file
->currentExt
->dataBlocks
[MAX_DATABLK
-1-file
->posInExtBlk
] = nSect
;
562 file
->currentExt
->highSeq
++;
566 /* builds OFS header */
567 if (isOFS(file
->volume
->dosType
)) {
568 /* writes previous data block and link it */
569 if (file
->pos
>=blockSize
) {
570 data
->nextData
= nSect
;
571 adfWriteDataBlock(file
->volume
, file
->curDataPtr
, file
->currentData
);
572 //printf ("writedata=%d\n",file->curDataPtr);
574 /* initialize a new data block */
575 for(i
=0; i
<(int)blockSize
; i
++)
577 data
->seqNum
= file
->nDataBlock
+1;
578 data
->dataSize
= blockSize
;
580 data
->headerKey
= file
->fileHdr
->headerKey
;
583 if (file
->pos
>=blockSize
) {
584 adfWriteDataBlock(file
->volume
, file
->curDataPtr
, file
->currentData
);
585 //printf ("writedata=%d\n",file->curDataPtr);
586 memset(file
->currentData
,0,512);
589 //printf("datablk=%d\n",nSect);
590 file
->curDataPtr
= nSect
;
601 long adfPos2DataBlock(long pos
, int blockSize
,
602 int *posInExtBlk
, int *posInDataBlk
, long *curDataN
)
606 *posInDataBlk
= pos
%blockSize
;
607 *curDataN
= pos
/blockSize
;
608 if (*posInDataBlk
==0)
615 *posInExtBlk
= (pos
-72*blockSize
)%blockSize
;
616 extBlock
= (pos
-72*blockSize
)/blockSize
;
628 RETCODE
adfReadDataBlock(struct Volume
*vol
, SECTNUM nSect
, void *data
)
630 unsigned char buf
[512];
631 struct bOFSDataBlock
*dBlock
;
634 adfReadBlock(vol
, nSect
,buf
);
636 memcpy(data
,buf
,512);
638 if (isOFS(vol
->dosType
)) {
640 swapEndian(data
, SWBL_DATA
);
642 dBlock
= (struct bOFSDataBlock
*)data
;
643 //printf("adfReadDataBlock %ld\n",nSect);
645 if (dBlock
->checkSum
!=adfNormalSum(buf
,20,sizeof(struct bOFSDataBlock
)))
646 (*adfEnv
.wFct
)("adfReadDataBlock : invalid checksum");
647 if (dBlock
->type
!=T_DATA
)
648 (*adfEnv
.wFct
)("adfReadDataBlock : id T_DATA not found");
649 if (dBlock
->dataSize
<0 || dBlock
->dataSize
>488)
650 (*adfEnv
.wFct
)("adfReadDataBlock : dataSize incorrect");
651 if ( !isSectNumValid(vol
,dBlock
->headerKey
) )
652 (*adfEnv
.wFct
)("adfReadDataBlock : headerKey out of range");
653 if ( !isSectNumValid(vol
,dBlock
->nextData
) )
654 (*adfEnv
.wFct
)("adfReadDataBlock : nextData out of range");
665 RETCODE
adfWriteDataBlock(struct Volume
*vol
, SECTNUM nSect
, void *data
)
667 unsigned char buf
[512];
668 unsigned long newSum
;
669 struct bOFSDataBlock
*dataB
;
673 if (isOFS(vol
->dosType
)) {
674 dataB
= (struct bOFSDataBlock
*)data
;
675 dataB
->type
= T_DATA
;
676 memcpy(buf
,dataB
,512);
678 swapEndian(buf
, SWBL_DATA
);
680 newSum
= adfNormalSum(buf
,20,512);
681 swLong(buf
+20,newSum
);
682 // *(long*)(buf+20) = swapLong((unsigned char*)&newSum);
683 adfWriteBlock(vol
,nSect
,buf
);
686 adfWriteBlock(vol
,nSect
,data
);
688 //printf("adfWriteDataBlock %ld\n",nSect);
695 * adfReadFileExtBlock
698 RETCODE
adfReadFileExtBlock(struct Volume
*vol
, SECTNUM nSect
, struct bFileExtBlock
* fext
)
700 unsigned char buf
[sizeof(struct bFileExtBlock
)];
703 adfReadBlock(vol
, nSect
,buf
);
704 /*printf("read fext=%d\n",nSect);*/
705 memcpy(fext
,buf
,sizeof(struct bFileExtBlock
));
707 swapEndian((unsigned char*)fext
, SWBL_FEXT
);
709 if (fext
->checkSum
!=adfNormalSum(buf
,20,sizeof(struct bFileExtBlock
)))
710 (*adfEnv
.wFct
)("adfReadFileExtBlock : invalid checksum");
711 if (fext
->type
!=T_LIST
)
712 (*adfEnv
.wFct
)("adfReadFileExtBlock : type T_LIST not found");
713 if (fext
->secType
!=ST_FILE
)
714 (*adfEnv
.wFct
)("adfReadFileExtBlock : stype ST_FILE not found");
715 if (fext
->headerKey
!=nSect
)
716 (*adfEnv
.wFct
)("adfReadFileExtBlock : headerKey!=nSect");
717 if (fext
->highSeq
<0 || fext
->highSeq
>MAX_DATABLK
)
718 (*adfEnv
.wFct
)("adfReadFileExtBlock : highSeq out of range");
719 if ( !isSectNumValid(vol
, fext
->parent
) )
720 (*adfEnv
.wFct
)("adfReadFileExtBlock : parent out of range");
721 if ( fext
->extension
!=0 && !isSectNumValid(vol
, fext
->extension
) )
722 (*adfEnv
.wFct
)("adfReadFileExtBlock : extension out of range");
729 * adfWriteFileExtBlock
732 RETCODE
adfWriteFileExtBlock(struct Volume
*vol
, SECTNUM nSect
, struct bFileExtBlock
* fext
)
734 unsigned char buf
[512];
735 unsigned long newSum
;
739 fext
->secType
= ST_FILE
;
741 fext
->firstData
= 0L;
743 memcpy(buf
,fext
,512);
745 swapEndian(buf
, SWBL_FEXT
);
747 newSum
= adfNormalSum(buf
,20,512);
748 swLong(buf
+20,newSum
);
749 // *(long*)(buf+20) = swapLong((unsigned char*)&newSum);
751 adfWriteBlock(vol
,nSect
,buf
);
755 /*###########################################################################*/