Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4973 right-hear 1
#include
2
#include
3
#include
4
#include
5
#include
6
#include
7
 
8
struct systree_blk
9
{
10
 unsigned long cmd,pos,blks;
11
 void * data,* work;
12
 char name[256];
13
} __attribute__((packed));
14
 
15
typedef struct EMU_FILE
16
{
17
 int			handle;
18
 unsigned long		size;
19
 unsigned long		pos;
20
 unsigned long		mode;
21
 unsigned long		current_sector;
22
 unsigned long		size_sectors;
23
 char 		      * write_buf;
24
 unsigned long		write_bufsize;
25
 char			rd_buffer[512];
26
 char			name[256];
27
 unsigned char		dirty;
28
} EMU_FILE;
29
 
30
#define _MAX_HANDLES		64
31
 
32
static EMU_FILE		* EMU_file_table[_MAX_HANDLES];
33
static char		  systree_work_area[16384+512];
34
static volatile struct systree_blk sblk;
35
static volatile int S_eax,S_ebx;
36
 
37
static inline int EMU_alloc_handle(void)
38
{
39
 register int i;
40
 for(i=0;i<_MAX_HANDLES;i++)
41
  if(!EMU_file_table[i])
42
  {
43
   EMU_file_table[i]=(EMU_FILE *)malloc(sizeof(EMU_FILE));
44
   if(!EMU_file_table[i]) return -ENOMEM;
45
   return i;
46
  }
47
 return -EAGAIN;
48
}
49
 
50
static inline int EMU_systree_cmd(void)
51
{
52
 __asm__ __volatile__("int $0x40"
53
     :"=a"(S_eax),"=b"(S_ebx)
54
     :"0"(58),"1"((void *)&sblk));
55
 return S_eax;
56
}
57
 
58
static int EMU_loadsector(EMU_FILE * filp)
59
{
60
 sblk.cmd=0;
61
 sblk.pos=filp->current_sector;
62
 sblk.blks=1;
63
 sblk.data=filp->rd_buffer;
64
 sblk.work=systree_work_area;
65
 memcpy((void *)&sblk.name,(const void *)filp->name,strlen(filp->name)+1);
66
 return EMU_systree_cmd();
67
}
68
 
69
static int EMU_fsync(EMU_FILE * filp)
70
{
71
 if(filp->mode==O_RDONLY) return 0;
72
 if(!filp->dirty) return 0;
73
 filp->dirty=0;
74
 sblk.cmd=1;
75
 sblk.pos=0;
76
 sblk.blks=filp->size;
77
 sblk.data=filp->write_buf;
78
 sblk.work=systree_work_area;
79
 memcpy((void *)sblk.name,(const void *)filp->name,strlen(filp->name)+1);
80
 return EMU_systree_cmd();
81
}
82
 
83
static inline int EMU_realloc_buf(EMU_FILE * filp,unsigned long newsize)
84
{
85
 char * n;
86
 newsize=(newsize+511)&~511;
87
 if(filp->write_bufsize==newsize) return 0;
88
 n=(char *)realloc(filp->write_buf,newsize);
89
 if(!n) return -ENOSPC;
90
 filp->write_buf=n;
91
 filp->write_bufsize=newsize;
92
 filp->dirty=1;
93
 return 0;
94
}
95
 
96
static int EMU_createtrunc(char * fname)
97
{
98
 sblk.cmd=1;
99
 sblk.pos=0;
100
 sblk.blks=0;
101
 sblk.data=sblk.work=systree_work_area;
102
 memcpy((void *)sblk.name,(const void *)fname,strlen(fname)+1);
103
 return EMU_systree_cmd();
104
}
105
 
106
static int EMU_getfsize(char * fname,unsigned long * sizep)
107
{
108
 sblk.cmd=0;
109
 sblk.pos=0;
110
 sblk.blks=1;
111
 sblk.data=systree_work_area+16384;
112
 sblk.work=systree_work_area;
113
 memcpy((void *)sblk.name,(const void *)fname,strlen(fname)+1);
114
 if(EMU_systree_cmd()!=0) return -EINVAL;
115
 if(sizep) *sizep=(unsigned long)S_ebx;
116
 return 0;
117
}
118
 
