bool physfsDrive::MakeDir(const char * dir) { char newdir[CROSS_LEN]; strcpy(newdir,basedir); strcat(newdir,dir); CROSS_FILENAME(newdir); dirCache.ExpandName(newdir); normalize(newdir,basedir); if (PHYSFS_mkdir(newdir)) { CROSS_FILENAME(newdir); dirCache.CacheOut(newdir,true); return true; } return false; }
bool physfsDrive::FileUnlink(const char * name) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); normalize(newname,basedir); if (PHYSFS_delete(newname)) { CROSS_FILENAME(newname); dirCache.DeleteEntry(newname); return true; }; return false; }
bool physfsDrive::RemoveDir(const char * dir) { char newdir[CROSS_LEN]; strcpy(newdir,basedir); strcat(newdir,dir); CROSS_FILENAME(newdir); dirCache.ExpandName(newdir); normalize(newdir,basedir); if (PHYSFS_isDirectory(newdir) && PHYSFS_delete(newdir)) { CROSS_FILENAME(newdir); dirCache.DeleteEntry(newdir,true); return true; } return false; }
bool localDrive::FileCreate(DOS_File * * file,char * name,Bit16u /*attributes*/) { //TODO Maybe care for attributes but not likely char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); char* temp_name = dirCache.GetExpandName(newname); //Can only be used in till a new drive_cache action is preformed */ /* Test if file exists (so we need to truncate it). don't add to dirCache then */ bool existing_file=false; FILE * test=fopen(temp_name,"rb+"); if(test) { fclose(test); existing_file=true; } FILE * hand=fopen(temp_name,"wb+"); if (!hand){ LOG_MSG("Warning: file creation failed: %s",newname); return false; } if(!existing_file) dirCache.AddEntry(newname, true); /* Make the 16 bit device information */ *file=new localFile(name,hand); (*file)->flags=OPEN_READWRITE; return true; }
bool physfsDrive::FileOpen(DOS_File * * file,const char * name,Bit32u flags) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); normalize(newname,basedir); PHYSFS_file * hand; if (!PHYSFS_exists(newname)) return false; if ((flags&0xf) == OPEN_READ) { hand = PHYSFS_openRead(newname); } else { /* open for reading, deal with writing later */ hand = PHYSFS_openRead(newname); } if (!hand) { if((flags&0xf) != OPEN_READ) { PHYSFS_file *hmm = PHYSFS_openRead(newname); if (hmm) { PHYSFS_close(hmm); LOG_MSG("Warning: file %s exists and failed to open in write mode.\nPlease mount a write directory (see docs).",newname); } } return false; } *file=new physfsFile(name,hand,0x202,newname,false); (*file)->flags=flags; //for the inheritance flag and maybe check for others. return true; }
bool localDrive::Rename(char * oldname,char * newname) { char newold[CROSS_LEN]; strcpy(newold,basedir); strcat(newold,oldname); CROSS_FILENAME(newold); dirCache.ExpandName(newold); char newnew[CROSS_LEN]; strcpy(newnew,basedir); strcat(newnew,newname); CROSS_FILENAME(newnew); int temp=rename(newold,dirCache.GetExpandName(newnew)); if (temp==0) dirCache.CacheOut(newnew); return (temp==0); }
bool localDrive::GetSystemFilename(char *sysName, char const * const dosName) { strcpy(sysName, basedir); strcat(sysName, dosName); CROSS_FILENAME(sysName); dirCache.ExpandName(sysName); return true; }
physfsDrive::physfsDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid) :localDrive(startdir,_bytes_sector,_sectors_cluster,_total_clusters,_free_clusters,_mediaid) { char newname[CROSS_LEN+1]; /* No writedir given, use capture directory */ if(startdir[0] == ':') { strcpy(newname,capturedir.c_str()); strcat(newname,startdir); } else { strcpy(newname,startdir); } CROSS_FILENAME(newname); if (!physfs_used) { PHYSFS_init(""); PHYSFS_permitSymbolicLinks(1); } physfs_used++; char *lastdir = newname; char *dir = strchr(lastdir+(((lastdir[0]|0x20) >= 'a' && (lastdir[0]|0x20) <= 'z')?2:0),':'); while (dir) { *dir++ = 0; if((lastdir == newname) && !strchr(dir+(((dir[0]|0x20) >= 'a' && (dir[0]|0x20) <= 'z')?2:0),':')) { // If the first parameter is a directory, the next one has to be the archive file, // do not confuse it with basedir if trailing : is not there! int tmp = strlen(dir)-1; dir[tmp++] = ':'; dir[tmp++] = CROSS_FILESPLIT; dir[tmp] = '\0'; } if (*lastdir && PHYSFS_addToSearchPath(lastdir,true) == 0) { LOG_MSG("PHYSFS couldn't add '%s': %s",lastdir,PHYSFS_getLastError()); } lastdir = dir; dir = strchr(lastdir+(((lastdir[0]|0x20) >= 'a' && (lastdir[0]|0x20) <= 'z')?2:0),':'); } const char *oldwrite = PHYSFS_getWriteDir(); if (oldwrite) oldwrite = strdup(oldwrite); if (!PHYSFS_setWriteDir(newname)) { if (!oldwrite) LOG_MSG("PHYSFS can't use '%s' for writing, you might encounter problems",newname); else PHYSFS_setWriteDir(oldwrite); } if (oldwrite) free((char *)oldwrite); strcpy(basedir,lastdir); allocation.bytes_sector=_bytes_sector; allocation.sectors_cluster=_sectors_cluster; allocation.total_clusters=_total_clusters; allocation.free_clusters=_free_clusters; allocation.mediaid=_mediaid; dirCache.SetBaseDir(basedir, this); }
bool physfsDrive::TestDir(const char * dir) { char newdir[CROSS_LEN]; strcpy(newdir,basedir); strcat(newdir,dir); CROSS_FILENAME(newdir); dirCache.ExpandName(newdir); normalize(newdir,basedir); return (PHYSFS_isDirectory(newdir)); }
bool localDrive::RemoveDir(char * dir) { char newdir[CROSS_LEN]; strcpy(newdir,basedir); strcat(newdir,dir); CROSS_FILENAME(newdir); int temp=rmdir(dirCache.GetExpandName(newdir)); if (temp==0) dirCache.DeleteEntry(newdir,true); return (temp==0); }
bool physfsDrive::FileExists(const char* name) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); normalize(newname,basedir); return PHYSFS_exists(newname) && !PHYSFS_isDirectory(newname); }
bool physfsDrive::Rename(const char * oldname,const char * newname) { char newold[CROSS_LEN]; strcpy(newold,basedir); strcat(newold,oldname); CROSS_FILENAME(newold); dirCache.ExpandName(newold); normalize(newold,basedir); char newnew[CROSS_LEN]; strcpy(newnew,basedir); strcat(newnew,newname); CROSS_FILENAME(newnew); dirCache.ExpandName(newnew); normalize(newnew,basedir); /* yuck. physfs doesn't have "rename". */ LOG_MSG("PHYSFS TODO: rename not yet implemented (%s -> %s)",newold,newnew); return false; }
FILE * localDrive::GetSystemFilePtr(char const * const name, char const * const type) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); return fopen(newname,type); }
bool localDrive::FileExists(const char* name) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); FILE* Temp=fopen(newname,"rb"); if(Temp==NULL) return false; fclose(Temp); return true; }
bool localDrive::FileExists(const char* name) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); struct stat temp_stat; if(stat(newname,&temp_stat)!=0) return false; if(temp_stat.st_mode & S_IFDIR) return false; return true; }
bool localDrive::FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst) { char tempDir[CROSS_LEN]; strcpy(tempDir,basedir); strcat(tempDir,_dir); CROSS_FILENAME(tempDir); if (allocation.mediaid==0xF0 ) { EmptyCache(); //rescan floppie-content on each findfirst } char end[2]={CROSS_FILESPLIT,0}; if (tempDir[strlen(tempDir)-1]!=CROSS_FILESPLIT) strcat(tempDir,end); Bit16u id; if (!dirCache.FindFirst(tempDir,id)) { DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; } strcpy(srchInfo[id].srch_dir,tempDir); dta.SetDirID(id); Bit8u sAttr; dta.GetSearchParams(sAttr,tempDir); if (this->isRemote() && this->isRemovable()) { // cdroms behave a bit different than regular drives if (sAttr == DOS_ATTR_VOLUME) { dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); return true; } } else { if (sAttr == DOS_ATTR_VOLUME) { if ( strcmp(dirCache.GetLabel(), "") == 0 ) { // LOG(LOG_DOSMISC,LOG_ERROR)("DRIVELABEL REQUESTED: none present, returned NOLABEL"); // dta.SetResult("NO_LABEL",0,0,0,DOS_ATTR_VOLUME); // return true; DOS_SetError(DOSERR_NO_MORE_FILES); return false; } dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); return true; } else if ((sAttr & DOS_ATTR_VOLUME) && (*_dir == 0) && !fcb_findfirst) { //should check for a valid leading directory instead of 0 //exists==true if the volume label matches the searchmask and the path is valid if (WildFileCmp(dirCache.GetLabel(),tempDir)) { dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); return true; } } } return FindNext(dta); }
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 localDrive::MakeDir(char * dir) { char newdir[CROSS_LEN]; strcpy(newdir,basedir); strcat(newdir,dir); CROSS_FILENAME(newdir); #if defined (WIN32) /* MS Visual C++ */ int temp=mkdir(dirCache.GetExpandName(newdir)); #else int temp=mkdir(dirCache.GetExpandName(newdir),0700); #endif if (temp==0) dirCache.CacheOut(newdir,true); return (temp==0);// || ((temp!=0) && (errno==EEXIST)); }
bool physfsDrive::FileCreate(DOS_File * * file,const char * name,Bit16u attributes) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); normalize(newname,basedir); /* Test if file exists, don't add to dirCache then */ bool existing_file=PHYSFS_exists(newname); char *slash = strrchr(newname,'/'); if (slash && slash != newname) { *slash = 0; if (!PHYSFS_isDirectory(newname)) return false; PHYSFS_mkdir(newname); *slash = '/'; } PHYSFS_file * hand=PHYSFS_openWrite(newname); if (!hand){ LOG_MSG("Warning: file creation failed: %s (%s)",newname,PHYSFS_getLastError()); return false; } /* Make the 16 bit device information */ *file=new physfsFile(name,hand,0x202,newname,true); (*file)->flags=OPEN_READWRITE; if(!existing_file) { strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.AddEntry(newname, true); } return true; }
bool localDrive::GetFileAttr(char * name,Bit16u * attr) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); struct stat status; if (stat(newname,&status)==0) { *attr=DOS_ATTR_ARCHIVE; if(status.st_mode & S_IFDIR) *attr|=DOS_ATTR_DIRECTORY; return true; } *attr=0; return false; }
bool physfsDrive::GetFileAttr(const char * name,Bit16u * attr) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); normalize(newname,basedir); char *last = strrchr(newname,'/'); if (last == NULL) last = newname-1; *attr = 0; if (!PHYSFS_exists(newname)) return false; *attr=DOS_ATTR_ARCHIVE; if (PHYSFS_isDirectory(newname)) *attr|=DOS_ATTR_DIRECTORY; return true; }
bool localDrive::TestDir(char * dir) { char newdir[CROSS_LEN]; strcpy(newdir,basedir); strcat(newdir,dir); CROSS_FILENAME(newdir); dirCache.ExpandName(newdir); // Skip directory test, if "\" size_t len = strlen(newdir); if (len && (newdir[len-1]!='\\')) { // It has to be a directory ! struct stat test; if (stat(newdir,&test)) return false; if ((test.st_mode & S_IFDIR)==0) return false; }; int temp=access(newdir,F_OK); return (temp==0); }
bool physfsDrive::FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst) { char tempDir[CROSS_LEN]; strcpy(tempDir,basedir); strcat(tempDir,_dir); CROSS_FILENAME(tempDir); char end[2]={CROSS_FILESPLIT,0}; if (tempDir[strlen(tempDir)-1]!=CROSS_FILESPLIT) strcat(tempDir,end); Bit16u id; if (!dirCache.FindFirst(tempDir,id)) { DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; } strcpy(srchInfo[id].srch_dir,tempDir); dta.SetDirID(id); Bit8u sAttr; dta.GetSearchParams(sAttr,tempDir); if (sAttr == DOS_ATTR_VOLUME) { if ( strcmp(dirCache.GetLabel(), "") == 0 ) { LOG(LOG_DOSMISC,LOG_ERROR)("DRIVELABEL REQUESTED: none present, returned NOLABEL"); dta.SetResult("NO_LABEL",0,0,0,DOS_ATTR_VOLUME); return true; } dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); return true; } else if ((sAttr & DOS_ATTR_VOLUME) && (*_dir == 0) && !fcb_findfirst) { //should check for a valid leading directory instead of 0 //exists==true if the volume label matches the searchmask and the path is valid if ( strcmp(dirCache.GetLabel(), "") == 0 ) { LOG(LOG_DOSMISC,LOG_ERROR)("DRIVELABEL REQUESTED: none present, returned NOLABEL"); dta.SetResult("NO_LABEL",0,0,0,DOS_ATTR_VOLUME); return true; } if (WildFileCmp(dirCache.GetLabel(),tempDir)) { dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); return true; } } return FindNext(dta); }
bool localDrive::FileStat(const char* name, FileStat_Block * const stat_block) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); struct stat temp_stat; if(stat(newname,&temp_stat)!=0) return false; /* Convert the stat to a FileStat */ struct tm *time; if((time=localtime(&temp_stat.st_mtime))!=0) { stat_block->time=DOS_PackTime((Bit16u)time->tm_hour,(Bit16u)time->tm_min,(Bit16u)time->tm_sec); stat_block->date=DOS_PackDate((Bit16u)(time->tm_year+1900),(Bit16u)(time->tm_mon+1),(Bit16u)time->tm_mday); } else { } stat_block->size=(Bit32u)temp_stat.st_size; return true; }
bool physfsDrive::FileStat(const char* name, FileStat_Block * const stat_block) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); dirCache.ExpandName(newname); normalize(newname,basedir); time_t mytime = (time_t)PHYSFS_getLastModTime(newname); /* Convert the stat to a FileStat */ struct tm *time; if((time=localtime(&mytime))!=0) { stat_block->time=DOS_PackTime((Bit16u)time->tm_hour,(Bit16u)time->tm_min,(Bit16u)time->tm_sec); stat_block->date=DOS_PackDate((Bit16u)(time->tm_year+1900),(Bit16u)(time->tm_mon+1),(Bit16u)time->tm_mday); } else { stat_block->time=DOS_PackTime(0,0,0); stat_block->date=DOS_PackDate(1980,1,1); } stat_block->size=(Bit32u)PHYSFS_fileLength(newname); return true; }
bool localDrive::FileUnlink(char * name) { char newname[CROSS_LEN]; strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); char *fullname = dirCache.GetExpandName(newname); if (unlink(fullname)) { //Unlink failed for some reason try finding it. struct stat buffer; if(stat(fullname,&buffer)) return false; // File not found. FILE* file_writable = fopen(fullname,"rb+"); if(!file_writable) return false; //No acces ? ERROR MESSAGE NOT SET. FIXME ? fclose(file_writable); //File exists and can technically be deleted, nevertheless it failed. //This means that the file is probably open by some process. //See if We have it open. bool found_file = false; for(Bitu i = 0;i < DOS_FILES;i++){ if(Files[i] && Files[i]->IsName(name)) { Bitu max = DOS_FILES; while(Files[i]->IsOpen() && max--) { Files[i]->Close(); if (Files[i]->RemoveRef()<=0) break; } found_file=true; } } if(!found_file) return false; if (!unlink(fullname)) { dirCache.DeleteEntry(newname); return true; } return false; } else { dirCache.DeleteEntry(newname); return true; } }
void DOS_Shell::CMD_SUBST (char * args) { /* If more that one type can be substed think of something else * E.g. make basedir member dos_drive instead of localdrive */ HELP("SUBST"); localDrive* ldp=0; char mountstring[DOS_PATHLENGTH+CROSS_LEN+20]; char temp_str[2] = { 0,0 }; try { strcpy(mountstring,"MOUNT "); StripSpaces(args); std::string arg; CommandLine command(0,args); if (command.GetCount() != 2) throw 0 ; command.FindCommand(1,arg); if( (arg.size()>1) && arg[1] !=':') throw(0); temp_str[0]=(char)toupper(args[0]); command.FindCommand(2,arg); if((arg=="/D") || (arg=="/d")) { if(!Drives[temp_str[0]-'A'] ) throw 1; //targetdrive not in use strcat(mountstring,"-u "); strcat(mountstring,temp_str); this->ParseLine(mountstring); return; } if(Drives[temp_str[0]-'A'] ) throw 0; //targetdrive in use strcat(mountstring,temp_str); strcat(mountstring," "); Bit8u drive;char dir[DOS_PATHLENGTH+2],fulldir[DOS_PATHLENGTH]; if (strchr(arg.c_str(),'\"')==NULL) sprintf(dir,"\"%s\"",arg.c_str()); else strcpy(dir,arg.c_str()); if (!DOS_MakeName(dir,fulldir,&drive)) throw 0; if( ( ldp=dynamic_cast<localDrive*>(Drives[drive])) == 0 ) throw 0; char newname[CROSS_LEN]; strcpy(newname, ldp->basedir); strcat(newname,fulldir); CROSS_FILENAME(newname); ldp->dirCache.ExpandName(newname); strcat(mountstring,"\""); strcat(mountstring, newname); strcat(mountstring,"\""); this->ParseLine(mountstring); } catch(int a){ if(a == 0) { WriteOut(MSG_Get("SHELL_CMD_SUBST_FAILURE")); } else { WriteOut(MSG_Get("SHELL_CMD_SUBST_NO_REMOVE")); } return; } catch(...) { //dynamic cast failed =>so no localdrive WriteOut(MSG_Get("SHELL_CMD_SUBST_FAILURE")); return; } return; }