2 * ADF Library. (C) 1997-1999 Laurent Clevy
23 extern struct Env adfEnv
;
25 freeEntCache(struct CacheEntry *cEntry)
27 if (cEntry->name!=NULL)
29 if (cEntry->comm!=NULL)
37 * replace 'adfGetDirEnt'. returns a the dir contents based on the dircache list
39 struct List
* adfGetDirEntCache(struct Volume
*vol
, SECTNUM dir
, BOOL recurs
)
41 struct bEntryBlock parent
;
42 struct bDirCacheBlock dirc
;
44 struct List
*cell
, *head
;
45 struct CacheEntry caEntry
;
49 if (adfReadEntryBlock(vol
,dir
,&parent
)!=RC_OK
)
52 nSect
= parent
.extension
;
56 /* one loop per cache block */
58 if (adfReadDirCBlock(vol
, nSect
, &dirc
)!=RC_OK
)
60 while (n
<dirc
.recordsNb
) {
61 /* one loop per record */
62 entry
= (struct Entry
*)malloc(sizeof(struct Entry
));
67 adfGetCacheEntry(&dirc
, &offset
, &caEntry
);
69 /* converts a cache entry into a dir entry */
70 entry
->type
= (int)caEntry
.type
;
71 entry
->name
= strdup(caEntry
.name
);
72 if (entry
->name
==NULL
) {
73 free(entry
); adfFreeDirList(head
);
76 entry
->sector
= caEntry
.header
;
77 entry
->comment
= strdup(caEntry
.comm
);
78 if (entry
->comment
==NULL
) {
79 free(entry
->name
); adfFreeDirList(head
);
82 entry
->size
= caEntry
.size
;
83 entry
->access
= caEntry
.protect
;
84 adfDays2Date( caEntry
.days
, &(entry
->year
), &(entry
->month
),
86 entry
->hour
= caEntry
.mins
/60;
87 entry
->mins
= caEntry
.mins
%60;
88 entry
->secs
= caEntry
.ticks
/50;
90 /* add it into the linked list */
92 head
= cell
= newCell(NULL
, (void*)entry
);
94 cell
= newCell(cell
, (void*)entry
);
102 if (recurs
&& entry
->type
==ST_DIR
)
103 cell
->subdir
= adfGetDirEntCache(vol
,entry
->sector
,recurs
);
107 nSect
= dirc
.nextDirC
;
118 * Returns a cache entry, starting from the offset p (the index into records[])
119 * This offset is updated to the end of the returned entry.
121 void adfGetCacheEntry(struct bDirCacheBlock
*dirc
, int *p
, struct CacheEntry
*cEntry
)
127 //printf("p=%d\n",ptr);
130 cEntry
->header
= swapLong(dirc
->records
+ptr
);
131 cEntry
->size
= swapLong(dirc
->records
+ptr
+4);
132 cEntry
->protect
= swapLong(dirc
->records
+ptr
+8);
133 cEntry
->days
= swapShort(dirc
->records
+ptr
+16);
134 cEntry
->mins
= swapShort(dirc
->records
+ptr
+18);
135 cEntry
->ticks
= swapShort(dirc
->records
+ptr
+20);
137 cEntry
->header
= Long(dirc
->records
+ptr
);
138 cEntry
->size
= Long(dirc
->records
+ptr
+4);
139 cEntry
->protect
= Long(dirc
->records
+ptr
+8);
140 cEntry
->days
= Short(dirc
->records
+ptr
+16);
141 cEntry
->mins
= Short(dirc
->records
+ptr
+18);
142 cEntry
->ticks
= Short(dirc
->records
+ptr
+20);
144 cEntry
->type
=(signed char) dirc
->records
[ptr
+22];
146 cEntry
->nLen
= dirc
->records
[ptr
+23];
147 /* cEntry->name = (char*)malloc(sizeof(char)*(cEntry->nLen+1));
150 */ memcpy(cEntry
->name
, dirc
->records
+ptr
+24, cEntry
->nLen
);
151 cEntry
->name
[(int)(cEntry
->nLen
)]='\0';
153 cEntry
->cLen
= dirc
->records
[ptr
+24+cEntry
->nLen
];
154 if (cEntry
->cLen
>0) {
155 /* cEntry->comm =(char*)malloc(sizeof(char)*(cEntry->cLen+1));
157 free( cEntry->name ); cEntry->name=NULL;
160 */ memcpy(cEntry
->comm
,dirc
->records
+ptr
+24+cEntry
->nLen
+1,cEntry
->cLen
);
162 cEntry
->comm
[(int)(cEntry
->cLen
)]='\0';
163 //printf("cEntry->nLen %d cEntry->cLen %d %s\n",cEntry->nLen,cEntry->cLen,cEntry->name);
164 *p
= ptr
+24+cEntry
->nLen
+1+cEntry
->cLen
;
166 /* the starting offset of each record must be even (68000 constraint) */
175 * remplaces one cache entry at the p offset, and returns its length
177 int adfPutCacheEntry( struct bDirCacheBlock
*dirc
, int *p
, struct CacheEntry
*cEntry
)
184 swLong(dirc
->records
+ptr
, cEntry
->header
);
185 swLong(dirc
->records
+ptr
+4, cEntry
->size
);
186 swLong(dirc
->records
+ptr
+8, cEntry
->protect
);
187 swShort(dirc
->records
+ptr
+16, cEntry
->days
);
188 swShort(dirc
->records
+ptr
+18, cEntry
->mins
);
189 swShort(dirc
->records
+ptr
+20, cEntry
->ticks
);
191 memcpy(dirc
->records
+ptr
,&(cEntry
->header
),4);
192 memcpy(dirc
->records
+ptr
+4,&(cEntry
->size
),4);
193 memcpy(dirc
->records
+ptr
+8,&(cEntry
->protect
),4);
194 memcpy(dirc
->records
+ptr
+16,&(cEntry
->days
),2);
195 memcpy(dirc
->records
+ptr
+18,&(cEntry
->mins
),2);
196 memcpy(dirc
->records
+ptr
+20,&(cEntry
->ticks
),2);
198 dirc
->records
[ptr
+22] =(signed char)cEntry
->type
;
200 dirc
->records
[ptr
+23] = cEntry
->nLen
;
201 memcpy(dirc
->records
+ptr
+24, cEntry
->name
, cEntry
->nLen
);
203 dirc
->records
[ptr
+24+cEntry
->nLen
] = cEntry
->cLen
;
204 memcpy(dirc
->records
+ptr
+24+cEntry
->nLen
+1, cEntry
->comm
, cEntry
->cLen
);
206 //puts("adfPutCacheEntry");
208 l
= 25+cEntry
->nLen
+cEntry
->cLen
;
212 dirc
->records
[ptr
+l
] =(char)0;
216 /* ptr%2 must be == 0, if l%2==0, (ptr+l)%2==0 */
221 * adfEntry2CacheEntry
223 * converts one dir entry into a cache entry, and return its future length in records[]
225 int adfEntry2CacheEntry(struct bEntryBlock
*entry
, struct CacheEntry
*newEntry
)
230 newEntry
->header
= entry
->headerKey
;
231 if (entry
->secType
==ST_FILE
)
232 newEntry
->size
= entry
->byteSize
;
235 newEntry
->protect
= entry
->access
;
236 newEntry
->days
= (short)entry
->days
;
237 newEntry
->mins
= (short)entry
->mins
;
238 newEntry
->ticks
= (short)entry
->ticks
;
239 newEntry
->type
= (signed char)entry
->secType
;
240 newEntry
->nLen
= entry
->nameLen
;
241 memcpy(newEntry
->name
, entry
->name
, newEntry
->nLen
);
242 newEntry
->name
[(int)(newEntry
->nLen
)] = '\0';
243 newEntry
->cLen
= entry
->commLen
;
244 if (newEntry
->cLen
>0)
245 memcpy(newEntry
->comm
, entry
->comment
, newEntry
->cLen
);
247 entryLen
= 24+newEntry
->nLen
+1+newEntry
->cLen
;
249 /*printf("entry->name %d entry->comment %d\n",entry->nameLen,entry->commLen);
250 printf("newEntry->nLen %d newEntry->cLen %d\n",newEntry->nLen,newEntry->cLen);
251 */ if ((entryLen
%2)==0)
261 * delete one cache entry from its block. don't do 'records garbage collecting'
263 RETCODE
adfDelFromCache(struct Volume
*vol
, struct bEntryBlock
*parent
,
266 struct bDirCacheBlock dirc
;
267 SECTNUM nSect
, prevSect
;
268 struct CacheEntry caEntry
;
269 int offset
, oldOffset
, n
;
276 nSect
= parent
->extension
;
279 adfReadDirCBlock(vol
, nSect
, &dirc
);
281 while(n
< dirc
.recordsNb
&& !found
) {
283 adfGetCacheEntry(&dirc
, &offset
, &caEntry
);
284 found
= (caEntry
.header
==headerKey
);
286 entryLen
= offset
-oldOffset
;
287 if (dirc
.recordsNb
>1 || prevSect
==-1) {
288 if (n
<dirc
.recordsNb
-1) {
289 /* not the last of the block : switch the following records */
290 for(i
=oldOffset
; i
<(488-entryLen
); i
++)
291 dirc
.records
[i
] = dirc
.records
[i
+entryLen
];
292 /* and clear the following bytes */
293 for(i
=488-entryLen
; i
<488; i
++)
297 /* the last record of this cache block */
298 for(i
=oldOffset
; i
<offset
; i
++)
302 if (adfWriteDirCBlock(vol
, dirc
.headerKey
, &dirc
)!=RC_OK
)
306 /* dirc.recordsNb ==1 or == 0 , prevSect!=-1 :
307 * the only record in this dirc block and a previous dirc block exists
309 adfSetBlockFree(vol
, dirc
.headerKey
);
310 adfReadDirCBlock(vol
, prevSect
, &dirc
);
312 adfWriteDirCBlock(vol
, prevSect
, &dirc
);
314 adfUpdateBitmap(vol
);
320 nSect
= dirc
.nextDirC
;
321 }while(nSect
!=0 && !found
);
324 (*adfEnv
.wFct
)("adfUpdateCache : entry not found");
334 RETCODE
adfAddInCache(struct Volume
*vol
, struct bEntryBlock
*parent
,
335 struct bEntryBlock
*entry
)
337 struct bDirCacheBlock dirc
, newDirc
;
338 SECTNUM nSect
, nCache
;
339 struct CacheEntry caEntry
, newEntry
;
343 entryLen
= adfEntry2CacheEntry(entry
, &newEntry
);
344 /*printf("adfAddInCache--%4ld %2d %6ld %8lx %4d %2d:%02d:%02d %30s %22s\n",
345 newEntry.header, newEntry.type, newEntry.size, newEntry.protect,
346 newEntry.days, newEntry.mins/60, newEntry.mins%60,
348 newEntry.name, newEntry.comm);
350 nSect
= parent
->extension
;
352 if (adfReadDirCBlock(vol
, nSect
, &dirc
)!=RC_OK
)
355 //printf("parent=%4ld\n",dirc.parent);
356 while(n
< dirc
.recordsNb
) {
357 adfGetCacheEntry(&dirc
, &offset
, &caEntry
);
358 /*printf("*%4ld %2d %6ld %8lx %4d %2d:%02d:%02d %30s %22s\n",
359 caEntry.header, caEntry.type, caEntry.size, caEntry.protect,
360 caEntry.days, caEntry.mins/60, caEntry.mins%60,
362 caEntry.name, caEntry.comm);
367 /* if (offset+entryLen<=488) {
368 adfPutCacheEntry(&dirc, &offset, &newEntry);
370 adfWriteDirCBlock(vol, dirc.headerKey, &dirc);
373 nSect
= dirc
.nextDirC
;
376 /* in the last block */
377 if (offset
+entryLen
<=488) {
378 adfPutCacheEntry(&dirc
, &offset
, &newEntry
);
380 //printf("entry name=%s\n",newEntry.name);
383 /* request one new block free */
384 nCache
= adfGet1FreeBlock(vol
);
386 (*adfEnv
.wFct
)("adfCreateDir : nCache==-1");
390 /* create a new dircache block */
391 memset(&newDirc
,0,512);
392 if (parent
->secType
==ST_ROOT
)
393 newDirc
.parent
= vol
->rootBlock
;
394 else if (parent
->secType
==ST_DIR
)
395 newDirc
.parent
= parent
->headerKey
;
397 (*adfEnv
.wFct
)("adfAddInCache : unknown secType");
398 newDirc
.recordsNb
= 0L;
399 newDirc
.nextDirC
= 0L;
401 adfPutCacheEntry(&dirc
, &offset
, &newEntry
);
403 if (adfWriteDirCBlock(vol
, nCache
, &newDirc
)!=RC_OK
)
405 dirc
.nextDirC
= nCache
;
407 //printf("dirc.headerKey=%ld\n",dirc.headerKey);
408 if (adfWriteDirCBlock(vol
, dirc
.headerKey
, &dirc
)!=RC_OK
)
410 /*if (strcmp(entry->name,"file_5u")==0)
421 RETCODE
adfUpdateCache(struct Volume
*vol
, struct bEntryBlock
*parent
,
422 struct bEntryBlock
*entry
, BOOL entryLenChg
)
424 struct bDirCacheBlock dirc
;
426 struct CacheEntry caEntry
, newEntry
;
427 int offset
, oldOffset
, n
;
430 int sLen
; /* shift length */
432 nLen
= adfEntry2CacheEntry(entry
, &newEntry
);
434 nSect
= parent
->extension
;
437 //printf("dirc=%ld\n",nSect);
438 if (adfReadDirCBlock(vol
, nSect
, &dirc
)!=RC_OK
)
441 /* search entry to update with its header_key */
442 while(n
< dirc
.recordsNb
&& !found
) {
444 /* offset is updated */
445 adfGetCacheEntry(&dirc
, &offset
, &caEntry
);
446 oLen
= offset
-oldOffset
;
448 //printf("olen=%d nlen=%d\n",oLen,nLen);
449 found
= (caEntry
.header
==newEntry
.header
);
451 if (!entryLenChg
|| oLen
==nLen
) {
452 /* same length : remplace the old values */
453 adfPutCacheEntry(&dirc
, &oldOffset
, &newEntry
);
454 //if (entryLenChg) puts("oLen==nLen");
455 if (adfWriteDirCBlock(vol
, dirc
.headerKey
, &dirc
)!=RC_OK
)
458 else if (oLen
>nLen
) {
460 /* the new record is shorter, write it,
461 * then shift down the following records
463 adfPutCacheEntry(&dirc
, &oldOffset
, &newEntry
);
464 for(i
=oldOffset
+nLen
; i
<(488-sLen
); i
++)
465 dirc
.records
[i
] = dirc
.records
[i
+sLen
];
466 /* then clear the following bytes */
467 for(i
=488-sLen
; i
<488; i
++)
468 dirc
.records
[i
] = (char)0;
470 if (adfWriteDirCBlock(vol
, dirc
.headerKey
, &dirc
)!=RC_OK
)
474 /* the new record is larger */
476 adfDelFromCache(vol
,parent
,entry
->headerKey
);
477 adfAddInCache(vol
,parent
,entry
);
478 //puts("oLen<nLen end");
484 nSect
= dirc
.nextDirC
;
485 }while(nSect
!=0 && !found
);
488 if (adfUpdateBitmap(vol
)!=RC_OK
)
492 (*adfEnv
.wFct
)("adfUpdateCache : entry not found");
499 * adfCreateEmptyCache
502 RETCODE
adfCreateEmptyCache(struct Volume
*vol
, struct bEntryBlock
*parent
, SECTNUM nSect
)
504 struct bDirCacheBlock dirc
;
508 nCache
= adfGet1FreeBlock(vol
);
510 (*adfEnv
.wFct
)("adfCreateDir : nCache==-1");
517 if (parent
->extension
==0)
518 parent
->extension
= nCache
;
520 memset(&dirc
,0, sizeof(struct bDirCacheBlock
));
522 if (parent
->secType
==ST_ROOT
)
523 dirc
.parent
= vol
->rootBlock
;
524 else if (parent
->secType
==ST_DIR
)
525 dirc
.parent
= parent
->headerKey
;
527 (*adfEnv
.wFct
)("adfCreateEmptyCache : unknown secType");
528 //printf("secType=%ld\n",parent->secType);
534 if (adfWriteDirCBlock(vol
, nCache
, &dirc
)!=RC_OK
)
545 RETCODE
adfReadDirCBlock(struct Volume
*vol
, SECTNUM nSect
, struct bDirCacheBlock
*dirc
)
547 unsigned char buf
[512];
549 if (adfReadBlock(vol
, nSect
, buf
)!=RC_OK
)
552 memcpy(dirc
,buf
,512);
554 swapEndian((unsigned char*)dirc
,SWBL_CACHE
);
556 if (dirc
->checkSum
!=adfNormalSum(buf
,20,512))
557 (*adfEnv
.wFct
)("adfReadDirCBlock : invalid checksum");
558 if (dirc
->type
!=T_DIRC
)
559 (*adfEnv
.wFct
)("adfReadDirCBlock : T_DIRC not found");
560 if (dirc
->headerKey
!=nSect
)
561 (*adfEnv
.wFct
)("adfReadDirCBlock : headerKey!=nSect");
571 RETCODE
adfWriteDirCBlock(struct Volume
* vol
, ULONG nSect
, struct bDirCacheBlock
* dirc
)
573 unsigned char buf
[LOGICAL_BLOCK_SIZE
];
577 dirc
->headerKey
= nSect
;
579 memcpy(buf
, dirc
, LOGICAL_BLOCK_SIZE
);
581 swapEndian(buf
, SWBL_CACHE
);
584 newSum
= adfNormalSum(buf
, 20, LOGICAL_BLOCK_SIZE
);
585 swLong(buf
+20,newSum
);
586 // *(ULONG*)(buf+20) = swapLong((unsigned char*)&newSum);
588 if (adfWriteBlock(vol
, nSect
, buf
)!=RC_OK
)
590 //puts("adfWriteDirCBlock");
595 /*################################################################################*/