119
static int EMU_open(char * fname,int mode)
120
{
121
 EMU_FILE * filp;
122
 register int hid;
123
 unsigned long iomode;
124
 hid=EMU_alloc_handle();
125
 if(hid<0) return hid;
126
 filp=EMU_file_table[hid];
127
 filp->handle=hid;
128
 iomode=mode&(O_RDONLY|O_WRONLY|O_RDWR);
129
 memcpy((void *)filp->name,(const void *)fname,strlen(fname)+1);
130
 strupr(filp->name);
131
 filp->mode=iomode;
132
 if(mode&O_CREAT)
133
 {
134
  int createflags=mode&(O_TRUNC|O_EXCL);
135
  if(createflags&O_EXCL)
136
  {
137
   unsigned long psz=0;
138
   if(EMU_getfsize(filp->name,&psz)==0)
139
   {
140
    free(EMU_file_table[hid=filp->handle]);
141
    EMU_file_table[hid]=NULL;
142
    return -EEXIST;
143
   }
144
  }
145
  if(createflags&O_TRUNC)
146
  {
147
   EMU_createtrunc(filp->name);
148
  }
149
 }
150
 if(iomode==O_RDONLY)
151
 {
152
  hid=EMU_getfsize(filp->name,&filp->size);
153
  if(hid<0)
154
  {
155
   free(EMU_file_table[hid=filp->handle]);
156
   EMU_file_table[hid]=NULL;
157
   return -ENOENT;
158
  }
159
  filp->current_sector=0;
160
  if(EMU_loadsector(filp)<0) filp->current_sector=-1UL;
161
  filp->mode=O_RDONLY;
162
  filp->size_sectors=(filp->size+511)/512;
163
  filp->write_bufsize=0;
164
  filp->dirty=0;
165
  return filp->handle;
166
 }
167
 if(iomode==O_WRONLY)
168
 {
169
  hid=EMU_getfsize(filp->name,&filp->size);
170
  if(hid<0)
171
  {
172
BAD_WRO:
173
   free(EMU_file_table[hid=filp->handle]);
174
   EMU_file_table[hid]=NULL;
175
   return -ENOENT;
176
  }
177
  filp->current_sector=-1UL;
178
  filp->mode=O_WRONLY;
179
  filp->size_sectors=0;
180
  filp->write_bufsize=(filp->size+511)&~511;
181
  filp->write_buf=(char *)malloc(filp->write_bufsize);
182
  if(!filp->write_buf)
183
  {
184
   free(filp->write_buf);
185
   goto BAD_WRO;
186
  }
187
  sblk.cmd=0;
188
  sblk.pos=0;
189
  sblk.blks=filp->write_bufsize/512;
190
  sblk.data=filp->write_buf;
191
  sblk.work=systree_work_area;
192
  if(EMU_systree_cmd()!=0) goto BAD_WRO1;
193
  return filp->handle;
194
 }
195
 hid=EMU_getfsize(filp->name,&filp->size);
196
 if(hid<0)
197
 {
198
BAD_WRO1:
199
  free(EMU_file_table[hid=filp->handle]);
200
  EMU_file_table[hid]=NULL;
201
  return -ENOENT;
202
 }
203
 filp->current_sector=-1UL;
204
 filp->mode=O_RDWR;
205
 filp->size_sectors=0;
206
 filp->write_bufsize=(filp->size+511)&~511;
207
 filp->write_buf=(char *)malloc(filp->write_bufsize);
208
 if(!filp->write_buf)
209
 {
210
  free(filp->write_buf);
211
  goto BAD_WRO1;
212
 }
213
 sblk.cmd=0;
214
 sblk.pos=0;
215
 sblk.blks=filp->write_bufsize/512;
216
 sblk.data=filp->write_buf;
217
 sblk.work=systree_work_area;
218
 if(EMU_systree_cmd()!=0) goto BAD_WRO1;
219
 return filp->handle;
220
}
221
 
222
static int EMU_close(EMU_FILE * filp)
223
{
224
 int hid;
225
 if(!filp) return -ENOENT;
226
 if(EMU_file_table[hid=filp->handle]!=filp) return -EBADF;
227
 if(filp->write_buf) free(filp->write_buf);
228
 free(filp);
229
 EMU_file_table[hid]=NULL;
230
 return 0;
231
}
232
 
233
static int EMU_lseek(EMU_FILE * filp,unsigned long off,int whence)
234
{
235
 unsigned long newpos;
236
 switch(whence)
237
 {
238
  case SEEK_SET:
239
   newpos=off;
240
   break;
241
  case SEEK_CUR:
242
   newpos=filp->pos+off;
243
   break;
244
  case SEEK_END:
245
   newpos=filp->size+off-1;
246
   break;
247
 }
248
 if(newpos>=filp->size) return -1;
249
 filp->pos=newpos;
250
 return filp->pos;
251
}
252
 
253
static int EMU_read(EMU_FILE * filp,unsigned long size,void * buf)
254
{
255
 int icount,curr_sector,curr_sector_ofs,n;
256
 int nbufbytes,totalremaining;
257
 if(filp->pos+count>filp->size)
258
  count=filp->size-filp->pos;
259
 if(filp->mode==O_RDWR)
260
 {
261
  memcpy(buffer,filp->write_buf+filp->pos,count);
262
  filp->pos+=count;
263
  return count;
264
 }
265
 icount=count;
266
 while(count>0)
267
 {
268
  if(filp->pos>=filp->size) return icount=count;
269
  curr_sector=sh->pointer>>9;
270
  curr_sector_ofs=sh->pointer&511;
271
  n=count;
272
  if(sh->bufsector==-1 || curr_sector!=sh->bufsector)
273
  {
274
   if(dosemu_loadcurrsector(sh)==-1) return -1;
275
  }
276
  nbufbytes=512-curr_sector_ofs;
277
  totalremaining=sh->size-sh->pointer;
278
  if(nbufbytes>totalremaining) nbufbytes=totalremaining;
279
  if(n>nbufbytes) n=nbufbytes;
280
  memcpy(buffer,&sh->buf[curr_sector_ofs],n);
281
  buffer+=n;
282
  count-=n;
283
  sh->pointer+=n;
284
 }
285
 return icount;
286
}
287
}