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>
22 //#include <linux/fd.h>
26 #define _WIN32_WINNT 0x0400
29 #define __LITTLE_ENDIAN 1234
30 #define __BIG_ENDIAN 4321
31 #define __BYTE_ORDER __LITTLE_ENDIAN
33 #define __attribute__(x)
34 #define BLOCK_SIZE 512
43 typedef struct _change
{
51 static CHANGE
*changes
,*last
;
52 static int fd
,did_change
= 0;
56 static int WIN32open(const char *path
, int oflag
, ...);
57 #define open WIN32open
58 static int WIN32close(int fd
);
59 #define close WIN32close
60 static int WIN32read(int fd
, void *buf
, unsigned int len
);
61 #define read WIN32read
62 static int WIN32write(int fd
, void *buf
, unsigned int len
);
63 #define write WIN32write
64 static loff_t
WIN32llseek(int fd
, loff_t offset
, int whence
);
65 #define llseek WIN32llseek
67 static int is_device
= 0;
69 void fs_open(char *path
,int rw
)
72 static char dev_buf
[] = "\\\\.\\X:";
77 if (path
[1] == ':' && path
[2] == '\0') {
83 if ((fd
= open(path
,rw
? O_RDWR
: O_RDONLY
)) < 0)
85 changes
= last
= NULL
;
89 if (fstat(fd
,&stbuf
) < 0)
90 pdie("fstat %s",path
);
91 device_no
= S_ISBLK(stbuf
.st_mode
) ? (stbuf
.st_rdev
>> 8) & 0xff : 0;
96 void fs_read(loff_t pos
,int size
,void *data
)
101 if (llseek(fd
,pos
,0) != pos
) pdie("Seek to %lld",pos
);
102 if ((got
= read(fd
,data
,size
)) < 0) pdie("Read %d bytes at %lld",size
,pos
);
103 if (got
!= size
) die("Got %d bytes instead of %d at %lld",got
,size
,pos
);
104 for (walk
= changes
; walk
; walk
= walk
->next
) {
105 if (walk
->pos
< pos
+size
&& walk
->pos
+walk
->size
> pos
) {
107 memcpy(data
,(char *) walk
->data
+pos
-walk
->pos
,min(size
,
108 walk
->size
-pos
+walk
->pos
));
109 else memcpy((char *) data
+walk
->pos
-pos
,walk
->data
,min(walk
->size
,
110 size
+pos
-walk
->pos
));
116 int fs_test(loff_t pos
,int size
)
121 if (llseek(fd
,pos
,0) != pos
) pdie("Seek to %lld",pos
);
122 scratch
= alloc(size
);
123 okay
= read(fd
,scratch
,size
) == size
;
129 void fs_write(loff_t pos
,int size
,void *data
)
136 if (llseek(fd
,pos
,0) != pos
) pdie("Seek to %lld",pos
);
137 if ((did
= write(fd
,data
,size
)) == size
) return;
138 if (did
< 0) pdie("Write %d bytes at %lld",size
,pos
);
139 die("Wrote %d bytes instead of %d at %lld",did
,size
,pos
);
141 new = alloc(sizeof(CHANGE
));
143 memcpy(new->data
= alloc(new->size
= size
),data
,size
);
145 if (last
) last
->next
= new;
151 static void fs_flush(void)
158 changes
= changes
->next
;
159 if (llseek(fd
,this->pos
,0) != this->pos
)
160 fprintf(stderr
,"Seek to %lld failed: %s\n Did not write %d bytes.\n",
161 (long long)this->pos
,strerror(errno
),this->size
);
162 else if ((size
= write(fd
,this->data
,this->size
)) < 0)
163 fprintf(stderr
,"Writing %d bytes at %lld failed: %s\n",this->size
,
164 (long long)this->pos
,strerror(errno
));
165 else if (size
!= this->size
)
166 fprintf(stderr
,"Wrote %d bytes instead of %d bytes at %lld."
167 "\n",size
,this->size
,(long long)this->pos
);
174 int fs_close(int write
)
180 if (write
) fs_flush();
181 else while (changes
) {
182 next
= changes
->next
;
187 if (close(fd
) < 0) pdie("closing file system");
188 return changed
|| did_change
;
194 return !!changes
|| did_change
;
197 /* Local Variables: */
202 #define O_SHORT_LIVED _O_SHORT_LIVED
205 #define O_BACKUP 0x10000
206 #define O_SHARED 0x20000
208 static int WIN32open(const char *path
, int oflag
, ...)
213 DWORD creationDisposition
;
214 DWORD flagsAttributes
= FILE_ATTRIBUTE_NORMAL
;
215 SECURITY_ATTRIBUTES securityAttributes
;
220 securityAttributes
.nLength
= sizeof(securityAttributes
);
221 securityAttributes
.lpSecurityDescriptor
= NULL
;
222 securityAttributes
.bInheritHandle
= oflag
& O_NOINHERIT
? FALSE
: TRUE
;
223 switch (oflag
& O_ACCMODE
) {
225 desiredAccess
= GENERIC_READ
;
226 shareMode
= FILE_SHARE_READ
;
229 desiredAccess
= GENERIC_WRITE
;
233 desiredAccess
= GENERIC_READ
|GENERIC_WRITE
;
238 shareMode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
240 if (oflag
& O_APPEND
) {
241 desiredAccess
|= FILE_APPEND_DATA
|SYNCHRONIZE
;
242 shareMode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
244 if (oflag
& O_SHARED
)
245 shareMode
|= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
246 switch (oflag
& (O_CREAT
|O_EXCL
|O_TRUNC
)) {
249 creationDisposition
= OPEN_EXISTING
;
252 creationDisposition
= OPEN_ALWAYS
;
255 case O_CREAT
|O_TRUNC
|O_EXCL
:
256 creationDisposition
= CREATE_NEW
;
260 creationDisposition
= TRUNCATE_EXISTING
;
262 case O_CREAT
|O_TRUNC
:
263 creationDisposition
= OPEN_ALWAYS
;
267 if (oflag
& O_CREAT
) {
269 pmode
= va_arg(ap
, int);
271 if ((pmode
& 0222) == 0)
272 flagsAttributes
|= FILE_ATTRIBUTE_READONLY
;
274 if (oflag
& O_TEMPORARY
) {
275 flagsAttributes
|= FILE_FLAG_DELETE_ON_CLOSE
;
276 desiredAccess
|= DELETE
;
278 if (oflag
& O_SHORT_LIVED
)
279 flagsAttributes
|= FILE_ATTRIBUTE_TEMPORARY
;
280 if (oflag
& O_SEQUENTIAL
)
281 flagsAttributes
|= FILE_FLAG_SEQUENTIAL_SCAN
;
282 else if (oflag
& O_RANDOM
)
283 flagsAttributes
|= FILE_FLAG_RANDOM_ACCESS
;
284 if (oflag
& O_BACKUP
)
285 flagsAttributes
|= FILE_FLAG_BACKUP_SEMANTICS
;
286 if ((fh
= CreateFile(path
, desiredAccess
, shareMode
, &securityAttributes
,
287 creationDisposition
, flagsAttributes
, NULL
)) == INVALID_HANDLE_VALUE
) {
288 errno
= GetLastError();
292 if (!SetEndOfFile(fh
)) {
293 errno
= GetLastError();
302 static int WIN32close(int fd
)
304 if (!CloseHandle((HANDLE
)fd
)) {
305 errno
= GetLastError();
311 static int WIN32read(int fd
, void *buf
, unsigned int len
)
315 if (!ReadFile((HANDLE
)fd
, buf
, (DWORD
)len
, &actualLen
, NULL
)) {
316 errno
= GetLastError();
317 if (errno
== ERROR_BROKEN_PIPE
)
322 return (int)actualLen
;
325 static int WIN32write(int fd
, void *buf
, unsigned int len
)
329 if (!WriteFile((HANDLE
)fd
, buf
, (DWORD
)len
, &actualLen
, NULL
)) {
330 errno
= GetLastError();
333 return (int)actualLen
;
336 static loff_t
WIN32llseek(int fd
, loff_t offset
, int whence
)
341 lo
= offset
& 0xffffffff;
343 lo
= SetFilePointer((HANDLE
)fd
, lo
, &hi
, whence
);
344 if (lo
== 0xFFFFFFFF && (err
= GetLastError()) != NO_ERROR
) {
348 return ((loff_t
)hi
<< 32) | (off_t
)lo
;
351 int fsctl(int fd
, int code
)
354 if (!DeviceIoControl((HANDLE
)fd
, code
, NULL
, 0, NULL
, 0, &ret
, NULL
)) {
355 errno
= GetLastError();