1 /* io.c - Virtual disk input/output */
3 /* Written 1993 by Werner Almesberger */
6 * Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de>
7 * Fixed nasty bug that caused every file with a name like
8 * xxxxxxxx.xxx to be treated as bad name that needed to be fixed.
11 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
12 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
19 //#include <sys/ioctl.h>
23 //#include <linux/fd.h>
27 #define _WIN32_WINNT 0x0400
30 #define __LITTLE_ENDIAN 1234
31 #define __BIG_ENDIAN 4321
32 #define __BYTE_ORDER __LITTLE_ENDIAN
34 #define __attribute__(x)
35 #define BLOCK_SIZE 512
44 typedef struct _change
{
52 static CHANGE
*changes
,*last
;
53 static int fd
,did_change
= 0;
57 static int WIN32open(const char *path
, int oflag
, ...);
58 #define open WIN32open
59 static int WIN32close(int fd
);
60 #define close WIN32close
61 static int WIN32read(int fd
, void *buf
, unsigned int len
);
62 #define read WIN32read
63 static int WIN32write(int fd
, void *buf
, unsigned int len
);
64 #define write WIN32write
65 static loff_t
WIN32llseek(int fd
, loff_t offset
, int whence
);
69 #define llseek WIN32llseek
71 static int is_device
= 0;
73 void fs_open(char *path
,int rw
)
76 static char dev_buf
[] = "\\\\.\\X:";
81 if (path
[1] == ':' && path
[2] == '\0') {
87 if ((fd
= open(path
,rw
? O_RDWR
: O_RDONLY
)) < 0)
89 changes
= last
= NULL
;
93 if (fstat(fd
,&stbuf
) < 0)
94 pdie("fstat %s",path
);
95 device_no
= S_ISBLK(stbuf
.st_mode
) ? (stbuf
.st_rdev
>> 8) & 0xff : 0;
100 void fs_read(loff_t pos
,int size
,void *data
)
105 const size_t readsize_aligned
= (size
% 512) ? (size
+ (512 - (size
% 512))) : size
; // TMN:
106 const loff_t seekpos_aligned
= pos
- (pos
% 512); // TMN:
107 const size_t seek_delta
= (size_t)(pos
- seekpos_aligned
); // TMN:
108 const size_t readsize
= (size_t)(pos
- seekpos_aligned
) + readsize_aligned
; // TMN:
109 char* tmpBuf
= malloc(readsize_aligned
); // TMN:
111 if (llseek(fd
,seekpos_aligned
,0) != seekpos_aligned
) pdie("Seek to %I64d",pos
);
112 if ((got
= read(fd
,tmpBuf
,readsize_aligned
)) < 0) pdie("Read %d bytes at %I64dd",size
,pos
);
114 if (llseek(fd
,seekpos_aligned
,0) != seekpos_aligned
) pdie("Seek to %lld",pos
);
115 if ((got
= read(fd
,tmpBuf
,readsize_aligned
)) < 0) pdie("Read %d bytes at %lld",size
,pos
);
119 assert(seek_delta
+ size
<= readsize
);
120 memcpy(data
, tmpBuf
+seek_delta
, size
);
123 if (llseek(fd
,pos
,0) != pos
) pdie("Seek to %lld",pos
);
124 if ((got
= read(fd
,data
,size
)) < 0) pdie("Read %d bytes at %lld",size
,pos
);
126 if (got
!= size
) die("Got %d bytes instead of %d at %lld",got
,size
,pos
);
127 for (walk
= changes
; walk
; walk
= walk
->next
) {
128 if (walk
->pos
< pos
+size
&& walk
->pos
+walk
->size
> pos
) {
130 memcpy(data
,(char *) walk
->data
+pos
-walk
->pos
,min((size_t)size
,
131 (size_t)(walk
->size
-pos
+walk
->pos
)));
132 else memcpy((char *) data
+walk
->pos
-pos
,walk
->data
,min((size_t)walk
->size
,
133 (size_t)(size
+pos
-walk
->pos
)));
139 int fs_test(loff_t pos
,int size
)
145 const size_t readsize_aligned
= (size
% 512) ? (size
+ (512 - (size
% 512))) : size
; // TMN:
146 const loff_t seekpos_aligned
= pos
- (pos
% 512); // TMN:
147 const size_t seek_delta
= (size_t)(pos
- seekpos_aligned
); // TMN:
148 const size_t readsize
= (size_t)(pos
- seekpos_aligned
) + readsize_aligned
; // TMN:
149 scratch
= alloc(readsize_aligned
);
150 if (llseek(fd
,seekpos_aligned
,0) != seekpos_aligned
) pdie("Seek to %lld",pos
);
151 okay
= read(fd
,scratch
,readsize_aligned
) == (int)readsize_aligned
;
154 if (llseek(fd
,pos
,0) != pos
) pdie("Seek to %lld",pos
);
155 scratch
= alloc(size
);
156 okay
= read(fd
,scratch
,size
) == size
;
163 void fs_write(loff_t pos
,int size
,void *data
)
170 const size_t readsize_aligned
= (size
% 512) ? (size
+ (512 - (size
% 512))) : size
;
171 const loff_t seekpos_aligned
= pos
- (pos
% 512);
172 const size_t seek_delta
= (size_t)(pos
- seekpos_aligned
);
173 const size_t readsize
= (size_t)(pos
- seekpos_aligned
) + readsize_aligned
;
174 scratch
= alloc(readsize_aligned
);
178 if (llseek(fd
,seekpos_aligned
,0) != seekpos_aligned
) pdie("Seek to %lld",pos
);
179 if ((did
= write(fd
,data
,readsize_aligned
)) == (int)readsize_aligned
)
184 if (did
< 0) pdie("Write %d bytes at %lld",size
,pos
);
185 die("Wrote %d bytes instead of %d at %lld",did
,size
,pos
);
187 new = alloc(sizeof(CHANGE
));
189 memcpy(new->data
= alloc(new->size
= readsize_aligned
),data
,readsize_aligned
);
191 if (last
) last
->next
= new;
198 if (llseek(fd
,pos
,0) != pos
) pdie("Seek to %lld",pos
);
199 if ((did
= write(fd
,data
,size
)) == size
) return;
200 if (did
< 0) pdie("Write %d bytes at %lld",size
,pos
);
201 die("Wrote %d bytes instead of %d at %lld",did
,size
,pos
);
203 new = alloc(sizeof(CHANGE
));
205 memcpy(new->data
= alloc(new->size
= size
),data
,size
);
207 if (last
) last
->next
= new;
214 static void fs_flush(void)
221 changes
= changes
->next
;
222 if (llseek(fd
,this->pos
,0) != this->pos
)
223 fprintf(stderr
,"Seek to %lld failed: %s\n Did not write %d bytes.\n",
224 (__int64
)this->pos
,strerror(errno
),this->size
);
225 else if ((size
= write(fd
,this->data
,this->size
)) < 0)
226 fprintf(stderr
,"Writing %d bytes at %lld failed: %s\n",this->size
,
227 (__int64
)this->pos
,strerror(errno
));
228 else if (size
!= this->size
)
229 fprintf(stderr
,"Wrote %d bytes instead of %d bytes at %lld."
230 "\n",size
,this->size
,(__int64
)this->pos
);
237 int fs_close(int write
)
243 if (write
) fs_flush();
244 else while (changes
) {
245 next
= changes
->next
;
250 if (close(fd
) < 0) pdie("closing file system");
251 return changed
|| did_change
;
257 return !!changes
|| did_change
;
260 /* Local Variables: */
265 #define O_SHORT_LIVED _O_SHORT_LIVED
266 //#define O_ACCMODE 3
268 #define O_BACKUP 0x10000
269 #define O_SHARED 0x20000
271 static int WIN32open(const char *path
, int oflag
, ...)
276 DWORD creationDisposition
;
277 DWORD flagsAttributes
= FILE_ATTRIBUTE_NORMAL
;
278 SECURITY_ATTRIBUTES securityAttributes
;
283 securityAttributes
.nLength
= sizeof(securityAttributes
);
284 securityAttributes
.lpSecurityDescriptor
= NULL
;
285 securityAttributes
.bInheritHandle
= oflag
& O_NOINHERIT
? FALSE
: TRUE
;
286 switch (oflag
& O_ACCMODE
) {
288 desiredAccess
= GENERIC_READ
;
289 // shareMode = FILE_SHARE_READ;
290 shareMode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
; // TMN:
293 desiredAccess
= GENERIC_WRITE
;
297 desiredAccess
= GENERIC_READ
|GENERIC_WRITE
;
302 shareMode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
304 if (oflag
& O_APPEND
) {
305 desiredAccess
|= FILE_APPEND_DATA
|SYNCHRONIZE
;
306 shareMode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
308 if (oflag
& O_SHARED
)
309 shareMode
|= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
310 switch (oflag
& (O_CREAT
|O_EXCL
|O_TRUNC
)) {
313 creationDisposition
= OPEN_EXISTING
;
316 creationDisposition
= OPEN_ALWAYS
;
319 case O_CREAT
|O_TRUNC
|O_EXCL
:
320 creationDisposition
= CREATE_NEW
;
324 creationDisposition
= TRUNCATE_EXISTING
;
326 case O_CREAT
|O_TRUNC
:
327 creationDisposition
= OPEN_ALWAYS
;
331 if (oflag
& O_CREAT
) {
333 pmode
= va_arg(ap
, int);
335 if ((pmode
& 0222) == 0)
336 flagsAttributes
|= FILE_ATTRIBUTE_READONLY
;
338 if (oflag
& O_TEMPORARY
) {
339 flagsAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
340 desiredAccess
|= DELETE
;
342 if (oflag
& O_SHORT_LIVED
)
343 flagsAttributes
|= FILE_ATTRIBUTE_TEMPORARY
;
344 if (oflag
& O_SEQUENTIAL
)
345 flagsAttributes
|= FILE_FLAG_SEQUENTIAL_SCAN
;
346 else if (oflag
& O_RANDOM
)
347 flagsAttributes
|= FILE_FLAG_RANDOM_ACCESS
;
348 if (oflag
& O_BACKUP
)
349 flagsAttributes
|= FILE_FLAG_BACKUP_SEMANTICS
;
350 if ((fh
= CreateFile(path
, desiredAccess
, shareMode
, &securityAttributes
,
351 creationDisposition
, flagsAttributes
, NULL
)) == INVALID_HANDLE_VALUE
) {
352 errno
= GetLastError();
356 if (!SetEndOfFile(fh
)) {
357 errno
= GetLastError();
366 static int WIN32close(int fd
)
368 if (!CloseHandle((HANDLE
)fd
)) {
369 errno
= GetLastError();
375 static int WIN32read(int fd
, void *buf
, unsigned int len
)
379 if (!ReadFile((HANDLE
)fd
, buf
, (DWORD
)len
, &actualLen
, NULL
)) {
380 errno
= GetLastError();
381 if (errno
== ERROR_BROKEN_PIPE
)
386 return (int)actualLen
;
389 static int WIN32write(int fd
, void *buf
, unsigned int len
)
393 if (!WriteFile((HANDLE
)fd
, buf
, (DWORD
)len
, &actualLen
, NULL
)) {
394 errno
= GetLastError();
397 return (int)actualLen
;
400 static loff_t
WIN32llseek(int fd
, loff_t offset
, int whence
)
405 lo
= (long)(offset
& 0xffffffff);
406 hi
= (long)(offset
>> 32);
407 lo
= SetFilePointer((HANDLE
)fd
, lo
, &hi
, whence
);
408 if (lo
== 0xFFFFFFFF && (err
= GetLastError()) != NO_ERROR
) {
412 return ((loff_t
)hi
<< 32) | (__u32
)lo
;
415 int fsctl(int fd
, int code
)
418 if (!DeviceIoControl((HANDLE
)fd
, code
, NULL
, 0, NULL
, 0, &ret
, NULL
)) {
419 errno
= GetLastError();