DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include <stdio.h> 00020 #include <stdlib.h> 00021 #include <string.h> 00022 #include <time.h> 00023 #include "dosbox.h" 00024 #include "dos_inc.h" 00025 #include "drives.h" 00026 #include "support.h" 00027 #include "control.h" 00028 #include "cross.h" 00029 #include "regs.h" 00030 00031 struct VFILE_Block { 00032 const char * name; 00033 const char * lname; 00034 Bit8u * data; 00035 Bit32u size; 00036 Bit16u date; 00037 Bit16u time; 00038 VFILE_Block * next; 00039 }; 00040 00041 extern int lfn_filefind_handle; 00042 static VFILE_Block * first_file, * lfn_search[256]; 00043 00044 void VFILE_Shutdown(void) { 00045 LOG(LOG_MISC,LOG_DEBUG)("Shutting down VFILE system"); 00046 00047 while (first_file != NULL) { 00048 VFILE_Block *n = first_file->next; 00049 delete first_file; 00050 first_file = n; 00051 } 00052 } 00053 00054 void VFILE_RegisterBuiltinFileBlob(const struct BuiltinFileBlob &b) { 00055 VFILE_Register(b.recommended_file_name, (Bit8u*)b.data, (Bit32u)b.length); 00056 } 00057 00058 void VFILE_Register(const char * name,Bit8u * data,Bit32u size) { 00059 VFILE_Block * new_file=new VFILE_Block; 00060 new_file->name=name; 00061 new_file->lname=name; 00062 new_file->data=data; 00063 new_file->size=size; 00064 new_file->date=DOS_PackDate(2002,10,1); 00065 new_file->time=DOS_PackTime(12,34,56); 00066 new_file->next=first_file; 00067 first_file=new_file; 00068 } 00069 00070 void VFILE_Remove(const char *name) { 00071 VFILE_Block * chan=first_file; 00072 VFILE_Block * * where=&first_file; 00073 while (chan) { 00074 if (strcmp(name,chan->name) == 0) { 00075 *where = chan->next; 00076 if(chan == first_file) first_file = chan->next; 00077 delete chan; 00078 return; 00079 } 00080 where=&chan->next; 00081 chan=chan->next; 00082 } 00083 } 00084 00085 class Virtual_File : public DOS_File { 00086 public: 00087 Virtual_File(Bit8u * in_data,Bit32u in_size); 00088 bool Read(Bit8u * data,Bit16u * size); 00089 bool Write(const Bit8u * data,Bit16u * size); 00090 bool Seek(Bit32u * new_pos,Bit32u type); 00091 bool Close(); 00092 Bit16u GetInformation(void); 00093 private: 00094 Bit32u file_size; 00095 Bit32u file_pos = 0; 00096 Bit8u * file_data; 00097 }; 00098 00099 00100 Virtual_File::Virtual_File(Bit8u* in_data, Bit32u in_size) : file_size(in_size), file_data(in_data) { 00101 date=DOS_PackDate(2002,10,1); 00102 time=DOS_PackTime(12,34,56); 00103 open=true; 00104 } 00105 00106 bool Virtual_File::Read(Bit8u * data,Bit16u * size) { 00107 Bit32u left=file_size-file_pos; 00108 if (left<=*size) { 00109 memcpy(data,&file_data[file_pos],left); 00110 *size=(Bit16u)left; 00111 } else { 00112 memcpy(data,&file_data[file_pos],*size); 00113 } 00114 file_pos+=*size; 00115 return true; 00116 } 00117 00118 bool Virtual_File::Write(const Bit8u * data,Bit16u * size){ 00119 (void)data;//UNUSED 00120 (void)size;//UNUSED 00121 /* Not really writable */ 00122 return false; 00123 } 00124 00125 bool Virtual_File::Seek(Bit32u * new_pos,Bit32u type){ 00126 switch (type) { 00127 case DOS_SEEK_SET: 00128 if (*new_pos<=file_size) file_pos=*new_pos; 00129 else return false; 00130 break; 00131 case DOS_SEEK_CUR: 00132 if ((*new_pos+file_pos)<=file_size) file_pos=*new_pos+file_pos; 00133 else return false; 00134 break; 00135 case DOS_SEEK_END: 00136 if (*new_pos<=file_size) file_pos=file_size-*new_pos; 00137 else return false; 00138 break; 00139 } 00140 *new_pos=file_pos; 00141 return true; 00142 } 00143 00144 bool Virtual_File::Close(){ 00145 return true; 00146 } 00147 00148 00149 Bit16u Virtual_File::GetInformation(void) { 00150 return 0x40; // read-only drive 00151 } 00152 00153 00154 Virtual_Drive::Virtual_Drive() { 00155 strcpy(info,"Internal Virtual Drive"); 00156 for (int i=0; i<256; i++) lfn_search[i] = 0; 00157 } 00158 00159 00160 bool Virtual_Drive::FileOpen(DOS_File * * file,const char * name,Bit32u flags) { 00161 /* Scan through the internal list of files */ 00162 const VFILE_Block* cur_file = first_file; 00163 while (cur_file) { 00164 if (strcasecmp(name,cur_file->name)==0) { 00165 /* We have a match */ 00166 *file=new Virtual_File(cur_file->data,cur_file->size); 00167 (*file)->flags=flags; 00168 return true; 00169 } 00170 cur_file=cur_file->next; 00171 } 00172 return false; 00173 } 00174 00175 bool Virtual_Drive::FileCreate(DOS_File * * file,const char * name,Bit16u attributes) { 00176 (void)file;//UNUSED 00177 (void)name;//UNUSED 00178 (void)attributes;//UNUSED 00179 return false; 00180 } 00181 00182 bool Virtual_Drive::FileUnlink(const char * name) { 00183 const VFILE_Block* cur_file = first_file; 00184 while (cur_file) { 00185 if (strcasecmp(name,cur_file->name)==0) { 00186 DOS_SetError(DOSERR_ACCESS_DENIED); 00187 return false; 00188 } 00189 cur_file=cur_file->next; 00190 } 00191 return false; 00192 } 00193 00194 bool Virtual_Drive::RemoveDir(const char * dir) { 00195 (void)dir;//UNUSED 00196 return false; 00197 } 00198 00199 bool Virtual_Drive::MakeDir(const char * dir) { 00200 (void)dir;//UNUSED 00201 return false; 00202 } 00203 00204 bool Virtual_Drive::TestDir(const char * dir) { 00205 if (!dir[0]) return true; //only valid dir is the empty dir 00206 return false; 00207 } 00208 00209 bool Virtual_Drive::FileStat(const char* name, FileStat_Block * const stat_block){ 00210 const VFILE_Block* cur_file = first_file; 00211 while (cur_file) { 00212 if (strcasecmp(name,cur_file->name)==0) { 00213 stat_block->attr=DOS_ATTR_ARCHIVE; 00214 stat_block->size=cur_file->size; 00215 stat_block->date=DOS_PackDate(2002,10,1); 00216 stat_block->time=DOS_PackTime(12,34,56); 00217 return true; 00218 } 00219 cur_file=cur_file->next; 00220 } 00221 return false; 00222 } 00223 00224 bool Virtual_Drive::FileExists(const char* name){ 00225 const VFILE_Block* cur_file = first_file; 00226 while (cur_file) { 00227 if (strcasecmp(name,cur_file->name)==0) return true; 00228 cur_file=cur_file->next; 00229 } 00230 return false; 00231 } 00232 00233 bool Virtual_Drive::FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst) { 00234 (void)_dir;//UNUSED 00235 if (lfn_filefind_handle>=LFN_FILEFIND_MAX) 00236 search_file=first_file; 00237 else 00238 lfn_search[lfn_filefind_handle]=first_file; 00239 Bit8u attr;char pattern[CROSS_LEN]; 00240 dta.GetSearchParams(attr,pattern,uselfn); 00241 if (attr == DOS_ATTR_VOLUME) { 00242 dta.SetResult(GetLabel(),GetLabel(),0,0,0,DOS_ATTR_VOLUME); 00243 return true; 00244 } else if ((attr & DOS_ATTR_VOLUME) && !fcb_findfirst) { 00245 if (WildFileCmp(GetLabel(),pattern)) { 00246 dta.SetResult(GetLabel(),GetLabel(),0,0,0,DOS_ATTR_VOLUME); 00247 return true; 00248 } 00249 } 00250 return FindNext(dta); 00251 } 00252 00253 bool Virtual_Drive::FindNext(DOS_DTA & dta) { Bit8u attr;char pattern[CROSS_LEN]; 00254 dta.GetSearchParams(attr,pattern,uselfn); 00255 if (lfn_filefind_handle>=LFN_FILEFIND_MAX) 00256 while (search_file) { 00257 if (WildFileCmp(search_file->name,pattern)) { 00258 dta.SetResult(search_file->name,search_file->lname,search_file->size,search_file->date,search_file->time,DOS_ATTR_ARCHIVE); 00259 search_file=search_file->next; 00260 return true; 00261 } 00262 search_file=search_file->next; 00263 } 00264 else 00265 while (lfn_search[lfn_filefind_handle]) { 00266 if (WildFileCmp(lfn_search[lfn_filefind_handle]->name,pattern)) { 00267 dta.SetResult(lfn_search[lfn_filefind_handle]->name,lfn_search[lfn_filefind_handle]->lname,lfn_search[lfn_filefind_handle]->size,lfn_search[lfn_filefind_handle]->date,lfn_search[lfn_filefind_handle]->time,DOS_ATTR_ARCHIVE); 00268 lfn_search[lfn_filefind_handle]=lfn_search[lfn_filefind_handle]->next; 00269 return true; 00270 } 00271 lfn_search[lfn_filefind_handle]=lfn_search[lfn_filefind_handle]->next; 00272 } 00273 DOS_SetError(DOSERR_NO_MORE_FILES); 00274 return false; 00275 } 00276 00277 bool Virtual_Drive::SetFileAttr(const char * name,Bit16u attr) { 00278 (void)name; 00279 (void)attr; 00280 return false; 00281 } 00282 00283 bool Virtual_Drive::GetFileAttr(const char * name,Bit16u * attr) { 00284 const VFILE_Block* cur_file = first_file; 00285 while (cur_file) { 00286 if (strcasecmp(name,cur_file->name)==0) { 00287 *attr = DOS_ATTR_ARCHIVE; //Maybe readonly ? 00288 return true; 00289 } 00290 cur_file=cur_file->next; 00291 } 00292 return false; 00293 } 00294 00295 bool Virtual_Drive::GetFileAttrEx(char* name, struct stat *status) { 00296 (void)name; 00297 (void)status; 00298 return false; 00299 } 00300 00301 unsigned long Virtual_Drive::GetCompressedSize(char* name) { 00302 (void)name; 00303 return 0; 00304 } 00305 00306 #if defined (WIN32) 00307 HANDLE Virtual_Drive::CreateOpenFile(const char* name) { 00308 (void)name; 00309 DOS_SetError(1); 00310 return INVALID_HANDLE_VALUE; 00311 } 00312 #endif 00313 00314 bool Virtual_Drive::Rename(const char * oldname,const char * newname) { 00315 (void)newname;//UNUSED 00316 const VFILE_Block* cur_file = first_file; 00317 while (cur_file) { 00318 if (strcasecmp(oldname,cur_file->name)==0) { 00319 DOS_SetError(DOSERR_ACCESS_DENIED); 00320 return false; 00321 } 00322 cur_file=cur_file->next; 00323 } 00324 return false; 00325 } 00326 00327 bool Virtual_Drive::AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters) { 00328 *_bytes_sector=512; 00329 *_sectors_cluster=32; 00330 *_total_clusters=32765; // total size is always 500 mb 00331 *_free_clusters=0; // nothing free here 00332 return true; 00333 } 00334 00335 Bit8u Virtual_Drive::GetMediaByte(void) { 00336 return 0xF8; 00337 } 00338 00339 bool Virtual_Drive::isRemote(void) { 00340 const Section_prop * section=static_cast<Section_prop *>(control->GetSection("dos")); 00341 const char * opt = section->Get_string("drive z is remote"); 00342 00343 if (!strcmp(opt,"1") || !strcmp(opt,"true")) { 00344 return true; 00345 } 00346 else if (!strcmp(opt,"0") || !strcmp(opt,"false")) { 00347 return false; 00348 } 00349 char psp_name[9]; 00350 DOS_MCB psp_mcb(dos.psp()-1); 00351 psp_mcb.GetFileName(psp_name); 00352 if (strcmp(psp_name, "SCANDISK") == 0) { 00353 /* Check for SCANDISK.EXE and return true (Wengier) */ 00354 return true; 00355 } 00356 /* Automatically detect if called by SCANDISK.EXE even if it is renamed (tested with the program from MS-DOS 6.20 to Windows ME) */ 00357 if (dos.version.major >= 5 && reg_sp >=0x4000 && mem_readw(SegPhys(ss)+reg_sp)/0x100 == 0x1 && mem_readw(SegPhys(ss)+reg_sp+2)/0x100 >= 0xB && mem_readw(SegPhys(ss)+reg_sp+2)/0x100 <= 0x12) 00358 return true; 00359 00360 return false; 00361 } 00362 00363 bool Virtual_Drive::isRemovable(void) { 00364 return false; 00365 } 00366 00367 Bits Virtual_Drive::UnMount(void) { 00368 return 1; 00369 } 00370 00371 char const* Virtual_Drive::GetLabel(void) { 00372 return "DOSBOX-X"; 00373 }