/* * adfFreeFileBlocks * */ RETCODE adfFreeFileBlocks(struct Volume* vol, struct bFileHeaderBlock *entry) { int i; struct FileBlocks fileBlocks; RETCODE rc = RC_OK; adfGetFileBlocks(vol,entry,&fileBlocks); for(i=0; i<fileBlocks.nbData; i++) { adfSetBlockFree(vol, fileBlocks.data[i]); } for(i=0; i<fileBlocks.nbExtens; i++) { adfSetBlockFree(vol, fileBlocks.extens[i]); } free(fileBlocks.data); free(fileBlocks.extens); return rc; }
/* * adfCreateBitmap * * create bitmap structure in vol */ RETCODE adfCreateBitmap(struct Volume *vol) { int32_t nBlock, mapSize ; int i, j; nBlock = vol->lastBlock - vol->firstBlock +1 - 2; mapSize = nBlock / (127*32); if ( (nBlock%(127*32))!=0 ) mapSize++; vol->bitmapSize = mapSize; vol->bitmapTable = (struct bBitmapBlock**)malloc( sizeof(struct bBitmapBlock*)*mapSize ); if (!vol->bitmapTable) { (*adfEnv.eFct)("adfCreateBitmap : malloc, vol->bitmapTable"); return RC_MALLOC; } vol->bitmapBlocksChg = (BOOL*) malloc(sizeof(BOOL)*mapSize); if (!vol->bitmapBlocksChg) { free(vol->bitmapTable); (*adfEnv.eFct)("adfCreateBitmap : malloc, vol->bitmapBlocksChg"); return RC_MALLOC; } vol->bitmapBlocks = (SECTNUM*) malloc(sizeof(SECTNUM)*mapSize); if (!vol->bitmapBlocks) { free(vol->bitmapTable); free(vol->bitmapBlocksChg); (*adfEnv.eFct)("adfCreateBitmap : malloc, vol->bitmapBlocks"); return RC_MALLOC; } for(i=0; i<mapSize; i++) { vol->bitmapTable[i] = (struct bBitmapBlock*)malloc(sizeof(struct bBitmapBlock)); if (!vol->bitmapTable[i]) { free(vol->bitmapTable); free(vol->bitmapBlocksChg); for(j=0; j<i; j++) free(vol->bitmapTable[j]); free(vol->bitmapTable); (*adfEnv.eFct)("adfCreateBitmap : malloc"); return RC_MALLOC; } } for(i=vol->firstBlock+2; i<=(vol->lastBlock - vol->firstBlock); i++) adfSetBlockFree(vol, i); return RC_OK; }
/* * adfDelFromCache * * delete one cache entry from its block. don't do 'records garbage collecting' */ RETCODE adfDelFromCache(struct Volume *vol, struct bEntryBlock *parent, SECTNUM headerKey) { struct bDirCacheBlock dirc; SECTNUM nSect, prevSect; struct CacheEntry caEntry; int offset, oldOffset, n; BOOL found; int entryLen; int i; RETCODE rc = RC_OK; prevSect = -1; nSect = parent->extension; found = FALSE; do { adfReadDirCBlock(vol, nSect, &dirc); offset = 0; n = 0; while(n < dirc.recordsNb && !found) { oldOffset = offset; adfGetCacheEntry(&dirc, &offset, &caEntry); found = (caEntry.header==headerKey); if (found) { entryLen = offset-oldOffset; if (dirc.recordsNb>1 || prevSect==-1) { if (n<dirc.recordsNb-1) { /* not the last of the block : switch the following records */ for(i=oldOffset; i<(488-entryLen); i++) dirc.records[i] = dirc.records[i+entryLen]; /* and clear the following bytes */ for(i=488-entryLen; i<488; i++) dirc.records[i] = 0; } else { /* the last record of this cache block */ for(i=oldOffset; i<offset; i++) dirc.records[i] = 0; } dirc.recordsNb--; if (adfWriteDirCBlock(vol, dirc.headerKey, &dirc)!=RC_OK) return -1; } else { /* dirc.recordsNb ==1 or == 0 , prevSect!=-1 : * the only record in this dirc block and a previous dirc block exists */ adfSetBlockFree(vol, dirc.headerKey); adfReadDirCBlock(vol, prevSect, &dirc); dirc.nextDirC = 0L; adfWriteDirCBlock(vol, prevSect, &dirc); adfUpdateBitmap(vol); } } n++; } prevSect = nSect; nSect = dirc.nextDirC; }while(nSect!=0 && !found); if (!found) (*adfEnv.wFct)("adfUpdateCache : entry not found"); return rc; }
/* * adfCreateNextFileBlock * */ SECTNUM adfCreateNextFileBlock(struct File* file) { SECTNUM nSect, extSect; struct bOFSDataBlock *data; unsigned int blockSize; int i; /*puts("adfCreateNextFileBlock");*/ blockSize = file->volume->datablockSize; data = file->currentData; /* the first data blocks pointers are inside the file header block */ if (file->nDataBlock<MAX_DATABLK) { nSect = adfGet1FreeBlock(file->volume); if (nSect==-1) return -1; /*printf("adfCreateNextFileBlock fhdr %ld\n",nSect);*/ if (file->nDataBlock==0) file->fileHdr->firstData = nSect; file->fileHdr->dataBlocks[MAX_DATABLK-1-file->nDataBlock] = nSect; file->fileHdr->highSeq++; } else { /* one more sector is needed for one file extension block */ if ((file->nDataBlock%MAX_DATABLK)==0) { extSect = adfGet1FreeBlock(file->volume); /*printf("extSect=%ld\n",extSect);*/ if (extSect==-1) return -1; /* the future block is the first file extension block */ if (file->nDataBlock==MAX_DATABLK) { file->currentExt=(struct bFileExtBlock*)calloc(1,sizeof(struct bFileExtBlock)); if (!file->currentExt) { adfSetBlockFree(file->volume, extSect); (*adfEnv.eFct)("adfCreateNextFileBlock : malloc"); return -1; } file->fileHdr->extension = extSect; } /* not the first : save the current one, and link it with the future */ if (file->nDataBlock>=2*MAX_DATABLK) { file->currentExt->extension = extSect; /*printf ("write ext=%d\n",file->currentExt->headerKey);*/ adfWriteFileExtBlock(file->volume, file->currentExt->headerKey, file->currentExt); } /* initializes a file extension block */ for(i=0; i<MAX_DATABLK; i++) file->currentExt->dataBlocks[i] = 0L; file->currentExt->headerKey = extSect; file->currentExt->parent = file->fileHdr->headerKey; file->currentExt->highSeq = 0L; file->currentExt->extension = 0L; file->posInExtBlk = 0L; /*printf("extSect=%ld\n",extSect);*/ } nSect = adfGet1FreeBlock(file->volume); if (nSect==-1) return -1; /*printf("adfCreateNextFileBlock ext %ld\n",nSect);*/ file->currentExt->dataBlocks[MAX_DATABLK-1-file->posInExtBlk] = nSect; file->currentExt->highSeq++; file->posInExtBlk++; } /* builds OFS header */ if (isOFS(file->volume->dosType)) { /* writes previous data block and link it */ if (file->pos>=blockSize) { data->nextData = nSect; adfWriteDataBlock(file->volume, file->curDataPtr, file->currentData); /*printf ("writedata=%d\n",file->curDataPtr);*/ } /* initialize a new data block */ for(i=0; i<(int)blockSize; i++) data->data[i]=0; data->seqNum = file->nDataBlock+1; data->dataSize = blockSize; data->nextData = 0L; data->headerKey = file->fileHdr->headerKey; } else if (file->pos>=blockSize) { adfWriteDataBlock(file->volume, file->curDataPtr, file->currentData); /*printf ("writedata=%d\n",file->curDataPtr);*/ memset(file->currentData,0,512); } /*printf("datablk=%d\n",nSect);*/ file->curDataPtr = nSect; file->nDataBlock++; return(nSect); }
/* * adfCreateEntry * * if 'thisSect'==-1, allocate a sector, and insert its pointer into the hashTable of 'dir', using the * name 'name'. if 'thisSect'!=-1, insert this sector pointer into the hashTable * (here 'thisSect' must be allocated before in the bitmap). */ SECTNUM adfCreateEntry(struct Volume *vol, struct bEntryBlock *dir, char *name, SECTNUM thisSect ) { BOOL intl; struct bEntryBlock updEntry; int len, hashValue; RETCODE rc; char name2[MAXNAMELEN+1], name3[MAXNAMELEN+1]; SECTNUM nSect, newSect, newSect2; struct bRootBlock* root; /*puts("adfCreateEntry in");*/ intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType); len = min(strlen(name), MAXNAMELEN) ; myToUpper((unsigned char*)name2, (unsigned char*)name, len, intl); hashValue = adfGetHashValue((unsigned char*)name, intl); nSect = dir->hashTable[ hashValue ]; if ( nSect==0 ) { if (thisSect!=-1) newSect = thisSect; else { newSect = adfGet1FreeBlock(vol); if (newSect==-1) { (*adfEnv.wFct)("adfCreateEntry : nSect==-1"); return -1; } } dir->hashTable[ hashValue ] = newSect; if (dir->secType==ST_ROOT) { root = (struct bRootBlock*)dir; adfTime2AmigaTime(adfGiveCurrentTime(), &(root->cDays),&(root->cMins),&(root->cTicks)); rc=adfWriteRootBlock(vol, vol->rootBlock, root); } else { adfTime2AmigaTime(adfGiveCurrentTime(),&(dir->days),&(dir->mins),&(dir->ticks)); rc=adfWriteDirBlock(vol, dir->headerKey, (struct bDirBlock*)dir); } /*puts("adfCreateEntry out, dir");*/ if (rc!=RC_OK) { adfSetBlockFree(vol, newSect); return -1; } else return( newSect ); } do { if (adfReadEntryBlock(vol, nSect, &updEntry)!=RC_OK) return -1; if (updEntry.nameLen==len) { myToUpper((unsigned char*)name3,(unsigned char*)updEntry.name,updEntry.nameLen,intl); if (strncmp(name3,name2,len)==0) { (*adfEnv.wFct)("adfCreateEntry : entry already exists"); return -1; } } nSect = updEntry.nextSameHash; }while(nSect!=0); if (thisSect!=-1) newSect2 = thisSect; else { newSect2 = adfGet1FreeBlock(vol); if (newSect2==-1) { (*adfEnv.wFct)("adfCreateEntry : nSect==-1"); return -1; } } rc = RC_OK; updEntry.nextSameHash = newSect2; if (updEntry.secType==ST_DIR) rc=adfWriteDirBlock(vol, updEntry.headerKey, (struct bDirBlock*)&updEntry); else if (updEntry.secType==ST_FILE) rc=adfWriteFileHdrBlock(vol, updEntry.headerKey, (struct bFileHeaderBlock*)&updEntry); else (*adfEnv.wFct)("adfCreateEntry : unknown entry type"); /*puts("adfCreateEntry out, hash");*/ if (rc!=RC_OK) { adfSetBlockFree(vol, newSect2); return -1; } else return(newSect2); }
/* * adfRemoveEntry * */ RETCODE adfRemoveEntry(struct Volume *vol, SECTNUM pSect, char *name) { struct bEntryBlock parent, previous, entry; SECTNUM nSect2, nSect; int hashVal; BOOL intl; char buf[200]; if (adfReadEntryBlock( vol, pSect, &parent )!=RC_OK) return RC_ERROR; nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, &nSect2); if (nSect==-1) { sprintf(buf, "adfRemoveEntry : entry '%s' not found", name); (*adfEnv.wFct)(buf); return RC_ERROR; } /* if it is a directory, is it empty ? */ if ( entry.secType==ST_DIR && !isDirEmpty((struct bDirBlock*)&entry) ) { sprintf(buf, "adfRemoveEntry : directory '%s' not empty", name); (*adfEnv.wFct)(buf); return RC_ERROR; } /* printf("name=%s nSect2=%ld\n",name, nSect2);*/ /* in parent hashTable */ if (nSect2==0) { intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType); hashVal = adfGetHashValue( (unsigned char*)name, intl ); /*printf("hashTable=%d nexthash=%d\n",parent.hashTable[hashVal], entry.nextSameHash);*/ parent.hashTable[hashVal] = entry.nextSameHash; if (adfWriteEntryBlock(vol, pSect, &parent)!=RC_OK) return RC_ERROR; } /* in linked list */ else { if (adfReadEntryBlock(vol, nSect2, &previous)!=RC_OK) return RC_ERROR; previous.nextSameHash = entry.nextSameHash; if (adfWriteEntryBlock(vol, nSect2, &previous)!=RC_OK) return RC_ERROR; } if (entry.secType==ST_FILE) { adfFreeFileBlocks(vol, (struct bFileHeaderBlock*)&entry); if (adfEnv.useNotify) (*adfEnv.notifyFct)(pSect,ST_FILE); } else if (entry.secType==ST_DIR) { adfSetBlockFree(vol, nSect); /* free dir cache block : the directory must be empty, so there's only one cache block */ if (isDIRCACHE(vol->dosType)) adfSetBlockFree(vol, entry.extension); if (adfEnv.useNotify) (*adfEnv.notifyFct)(pSect,ST_DIR); } else { sprintf(buf, "adfRemoveEntry : secType %d not supported", entry.secType); (*adfEnv.wFct)(buf); return RC_ERROR; } if (isDIRCACHE(vol->dosType)) adfDelFromCache(vol, &parent, entry.headerKey); adfUpdateBitmap(vol); return RC_OK; }