DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/dos/drive_virtual.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  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
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "cross.h"
00028 
00029 struct VFILE_Block {
00030         const char * name;
00031         Bit8u * data;
00032         Bit32u size;
00033         Bit16u date;
00034         Bit16u time;
00035         VFILE_Block * next;
00036 };
00037 
00038 
00039 static VFILE_Block * first_file;        
00040 
00041 void VFILE_Shutdown(void) {
00042         LOG(LOG_MISC,LOG_DEBUG)("Shutting down VFILE system");
00043 
00044         while (first_file != NULL) {
00045                 VFILE_Block *n = first_file->next;
00046                 delete first_file;
00047                 first_file = n;
00048         }
00049 }
00050 
00051 void VFILE_RegisterBuiltinFileBlob(const struct BuiltinFileBlob &b) {
00052         VFILE_Register(b.recommended_file_name, (Bit8u*)b.data, (Bit32u)b.length);
00053 }
00054 
00055 void VFILE_Register(const char * name,Bit8u * data,Bit32u size) {
00056         VFILE_Block * new_file=new VFILE_Block;
00057         new_file->name=name;
00058         new_file->data=data;
00059         new_file->size=size;
00060         new_file->date=DOS_PackDate(2002,10,1);
00061         new_file->time=DOS_PackTime(12,34,56);
00062         new_file->next=first_file;
00063         first_file=new_file;
00064 }
00065 
00066 void VFILE_Remove(const char *name) {
00067         VFILE_Block * chan=first_file;
00068         VFILE_Block * * where=&first_file;
00069         while (chan) {
00070                 if (strcmp(name,chan->name) == 0) {
00071                         *where = chan->next;
00072                         if(chan == first_file) first_file = chan->next;
00073                         delete chan;
00074                         return;
00075                 }
00076                 where=&chan->next;
00077                 chan=chan->next;
00078         }
00079 }
00080 
00081 class Virtual_File : public DOS_File {
00082 public:
00083         Virtual_File(Bit8u * in_data,Bit32u in_size);
00084         bool Read(Bit8u * data,Bit16u * size);
00085         bool Write(const Bit8u * data,Bit16u * size);
00086         bool Seek(Bit32u * pos,Bit32u type);
00087         bool Close();
00088         Bit16u GetInformation(void);
00089 private:
00090         Bit32u file_size;
00091         Bit32u file_pos;
00092         Bit8u * file_data;
00093 };
00094 
00095 
00096 Virtual_File::Virtual_File(Bit8u * in_data,Bit32u in_size) {
00097         file_size=in_size;
00098         file_data=in_data;
00099         file_pos=0;
00100         date=DOS_PackDate(2002,10,1);
00101         time=DOS_PackTime(12,34,56);
00102         open=true;
00103 }
00104 
00105 bool Virtual_File::Read(Bit8u * data,Bit16u * size) {
00106         Bit32u left=file_size-file_pos;
00107         if (left<=*size) { 
00108                 memcpy(data,&file_data[file_pos],left);
00109                 *size=(Bit16u)left;
00110         } else {
00111                 memcpy(data,&file_data[file_pos],*size);
00112         }
00113         file_pos+=*size;
00114         return true;
00115 }
00116 
00117 bool Virtual_File::Write(const Bit8u * data,Bit16u * size){
00118     (void)data;//UNUSED
00119     (void)size;//UNUSED
00120         /* Not really writable */
00121         return false;
00122 }
00123 
00124 bool Virtual_File::Seek(Bit32u * new_pos,Bit32u type){
00125         switch (type) {
00126         case DOS_SEEK_SET:
00127                 if (*new_pos<=file_size) file_pos=*new_pos;
00128                 else return false;
00129                 break;
00130         case DOS_SEEK_CUR:
00131                 if ((*new_pos+file_pos)<=file_size) file_pos=*new_pos+file_pos;
00132                 else return false;
00133                 break;
00134         case DOS_SEEK_END:
00135                 if (*new_pos<=file_size) file_pos=file_size-*new_pos;
00136                 else return false;
00137                 break;
00138         }
00139         *new_pos=file_pos;
00140         return true;
00141 }
00142 
00143 bool Virtual_File::Close(){
00144         return true;
00145 }
00146 
00147 
00148 Bit16u Virtual_File::GetInformation(void) {
00149         return 0x40;    // read-only drive
00150 }
00151 
00152 
00153 Virtual_Drive::Virtual_Drive() {
00154         strcpy(info,"Internal Virtual Drive");
00155         search_file=0;
00156 }
00157 
00158 
00159 bool Virtual_Drive::FileOpen(DOS_File * * file,const char * name,Bit32u flags) {
00160 /* Scan through the internal list of files */
00161         VFILE_Block * cur_file=first_file;
00162         while (cur_file) {
00163                 if (strcasecmp(name,cur_file->name)==0) {
00164                 /* We have a match */
00165                         *file=new Virtual_File(cur_file->data,cur_file->size);
00166                         (*file)->flags=flags;
00167                         return true;
00168                 }
00169                 cur_file=cur_file->next;
00170         }
00171         return false;
00172 }
00173 
00174 bool Virtual_Drive::FileCreate(DOS_File * * file,const char * name,Bit16u attributes) {
00175     (void)file;//UNUSED
00176     (void)name;//UNUSED
00177     (void)attributes;//UNUSED
00178         return false;
00179 }
00180 
00181 bool Virtual_Drive::FileUnlink(const char * name) {
00182     (void)name;//UNUSED
00183         return false;
00184 }
00185 
00186 bool Virtual_Drive::RemoveDir(const char * dir) {
00187     (void)dir;//UNUSED
00188         return false;
00189 }
00190 
00191 bool Virtual_Drive::MakeDir(const char * dir) {
00192     (void)dir;//UNUSED
00193         return false;
00194 }
00195 
00196 bool Virtual_Drive::TestDir(const char * dir) {
00197         if (!dir[0]) return true;               //only valid dir is the empty dir
00198         return false;
00199 }
00200 
00201 bool Virtual_Drive::FileStat(const char* name, FileStat_Block * const stat_block){
00202         VFILE_Block * cur_file=first_file;
00203         while (cur_file) {
00204                 if (strcasecmp(name,cur_file->name)==0) {
00205                         stat_block->attr=DOS_ATTR_ARCHIVE;
00206                         stat_block->size=cur_file->size;
00207                         stat_block->date=DOS_PackDate(2002,10,1);
00208                         stat_block->time=DOS_PackTime(12,34,56);
00209                         return true;
00210                 }
00211                 cur_file=cur_file->next;
00212         }
00213         return false;
00214 }
00215 
00216 bool Virtual_Drive::FileExists(const char* name){
00217         VFILE_Block * cur_file=first_file;
00218         while (cur_file) {
00219                 if (strcasecmp(name,cur_file->name)==0) return true;
00220                 cur_file=cur_file->next;
00221         }
00222         return false;
00223 }
00224 
00225 bool Virtual_Drive::FindFirst(const char * _dir,DOS_DTA & dta,bool fcb_findfirst) {
00226     (void)_dir;//UNUSED
00227         search_file=first_file;
00228         Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII];
00229         dta.GetSearchParams(attr,pattern);
00230         if (attr == DOS_ATTR_VOLUME) {
00231                 dta.SetResult("DOSBOX",0,0,0,DOS_ATTR_VOLUME);
00232                 return true;
00233         } else if ((attr & DOS_ATTR_VOLUME) && !fcb_findfirst) {
00234                 if (WildFileCmp("DOSBOX",pattern)) {
00235                         dta.SetResult("DOSBOX",0,0,0,DOS_ATTR_VOLUME);
00236                         return true;
00237                 }
00238         }
00239         return FindNext(dta);
00240 }
00241 
00242 bool Virtual_Drive::FindNext(DOS_DTA & dta) {
00243         Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII];
00244         dta.GetSearchParams(attr,pattern);
00245         while (search_file) {
00246                 if (WildFileCmp(search_file->name,pattern)) {
00247                         dta.SetResult(search_file->name,search_file->size,search_file->date,search_file->time,DOS_ATTR_ARCHIVE);
00248                         search_file=search_file->next;
00249                         return true;
00250                 }
00251                 search_file=search_file->next;
00252         }
00253         DOS_SetError(DOSERR_NO_MORE_FILES);
00254         return false;
00255 }
00256 
00257 bool Virtual_Drive::GetFileAttr(const char * name,Bit16u * attr) {
00258         VFILE_Block * cur_file=first_file;
00259         while (cur_file) {
00260                 if (strcasecmp(name,cur_file->name)==0) { 
00261                         *attr = DOS_ATTR_ARCHIVE;       //Maybe readonly ?
00262                         return true;
00263                 }
00264                 cur_file=cur_file->next;
00265         }
00266         return false;
00267 }
00268 
00269 bool Virtual_Drive::Rename(const char * oldname,const char * newname) {
00270     (void)oldname;//UNUSED
00271     (void)newname;//UNUSED
00272         return false;
00273 }
00274 
00275 bool Virtual_Drive::AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters) {
00276         *_bytes_sector=512;
00277         *_sectors_cluster=32;
00278         *_total_clusters=32765; // total size is always 500 mb
00279         *_free_clusters=0;              // nothing free here
00280         return true;
00281 }
00282 
00283 Bit8u Virtual_Drive::GetMediaByte(void) {
00284         return 0xF8;
00285 }
00286 
00287 bool Virtual_Drive::isRemote(void) {
00288         return false;
00289 }
00290 
00291 bool Virtual_Drive::isRemovable(void) {
00292         return false;
00293 }
00294 
00295 Bits Virtual_Drive::UnMount(void) {
00296         return 1;
00297 }
00298