bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry,bool fcb) { // Creation of a device is the same as opening it // Tc201 installer if (DOS_FindDevice(name) != DOS_DEVICES) return DOS_OpenFile(name, OPEN_READ, entry, fcb); LOG(LOG_FILES,LOG_NORMAL)("file create attributes %X file %s",attributes,name); char fullname[DOS_PATHLENGTH]; Bit8u drive; DOS_PSP psp(dos.psp()); if (!DOS_MakeName(name,fullname,&drive)) return false; /* Check for a free file handle */ Bit8u handle=DOS_FILES; Bit8u i; for (i=0; i<DOS_FILES; i++) { if (!Files[i]) { handle=i; break; } } if (handle==DOS_FILES) { DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); return false; } /* We have a position in the main table now find one in the psp table */ *entry = fcb?handle:psp.FindFreeFileEntry(); if (*entry==0xff) { DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); return false; } /* Don't allow directories to be created */ if (attributes&DOS_ATTR_DIRECTORY) { DOS_SetError(DOSERR_ACCESS_DENIED); return false; } bool foundit=Drives[drive]->FileCreate(&Files[handle],fullname,attributes); if (foundit) { Files[handle]->SetDrive(drive); Files[handle]->AddRef(); if (!fcb) psp.SetFileHandle(*entry,handle); return true; } else { if(!PathExists(name)) DOS_SetError(DOSERR_PATH_NOT_FOUND); else DOS_SetError(DOSERR_FILE_NOT_FOUND); return false; } }
bool DOS_MakeDir(char const * const dir) { Bit8u drive;char fulldir[DOS_PATHLENGTH]; size_t len = strlen(dir); if(!len || dir[len-1] == '\\') { DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; } if (!DOS_MakeName(dir,fulldir,&drive)) return false; if(Drives[drive]->MakeDir(fulldir)) return true; /* Determine reason for failing */ if(Drives[drive]->TestDir(fulldir)) DOS_SetError(DOSERR_ACCESS_DENIED); else DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; }
bool DOS_FreeMemory(Bit16u segment) { //TODO Check if allowed to free this segment if (segment < DOS_MEM_START+1) { LOG(LOG_DOSMISC,LOG_ERROR)("Program tried to free %X ---ERROR",segment); DOS_SetError(DOSERR_MB_ADDRESS_INVALID); return false; } DOS_MCB mcb(segment-1); if ((mcb.GetType()!=0x4d) && (mcb.GetType()!=0x5a)) { DOS_SetError(DOSERR_MB_ADDRESS_INVALID); return false; } mcb.SetPSPSeg(MCB_FREE); // DOS_CompressMemory(); return true; }
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free) { if (drive==0) drive=DOS_GetDefaultDrive(); else drive--; if ((drive>=DOS_DRIVES) || (!Drives[drive])) { DOS_SetError(DOSERR_INVALID_DRIVE); return false; } return Drives[drive]->AllocationInfo(bytes,sectors,clusters,free); }
bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate) { Bit32u handle=RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; if (!Files[handle] || !Files[handle]->IsOpen()) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; if (!Files[handle]->UpdateDateTimeFromHost()) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } *otime = Files[handle]->time; *odate = Files[handle]->date; return true; }
bool physfscdromDrive::FileOpen(DOS_File * * file,const char * name,Bit32u flags) { if ((flags&0xf)==OPEN_READWRITE) { flags &= ~OPEN_READWRITE; } else if ((flags&0xf)==OPEN_WRITE) { DOS_SetError(DOSERR_ACCESS_DENIED); return false; } return physfsDrive::FileOpen(file,name,flags); };
bool DOS_UnlinkFile(char const * const name) { char fullname[DOS_PATHLENGTH];Bit8u drive; if (!DOS_MakeName(name,fullname,&drive)) return false; if(Drives[drive]->FileUnlink(fullname)){ return true; } else { DOS_SetError(DOSERR_FILE_NOT_FOUND); return false; } }
bool DOS_FlushFile(Bit16u entry) { Bit32u handle = RealHandle(entry); if (handle >= DOS_FILES || !Files[handle]) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } return true; }
bool DOS_SeekFile(Bit16u entry, Bit32u* pos, Bit32u type) { Bit32u handle = RealHandle(entry); if (handle >= DOS_FILES || !Files[handle]) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } return Files[handle]->Seek(pos, type); }
bool DOS_ReadFile(Bit16u entry, Bit8u* data, Bit16u* amount) { Bit32u handle = RealHandle(entry); if (handle >= DOS_FILES || !Files[handle]) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } return Files[handle]->Read(data, amount); }
bool DOS_GetCurrentDir(Bit8u drive,char * const buffer) { if (drive==0) drive=DOS_GetDefaultDrive(); else drive--; if ((drive>=DOS_DRIVES) || (!Drives[drive])) { DOS_SetError(DOSERR_INVALID_DRIVE); return false; } strcpy(buffer,Drives[drive]->curdir); return true; }
bool DOS_LockFile(Bit16u entry, Bit8u mode, Bit32u pos, Bit32u size) { Bit32u handle = RealHandle(entry); if (handle >= DOS_FILES || !Files[handle]) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } return Files[handle]->LockFile(mode, pos, size); }
bool DOS_GetFileAttr(char const * const name,Bit16u * attr) { char fullname[DOS_PATHLENGTH];Bit8u drive; if (!DOS_MakeName(name,fullname,&drive)) return false; if (Drives[drive]->GetFileAttr(fullname,attr)) { return true; } else { DOS_SetError(DOSERR_FILE_NOT_FOUND); return false; } }
bool localDrive::FindNext(DOS_DTA & dta) { char * dir_ent; struct stat stat_block; char full_name[CROSS_LEN]; char dir_entcopy[CROSS_LEN]; Bit8u srch_attr;char srch_pattern[DOS_NAMELENGTH_ASCII]; Bit8u find_attr; dta.GetSearchParams(srch_attr,srch_pattern); Bit16u id = dta.GetDirID(); again: if (!dirCache.FindNext(id,dir_ent)) { DOS_SetError(DOSERR_NO_MORE_FILES); return false; } if(!WildFileCmp(dir_ent,srch_pattern)) goto again; strcpy(full_name,srchInfo[id].srch_dir); strcat(full_name,dir_ent); //GetExpandName might indirectly destroy dir_ent (by caching in a new directory //and due to its design dir_ent might be lost.) //Copying dir_ent first strcpy(dir_entcopy,dir_ent); if (stat(dirCache.GetExpandName(full_name),&stat_block)!=0) { goto again;//No symlinks and such } if(stat_block.st_mode & S_IFDIR) find_attr=DOS_ATTR_DIRECTORY; else find_attr=DOS_ATTR_ARCHIVE; if (~srch_attr & find_attr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM)) goto again; /*file is okay, setup everything to be copied in DTA Block */ char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size; if(strlen(dir_entcopy)<DOS_NAMELENGTH_ASCII){ strcpy(find_name,dir_entcopy); upcase(find_name); } find_size=(Bit32u) stat_block.st_size; struct tm *time; if((time=localtime(&stat_block.st_mtime))!=0){ find_date=DOS_PackDate((Bit16u)(time->tm_year+1900),(Bit16u)(time->tm_mon+1),(Bit16u)time->tm_mday); find_time=DOS_PackTime((Bit16u)time->tm_hour,(Bit16u)time->tm_min,(Bit16u)time->tm_sec); } else { find_time=6; find_date=4; } dta.SetResult(find_name,find_size,find_date,find_time,find_attr); return true; }
bool cdromDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { if ((flags&0xf)==OPEN_READWRITE) { flags &= ~OPEN_READWRITE; } else if ((flags&0xf)==OPEN_WRITE) { DOS_SetError(DOSERR_ACCESS_DENIED); return false; } bool retcode = localDrive::FileOpen(file,name,flags); if(retcode) (dynamic_cast<localFile*>(*file))->FlagReadOnlyMedium(); return retcode; }
bool DOS_CreateFile(char const* name, Bit16u attributes, Bit16u* entry) { if (DOS_FindDevice(name) != DOS_DEVICES) // Creating a device is the same as opening it return DOS_OpenFile(name, OPEN_READWRITE, entry); char fullname[DOS_PATHLENGTH]; Bit8u drive; if (!DOS_MakeName(name, fullname, &drive)) return false; Bit8u handle; for (handle = 0; handle < DOS_FILES; handle++) // Check for a free file handle if (!Files[handle]) break; if (handle == DOS_FILES) { DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); return false; } DOS_PSP psp(dos.psp()); // We have a position in the main table, now find one in the psp table *entry = psp.FindFreeFileEntry(); if (*entry == 0xff) { DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); return false; } if (attributes&DOS_ATTR_DIRECTORY) // Don't allow directories to be created { DOS_SetError(DOSERR_ACCESS_DENIED); return false; } if (Drives[drive]->FileCreate(&Files[handle], fullname, attributes)) { Files[handle]->SetDrive(drive); Files[handle]->AddRef(); psp.SetFileHandle(*entry, handle); return true; } DOS_SetError(PathExists(name) ? DOSERR_FILE_ALREADY_EXISTS : DOSERR_PATH_NOT_FOUND); return false; }
bool DOS_ReadFile(Bit16u entry,Bit8u * data,Bit16u * amount) { Bit32u handle=RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; if (!Files[handle] || !Files[handle]->IsOpen()) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; /* if ((Files[handle]->flags & 0x0f) == OPEN_WRITE)) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } */ Bit16u toread=*amount; bool ret=Files[handle]->Read(data,&toread); *amount=toread; return ret; }
bool DOS_WriteFile(Bit16u entry,Bit8u * data,Bit16u * amount,bool fcb) { Bit32u handle = fcb?entry:RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; if (!Files[handle] || !Files[handle]->IsOpen()) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; /* if ((Files[handle]->flags & 0x0f) == OPEN_READ)) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } */ Bit16u towrite=*amount; bool ret=Files[handle]->Write(data,&towrite); *amount=towrite; return ret; }
bool DOS_FindNext(void) { DOS_DTA dta(dos.dta()); Bit8u i = dta.GetSearchDrive(); if(i >= DOS_DRIVES || !Drives[i]) { /* Corrupt search. */ LOG(LOG_FILES,LOG_ERROR)("Corrupt search!!!!"); DOS_SetError(DOSERR_NO_MORE_FILES); return false; } if (Drives[i]->FindNext(dta)) return true; return false; }
bool DOS_ForceDuplicateEntry(Bit16u entry, Bit16u newentry) { if (entry == newentry) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } Bit8u orig = RealHandle(entry); if (orig >= DOS_FILES || !Files[orig]) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; } Bit8u newone = RealHandle(newentry); if (newone < DOS_FILES && Files[newone]) DOS_CloseFile(newentry); DOS_PSP psp(dos.psp()); Files[orig]->AddRef(); psp.SetFileHandle(newentry, orig); return true; }
bool DOS_CloseFile(Bit16u entry) { Bit32u handle=RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; if (!Files[handle]) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; if (Files[handle]->IsOpen()) { Files[handle]->Close(); } DOS_PSP psp(dos.psp()); psp.SetFileHandle(entry,0xff); if (Files[handle]->RemoveRef()<=0) { delete Files[handle]; Files[handle]=0; } return true; }
bool DOS_ChangeDir(char const * const dir) { Bit8u drive;char fulldir[DOS_PATHLENGTH]; if (!DOS_MakeName(dir,fulldir,&drive)) return false; if (Drives[drive]->TestDir(fulldir)) { strcpy(Drives[drive]->curdir,fulldir); return true; } else { DOS_SetError(DOSERR_PATH_NOT_FOUND); } return false; }
bool physfsFile::Read(Bit8u * data,Bit16u * size) { if ((this->flags & 0xf) == OPEN_WRITE) { // check if file opened in write-only mode DOS_SetError(DOSERR_ACCESS_DENIED); return false; } if (last_action==WRITE) prepareRead(); last_action=READ; PHYSFS_sint64 mysize = PHYSFS_read(fhandle,data,1,(PHYSFS_uint32)*size); //LOG_MSG("Read %i bytes (wanted %i) at %i of %s (%s)",(int)mysize,(int)*size,(int)PHYSFS_tell(fhandle),name,PHYSFS_getLastError()); *size = (Bit16u)mysize; return true; }
bool DOS_RemoveDir(char const * const dir) { /* We need to do the test before the removal as can not rely on * the host to forbid removal of the current directory. * We never change directory. Everything happens in the drives. */ Bit8u drive; const char *testdir = dir; if (*testdir && testdir[1] == ':') { drive = (*testdir | 0x20)-'a'; if (drive >= DOS_DRIVES || !Drives[drive]) { DOS_SetError(DOSERR_INVALID_DRIVE); return false; } testdir += 2; } size_t len = strlen(testdir); char fulldir[DOS_PATHLENGTH]; if (!len || !DOS_MakeName(dir, fulldir, &drive) || (*fulldir && testdir[len-1] == '\\')) { DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; } if (!Drives[drive]->TestDir(fulldir)) // Check if exists { DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; } if (strcmp(Drives[drive]->curdir, fulldir) == 0) // Test if it's current directory { DOS_SetError(DOSERR_REMOVE_CURRENT_DIRECTORY); return false; } if (Drives[drive]->RemoveDir(fulldir)) return true; DOS_SetError(DOSERR_ACCESS_DENIED); // Failed. We know it exists and it's not the current dir assume non empty return false; }
bool fatFile::Read(Bit8u * data, Bit16u *size) { if ((this->flags & 0xf) == OPEN_WRITE) { // check if file opened in write-only mode DOS_SetError(DOSERR_ACCESS_DENIED); return false; } Bit16u sizedec, sizecount; if(seekpos >= filelength) { *size = 0; return true; } if (!loadedSector) { currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); if(currentSector == 0) { /* EOC reached before EOF */ *size = 0; loadedSector = false; return true; } curSectOff = 0; myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); loadedSector = true; } sizedec = *size; sizecount = 0; while(sizedec != 0) { if(seekpos >= filelength) { *size = sizecount; return true; } data[sizecount++] = sectorBuffer[curSectOff++]; seekpos++; if(curSectOff >= myDrive->getSectorSize()) { currentSector = myDrive->getAbsoluteSectFromBytePos(firstCluster, seekpos); if(currentSector == 0) { /* EOC reached before EOF */ //LOG_MSG("EOC reached before EOF, seekpos %d, filelen %d", seekpos, filelength); *size = sizecount; loadedSector = false; return true; } curSectOff = 0; myDrive->loadedDisk->Read_AbsoluteSector(currentSector, sectorBuffer); loadedSector = true; //LOG_MSG("Reading absolute sector at %d for seekpos %d", currentSector, seekpos); } --sizedec; } *size =sizecount; return true; }
bool DOS_OpenFileExtended(char const* name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u* entry, Bit16u* status) { // FIXME: Not yet supported : Bit 13 of flags (int 0x24 on critical error) Bit16u result = 0; if (action == 0 || action&0xffec) { DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID); return false; } if (DOS_OpenFile(name, (Bit8u)(flags&0xff), entry)) // File already exists { switch (action & 0x0f) { case 0: // Failed DOS_CloseFile(*entry); DOS_SetError(DOSERR_FILE_ALREADY_EXISTS); return false; case 1: // File open (already done) result = 1; break; case 2: // Replace DOS_CloseFile(*entry); if (!DOS_CreateFile(name, createAttr, entry)) return false; result = 3; break; } } else // File doesn't exist { if ((action & 0xf0) == 0) return false; // Uses error code from failed open if (!DOS_CreateFile(name, createAttr, entry)) // Create File return false; // Uses error code from failed create result = 2; } *status = result; // Success return true; }
bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters) { if (!drive) drive = DOS_GetDefaultDrive(); else drive--; if (drive >= DOS_DRIVES || !Drives[drive]) { DOS_SetError(DOSERR_INVALID_DRIVE); return false; } Bit16u _free_clusters; Drives[drive]->AllocationInfo(_bytes_sector,_sectors_cluster,_total_clusters,&_free_clusters); SegSet16(ds,RealSeg(dos.tables.mediaid)); reg_bx=RealOff(dos.tables.mediaid+drive*2); return true; }
bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { const char* type; switch (flags&0xf) { case OPEN_READ: type = "rb" ; break; case OPEN_WRITE: type = "rb+"; break; case OPEN_READWRITE: type = "rb+"; break; case OPEN_READ_NO_MOD: type = "rb" ; break; //No modification of dates. LORD4.07 uses this default: DOS_SetError(DOSERR_ACCESS_CODE_INVALID); return false; } char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); //Flush the buffer of handles for the same file. (Betrayal in Antara) Bit8u i,drive=DOS_DRIVES; localFile *lfp; for (i=0;i<DOS_DRIVES;i++) { if (Drives[i]==this) { drive=i; break; } } for (i=0;i<DOS_FILES;i++) { if (Files[i] && Files[i]->IsOpen() && Files[i]->GetDrive()==drive && Files[i]->IsName(name)) { lfp=dynamic_cast<localFile*>(Files[i]); if (lfp) lfp->Flush(); } } FILE * hand=fopen(newname,type); // Bit32u err=errno; if (!hand) { if((flags&0xf) != OPEN_READ) { FILE * hmm=fopen(newname,"rb"); if (hmm) { fclose(hmm); LOG_MSG("Warning: file %s exists and failed to open in write mode.\nPlease Remove write-protection",newname); } } return false; } *file=new localFile(name,hand); (*file)->flags=flags; //for the inheritance flag and maybe check for others. // (*file)->SetFileName(newname); return true; }
bool DOS_SetFileAttr(char const * const name,Bit16u /*attr*/) // this function does not change the file attributs // it just does some tests if file is available // returns false when using on cdrom (stonekeep) { Bit16u attrTemp; char fullname[DOS_PATHLENGTH];Bit8u drive; if (!DOS_MakeName(name,fullname,&drive)) return false; if (strncmp(Drives[drive]->GetInfo(),"CDRom ",6)==0 || strncmp(Drives[drive]->GetInfo(),"isoDrive ",9)==0) { DOS_SetError(DOSERR_ACCESS_DENIED); return false; } return Drives[drive]->GetFileAttr(fullname,&attrTemp); }
bool DOS_ChangeDir(char const * const dir) { Bit8u drive;char fulldir[DOS_PATHLENGTH]; const char * testdir=dir; if (strlen(testdir) && testdir[1]==':') testdir+=2; size_t len=strlen(testdir); if (!len) { DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; } if (!DOS_MakeName(dir,fulldir,&drive)) return false; if (strlen(fulldir) && testdir[len-1]=='\\') { DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; } if (Drives[drive]->TestDir(fulldir)) { strcpy(Drives[drive]->curdir,fulldir); return true; } else { DOS_SetError(DOSERR_PATH_NOT_FOUND); } return false; }