/* * adfUndelFile * */ RETCODE adfUndelFile(struct Volume* vol, SECTNUM pSect, SECTNUM nSect, struct bFileHeaderBlock* entry) { long i; char name[MAXNAMELEN+1]; struct bEntryBlock parent; RETCODE rc; struct FileBlocks fileBlocks; /* check if the given parent sector pointer seems OK */ if ( (rc=adfCheckParent(vol,pSect)) != RC_OK) return rc; if (pSect!=entry->parent) { (*adfEnv.wFct)("adfUndelFile : the given parent sector isn't the entry parent"); return RC_ERROR; } adfGetFileBlocks(vol, entry, &fileBlocks); for(i=0; i<fileBlocks.nbData; i++) if ( !adfIsBlockFree(vol,fileBlocks.data[i]) ) return RC_ERROR; else adfSetBlockUsed(vol, fileBlocks.data[i]); for(i=0; i<fileBlocks.nbExtens; i++) if ( !adfIsBlockFree(vol,fileBlocks.extens[i]) ) return RC_ERROR; else adfSetBlockUsed(vol, fileBlocks.extens[i]); free(fileBlocks.data); free(fileBlocks.extens); if (adfReadEntryBlock(vol, pSect, &parent)!=RC_OK) return RC_ERROR; strncpy(name, entry->fileName, entry->nameLen); name[(int)entry->nameLen] = '\0'; /* insert the entry in the parent hashTable, with the headerKey sector pointer */ adfCreateEntry(vol, &parent, name, entry->headerKey); if (isDIRCACHE(vol->dosType)) adfAddInCache(vol, &parent, (struct bEntryBlock *)entry); adfUpdateBitmap(vol); return RC_OK; }
/* * adfCreateDir * */ RETCODE adfCreateDir(struct Volume* vol, SECTNUM nParent, char* name) { SECTNUM nSect; struct bDirBlock dir; struct bEntryBlock parent; if (adfReadEntryBlock(vol, nParent, &parent)!=RC_OK) return RC_ERROR; /* -1 : do not use a specific, already allocated sector */ nSect = adfCreateEntry(vol, &parent, name, -1); if (nSect==-1) { (*adfEnv.wFct)("adfCreateDir : no sector available"); return RC_ERROR; } memset(&dir, 0, sizeof(struct bDirBlock)); dir.nameLen = (char)min(MAXNAMELEN, strlen(name)); memcpy(dir.dirName,name,dir.nameLen); dir.headerKey = nSect; if (parent.secType==ST_ROOT) dir.parent = vol->rootBlock; else dir.parent = parent.headerKey; adfTime2AmigaTime(adfGiveCurrentTime(),&(dir.days),&(dir.mins),&(dir.ticks)); if (isDIRCACHE(vol->dosType)) { /* for adfCreateEmptyCache, will be added by adfWriteDirBlock */ dir.secType = ST_DIR; adfAddInCache(vol, &parent, (struct bEntryBlock *)&dir); adfCreateEmptyCache(vol, (struct bEntryBlock *)&dir, -1); } /* writes the dirblock, with the possible dircache assiocated */ if (adfWriteDirBlock(vol, nSect, &dir)!=RC_OK) return RC_ERROR; adfUpdateBitmap(vol); if (adfEnv.useNotify) (*adfEnv.notifyFct)(nParent,ST_DIR); return RC_OK; }
/* * adfUndelDir * */ RETCODE adfUndelDir(struct Volume* vol, SECTNUM pSect, SECTNUM nSect, struct bDirBlock* entry) { RETCODE rc; struct bEntryBlock parent; char name[MAXNAMELEN+1]; /* check if the given parent sector pointer seems OK */ if ( (rc=adfCheckParent(vol,pSect)) != RC_OK) return rc; if (pSect!=entry->parent) { (*adfEnv.wFct)("adfUndelDir : the given parent sector isn't the entry parent"); return RC_ERROR; } if (!adfIsBlockFree(vol, entry->headerKey)) return RC_ERROR; if (isDIRCACHE(vol->dosType) && !adfIsBlockFree(vol,entry->extension)) return RC_ERROR; if (adfReadEntryBlock(vol, pSect, &parent)!=RC_OK) return RC_ERROR; strncpy(name, entry->dirName, entry->nameLen); name[(int)entry->nameLen] = '\0'; /* insert the entry in the parent hashTable, with the headerKey sector pointer */ adfSetBlockUsed(vol,entry->headerKey); adfCreateEntry(vol, &parent, name, entry->headerKey); if (isDIRCACHE(vol->dosType)) { adfAddInCache(vol, &parent, (struct bEntryBlock *)entry); adfSetBlockUsed(vol,entry->extension); } adfUpdateBitmap(vol); return RC_OK; }
/* * adfCreateFile * */ RETCODE adfCreateFile(struct Volume* vol, SECTNUM nParent, char *name, struct bFileHeaderBlock *fhdr) { SECTNUM nSect; struct bEntryBlock parent; /*puts("adfCreateFile in");*/ if (adfReadEntryBlock(vol, nParent, &parent)!=RC_OK) return RC_ERROR; /* -1 : do not use a specific, already allocated sector */ nSect = adfCreateEntry(vol, &parent, name, -1); if (nSect==-1) return RC_ERROR; /*printf("new fhdr=%d\n",nSect);*/ memset(fhdr,0,512); fhdr->nameLen = (char)min(MAXNAMELEN, strlen(name)); memcpy(fhdr->fileName,name,fhdr->nameLen); fhdr->headerKey = nSect; if (parent.secType==ST_ROOT) fhdr->parent = vol->rootBlock; else if (parent.secType==ST_DIR) fhdr->parent = parent.headerKey; else (*adfEnv.wFct)("adfCreateFile : unknown parent secType"); adfTime2AmigaTime(adfGiveCurrentTime(), &(fhdr->days),&(fhdr->mins),&(fhdr->ticks)); if (adfWriteFileHdrBlock(vol,nSect,fhdr)!=RC_OK) return RC_ERROR; if (isDIRCACHE(vol->dosType)) adfAddInCache(vol, &parent, (struct bEntryBlock *)fhdr); adfUpdateBitmap(vol); if (adfEnv.useNotify) (*adfEnv.notifyFct)(nParent,ST_FILE); return RC_OK; }
/* * adfUpdateCache * */ RETCODE adfUpdateCache(struct Volume *vol, struct bEntryBlock *parent, struct bEntryBlock *entry, BOOL entryLenChg) { struct bDirCacheBlock dirc; SECTNUM nSect; struct CacheEntry caEntry, newEntry; int offset, oldOffset, n; BOOL found; int i, oLen, nLen; int sLen; /* shift length */ nLen = adfEntry2CacheEntry(entry, &newEntry); nSect = parent->extension; found = FALSE; do { /*printf("dirc=%ld\n",nSect);*/ if (adfReadDirCBlock(vol, nSect, &dirc)!=RC_OK) return RC_ERROR; offset = 0; n = 0; /* search entry to update with its header_key */ while(n < dirc.recordsNb && !found) { oldOffset = offset; /* offset is updated */ adfGetCacheEntry(&dirc, &offset, &caEntry); oLen = offset-oldOffset; sLen = oLen-nLen; /*printf("olen=%d nlen=%d\n",oLen,nLen);*/ found = (caEntry.header==newEntry.header); if (found) { if (!entryLenChg || oLen==nLen) { /* same length : remplace the old values */ adfPutCacheEntry(&dirc, &oldOffset, &newEntry); /*if (entryLenChg) puts("oLen==nLen");*/ if (adfWriteDirCBlock(vol, dirc.headerKey, &dirc)!=RC_OK) return RC_ERROR; } else if (oLen>nLen) { /*puts("oLen>nLen");*/ /* the new record is shorter, write it, * then shift down the following records */ adfPutCacheEntry(&dirc, &oldOffset, &newEntry); for(i=oldOffset+nLen; i<(488-sLen); i++) dirc.records[i] = dirc.records[i+sLen]; /* then clear the following bytes */ for(i=488-sLen; i<488; i++) dirc.records[i] = (char)0; if (adfWriteDirCBlock(vol, dirc.headerKey, &dirc)!=RC_OK) return RC_ERROR; } else { /* the new record is larger */ /*puts("oLen<nLen");*/ adfDelFromCache(vol,parent,entry->headerKey); adfAddInCache(vol,parent,entry); /*puts("oLen<nLen end");*/ } } n++; } nSect = dirc.nextDirC; }while(nSect!=0 && !found); if (found) { if (adfUpdateBitmap(vol)!=RC_OK) return RC_ERROR; } else (*adfEnv.wFct)("adfUpdateCache : entry not found"); 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; }