/* * adfSetEntryAccess * */ RETCODE adfSetEntryAccess(struct Volume* vol, SECTNUM parSect, char* name, int32_t newAcc) { struct bEntryBlock parent, entry; SECTNUM nSect; if (adfReadEntryBlock( vol, parSect, &parent )!=RC_OK) return RC_ERROR; nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, NULL); if (nSect==-1) { (*adfEnv.wFct)("adfSetEntryAccess : entry not found"); return RC_ERROR; } entry.access = newAcc; if (entry.secType==ST_DIR) adfWriteDirBlock(vol, nSect, (struct bDirBlock*)&entry); else if (entry.secType==ST_FILE) adfWriteFileHdrBlock(vol, nSect, (struct bFileHeaderBlock*)&entry); else (*adfEnv.wFct)("adfSetEntryAccess : entry secType incorrect"); if (isDIRCACHE(vol->dosType)) adfUpdateCache(vol, &parent, (struct bEntryBlock*)&entry, FALSE); return RC_OK; }
/* * adfSetEntryComment * */ RETCODE adfSetEntryComment(struct Volume* vol, SECTNUM parSect, char* name, char* newCmt) { struct bEntryBlock parent, entry; SECTNUM nSect; if (adfReadEntryBlock( vol, parSect, &parent )!=RC_OK) return RC_ERROR; nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, NULL); if (nSect==-1) { (*adfEnv.wFct)("adfSetEntryComment : entry not found"); return RC_ERROR; } entry.commLen = (char)min(MAXCMMTLEN, strlen(newCmt)); memcpy(entry.comment, newCmt, entry.commLen); if (entry.secType==ST_DIR) adfWriteDirBlock(vol, nSect, (struct bDirBlock*)&entry); else if (entry.secType==ST_FILE) adfWriteFileHdrBlock(vol, nSect, (struct bFileHeaderBlock*)&entry); else (*adfEnv.wFct)("adfSetEntryComment : entry secType incorrect"); if (isDIRCACHE(vol->dosType)) adfUpdateCache(vol, &parent, (struct bEntryBlock*)&entry, TRUE); return RC_OK; }
/* * adfVolumeInfo * */ void adfVolumeInfo(struct Volume *vol) { struct bRootBlock root; char diskName[35]; int days,month,year; if (adfReadRootBlock(vol, vol->rootBlock, &root)!=RC_OK) return; memset(diskName, 0, 35); memcpy(diskName, root.diskName, root.nameLen); printf ("Name : %-30s\n",vol->volName); printf ("Type : "); switch(vol->dev->devType) { case DEVTYPE_FLOPDD: printf ("Floppy Double Density : 880 KBytes\n"); break; case DEVTYPE_FLOPHD: printf ("Floppy High Density : 1760 KBytes\n"); break; case DEVTYPE_HARDDISK: printf ("Hard Disk partition : %3.1f KBytes\n", (vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0); break; case DEVTYPE_HARDFILE: printf ("HardFile : %3.1f KBytes\n", (vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0); break; default: printf ("Unknown devType!\n"); } printf ("Filesystem : "); printf("%s ",isFFS(vol->dosType) ? "FFS" : "OFS"); if (isINTL(vol->dosType)) printf ("INTL "); if (isDIRCACHE(vol->dosType)) printf ("DIRCACHE "); putchar('\n'); printf("Free blocks = %d\n", adfCountFreeBlocks(vol)); if (vol->readOnly) printf("Read only\n"); else printf("Read/Write\n"); /* created */ adfDays2Date(root.coDays, &year, &month, &days); printf ("created %d/%02d/%02d %d:%02d:%02d\n",days,month,year, root.coMins/60,root.coMins%60,root.coTicks/50); adfDays2Date(root.days, &year, &month, &days); printf ("last access %d/%02d/%02d %d:%02d:%02d, ",days,month,year, root.mins/60,root.mins%60,root.ticks/50); adfDays2Date(root.cDays, &year, &month, &days); printf ("%d/%02d/%02d %d:%02d:%02d\n",days,month,year, root.cMins/60,root.cMins%60,root.cTicks/50); }
/* * 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; }
/* * adfNameToEntryBlk * */ SECTNUM adfNameToEntryBlk(struct Volume *vol, int32_t ht[], char* name, struct bEntryBlock *entry, SECTNUM *nUpdSect) { int hashVal; unsigned char upperName[MAXNAMELEN+1]; unsigned char upperName2[MAXNAMELEN+1]; SECTNUM nSect; int nameLen; BOOL found; SECTNUM updSect; BOOL intl; intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType); hashVal = adfGetHashValue( (unsigned char*)name, intl ); nameLen = min(strlen(name), MAXNAMELEN); myToUpper( upperName, (unsigned char*)name, nameLen, intl ); nSect = ht[hashVal]; /*printf("name=%s ht[%d]=%d upper=%s len=%d\n",name,hashVal,nSect,upperName,nameLen); printf("hashVal=%d\n",adfGetHashValue(upperName, intl )); if (!strcmp("espaƱa.country",name)) { int i; for(i=0; i<HT_SIZE; i++) printf("ht[%d]=%d ",i,ht[i]); }*/ if (nSect==0) return -1; updSect = 0; found = FALSE; do { if (adfReadEntryBlock(vol, nSect, entry)!=RC_OK) return -1; if (nameLen==entry->nameLen) { myToUpper( upperName2, (unsigned char*)entry->name, nameLen, intl ); /*printf("2=%s %s\n",upperName2,upperName);*/ found = strncmp((char*)upperName, (char*)upperName2, nameLen)==0; } if (!found) { updSect = nSect; nSect = entry->nextSameHash; } }while( !found && nSect!=0 ); if ( nSect==0 && !found ) return -1; else { if (nUpdSect!=NULL) *nUpdSect = updSect; return nSect; } }
/* * 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; }
BOOL VolPropPage::OnInitDialog() { CPropertyPage::OnInitDialog(); WinADFDoc *pDoc = (WinADFDoc*)MDIGetActiveDoc(); ASSERT_VALID(pDoc); ASSERT(pDoc->IsKindOf(RUNTIME_CLASS(WinADFDoc))); Volume *pVol = pDoc->GetVolume(); GetDlgItem(IDC_VOLNAME)->SetWindowText(pVol->getName().c_str()); int8_t type = pVol->getType(); CButton *pButton = (CButton*)GetDlgItem(IDC_FFS); pButton->SetCheck(isFFS(type)); pButton = (CButton*)GetDlgItem(IDC_INTL); pButton->SetCheck(isINTL(type)); pButton = (CButton*)GetDlgItem(IDC_DIRCACHE); pButton->SetCheck(isDIRCACHE(type)); uint32_t totalblocks = (pVol->getLastBlock()+1) - pVol->getFirstBlock(); uint32_t totalcap = totalblocks * BSIZE; CString fmt; fmt.Format("%s KB", comma(totalcap / 1024).c_str()); GetDlgItem(IDC_VOL_TOTAL)->SetWindowText(fmt); uint32_t freeblocks = pVol->freeblocks(); uint32_t freecap = freeblocks * BSIZE; fmt.Format("%s KB", comma(freecap / 1024).c_str()); GetDlgItem(IDC_VOL_FREE)->SetWindowText(fmt); uint32_t full = totalblocks - freeblocks; m_FullProgress.SetRange32(0, totalblocks); m_FullProgress.SetPos(full); m_FullProgress.SendMessage(PBM_SETBARCOLOR, 0, COLOR_PURPLE); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
/* * 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; }
/* * 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; }
/* * adfFileFlush * */ void adfFlushFile(struct File *file) { struct bEntryBlock parent; struct bOFSDataBlock *data; if (file->currentExt) { if (file->writeMode) adfWriteFileExtBlock(file->volume, file->currentExt->headerKey, file->currentExt); } if (file->currentData) { if (file->writeMode) { file->fileHdr->byteSize = file->pos; if (isOFS(file->volume->dosType)) { data = (struct bOFSDataBlock *)file->currentData; data->dataSize = file->posInDataBlk; } if (file->fileHdr->byteSize>0) adfWriteDataBlock(file->volume, file->curDataPtr, file->currentData); } } if (file->writeMode) { file->fileHdr->byteSize = file->pos; /*printf("pos=%ld\n",file->pos);*/ adfTime2AmigaTime(adfGiveCurrentTime(), &(file->fileHdr->days),&(file->fileHdr->mins),&(file->fileHdr->ticks) ); adfWriteFileHdrBlock(file->volume, file->fileHdr->headerKey, file->fileHdr); if (isDIRCACHE(file->volume->dosType)) { /*printf("parent=%ld\n",file->fileHdr->parent);*/ adfReadEntryBlock(file->volume, file->fileHdr->parent, &parent); adfUpdateCache(file->volume, &parent, (struct bEntryBlock*)file->fileHdr,FALSE); } adfUpdateBitmap(file->volume); } }
void printVol(struct Volume* vol, int volNum) { printf("Volume : "); switch(vol->dev->devType) { case DEVTYPE_FLOPDD: printf ("Floppy 880 KBytes,"); break; case DEVTYPE_FLOPHD: printf ("Floppy 1760 KBytes,"); break; case DEVTYPE_HARDDISK: printf ("HD partition #%d %3.1f KBytes,", volNum, (vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0); break; case DEVTYPE_HARDFILE: printf ("HardFile %3.1f KBytes,", (vol->lastBlock - vol->firstBlock +1) * 512.0/1024.0); break; default: printf ("???,"); } if (vol->volName!=NULL) printf(" \"%s\"", vol->volName); printf(" between sectors [%ld-%ld].",vol->firstBlock, vol->lastBlock); printf(" %s ",isFFS(vol->dosType) ? "FFS" : "OFS"); if (isINTL(vol->dosType)) printf ("INTL "); if (isDIRCACHE(vol->dosType)) printf ("DIRCACHE "); printf(". Filled at %2.1f%%.\n", 100.0- (adfCountFreeBlocks(vol)*100.0)/(vol->lastBlock - vol->firstBlock +1) ); }
int main(int argc, char* argv[]) { int i, j; BOOL rflag, lflag, xflag, cflag, vflag, sflag, dflag, pflag, qflag; struct List* files, *rtfiles; char *devname, *dirname; char strbuf[80]; unsigned char *extbuf; int vInd, dInd, fInd, aInd; BOOL nextArg; struct Device *dev; struct Volume *vol; struct List *list, *cell; int volNum; BOOL true = TRUE; if (argc<2) { help(); exit(0); } rflag = lflag = cflag = vflag = sflag = dflag = pflag = qflag = FALSE; vInd = dInd = fInd = aInd = -1; xflag = TRUE; dirname = NULL; devname = NULL; files = rtfiles = NULL; volNum = 0; fprintf(stderr,"unADF v%s : a unzip like for .ADF files, powered by ADFlib (v%s - %s)\n\n", UNADF_VERSION, adfGetVersionNumber(),adfGetVersionDate()); /* parse options */ i=1; while(i<argc) { if (argv[i][0]=='-') { j=1; nextArg = FALSE; while(j<(int)strlen(argv[i]) && !nextArg) { switch(argv[i][j]) { case 'v': vflag = TRUE; if ((i+1)<(argc-1)) { i++; nextArg = TRUE; errno = 0; volNum = atoi(argv[i]); if (errno!=0 || volNum<0) { fprintf(stderr,"invalid volume number, aborting.\n"); exit(1); } } else fprintf(stderr,"no volume number, -v option ignored.\n"); break; case 'l': lflag = TRUE; xflag = FALSE; break; case 's': sflag = TRUE; break; case 'c': cflag = TRUE; break; case 'r': rflag = TRUE; break; case 'd': if (devname!=NULL && xflag && (i+1)==(argc-1)) { i++; dirname = argv[i]; if (dirname[strlen(dirname)-1]==DIRSEP) dirname[strlen(dirname)-1]='\0'; nextArg = TRUE; dflag = TRUE; } break; case 'p': if (xflag) { fprintf(stderr,"sending files to pipe.\n"); pflag = TRUE; qflag = TRUE; } else fprintf(stderr,"-p option must be used with extraction, ignored.\n"); break; case 'h': default: help(); exit(0); } /* switch */ j++; } /* while */ } /* if */ else { /* the last non option string is taken as a filename */ if (devname==NULL) /* if the device name has been already given */ devname = argv[i]; else { if (xflag) { if (rtfiles==NULL) rtfiles = files = newCell(NULL, (void*)argv[i]); else files = newCell(files, (void*)argv[i]); } else fprintf(stderr,"Must be used with extraction, ignored.\n"); } } i++; } /* while */ extbuf =(unsigned char*)malloc(EXTBUFL*sizeof(char)); if (!extbuf) { fprintf(stderr,"malloc error\n"); exit(1); } /* initialize the library */ adfEnvInitDefault(); dev = adfMountDev( devname,TRUE ); if (!dev) { sprintf(strbuf,"Can't mount the dump device '%s'.\n", devname); fprintf(stderr, strbuf); adfEnvCleanUp(); exit(1); } if (!qflag) printDev(dev); if (volNum>=dev->nVol) { fprintf(stderr,"This device has only %d volume(s), aborting.\n",dev->nVol); exit(1); } vol = adfMount(dev, volNum, TRUE); if (!vol) { adfUnMountDev(dev); fprintf(stderr, "Can't mount the volume\n"); adfEnvCleanUp(); exit(1); } if (!qflag) { printVol(vol, volNum); putchar('\n'); } if (cflag && isDIRCACHE(vol->dosType) && lflag) { adfChgEnvProp(PR_USEDIRC,&true); if (!qflag) puts("Using dir cache blocks."); } if (lflag) { if (!rflag) { cell = list = adfGetDirEnt(vol,vol->curDirPtr); while(cell) { printEnt(vol,cell->content,"", sflag); cell = cell->next; } adfFreeDirList(list); } else { cell = list = adfGetRDirEnt(vol,vol->curDirPtr,TRUE); printTree(vol,cell,"", sflag); adfFreeDirList(list); } }else if (xflag) { if (rtfiles!=NULL) { files = rtfiles; while(files!=NULL) { if (dirname!=NULL) processFile(vol, (char*)files->content, dirname, extbuf, pflag, qflag); else processFile(vol, (char*)files->content, "", extbuf, pflag, qflag); files = files->next; } freeList(rtfiles); } else { cell = list = adfGetRDirEnt(vol,vol->curDirPtr,TRUE); if (dirname==NULL) extractTree(vol, cell, "", extbuf, pflag, qflag); else extractTree(vol, cell, dirname, extbuf, pflag, qflag); adfFreeDirList(list); } } else help(); free(extbuf); adfUnMount(vol); adfUnMountDev(dev); adfEnvCleanUp(); return(0); }
/* * 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; }
/* * adfGetRDirEnt * */ struct List* adfGetRDirEnt(struct Volume* vol, SECTNUM nSect, BOOL recurs ) { struct bEntryBlock entryBlk; struct List *cell, *head; int i; struct Entry *entry; SECTNUM nextSector; int32_t *hashTable; struct bEntryBlock parent; if (adfEnv.useDirCache && isDIRCACHE(vol->dosType)) return (adfGetDirEntCache(vol, nSect, recurs )); if (adfReadEntryBlock(vol,nSect,&parent)!=RC_OK) return NULL; hashTable = parent.hashTable; cell = head = NULL; for(i=0; i<HT_SIZE; i++) { if (hashTable[i]!=0) { entry = (struct Entry *)calloc(1,sizeof(struct Entry)); if (!entry) { adfFreeDirList(head); (*adfEnv.eFct)("adfGetDirEnt : malloc"); return NULL; } if (adfReadEntryBlock(vol, hashTable[i], &entryBlk)!=RC_OK) { adfFreeDirList(head); return NULL; } if (adfEntBlock2Entry(&entryBlk, entry)!=RC_OK) { adfFreeDirList(head); return NULL; } entry->sector = hashTable[i]; if (head==NULL) head = cell = newCell(0, (void*)entry); else cell = newCell(cell, (void*)entry); if (cell==NULL) { adfFreeDirList(head); return NULL; } if (recurs && entry->type==ST_DIR) cell->subdir = adfGetRDirEnt(vol,entry->sector,recurs); /* same hashcode linked list */ nextSector = entryBlk.nextSameHash; while( nextSector!=0 ) { entry = (struct Entry *)calloc(1,sizeof(struct Entry)); if (!entry) { adfFreeDirList(head); (*adfEnv.eFct)("adfGetDirEnt : malloc"); return NULL; } if (adfReadEntryBlock(vol, nextSector, &entryBlk)!=RC_OK) { adfFreeDirList(head); return NULL; } if (adfEntBlock2Entry(&entryBlk, entry)!=RC_OK) { adfFreeDirList(head); return NULL; } entry->sector = nextSector; cell = newCell(cell, (void*)entry); if (cell==NULL) { adfFreeDirList(head); return NULL; } if (recurs && entry->type==ST_DIR) cell->subdir = adfGetRDirEnt(vol,entry->sector,recurs); nextSector = entryBlk.nextSameHash; } } } /* if (parent.extension && isDIRCACHE(vol->dosType) ) adfReadDirCache(vol,parent.extension); */ return head; }
/* * 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; }
/* * 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); }