update SVN properties
[reactos.git] / rosapps / sysutils / dosfsck / io.c
index 32aee9f..b089b00 100644 (file)
-/* 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; 
+}