1 /*
2 * Copyright (C) 2002-2010 The DOSBox Team
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <time.h>
23 #include "dosbox.h"
24 #include "dos_inc.h"
25 #include "drives.h"
26 #include "support.h"
27 #include "cross.h"
28
29 struct VFILE_Block {
30 const char * name;
31 Bit8u * data;
32 Bit32u size;
33 Bit16u date;
34 Bit16u time;
35 VFILE_Block * next;
36 };
37
38
39 static VFILE_Block * first_file;
40
VFILE_Register(const char * name,Bit8u * data,Bit32u size)41 void VFILE_Register(const char * name,Bit8u * data,Bit32u size) {
42 VFILE_Block * new_file=new VFILE_Block;
43 new_file->name=name;
44 new_file->data=data;
45 new_file->size=size;
46 new_file->date=DOS_PackDate(2002,10,1);
47 new_file->time=DOS_PackTime(12,34,56);
48 new_file->next=first_file;
49 first_file=new_file;
50 }
51
VFILE_Remove(const char * name)52 void VFILE_Remove(const char *name) {
53 VFILE_Block * chan=first_file;
54 VFILE_Block * * where=&first_file;
55 while (chan) {
56 if (strcmp(name,chan->name) == 0) {
57 *where = chan->next;
58 if(chan == first_file) first_file = chan->next;
59 delete chan;
60 return;
61 }
62 where=&chan->next;
63 chan=chan->next;
64 }
65 }
66
67 class Virtual_File : public DOS_File {
68 public:
69 Virtual_File(Bit8u * in_data,Bit32u in_size);
70 bool Read(Bit8u * data,Bit16u * size);
71 bool Write(Bit8u * data,Bit16u * size);
72 bool Seek(Bit32u * pos,Bit32u type);
73 bool Close();
74 Bit16u GetInformation(void);
75 private:
76 Bit32u file_size;
77 Bit32u file_pos;
78 Bit8u * file_data;
79 };
80
81
Virtual_File(Bit8u * in_data,Bit32u in_size)82 Virtual_File::Virtual_File(Bit8u * in_data,Bit32u in_size) {
83 file_size=in_size;
84 file_data=in_data;
85 file_pos=0;
86 date=DOS_PackDate(2002,10,1);
87 time=DOS_PackTime(12,34,56);
88 open=true;
89 }
90
Read(Bit8u * data,Bit16u * size)91 bool Virtual_File::Read(Bit8u * data,Bit16u * size) {
92 Bit32u left=file_size-file_pos;
93 if (left<=*size) {
94 memcpy(data,&file_data[file_pos],left);
95 *size=(Bit16u)left;
96 } else {
97 memcpy(data,&file_data[file_pos],*size);
98 }
99 file_pos+=*size;
100 return true;
101 }
102
Write(Bit8u * data,Bit16u * size)103 bool Virtual_File::Write(Bit8u * data,Bit16u * size){
104 /* Not really writeable */
105 return false;
106 }
107
Seek(Bit32u * new_pos,Bit32u type)108 bool Virtual_File::Seek(Bit32u * new_pos,Bit32u type){
109 switch (type) {
110 case DOS_SEEK_SET:
111 if (*new_pos<=file_size) file_pos=*new_pos;
112 else return false;
113 break;
114 case DOS_SEEK_CUR:
115 if ((*new_pos+file_pos)<=file_size) file_pos=*new_pos+file_pos;
116 else return false;
117 break;
118 case DOS_SEEK_END:
119 if (*new_pos<=file_size) file_pos=file_size-*new_pos;
120 else return false;
121 break;
122 }
123 *new_pos=file_pos;
124 return true;
125 }
126
Close()127 bool Virtual_File::Close(){
128 return true;
129 }
130
131
GetInformation(void)132 Bit16u Virtual_File::GetInformation(void) {
133 return 0x40; // read-only drive
134 }
135
136
Virtual_Drive()137 Virtual_Drive::Virtual_Drive() {
138 strcpy(info,"Internal Virtual Drive");
139 search_file=0;
140 }
141
142
FileOpen(DOS_File ** file,char * name,Bit32u flags)143 bool Virtual_Drive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
144 /* Scan through the internal list of files */
145 VFILE_Block * cur_file=first_file;
146 while (cur_file) {
147 if (strcasecmp(name,cur_file->name)==0) {
148 /* We have a match */
149 *file=new Virtual_File(cur_file->data,cur_file->size);
150 (*file)->flags=flags;
151 return true;
152 }
153 cur_file=cur_file->next;
154 }
155 return false;
156 }
157
FileCreate(DOS_File ** file,char * name,Bit16u attributes)158 bool Virtual_Drive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) {
159 return false;
160 }
161
FileUnlink(char * name)162 bool Virtual_Drive::FileUnlink(char * name) {
163 return false;
164 }
165
RemoveDir(char * dir)166 bool Virtual_Drive::RemoveDir(char * dir) {
167 return false;
168 }
169
MakeDir(char * dir)170 bool Virtual_Drive::MakeDir(char * dir) {
171 return false;
172 }
173
TestDir(char * dir)174 bool Virtual_Drive::TestDir(char * dir) {
175 if (!dir[0]) return true; //only valid dir is the empty dir
176 return false;
177 }
178
FileStat(const char * name,FileStat_Block * const stat_block)179 bool Virtual_Drive::FileStat(const char* name, FileStat_Block * const stat_block){
180 VFILE_Block * cur_file=first_file;
181 while (cur_file) {
182 if (strcasecmp(name,cur_file->name)==0) {
183 stat_block->attr=DOS_ATTR_ARCHIVE;
184 stat_block->size=cur_file->size;
185 stat_block->date=DOS_PackDate(2002,10,1);
186 stat_block->time=DOS_PackTime(12,34,56);
187 return true;
188 }
189 cur_file=cur_file->next;
190 }
191 return false;
192 }
193
FileExists(const char * name)194 bool Virtual_Drive::FileExists(const char* name){
195 VFILE_Block * cur_file=first_file;
196 while (cur_file) {
197 if (strcasecmp(name,cur_file->name)==0) return true;
198 cur_file=cur_file->next;
199 }
200 return false;
201 }
202
FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst)203 bool Virtual_Drive::FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst) {
204 search_file=first_file;
205 Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII];
206 dta.GetSearchParams(attr,pattern);
207 if (attr == DOS_ATTR_VOLUME) {
208 dta.SetResult("DOSBOX",0,0,0,DOS_ATTR_VOLUME);
209 return true;
210 } else if ((attr & DOS_ATTR_VOLUME) && !fcb_findfirst) {
211 if (WildFileCmp("DOSBOX",pattern)) {
212 dta.SetResult("DOSBOX",0,0,0,DOS_ATTR_VOLUME);
213 return true;
214 }
215 }
216 return FindNext(dta);
217 }
218
FindNext(DOS_DTA & dta)219 bool Virtual_Drive::FindNext(DOS_DTA & dta) {
220 Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII];
221 dta.GetSearchParams(attr,pattern);
222 while (search_file) {
223 if (WildFileCmp(search_file->name,pattern)) {
224 dta.SetResult(search_file->name,search_file->size,search_file->date,search_file->time,DOS_ATTR_ARCHIVE);
225 search_file=search_file->next;
226 return true;
227 }
228 search_file=search_file->next;
229 }
230 DOS_SetError(DOSERR_NO_MORE_FILES);
231 return false;
232 }
233
GetFileAttr(char * name,Bit16u * attr)234 bool Virtual_Drive::GetFileAttr(char * name,Bit16u * attr) {
235 VFILE_Block * cur_file=first_file;
236 while (cur_file) {
237 if (strcasecmp(name,cur_file->name)==0) {
238 *attr = DOS_ATTR_ARCHIVE; //Maybe readonly ?
239 return true;
240 }
241 cur_file=cur_file->next;
242 }
243 return false;
244 }
245
Rename(char * oldname,char * newname)246 bool Virtual_Drive::Rename(char * oldname,char * newname) {
247 return false;
248 }
249
AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters)250 bool Virtual_Drive::AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters) {
251 /* Always report 100 mb free should be enough */
252 /* Total size is always 1 gb */
253 *_bytes_sector=512;
254 *_sectors_cluster=127;
255 *_total_clusters=16513;
256 *_free_clusters=00;
257 return true;
258 }
259
GetMediaByte(void)260 Bit8u Virtual_Drive::GetMediaByte(void) {
261 return 0xF8;
262 }
263
isRemote(void)264 bool Virtual_Drive::isRemote(void) {
265 return false;
266 }
267
isRemovable(void)268 bool Virtual_Drive::isRemovable(void) {
269 return false;
270 }
271
UnMount(void)272 Bits Virtual_Drive::UnMount(void) {
273 return 1;
274 }
275
276