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