/* * adfUpdateBitmap * */ RETCODE adfUpdateBitmap(struct Volume *vol) { int i; struct bRootBlock root; /*printf("adfUpdateBitmap\n");*/ if (adfReadRootBlock(vol, vol->rootBlock,&root)!=RC_OK) return RC_ERROR; root.bmFlag = BM_INVALID; if (adfWriteRootBlock(vol,vol->rootBlock,&root)!=RC_OK) return RC_ERROR; for(i=0; i<vol->bitmapSize; i++) if (vol->bitmapBlocksChg[i]) { if (adfWriteBitmapBlock(vol, vol->bitmapBlocks[i], vol->bitmapTable[i])!=RC_OK) return RC_ERROR; vol->bitmapBlocksChg[i] = FALSE; } root.bmFlag = BM_VALID; adfTime2AmigaTime(adfGiveCurrentTime(),&(root.days),&(root.mins),&(root.ticks)); if (adfWriteRootBlock(vol,vol->rootBlock,&root)!=RC_OK) return RC_ERROR; return RC_OK; }
/* * adfWriteNewBitmap * * write ext blocks and bitmap * * uses vol->bitmapSize, */ RETCODE adfWriteNewBitmap(struct Volume *vol) { struct bBitmapExtBlock bitme; SECTNUM *bitExtBlock; int n, i, k; int nExtBlock; int nBlock; SECTNUM *sectList; struct bRootBlock root; sectList=(SECTNUM*)malloc(sizeof(SECTNUM)*vol->bitmapSize); if (!sectList) { (*adfEnv.eFct)("adfCreateBitmap : sectList"); return RC_MALLOC; } if (!adfGetFreeBlocks(vol, vol->bitmapSize, sectList)) { free(sectList); return RC_ERROR; } if (adfReadRootBlock(vol, vol->rootBlock, &root)!=RC_OK) { free(sectList); return RC_ERROR; } nBlock = 0; n = min( vol->bitmapSize, BM_SIZE ); for(i=0; i<n; i++) { root.bmPages[i] = vol->bitmapBlocks[i] = sectList[i]; } nBlock = n; /* for devices with more than 25*127 blocks == hards disks */ if (vol->bitmapSize>BM_SIZE) { nExtBlock = (vol->bitmapSize-BM_SIZE)/127; if ((vol->bitmapSize-BM_SIZE)%127) nExtBlock++; bitExtBlock=(SECTNUM*)malloc(sizeof(SECTNUM)*nExtBlock); if (!bitExtBlock) { free(sectList); adfEnv.eFct("adfWriteNewBitmap : malloc failed"); return RC_MALLOC; } if (!adfGetFreeBlocks(vol, nExtBlock, bitExtBlock)) { free(sectList); free(bitExtBlock); return RC_MALLOC; } k = 0; root.bmExt = bitExtBlock[ k ]; while( nBlock<vol->bitmapSize ) { i=0; while( i<127 && nBlock<vol->bitmapSize ) { bitme.bmPages[i] = vol->bitmapBlocks[nBlock] = sectList[i]; i++; nBlock++; } if ( k+1<nExtBlock ) bitme.nextBlock = bitExtBlock[ k+1 ]; else bitme.nextBlock = 0; if (adfWriteBitmapExtBlock(vol, bitExtBlock[ k ], &bitme)!=RC_OK) { free(sectList); free(bitExtBlock); return RC_ERROR; } k++; } free( bitExtBlock ); } free( sectList); if (adfWriteRootBlock(vol,vol->rootBlock,&root)!=RC_OK) return RC_ERROR; return RC_OK; }
/* * adfRenameEntry * */ RETCODE adfRenameEntry(struct Volume *vol, SECTNUM pSect, char *oldName, SECTNUM nPSect, char *newName) { struct bEntryBlock parent, previous, entry, nParent; SECTNUM nSect2, nSect, prevSect, tmpSect; int hashValueO, hashValueN, len; char name2[MAXNAMELEN+1], name3[MAXNAMELEN+1]; BOOL intl; RETCODE rc; if (strcmp(oldName,newName)==0) return RC_OK; intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType); len = strlen(newName); myToUpper((unsigned char*)name2, (unsigned char*)newName, len, intl); myToUpper((unsigned char*)name3, (unsigned char*)oldName, strlen(oldName), intl); /* newName == oldName ? */ if (adfReadEntryBlock( vol, pSect, &parent )!=RC_OK) return RC_ERROR; hashValueO = adfGetHashValue((unsigned char*)oldName, intl); nSect = adfNameToEntryBlk(vol, parent.hashTable, oldName, &entry, &prevSect); if (nSect==-1) { (*adfEnv.wFct)("adfRenameEntry : existing entry not found"); return RC_ERROR; } /* change name and parent dir */ entry.nameLen = (char)min(31, strlen(newName)); memcpy(entry.name, newName, entry.nameLen); entry.parent = nPSect; tmpSect = entry.nextSameHash; entry.nextSameHash = 0; if (adfWriteEntryBlock(vol, nSect, &entry)!=RC_OK) return RC_ERROR; /* del from the oldname list */ /* in hashTable */ if (prevSect==0) { parent.hashTable[hashValueO] = tmpSect; if (parent.secType==ST_ROOT) rc = adfWriteRootBlock(vol, pSect, (struct bRootBlock*)&parent); else rc = adfWriteDirBlock(vol, pSect, (struct bDirBlock*)&parent); if (rc!=RC_OK) return rc; } else { /* in linked list */ if (adfReadEntryBlock(vol, prevSect, &previous)!=RC_OK) return RC_ERROR; /* entry.nextSameHash (tmpSect) could be == 0 */ previous.nextSameHash = tmpSect; if (adfWriteEntryBlock(vol, prevSect, &previous)!=RC_OK) return RC_ERROR; } if (adfReadEntryBlock( vol, nPSect, &nParent )!=RC_OK) return RC_ERROR; hashValueN = adfGetHashValue((unsigned char*)newName, intl); nSect2 = nParent.hashTable[ hashValueN ]; /* no list */ if (nSect2==0) { nParent.hashTable[ hashValueN ] = nSect; if (nParent.secType==ST_ROOT) rc = adfWriteRootBlock(vol, nPSect, (struct bRootBlock*)&nParent); else rc = adfWriteDirBlock(vol, nPSect, (struct bDirBlock*)&nParent); } else { /* a list exists : addition at the end */ /* len = strlen(newName); * name2 == newName */ do { if (adfReadEntryBlock(vol, nSect2, &previous)!=RC_OK) return -1; if (previous.nameLen==len) { myToUpper((unsigned char*)name3,(unsigned char*)previous.name,previous.nameLen,intl); if (strncmp(name3,name2,len)==0) { (*adfEnv.wFct)("adfRenameEntry : entry already exists"); return -1; } } nSect2 = previous.nextSameHash; /*printf("sect=%ld\n",nSect2);*/ }while(nSect2!=0); previous.nextSameHash = nSect; if (previous.secType==ST_DIR) rc=adfWriteDirBlock(vol, previous.headerKey, (struct bDirBlock*)&previous); else if (previous.secType==ST_FILE) rc=adfWriteFileHdrBlock(vol, previous.headerKey, (struct bFileHeaderBlock*)&previous); else { (*adfEnv.wFct)("adfRenameEntry : unknown entry type"); rc = RC_ERROR; } } if (rc!=RC_OK) return rc; if (isDIRCACHE(vol->dosType)) { if (pSect==nPSect) { adfUpdateCache(vol, &parent, (struct bEntryBlock*)&entry,TRUE); } else { adfDelFromCache(vol,&parent,entry.headerKey); adfAddInCache(vol,&nParent,&entry); } } /* if (isDIRCACHE(vol->dosType) && pSect!=nPSect) { adfUpdateCache(vol, &nParent, (struct bEntryBlock*)&entry,TRUE); } */ return RC_OK; }
/* * 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); }
/* * adfCreateVol * * */ struct Volume* adfCreateVol( struct Device* dev, int32_t start, int32_t len, char* volName, int volType,struct DateTime * voldate ) { struct bBootBlock boot; struct bRootBlock root; /* struct bDirCacheBlock dirc;*/ SECTNUM blkList[2]; struct Volume* vol; int nlen; if (adfEnv.useProgressBar) (*adfEnv.progressBar)(0); vol=(struct Volume*)calloc(1,sizeof(struct Volume)); if (!vol) { (*adfEnv.eFct)("adfCreateVol : malloc vol"); return NULL; } vol->dev = dev; vol->firstBlock = (dev->heads * dev->sectors)*start; vol->lastBlock = (vol->firstBlock + (dev->heads * dev->sectors)*len)-1; vol->rootBlock = (vol->lastBlock - vol->firstBlock+1)/2; /*printf("first=%ld last=%ld root=%ld\n",vol->firstBlock, vol->lastBlock, vol->rootBlock); */ vol->curDirPtr = vol->rootBlock; vol->readOnly = dev->readOnly; vol->mounted = TRUE; nlen = min( MAXNAMELEN, strlen(volName) ); vol->volName = (char*)calloc(1,nlen+1); if (!vol->volName) { (*adfEnv.eFct)("adfCreateVol : malloc"); free(vol); return NULL; } memcpy(vol->volName, volName, nlen); vol->volName[nlen]='\0'; if (adfEnv.useProgressBar) (*adfEnv.progressBar)(25); memset(&boot, 0, 1024); boot.dosType[3] = volType; /*printf("first=%d last=%d\n", vol->firstBlock, vol->lastBlock); printf("name=%s root=%d\n", vol->volName, vol->rootBlock); */ if (adfWriteBootBlock(vol, &boot)!=RC_OK) { free(vol->volName); free(vol); return NULL; } if (adfEnv.useProgressBar) (*adfEnv.progressBar)(20); if (adfCreateBitmap( vol )!=RC_OK) { free(vol->volName); free(vol); return NULL; } if (adfEnv.useProgressBar) (*adfEnv.progressBar)(40); /*for(i=0; i<127; i++) printf("%3d %x, ",i,vol->bitmapTable[0]->map[i]); */ if ( isDIRCACHE(volType) ) adfGetFreeBlocks( vol, 2, blkList ); else adfGetFreeBlocks( vol, 1, blkList ); /*printf("[0]=%d [1]=%d\n",blkList[0],blkList[1]);*/ memset(&root, 0, LOGICAL_BLOCK_SIZE); if (strlen(volName)>MAXNAMELEN) volName[MAXNAMELEN]='\0'; root.nameLen = (char)strlen(volName); memcpy(root.diskName,volName,root.nameLen); if(voldate) { adfTime2AmigaTime(*voldate,&(root.coDays),&(root.coMins),&(root.coTicks)); } else { adfTime2AmigaTime(adfGiveCurrentTime(),&(root.coDays),&(root.coMins),&(root.coTicks)); } /* dircache block */ if ( isDIRCACHE(volType) ) { root.extension = 0L; root.secType = ST_ROOT; /* needed by adfCreateEmptyCache() */ adfCreateEmptyCache(vol, (struct bEntryBlock*)&root, blkList[1]); } if (adfEnv.useProgressBar) (*adfEnv.progressBar)(60); if (adfWriteRootBlock(vol, blkList[0], &root)!=RC_OK) { free(vol->volName); free(vol); return NULL; } /* fills root->bmPages[] and writes filled bitmapExtBlocks */ if (adfWriteNewBitmap(vol)!=RC_OK) return NULL; if (adfEnv.useProgressBar) (*adfEnv.progressBar)(80); if (adfUpdateBitmap(vol)!=RC_OK) return NULL; if (adfEnv.useProgressBar) (*adfEnv.progressBar)(100); /*printf("free blocks %ld\n",adfCountFreeBlocks(vol));*/ /* will be managed by adfMount() later */ adfFreeBitmap(vol); vol->mounted = FALSE; return(vol); }