Use CachePreDMA to flush data cache and obtain physical address of message to be...
[AROS.git] / tools / adflib / adf_dir.c
blob3bfec9a35f58473620ef01dedc8b43bf60bb5ce1
1 /*
2 * ADF Library. (C) 1997-1999 Laurent Clevy
4 * adf_dir.c
6 * directory code
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
14 #include "adf_dir.h"
15 #include "adf_str.h"
16 #include "adf_util.h"
17 #include "defendian.h"
18 #include "adf_blk.h"
19 #include "adf_raw.h"
20 #include "adf_disk.h"
21 #include "adf_bitm.h"
22 #include "adf_file.h"
23 #include "adf_err.h"
24 #include "adf_cache.h"
26 extern struct Env adfEnv;
30 * adfRenameEntry
32 */
33 RETCODE adfRenameEntry(struct Volume *vol, SECTNUM pSect, char *oldName,
34 SECTNUM nPSect, char *newName)
36 struct bEntryBlock parent, previous, entry, nParent;
37 SECTNUM nSect2, nSect, prevSect, tmpSect;
38 int hashValueO, hashValueN, len;
39 char name2[MAXNAMELEN+1], name3[MAXNAMELEN+1];
40 BOOL intl;
41 RETCODE rc;
43 if (strcmp(oldName,newName)==0)
44 return RC_OK;
46 intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType);
47 len = strlen(newName);
48 myToUpper(name2, newName, len, intl);
49 myToUpper(name3, oldName, strlen(oldName), intl);
50 /* newName == oldName ? */
52 if (adfReadEntryBlock( vol, pSect, &parent )!=RC_OK)
53 return RC_ERROR;
55 hashValueO = adfGetHashValue(oldName, intl);
57 nSect = adfNameToEntryBlk(vol, parent.hashTable, oldName, &entry, &prevSect);
58 if (nSect==-1) {
59 (*adfEnv.wFct)("adfRenameEntry : existing entry not found");
60 return RC_ERROR;
63 /* change name and parent dir */
64 entry.nameLen = min(31, strlen(newName));
65 memcpy(entry.name, newName, entry.nameLen);
66 entry.parent = nPSect;
67 tmpSect = entry.nextSameHash;
69 entry.nextSameHash = 0;
70 if (adfWriteEntryBlock(vol, nSect, &entry)!=RC_OK)
71 return RC_ERROR;
73 /* del from the oldname list */
75 /* in hashTable */
76 if (prevSect==0) {
77 parent.hashTable[hashValueO] = tmpSect;
78 if (parent.secType==ST_ROOT)
79 rc = adfWriteRootBlock(vol, pSect, (struct bRootBlock*)&parent);
80 else
81 rc = adfWriteDirBlock(vol, pSect, (struct bDirBlock*)&parent);
82 if (rc!=RC_OK)
83 return rc;
85 else {
86 /* in linked list */
87 if (adfReadEntryBlock(vol, prevSect, &previous)!=RC_OK)
88 return RC_ERROR;
89 /* entry.nextSameHash (tmpSect) could be == 0 */
90 previous.nextSameHash = tmpSect;
91 if (adfWriteEntryBlock(vol, prevSect, &previous)!=RC_OK)
92 return RC_ERROR;
96 if (adfReadEntryBlock( vol, nPSect, &nParent )!=RC_OK)
97 return RC_ERROR;
99 hashValueN = adfGetHashValue(newName, intl);
100 nSect2 = nParent.hashTable[ hashValueN ];
101 /* no list */
102 if (nSect2==0) {
103 nParent.hashTable[ hashValueN ] = nSect;
104 if (nParent.secType==ST_ROOT)
105 rc = adfWriteRootBlock(vol, nPSect, (struct bRootBlock*)&nParent);
106 else
107 rc = adfWriteDirBlock(vol, nPSect, (struct bDirBlock*)&nParent);
109 else {
110 /* a list exists : addition at the end */
111 /* len = strlen(newName);
112 * name2 == newName
114 do {
115 if (adfReadEntryBlock(vol, nSect2, &previous)!=RC_OK)
116 return -1;
117 if (previous.nameLen==len) {
118 myToUpper(name3,(char *)previous.name,previous.nameLen,intl);
119 if (strncmp(name3,name2,len)==0) {
120 (*adfEnv.wFct)("adfRenameEntry : entry already exists");
121 return -1;
124 nSect2 = previous.nextSameHash;
125 //printf("sect=%ld\n",nSect2);
126 }while(nSect2!=0);
128 previous.nextSameHash = nSect;
129 if (previous.secType==ST_DIR)
130 rc=adfWriteDirBlock(vol, previous.headerKey,
131 (struct bDirBlock*)&previous);
132 else if (previous.secType==ST_FILE)
133 rc=adfWriteFileHdrBlock(vol, previous.headerKey,
134 (struct bFileHeaderBlock*)&previous);
135 else {
136 (*adfEnv.wFct)("adfRenameEntry : unknown entry type");
137 rc = RC_ERROR;
141 if (rc!=RC_OK)
142 return rc;
144 if (isDIRCACHE(vol->dosType)) {
145 if (pSect==nPSect) {
146 adfUpdateCache(vol, &parent, (struct bEntryBlock*)&entry,TRUE);
148 else {
149 adfDelFromCache(vol,&parent,entry.headerKey);
150 adfAddInCache(vol,&nParent,&entry);
154 if (isDIRCACHE(vol->dosType) && pSect!=nPSect) {
155 adfUpdateCache(vol, &nParent, (struct bEntryBlock*)&entry,TRUE);
158 return RC_OK;
162 * adfRemoveEntry
165 RETCODE adfRemoveEntry(struct Volume *vol, SECTNUM pSect, char *name)
167 struct bEntryBlock parent, previous, entry;
168 SECTNUM nSect2, nSect;
169 int hashVal;
170 BOOL intl;
172 if (adfReadEntryBlock( vol, pSect, &parent )!=RC_OK)
173 return RC_ERROR;
174 nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, &nSect2);
175 if (nSect==-1) {
176 (*adfEnv.wFct)("adfRemoveEntry : entry not found");
177 return RC_ERROR;
179 /* if it is a directory, is it empty ? */
180 if ( entry.secType==ST_DIR && !isDirEmpty((struct bDirBlock*)&entry) ) {
181 (*adfEnv.wFct)("adfRemoveEntry : directory not empty");
182 return RC_ERROR;
184 /* printf("name=%s nSect2=%ld\n",name, nSect2);*/
186 /* in parent hashTable */
187 if (nSect2==0) {
188 intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType);
189 hashVal = adfGetHashValue( name, intl );
190 /*printf("hashTable=%d nexthash=%d\n",parent.hashTable[hashVal],
191 entry.nextSameHash);*/
192 parent.hashTable[hashVal] = entry.nextSameHash;
193 if (adfWriteEntryBlock(vol, pSect, &parent)!=RC_OK)
194 return RC_ERROR;
196 /* in linked list */
197 else {
198 if (adfReadEntryBlock(vol, nSect2, &previous)!=RC_OK)
199 return RC_ERROR;
200 previous.nextSameHash = entry.nextSameHash;
201 if (adfWriteEntryBlock(vol, nSect2, &previous)!=RC_OK)
202 return RC_ERROR;
205 if (entry.secType==ST_FILE) {
206 adfFreeFileBlocks(vol, (struct bFileHeaderBlock*)&entry);
207 if (adfEnv.useNotify)
208 (*adfEnv.notifyFct)(pSect,ST_FILE);
210 else if (entry.secType==ST_DIR) {
211 adfSetBlockFree(vol, nSect);
212 /* free dir cache block : the directory must be empty, so there's only one cache block */
213 if (isDIRCACHE(vol->dosType))
214 adfSetBlockFree(vol, entry.extension);
215 if (adfEnv.useNotify)
216 (*adfEnv.notifyFct)(pSect,ST_DIR);
218 else {
219 (*adfEnv.wFct)("adfRemoveEntry : secType not supported");
220 return RC_ERROR;
223 if (isDIRCACHE(vol->dosType))
224 adfDelFromCache(vol, &parent, entry.headerKey);
226 adfUpdateBitmap(vol);
228 return RC_OK;
233 * adfSetEntryComment
236 RETCODE adfSetEntryComment(struct Volume* vol, SECTNUM parSect, char* name,
237 char* newCmt)
239 struct bEntryBlock parent, entry;
240 SECTNUM nSect;
242 if (adfReadEntryBlock( vol, parSect, &parent )!=RC_OK)
243 return RC_ERROR;
244 nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, NULL);
245 if (nSect==-1) {
246 (*adfEnv.wFct)("adfSetEntryComment : entry not found");
247 return RC_ERROR;
250 entry.commLen = min(MAXCMMTLEN, strlen(newCmt));
251 memcpy(entry.comment, newCmt, entry.commLen);
253 if (entry.secType==ST_DIR)
254 adfWriteDirBlock(vol, nSect, (struct bDirBlock*)&entry);
255 else if (entry.secType==ST_FILE)
256 adfWriteFileHdrBlock(vol, nSect, (struct bFileHeaderBlock*)&entry);
257 else
258 (*adfEnv.wFct)("adfSetEntryComment : entry secType incorrect");
260 if (isDIRCACHE(vol->dosType))
261 adfUpdateCache(vol, &parent, (struct bEntryBlock*)&entry, TRUE);
263 return RC_OK;
268 * adfSetEntryAccess
271 RETCODE adfSetEntryAccess(struct Volume* vol, SECTNUM parSect, char* name,
272 ULONG newAcc)
274 struct bEntryBlock parent, entry;
275 SECTNUM nSect;
277 if (adfReadEntryBlock( vol, parSect, &parent )!=RC_OK)
278 return RC_ERROR;
279 nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, NULL);
280 if (nSect==-1) {
281 (*adfEnv.wFct)("adfSetEntryAccess : entry not found");
282 return RC_ERROR;
285 entry.access = newAcc;
286 if (entry.secType==ST_DIR)
287 adfWriteDirBlock(vol, nSect, (struct bDirBlock*)&entry);
288 else if (entry.secType==ST_FILE)
289 adfWriteFileHdrBlock(vol, nSect, (struct bFileHeaderBlock*)&entry);
290 else
291 (*adfEnv.wFct)("adfSetEntryAccess : entry secType incorrect");
293 if (isDIRCACHE(vol->dosType))
294 adfUpdateCache(vol, &parent, (struct bEntryBlock*)&entry, FALSE);
296 return RC_OK;
301 * isDirEmpty
304 BOOL isDirEmpty(struct bDirBlock *dir)
306 int i;
308 for(i=0; i<HT_SIZE; i++)
309 if (dir->hashTable[i]!=0)
310 return FALSE;
312 return TRUE;
317 * adfFreeDirList
320 void adfFreeDirList(struct List* list)
322 struct List *root, *cell;
324 root = cell = list;
325 while(cell!=NULL) {
326 adfFreeEntry(cell->content);
327 if (cell->subdir!=NULL)
328 adfFreeDirList(cell->subdir);
329 cell = cell->next;
331 freeList(root);
336 * adfGetRDirEnt
339 struct List* adfGetRDirEnt(struct Volume* vol, SECTNUM nSect, BOOL recurs )
341 struct bEntryBlock entryBlk;
342 struct List *cell, *head;
343 int i;
344 struct Entry *entry;
345 SECTNUM nextSector;
346 ULONG *hashTable;
347 struct bEntryBlock parent;
350 if (adfEnv.useDirCache && isDIRCACHE(vol->dosType))
351 return (adfGetDirEntCache(vol, nSect, recurs ));
354 if (adfReadEntryBlock(vol,nSect,&parent)!=RC_OK)
355 return NULL;
357 hashTable = parent.hashTable;
358 cell = head = NULL;
359 for(i=0; i<HT_SIZE; i++) {
360 if (hashTable[i]!=0) {
361 entry = (struct Entry *)malloc(sizeof(struct Entry));
362 if (!entry) {
363 adfFreeDirList(head);
364 (*adfEnv.eFct)("adfGetDirEnt : malloc");
365 return NULL;
367 if (adfReadEntryBlock(vol, hashTable[i], &entryBlk)!=RC_OK) {
368 adfFreeDirList(head);
369 return NULL;
371 if (adfEntBlock2Entry(&entryBlk, entry)!=RC_OK) {
372 adfFreeDirList(head); return NULL;
374 entry->sector = hashTable[i];
376 if (head==NULL)
377 head = cell = newCell(0, (void*)entry);
378 else
379 cell = newCell(cell, (void*)entry);
380 if (cell==NULL) {
381 adfFreeDirList(head); return NULL;
384 if (recurs && entry->type==ST_DIR)
385 cell->subdir = adfGetRDirEnt(vol,entry->sector,recurs);
387 /* same hashcode linked list */
388 nextSector = entryBlk.nextSameHash;
389 while( nextSector!=0 ) {
390 entry = (struct Entry *)malloc(sizeof(struct Entry));
391 if (!entry) {
392 adfFreeDirList(head);
393 (*adfEnv.eFct)("adfGetDirEnt : malloc");
394 return NULL;
396 if (adfReadEntryBlock(vol, nextSector, &entryBlk)!=RC_OK) {
397 adfFreeDirList(head); return NULL;
400 if (adfEntBlock2Entry(&entryBlk, entry)!=RC_OK) {
401 adfFreeDirList(head);
402 return NULL;
404 entry->sector = nextSector;
406 cell = newCell(cell, (void*)entry);
407 if (cell==NULL) {
408 adfFreeDirList(head); return NULL;
411 if (recurs && entry->type==ST_DIR)
412 cell->subdir = adfGetRDirEnt(vol,entry->sector,recurs);
414 nextSector = entryBlk.nextSameHash;
419 /* if (parent.extension && isDIRCACHE(vol->dosType) )
420 adfReadDirCache(vol,parent.extension);
422 return head;
427 * adfGetDirEnt
430 struct List* adfGetDirEnt(struct Volume* vol, SECTNUM nSect )
432 return adfGetRDirEnt(vol, nSect, FALSE);
437 * adfFreeEntry
440 void adfFreeEntry(struct Entry *entry)
442 if (entry==NULL)
443 return;
444 if (entry->name)
445 free(entry->name);
446 if (entry->comment)
447 free(entry->comment);
448 free(entry);
453 * adfToRootDir
456 RETCODE adfToRootDir(struct Volume *vol)
458 vol->curDirPtr = vol->rootBlock;
460 return RC_OK;
463 SECTNUM adfCurrentDir(struct Volume* vol)
465 return vol->curDirPtr;
470 * adfChangeDir
473 RETCODE adfChangeDir(struct Volume* vol, char *name)
475 struct bEntryBlock entry;
476 SECTNUM nSect;
478 if (adfReadEntryBlock( vol, vol->curDirPtr, &entry )!=RC_OK)
479 return RC_ERROR;
480 nSect = adfNameToEntryBlk(vol, entry.hashTable, name, &entry, NULL);
481 /*printf("adfChangeDir=%d\n",nSect);*/
482 if (nSect!=-1) {
483 vol->curDirPtr = nSect;
484 /* if (*adfEnv.useNotify)
485 (*adfEnv.notifyFct)(0,ST_ROOT);*/
486 return RC_OK;
488 else
489 return RC_ERROR;
494 * adfParentDir
497 RETCODE adfParentDir(struct Volume* vol)
499 struct bEntryBlock entry;
501 if (vol->curDirPtr!=vol->rootBlock) {
502 if (adfReadEntryBlock( vol, vol->curDirPtr, &entry )!=RC_OK)
503 return RC_ERROR;
504 vol->curDirPtr = entry.parent;
506 return RC_OK;
511 * adfEntBlock2Entry
514 RETCODE adfEntBlock2Entry(struct bEntryBlock *entryBlk, struct Entry *entry)
516 char buf[MAXCMMTLEN+1];
517 int len;
519 entry->type = entryBlk->secType;
520 entry->parent = entryBlk->parent;
522 len = min(entryBlk->nameLen, MAXNAMELEN);
523 strncpy(buf, (char *)entryBlk->name, len);
524 buf[len] = '\0';
525 entry->name = strdup(buf);
526 if (entry->name==NULL)
527 return RC_MALLOC;
528 //printf("len=%d name=%s parent=%ld\n",entryBlk->nameLen, entry->name,entry->parent );
529 adfDays2Date( entryBlk->days, &(entry->year), &(entry->month), &(entry->days));
530 entry->hour = entryBlk->mins/60;
531 entry->mins = entryBlk->mins%60;
532 entry->secs = entryBlk->ticks/50;
534 entry->access = -1;
535 entry->size = 0L;
536 entry->comment = NULL;
537 entry->real = 0L;
538 switch(entryBlk->secType) {
539 case ST_ROOT:
540 break;
541 case ST_DIR:
542 entry->access = entryBlk->access;
543 len = min(entryBlk->commLen, MAXCMMTLEN);
544 strncpy(buf, (char *)entryBlk->comment, len);
545 buf[len] = '\0';
546 entry->comment = strdup(buf);
547 if (entry->comment==NULL) {
548 free(entry->name);
549 return RC_MALLOC;
551 break;
552 case ST_FILE:
553 entry->access = entryBlk->access;
554 entry->size = entryBlk->byteSize;
555 len = min(entryBlk->commLen, MAXCMMTLEN);
556 strncpy(buf, (char *)entryBlk->comment, len);
557 buf[len] = '\0';
558 entry->comment = strdup(buf);
559 if (entry->comment==NULL) {
560 free(entry->name);
561 return RC_MALLOC;
563 break;
564 case ST_LFILE:
565 case ST_LDIR:
566 entry->real = entryBlk->realEntry;
567 case ST_LSOFT:
568 break;
569 default:
570 (*adfEnv.wFct)("unknown entry type");
573 return RC_OK;
578 * adfNameToEntryBlk
581 SECTNUM adfNameToEntryBlk(struct Volume *vol, ULONG ht[], char* name,
582 struct bEntryBlock *entry, SECTNUM *nUpdSect)
584 int hashVal;
585 char upperName[MAXNAMELEN+1];
586 char upperName2[MAXNAMELEN+1];
587 SECTNUM nSect;
588 int nameLen;
589 BOOL found;
590 SECTNUM updSect;
591 BOOL intl;
593 intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType);
594 hashVal = adfGetHashValue( name, intl );
595 nameLen = strlen(name);
596 myToUpper( upperName, name, nameLen, intl );
598 nSect = ht[hashVal];
599 /*printf("name=%s ht[%d]=%d upper=%s len=%d\n",name,hashVal,nSect,upperName,nameLen);
600 printf("hashVal=%d\n",adfGetHashValue(upperName, intl ));
601 if (!strcmp("españa.country",name)) {
602 int i;
603 for(i=0; i<HT_SIZE; i++) printf("ht[%d]=%d ",i,ht[i]);
605 if (nSect==0)
606 return -1;
608 updSect = 0;
609 found = FALSE;
610 do {
611 if (adfReadEntryBlock(vol, nSect, entry)!=RC_OK)
612 return -1;
613 if (nameLen==entry->nameLen) {
614 myToUpper( upperName2, (char *)entry->name, nameLen, intl );
615 //printf("2=%s %s\n",upperName2,upperName);
616 found = strncmp(upperName, upperName2, nameLen)==0;
618 if (!found) {
619 updSect = nSect;
620 nSect = entry->nextSameHash;
622 }while( !found && nSect!=0 );
624 if ( nSect==0 && !found )
625 return -1;
626 else {
627 if (nUpdSect!=NULL)
628 *nUpdSect = updSect;
629 return nSect;
635 * Access2String
638 char*
639 adfAccess2String(ULONG acc)
641 static char ret[8+1];
643 strcpy(ret,"----rwed");
644 if (hasD(acc)) ret[7]='-';
645 if (hasE(acc)) ret[6]='-';
646 if (hasW(acc)) ret[5]='-';
647 if (hasR(acc)) ret[4]='-';
648 if (hasA(acc)) ret[3]='a';
649 if (hasP(acc)) ret[2]='p';
650 if (hasS(acc)) ret[1]='s';
651 if (hasH(acc)) ret[0]='h';
653 return(ret);
658 * adfCreateEntry
660 * if 'thisSect'==-1, allocate a sector, and insert its pointer into the hashTable of 'dir', using the
661 * name 'name'. if 'thisSect'!=-1, insert this sector pointer into the hashTable
662 * (here 'thisSect' must be allocated before in the bitmap).
664 SECTNUM adfCreateEntry(struct Volume *vol, struct bEntryBlock *dir, char *name,
665 SECTNUM thisSect )
667 BOOL intl;
668 struct bEntryBlock updEntry;
669 int len, hashValue;
670 RETCODE rc;
671 char name2[MAXNAMELEN+1], name3[MAXNAMELEN+1];
672 SECTNUM nSect, newSect, newSect2;
673 struct bRootBlock* root;
675 //puts("adfCreateEntry in");
677 intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType);
678 len = strlen(name);
679 myToUpper(name2, name, len, intl);
680 hashValue = adfGetHashValue(name, intl);
681 nSect = dir->hashTable[ hashValue ];
683 if ( nSect==0 ) {
684 if (thisSect!=(SECTNUM)-1)
685 newSect = thisSect;
686 else {
687 newSect = adfGet1FreeBlock(vol);
688 if (newSect==(SECTNUM)-1) {
689 (*adfEnv.wFct)("adfCreateEntry : nSect==-1");
690 return (SECTNUM)-1;
694 dir->hashTable[ hashValue ] = newSect;
695 if (dir->secType==ST_ROOT) {
696 root = (struct bRootBlock*)dir;
697 adfTime2AmigaTime(adfGiveCurrentTime(),
698 &(root->cDays),&(root->cMins),&(root->cTicks));
699 rc=adfWriteRootBlock(vol, vol->rootBlock, root);
701 else {
702 adfTime2AmigaTime(adfGiveCurrentTime(),&(dir->days),&(dir->mins),&(dir->ticks));
703 rc=adfWriteDirBlock(vol, dir->headerKey, (struct bDirBlock*)dir);
705 //puts("adfCreateEntry out, dir");
706 if (rc!=RC_OK) {
707 adfSetBlockFree(vol, newSect);
708 return (SECTNUM)-1;
710 else
711 return( newSect );
714 do {
715 if (adfReadEntryBlock(vol, nSect, &updEntry)!=RC_OK)
716 return (SECTNUM)-1;
717 if (updEntry.nameLen==len) {
718 myToUpper(name3,(char *)updEntry.name,updEntry.nameLen,intl);
719 if (strncmp(name3,name2,len)==0) {
720 (*adfEnv.wFct)("adfCreateEntry : entry already exists");
721 return (SECTNUM)-1;
724 nSect = updEntry.nextSameHash;
725 }while(nSect!=0);
727 if (thisSect!=(SECTNUM)-1)
728 newSect2 = thisSect;
729 else {
730 newSect2 = adfGet1FreeBlock(vol);
731 if (newSect2==(SECTNUM)-1) {
732 (*adfEnv.wFct)("adfCreateEntry : nSect==-1");
733 return (SECTNUM)-1;
737 rc = RC_OK;
738 updEntry.nextSameHash = newSect2;
739 if (updEntry.secType==ST_DIR)
740 rc=adfWriteDirBlock(vol, updEntry.headerKey, (struct bDirBlock*)&updEntry);
741 else if (updEntry.secType==ST_FILE)
742 rc=adfWriteFileHdrBlock(vol, updEntry.headerKey,
743 (struct bFileHeaderBlock*)&updEntry);
744 else
745 (*adfEnv.wFct)("adfCreateEntry : unknown entry type");
747 //puts("adfCreateEntry out, hash");
748 if (rc!=RC_OK) {
749 adfSetBlockFree(vol, newSect2);
750 return (SECTNUM)-1;
752 else
753 return(newSect2);
760 * adfIntlToUpper
763 char adfIntlToUpper(char cin)
765 unsigned char c = (unsigned char)cin;
766 return (c>='a' && c<='z') || (c>=224 && c<=254 && c!=247) ? c - ('a'-'A') : c ;
769 char adfToUpper(char cin)
771 unsigned char c = (unsigned char)cin;
772 return (c>='a' && c<='z') ? c - ('a'-'A') : c ;
776 * myToUpper
779 void
780 myToUpper( char *nstr, char *ostr, int nlen, BOOL intl )
782 int i;
784 if (intl)
785 for(i=0; i<nlen; i++)
786 nstr[i]=adfIntlToUpper(ostr[i]);
787 else
788 for(i=0; i<nlen; i++)
789 nstr[i]=adfToUpper(ostr[i]);
790 nstr[nlen]='\0';
795 * adfGetHashValue
798 int
799 adfGetHashValue(char *name, BOOL intl)
801 ULONG hash, len;
802 unsigned int i;
803 char upper;
805 len = hash = strlen(name);
806 for(i=0; i<len; i++) {
807 if (intl)
808 upper = adfIntlToUpper(name[i]);
809 else
810 upper = toupper(name[i]);
811 hash = (hash * 13 + (unsigned char)upper) & 0x7ff;
813 hash = hash % HT_SIZE;
815 return(hash);
820 * printEntry
823 void printEntry(struct Entry* entry)
825 printf("%-30s %2d %6ld ", entry->name, entry->type, (long)entry->sector);
826 printf("%2d/%02d/%04d %2d:%02d:%02d",entry->days, entry->month, entry->year,
827 entry->hour, entry->mins, entry->secs);
828 if (entry->type==ST_FILE)
829 printf("%8ld ",entry->size);
830 else
831 printf(" ");
832 if (entry->type==ST_FILE || entry->type==ST_DIR)
833 printf("%-s ",adfAccess2String(entry->access));
834 if (entry->comment!=NULL)
835 printf("%s ",entry->comment);
836 putchar('\n');
841 * adfCreateDir
844 RETCODE adfCreateDir(struct Volume* vol, SECTNUM nParent, char* name)
846 SECTNUM nSect;
847 struct bDirBlock dir;
848 struct bEntryBlock parent;
850 if (adfReadEntryBlock(vol, nParent, &parent)!=RC_OK)
851 return RC_ERROR;
853 /* -1 : do not use a specific, already allocated sector */
854 nSect = adfCreateEntry(vol, &parent, name, -1);
855 if (nSect==-1) {
856 (*adfEnv.wFct)("adfCreateDir : no sector available");
857 return RC_ERROR;
859 memset(&dir, 0, sizeof(struct bDirBlock));
860 dir.nameLen = min(MAXNAMELEN, strlen(name));
861 memcpy(dir.dirName,name,dir.nameLen);
862 dir.headerKey = nSect;
864 if (parent.secType==ST_ROOT)
865 dir.parent = vol->rootBlock;
866 else
867 dir.parent = parent.headerKey;
868 adfTime2AmigaTime(adfGiveCurrentTime(),&(dir.days),&(dir.mins),&(dir.ticks));
870 if (isDIRCACHE(vol->dosType)) {
871 /* for adfCreateEmptyCache, will be added by adfWriteDirBlock */
872 dir.secType = ST_DIR;
873 adfAddInCache(vol, &parent, (struct bEntryBlock *)&dir);
874 adfCreateEmptyCache(vol, (struct bEntryBlock *)&dir, -1);
877 /* writes the dirblock, with the possible dircache assiocated */
878 if (adfWriteDirBlock(vol, nSect, &dir)!=RC_OK)
879 return RC_ERROR;
881 adfUpdateBitmap(vol);
883 if (adfEnv.useNotify)
884 (*adfEnv.notifyFct)(nParent,ST_DIR);
886 return RC_OK;
891 * adfCreateFile
894 RETCODE adfCreateFile(struct Volume* vol, SECTNUM nParent, char *name,
895 struct bFileHeaderBlock *fhdr)
897 SECTNUM nSect;
898 struct bEntryBlock parent;
899 //puts("adfCreateFile in");
900 if (adfReadEntryBlock(vol, nParent, &parent)!=RC_OK)
901 return RC_ERROR;
903 /* -1 : do not use a specific, already allocated sector */
904 nSect = adfCreateEntry(vol, &parent, name, (SECTNUM)-1);
905 if (nSect==-1) return RC_ERROR;
906 /*printf("new fhdr=%d\n",nSect);*/
907 memset(fhdr,0,512);
908 memset(fhdr->fileName, 0xff, MAXNAMELEN+1);
909 fhdr->nameLen = min(MAXNAMELEN, strlen(name));
910 memcpy(fhdr->fileName,name,fhdr->nameLen);
911 fhdr->headerKey = nSect;
912 if (parent.secType==ST_ROOT)
913 fhdr->parent = vol->rootBlock;
914 else if (parent.secType==ST_DIR)
915 fhdr->parent = parent.headerKey;
916 else
917 (*adfEnv.wFct)("adfCreateFile : unknown parent secType");
918 adfTime2AmigaTime(adfGiveCurrentTime(),
919 &(fhdr->days),&(fhdr->mins),&(fhdr->ticks));
921 if (adfWriteFileHdrBlock(vol,nSect,fhdr)!=RC_OK)
922 return RC_ERROR;
924 if (isDIRCACHE(vol->dosType))
925 adfAddInCache(vol, &parent, (struct bEntryBlock *)fhdr);
927 adfUpdateBitmap(vol);
929 if (adfEnv.useNotify)
930 (*adfEnv.notifyFct)(nParent,ST_FILE);
932 return RC_OK;
937 * adfReadEntryBlock
940 RETCODE adfReadEntryBlock(struct Volume* vol, SECTNUM nSect, struct bEntryBlock *ent)
942 unsigned char buf[512];
944 if (adfReadBlock(vol, nSect, buf)!=RC_OK)
945 return RC_ERROR;
947 memcpy(ent, buf, 512);
948 #ifdef LITT_ENDIAN
949 if (nSect == vol->rootBlock)
950 swapEndian((UBYTE *)ent, SWBL_ROOT);
951 else
952 swapEndian((UBYTE *)ent, SWBL_ENTRY);
953 #endif
954 /*printf("readentry=%d\n",nSect);*/
955 if (ent->checkSum!=adfNormalSum(buf,20,512)) {
956 (*adfEnv.wFct)("adfReadEntryBlock : invalid checksum");
957 return RC_ERROR;
959 if (ent->type!=T_HEADER) {
960 (*adfEnv.wFct)("adfReadEntryBlock : T_HEADER id not found");
961 return RC_ERROR;
963 if (ent->nameLen<0 || ent->nameLen>MAXNAMELEN || ent->commLen>MAXCMMTLEN) {
964 (*adfEnv.wFct)("adfReadEntryBlock : nameLen or commLen incorrect");
965 printf("nameLen=%d, commLen=%d, name=%s sector%ld\n",
966 ent->nameLen,ent->commLen,ent->name, (long)ent->headerKey);
969 return RC_OK;
974 * adfWriteEntryBlock
977 RETCODE adfWriteEntryBlock(struct Volume* vol, SECTNUM nSect, struct bEntryBlock *ent)
979 unsigned char buf[512];
980 ULONG newSum;
983 memcpy(buf, ent, sizeof(struct bEntryBlock));
985 #ifdef LITT_ENDIAN
986 if (nSect == vol->rootBlock)
987 swapEndian(buf, SWBL_ROOT);
988 else
989 swapEndian(buf, SWBL_ENTRY);
990 #endif
991 newSum = adfNormalSum(buf,20,sizeof(struct bEntryBlock));
992 swLong(buf+20, newSum);
994 if (adfWriteBlock(vol, nSect, buf)!=RC_OK)
995 return RC_ERROR;
997 return RC_OK;
1002 * adfWriteDirBlock
1005 RETCODE adfWriteDirBlock(struct Volume* vol, SECTNUM nSect, struct bDirBlock *dir)
1007 unsigned char buf[512];
1008 ULONG newSum;
1011 /*printf("wdirblk=%d\n",nSect);*/
1012 dir->type = T_HEADER;
1013 dir->highSeq = 0;
1014 dir->hashTableSize = 0;
1015 dir->secType = ST_DIR;
1017 memcpy(buf, dir, sizeof(struct bDirBlock));
1018 #ifdef LITT_ENDIAN
1019 swapEndian(buf, SWBL_DIR);
1020 #endif
1021 newSum = adfNormalSum(buf,20,sizeof(struct bDirBlock));
1022 swLong(buf+20, newSum);
1024 if (adfWriteBlock(vol, nSect, buf)!=RC_OK)
1025 return RC_ERROR;
1027 return RC_OK;
1032 /*###########################################################################*/