-/* io.c - Virtual disk input/output */\r
-\r
-/* Written 1993 by Werner Almesberger */\r
-\r
-/*\r
- * Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de>\r
- * Fixed nasty bug that caused every file with a name like\r
- * xxxxxxxx.xxx to be treated as bad name that needed to be fixed.\r
- */\r
-\r
-/* FAT32, VFAT, Atari format support, and various fixes additions May 1998\r
- * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */\r
-\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-//#include <unistd.h>\r
-#include <sys/stat.h>\r
-//#include <sys/ioctl.h>\r
-#include <errno.h>\r
-#include <fcntl.h>\r
-#include <assert.h>\r
-//#include <linux/fd.h>\r
-\r
-\r
-#ifdef _WIN32\r
-#define _WIN32_WINNT 0x0400\r
-#include <windows.h>\r
-#include <winioctl.h>\r
-#define __LITTLE_ENDIAN 1234\r
-#define __BIG_ENDIAN 4321\r
-#define __BYTE_ORDER __LITTLE_ENDIAN\r
-#define inline\r
-#define __attribute__(x)\r
-#define BLOCK_SIZE 512\r
-#endif\r
-\r
-\r
-#include "dosfsck.h"\r
-#include "common.h"\r
-#include "io.h"\r
-\r
-\r
-typedef struct _change {\r
- void *data;\r
- loff_t pos;\r
- int size;\r
- struct _change *next;\r
-} CHANGE;\r
-\r
-\r
-static CHANGE *changes,*last;\r
-static int fd,did_change = 0;\r
-\r
-unsigned device_no;\r
-\r
-static int WIN32open(const char *path, int oflag, ...);\r
-#define open WIN32open\r
-static int WIN32close(int fd);\r
-#define close WIN32close\r
-static int WIN32read(int fd, void *buf, unsigned int len);\r
-#define read WIN32read\r
-static int WIN32write(int fd, void *buf, unsigned int len);\r
-#define write WIN32write\r
-static loff_t WIN32llseek(int fd, loff_t offset, int whence);\r
-#ifdef llseek\r
-#undef llseek\r
-#endif\r
-#define llseek WIN32llseek\r
-\r
-static int is_device = 0;\r
-\r
-void fs_open(char *path,int rw)\r
-{\r
-#ifdef _WIN32\r
- static char dev_buf[] = "\\\\.\\X:";\r
-#else\r
- struct stat stbuf;\r
-#endif\r
-\r
- if (path[1] == ':' && path[2] == '\0') {\r
- dev_buf[4] = path[0];\r
- path = dev_buf;\r
-// is_device = 1;\r
- }\r
-\r
- if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0)\r
- pdie("open %s",path);\r
- changes = last = NULL;\r
- did_change = 0;\r
-\r
-#if 0\r
- if (fstat(fd,&stbuf) < 0)\r
- pdie("fstat %s",path);\r
- device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0;\r
-#endif\r
-}\r
-\r
-\r
-void fs_read(loff_t pos,int size,void *data)\r
-{\r
- CHANGE *walk;\r
- int got;\r
-#if 1 // TMN\r
- const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN:\r
- const loff_t seekpos_aligned = pos - (pos % 512); // TMN:\r
- const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN:\r
- const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN: \r
- char* tmpBuf = malloc(readsize_aligned); // TMN:\r
-#ifdef _MSC_VER\r
- if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %I64d",pos);\r
- if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %I64dd",size,pos);\r
-#else\r
- if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos);\r
- if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %lld",size,pos);\r
-#endif\r
- assert(got >= size);\r
- got = size;\r
- assert(seek_delta + size <= readsize);\r
- memcpy(data, tmpBuf+seek_delta, size);\r
- free(tmpBuf);\r
-#else // TMN:\r
- if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);\r
- if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos);\r
-#endif // TMN:\r
- if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos);\r
- for (walk = changes; walk; walk = walk->next) {\r
- if (walk->pos < pos+size && walk->pos+walk->size > pos) {\r
- if (walk->pos < pos)\r
- memcpy(data,(char *) walk->data+pos-walk->pos,min((size_t)size,\r
- (size_t)(walk->size-pos+walk->pos)));\r
- else memcpy((char *) data+walk->pos-pos,walk->data,min((size_t)walk->size,\r
- (size_t)(size+pos-walk->pos)));\r
- }\r
- }\r
-}\r
-\r
-\r
-int fs_test(loff_t pos,int size)\r
-{\r
- void *scratch;\r
- int okay;\r
-\r
-#if 1 // TMN\r
- const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN:\r
- const loff_t seekpos_aligned = pos - (pos % 512); // TMN:\r
- const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN:\r
- const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN: \r
- scratch = alloc(readsize_aligned);\r
- if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos);\r
- okay = read(fd,scratch,readsize_aligned) == (int)readsize_aligned;\r
- free(scratch);\r
-#else // TMN:\r
- if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);\r
- scratch = alloc(size);\r
- okay = read(fd,scratch,size) == size;\r
- free(scratch);\r
-#endif // TMN:\r
- return okay;\r
-}\r
-\r
-\r
-void fs_write(loff_t pos,int size,void *data)\r
-{\r
- CHANGE *new;\r
- int did;\r
+/* io.c - Virtual disk input/output */
+
+/* Written 1993 by Werner Almesberger */
+
+/*
+ * Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Fixed nasty bug that caused every file with a name like
+ * xxxxxxxx.xxx to be treated as bad name that needed to be fixed.
+ */
+
+/* FAT32, VFAT, Atari format support, and various fixes additions May 1998
+ * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+//#include <unistd.h>
+#include <sys/stat.h>
+//#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <assert.h>
+//#include <linux/fd.h>
+
+
+#ifdef _WIN32
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#include <winioctl.h>
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#define inline
+#define __attribute__(x)
+#define BLOCK_SIZE 512
+#endif
+
+
+#include "dosfsck.h"
+#include "common.h"
+#include "io.h"
+
+
+typedef struct _change {
+ void *data;
+ loff_t pos;
+ int size;
+ struct _change *next;
+} CHANGE;
+
+
+static CHANGE *changes,*last;
+static int fd,did_change = 0;
+
+unsigned device_no;
+
+static int WIN32open(const char *path, int oflag, ...);
+#define open WIN32open
+static int WIN32close(int fd);
+#define close WIN32close
+static int WIN32read(int fd, void *buf, unsigned int len);
+#define read WIN32read
+static int WIN32write(int fd, void *buf, unsigned int len);
+#define write WIN32write
+static loff_t WIN32llseek(int fd, loff_t offset, int whence);
+#ifdef llseek
+#undef llseek
+#endif
+#define llseek WIN32llseek
+
+static int is_device = 0;
+
+void fs_open(char *path,int rw)
+{
+#ifdef _WIN32
+ static char dev_buf[] = "\\\\.\\X:";
+#else
+ struct stat stbuf;
+#endif
+
+ if (path[1] == ':' && path[2] == '\0') {
+ dev_buf[4] = path[0];
+ path = dev_buf;
+// is_device = 1;
+ }
+
+ if ((fd = open(path,rw ? O_RDWR : O_RDONLY)) < 0)
+ pdie("open %s",path);
+ changes = last = NULL;
+ did_change = 0;
+
+#if 0
+ if (fstat(fd,&stbuf) < 0)
+ pdie("fstat %s",path);
+ device_no = S_ISBLK(stbuf.st_mode) ? (stbuf.st_rdev >> 8) & 0xff : 0;
+#endif
+}
+
+
+void fs_read(loff_t pos,int size,void *data)
+{
+ CHANGE *walk;
+ int got;
+#if 1 // TMN
+ const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN:
+ const loff_t seekpos_aligned = pos - (pos % 512); // TMN:
+ const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN:
+ const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN:
+ char* tmpBuf = malloc(readsize_aligned); // TMN:
+#ifdef _MSC_VER
+ if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %I64d",pos);
+ if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %I64dd",size,pos);
+#else
+ if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos);
+ if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %lld",size,pos);
+#endif
+ assert(got >= size);
+ got = size;
+ assert(seek_delta + size <= readsize);
+ memcpy(data, tmpBuf+seek_delta, size);
+ free(tmpBuf);
+#else // TMN:
+ if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
+ if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos);
+#endif // TMN:
+ if (got != size) die("Got %d bytes instead of %d at %lld",got,size,pos);
+ for (walk = changes; walk; walk = walk->next) {
+ if (walk->pos < pos+size && walk->pos+walk->size > pos) {
+ if (walk->pos < pos)
+ memcpy(data,(char *) walk->data+pos-walk->pos,min((size_t)size,
+ (size_t)(walk->size-pos+walk->pos)));
+ else memcpy((char *) data+walk->pos-pos,walk->data,min((size_t)walk->size,
+ (size_t)(size+pos-walk->pos)));
+ }
+ }
+}
+
+
+int fs_test(loff_t pos,int size)
+{
+ void *scratch;
+ int okay;
+
+#if 1 // TMN
+ const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN:
+ const loff_t seekpos_aligned = pos - (pos % 512); // TMN:
+ const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN:
+ const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN:
+ scratch = alloc(readsize_aligned);
+ if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos);
+ okay = read(fd,scratch,readsize_aligned) == (int)readsize_aligned;
+ free(scratch);
+#else // TMN:
+ if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
+ scratch = alloc(size);
+ okay = read(fd,scratch,size) == size;
+ free(scratch);
+#endif // TMN:
+ return okay;
+}
+
+
+void fs_write(loff_t pos,int size,void *data)
+{
+ CHANGE *new;
+ int did;
#if 1 //SAE
void *scratch;
- const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size;\r
- const loff_t seekpos_aligned = pos - (pos % 512);\r
- const size_t seek_delta = (size_t)(pos - seekpos_aligned);\r
- const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned;\r
+ const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size;
+ const loff_t seekpos_aligned = pos - (pos % 512);
+ const size_t seek_delta = (size_t)(pos - seekpos_aligned);
+ const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned;
scratch = alloc(readsize_aligned);
- if (write_immed) {\r
- did_change = 1;\r
- if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos);\r
+ if (write_immed) {
+ did_change = 1;
+ if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos);
if ((did = write(fd,data,readsize_aligned)) == (int)readsize_aligned)
{
free(scratch);
return;
- }\r
- if (did < 0) pdie("Write %d bytes at %lld",size,pos);\r
- die("Wrote %d bytes instead of %d at %lld",did,size,pos);\r
- }\r
- new = alloc(sizeof(CHANGE));\r
- new->pos = pos;\r
- memcpy(new->data = alloc(new->size = size),data,size);\r
- new->next = NULL;\r
- if (last) last->next = new;\r
- else changes = new;\r
+ }
+ if (did < 0) pdie("Write %d bytes at %lld",size,pos);
+ die("Wrote %d bytes instead of %d at %lld",did,size,pos);
+ }
+ new = alloc(sizeof(CHANGE));
+ new->pos = pos;
+ memcpy(new->data = alloc(new->size = size),data,size);
+ new->next = NULL;
+ if (last) last->next = new;
+ else changes = new;
last = new;
-#else //SAE\r
- if (write_immed) {\r
- did_change = 1;\r
- if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);\r
- if ((did = write(fd,data,size)) == size) return;\r
- if (did < 0) pdie("Write %d bytes at %lld",size,pos);\r
- die("Wrote %d bytes instead of %d at %lld",did,size,pos);\r
- }\r
- new = alloc(sizeof(CHANGE));\r
- new->pos = pos;\r
- memcpy(new->data = alloc(new->size = size),data,size);\r
- new->next = NULL;\r
- if (last) last->next = new;\r
- else changes = new;\r
+#else //SAE
+ if (write_immed) {
+ did_change = 1;
+ if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos);
+ if ((did = write(fd,data,size)) == size) return;
+ if (did < 0) pdie("Write %d bytes at %lld",size,pos);
+ die("Wrote %d bytes instead of %d at %lld",did,size,pos);
+ }
+ new = alloc(sizeof(CHANGE));
+ new->pos = pos;
+ memcpy(new->data = alloc(new->size = size),data,size);
+ new->next = NULL;
+ if (last) last->next = new;
+ else changes = new;
last = new;
-#endif //SAE\r
-}\r
-\r
-\r
-static void fs_flush(void)\r
-{\r
- CHANGE *this;\r
- int size;\r
-\r
- while (changes) {\r
- this = changes;\r
- changes = changes->next;\r
- if (llseek(fd,this->pos,0) != this->pos)\r
- fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n",\r
- (__int64)this->pos,strerror(errno),this->size);\r
- else if ((size = write(fd,this->data,this->size)) < 0)\r
- fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size,\r
- (__int64)this->pos,strerror(errno));\r
- else if (size != this->size)\r
- fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld."\r
- "\n",size,this->size,(__int64)this->pos);\r
- free(this->data);\r
- free(this);\r
- }\r
-}\r
-\r
-\r
-int fs_close(int write)\r
-{\r
- CHANGE *next;\r
- int changed;\r
-\r
- changed = !!changes;\r
- if (write) fs_flush();\r
- else while (changes) {\r
- next = changes->next;\r
- free(changes->data);\r
- free(changes);\r
- changes = next;\r
- }\r
- if (close(fd) < 0) pdie("closing file system");\r
- return changed || did_change;\r
-}\r
-\r
-\r
-int fs_changed(void)\r
-{\r
- return !!changes || did_change;\r
-}\r
-\r
-/* Local Variables: */\r
-/* tab-width: 8 */\r
-/* End: */\r
-\r
-\r
-#define O_SHORT_LIVED _O_SHORT_LIVED\r
-//#define O_ACCMODE 3\r
-#define O_NONE 3\r
-#define O_BACKUP 0x10000\r
-#define O_SHARED 0x20000\r
-\r
-static int WIN32open(const char *path, int oflag, ...)\r
-{\r
- HANDLE fh;\r
- DWORD desiredAccess;\r
- DWORD shareMode;\r
- DWORD creationDisposition;\r
- DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL;\r
- SECURITY_ATTRIBUTES securityAttributes;\r
- va_list ap;\r
- int pmode;\r
- int trunc = FALSE;\r
-\r
- securityAttributes.nLength = sizeof(securityAttributes);\r
- securityAttributes.lpSecurityDescriptor = NULL;\r
- securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE;\r
- switch (oflag & O_ACCMODE) {\r
- case O_RDONLY:\r
- desiredAccess = GENERIC_READ;\r
-// shareMode = FILE_SHARE_READ;\r
- shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; // TMN:\r
- break;\r
- case O_WRONLY:\r
- desiredAccess = GENERIC_WRITE;\r
- shareMode = 0;\r
- break;\r
- case O_RDWR:\r
- desiredAccess = GENERIC_READ|GENERIC_WRITE;\r
- shareMode = 0;\r
- break;\r
- case O_NONE:\r
- desiredAccess = 0;\r
- shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;\r
- }\r
- if (oflag & O_APPEND) {\r
- desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE;\r
- shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;\r
- }\r
- if (oflag & O_SHARED)\r
- shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE;\r
- switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) {\r
- case 0:\r
- case O_EXCL:\r
- creationDisposition = OPEN_EXISTING;\r
- break;\r
- case O_CREAT:\r
- creationDisposition = OPEN_ALWAYS;\r
- break;\r
- case O_CREAT|O_EXCL:\r
- case O_CREAT|O_TRUNC|O_EXCL:\r
- creationDisposition = CREATE_NEW;\r
- break;\r
- case O_TRUNC:\r
- case O_TRUNC|O_EXCL:\r
- creationDisposition = TRUNCATE_EXISTING;\r
- break;\r
- case O_CREAT|O_TRUNC:\r
- creationDisposition = OPEN_ALWAYS;\r
- trunc = TRUE;\r
- break;\r
- }\r
- if (oflag & O_CREAT) {\r
- va_start(ap, oflag);\r
- pmode = va_arg(ap, int);\r
- va_end(ap);\r
- if ((pmode & 0222) == 0)\r
- flagsAttributes |= FILE_ATTRIBUTE_READONLY;\r
- }\r
- if (oflag & O_TEMPORARY) {\r
- flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE;\r
- desiredAccess |= DELETE;\r
- }\r
- if (oflag & O_SHORT_LIVED)\r
- flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY;\r
- if (oflag & O_SEQUENTIAL)\r
- flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;\r
- else if (oflag & O_RANDOM)\r
- flagsAttributes |= FILE_FLAG_RANDOM_ACCESS;\r
- if (oflag & O_BACKUP)\r
- flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS;\r
- if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes,\r
- creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) {\r
- errno = GetLastError();\r
- return -1;\r
- }\r
- if (trunc) {\r
- if (!SetEndOfFile(fh)) {\r
- errno = GetLastError();\r
- CloseHandle(fh);\r
- DeleteFile(path);\r
- return -1;\r
- }\r
- }\r
- return (int)fh;\r
-}\r
-\r
-static int WIN32close(int fd)\r
-{\r
- if (!CloseHandle((HANDLE)fd)) {\r
- errno = GetLastError();\r
- return -1;\r
- }\r
- return 0;\r
-}\r
-\r
-static int WIN32read(int fd, void *buf, unsigned int len)\r
-{\r
- DWORD actualLen;\r
-\r
- if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {\r
- errno = GetLastError();\r
- if (errno == ERROR_BROKEN_PIPE)\r
- return 0;\r
- else\r
- return -1;\r
- }\r
- return (int)actualLen;\r
-}\r
-\r
-static int WIN32write(int fd, void *buf, unsigned int len)\r
-{\r
- DWORD actualLen;\r
-\r
- if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {\r
- errno = GetLastError();\r
- return -1;\r
- }\r
- return (int)actualLen;\r
-}\r
-\r
-static loff_t WIN32llseek(int fd, loff_t offset, int whence)\r
-{\r
- long lo, hi;\r
- DWORD err;\r
-\r
- lo = (long)(offset & 0xffffffff);\r
- hi = (long)(offset >> 32);\r
- lo = SetFilePointer((HANDLE)fd, lo, &hi, whence);\r
- if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) {\r
- errno = err;\r
- return -1;\r
- }\r
- return ((loff_t)hi << 32) | (__u32)lo;\r
-}\r
-\r
-int fsctl(int fd, int code)\r
-{\r
- DWORD ret;\r
- if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) {\r
- errno = GetLastError();\r
- return -1;\r
- }\r
- return 0; \r
-}\r
+#endif //SAE
+}
+
+
+static void fs_flush(void)
+{
+ CHANGE *this;
+ int size;
+
+ while (changes) {
+ this = changes;
+ changes = changes->next;
+ if (llseek(fd,this->pos,0) != this->pos)
+ fprintf(stderr,"Seek to %lld failed: %s\n Did not write %d bytes.\n",
+ (__int64)this->pos,strerror(errno),this->size);
+ else if ((size = write(fd,this->data,this->size)) < 0)
+ fprintf(stderr,"Writing %d bytes at %lld failed: %s\n",this->size,
+ (__int64)this->pos,strerror(errno));
+ else if (size != this->size)
+ fprintf(stderr,"Wrote %d bytes instead of %d bytes at %lld."
+ "\n",size,this->size,(__int64)this->pos);
+ free(this->data);
+ free(this);
+ }
+}
+
+
+int fs_close(int write)
+{
+ CHANGE *next;
+ int changed;
+
+ changed = !!changes;
+ if (write) fs_flush();
+ else while (changes) {
+ next = changes->next;
+ free(changes->data);
+ free(changes);
+ changes = next;
+ }
+ if (close(fd) < 0) pdie("closing file system");
+ return changed || did_change;
+}
+
+
+int fs_changed(void)
+{
+ return !!changes || did_change;
+}
+
+/* Local Variables: */
+/* tab-width: 8 */
+/* End: */
+
+
+#define O_SHORT_LIVED _O_SHORT_LIVED
+//#define O_ACCMODE 3
+#define O_NONE 3
+#define O_BACKUP 0x10000
+#define O_SHARED 0x20000
+
+static int WIN32open(const char *path, int oflag, ...)
+{
+ HANDLE fh;
+ DWORD desiredAccess;
+ DWORD shareMode;
+ DWORD creationDisposition;
+ DWORD flagsAttributes = FILE_ATTRIBUTE_NORMAL;
+ SECURITY_ATTRIBUTES securityAttributes;
+ va_list ap;
+ int pmode;
+ int trunc = FALSE;
+
+ securityAttributes.nLength = sizeof(securityAttributes);
+ securityAttributes.lpSecurityDescriptor = NULL;
+ securityAttributes.bInheritHandle = oflag & O_NOINHERIT ? FALSE : TRUE;
+ switch (oflag & O_ACCMODE) {
+ case O_RDONLY:
+ desiredAccess = GENERIC_READ;
+// shareMode = FILE_SHARE_READ;
+ shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE; // TMN:
+ break;
+ case O_WRONLY:
+ desiredAccess = GENERIC_WRITE;
+ shareMode = 0;
+ break;
+ case O_RDWR:
+ desiredAccess = GENERIC_READ|GENERIC_WRITE;
+ shareMode = 0;
+ break;
+ case O_NONE:
+ desiredAccess = 0;
+ shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+ }
+ if (oflag & O_APPEND) {
+ desiredAccess |= FILE_APPEND_DATA|SYNCHRONIZE;
+ shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+ }
+ if (oflag & O_SHARED)
+ shareMode |= FILE_SHARE_READ|FILE_SHARE_WRITE;
+ switch (oflag & (O_CREAT|O_EXCL|O_TRUNC)) {
+ case 0:
+ case O_EXCL:
+ creationDisposition = OPEN_EXISTING;
+ break;
+ case O_CREAT:
+ creationDisposition = OPEN_ALWAYS;
+ break;
+ case O_CREAT|O_EXCL:
+ case O_CREAT|O_TRUNC|O_EXCL:
+ creationDisposition = CREATE_NEW;
+ break;
+ case O_TRUNC:
+ case O_TRUNC|O_EXCL:
+ creationDisposition = TRUNCATE_EXISTING;
+ break;
+ case O_CREAT|O_TRUNC:
+ creationDisposition = OPEN_ALWAYS;
+ trunc = TRUE;
+ break;
+ }
+ if (oflag & O_CREAT) {
+ va_start(ap, oflag);
+ pmode = va_arg(ap, int);
+ va_end(ap);
+ if ((pmode & 0222) == 0)
+ flagsAttributes |= FILE_ATTRIBUTE_READONLY;
+ }
+ if (oflag & O_TEMPORARY) {
+ flagsAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+ desiredAccess |= DELETE;
+ }
+ if (oflag & O_SHORT_LIVED)
+ flagsAttributes |= FILE_ATTRIBUTE_TEMPORARY;
+ if (oflag & O_SEQUENTIAL)
+ flagsAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
+ else if (oflag & O_RANDOM)
+ flagsAttributes |= FILE_FLAG_RANDOM_ACCESS;
+ if (oflag & O_BACKUP)
+ flagsAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
+ if ((fh = CreateFile(path, desiredAccess, shareMode, &securityAttributes,
+ creationDisposition, flagsAttributes, NULL)) == INVALID_HANDLE_VALUE) {
+ errno = GetLastError();
+ return -1;
+ }
+ if (trunc) {
+ if (!SetEndOfFile(fh)) {
+ errno = GetLastError();
+ CloseHandle(fh);
+ DeleteFile(path);
+ return -1;
+ }
+ }
+ return (int)fh;
+}
+
+static int WIN32close(int fd)
+{
+ if (!CloseHandle((HANDLE)fd)) {
+ errno = GetLastError();
+ return -1;
+ }
+ return 0;
+}
+
+static int WIN32read(int fd, void *buf, unsigned int len)
+{
+ DWORD actualLen;
+
+ if (!ReadFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
+ errno = GetLastError();
+ if (errno == ERROR_BROKEN_PIPE)
+ return 0;
+ else
+ return -1;
+ }
+ return (int)actualLen;
+}
+
+static int WIN32write(int fd, void *buf, unsigned int len)
+{
+ DWORD actualLen;
+
+ if (!WriteFile((HANDLE)fd, buf, (DWORD)len, &actualLen, NULL)) {
+ errno = GetLastError();
+ return -1;
+ }
+ return (int)actualLen;
+}
+
+static loff_t WIN32llseek(int fd, loff_t offset, int whence)
+{
+ long lo, hi;
+ DWORD err;
+
+ lo = (long)(offset & 0xffffffff);
+ hi = (long)(offset >> 32);
+ lo = SetFilePointer((HANDLE)fd, lo, &hi, whence);
+ if (lo == 0xFFFFFFFF && (err = GetLastError()) != NO_ERROR) {
+ errno = err;
+ return -1;
+ }
+ return ((loff_t)hi << 32) | (__u32)lo;
+}
+
+int fsctl(int fd, int code)
+{
+ DWORD ret;
+ if (!DeviceIoControl((HANDLE)fd, code, NULL, 0, NULL, 0, &ret, NULL)) {
+ errno = GetLastError();
+ return -1;
+ }
+ return 0;
+}