OSDN Git Service

* fhandler.h: Rename FH_W95LSBUG flag to FH_LSEEKED.
authorcorinna <corinna>
Mon, 26 May 2003 09:54:00 +0000 (09:54 +0000)
committercorinna <corinna>
Mon, 26 May 2003 09:54:00 +0000 (09:54 +0000)
(fhandler_base::set_did_lseek): Rename from set_check_win95_lseek_bug.
(fhandler_base::get_did_lseek): Rename from get_check_win95_lseek_bug.
(fhandler_base::set_fs_flags): New method.
(fhandler_base::get_fs_flags): Ditto.
* fhandler.cc (fhandler_base::write): Make 64 bit clean.  Convert file
to a "sparse" file when writing after a long lseek (>64K) beyond EOF.
(fhandler_base::lseek): Call set_did_lseek() instead of
set_check_win95_lseek_bug().
(fhandler_base::fhandler_base): Initialize fs_flags to 0.
* fhandler_disk_file.cc (fhandler_disk_file::open): Don't create files
as "sparse" unconditionally.  Set fs_flags member.

winsup/cygwin/ChangeLog
winsup/cygwin/fhandler.cc
winsup/cygwin/fhandler.h
winsup/cygwin/fhandler_disk_file.cc

index 95f9493..6c4d65c 100644 (file)
@@ -1,3 +1,18 @@
+2003-05-26  Corinna Vinschen  <corinna@vinschen.de>
+
+       * fhandler.h: Rename FH_W95LSBUG flag to FH_LSEEKED.
+       (fhandler_base::set_did_lseek): Rename from set_check_win95_lseek_bug.
+       (fhandler_base::get_did_lseek): Rename from get_check_win95_lseek_bug.
+       (fhandler_base::set_fs_flags): New method.
+       (fhandler_base::get_fs_flags): Ditto.
+       * fhandler.cc (fhandler_base::write): Make 64 bit clean.  Convert file
+       to a "sparse" file when writing after a long lseek (>64K) beyond EOF.
+       (fhandler_base::lseek): Call set_did_lseek() instead of
+       set_check_win95_lseek_bug().
+       (fhandler_base::fhandler_base): Initialize fs_flags to 0.
+       * fhandler_disk_file.cc (fhandler_disk_file::open): Don't create files  
+       as "sparse" unconditionally.  Set fs_flags member.
+
 2003-05-25  Pierre Humblet  <pierre.humblet@ieee.org>
 
        * autoload.cc (GetDiskFreeSpaceEx): Add.
index bdbe288..83302dd 100644 (file)
@@ -27,6 +27,7 @@ details. */
 #include "pinfo.h"
 #include <assert.h>
 #include <limits.h>
+#include <winioctl.h>
 
 static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
 
@@ -610,47 +611,75 @@ fhandler_base::write (const void *ptr, size_t len)
 
   if (get_append_p ())
     SetFilePointer (get_handle (), 0, 0, FILE_END);
-  else if (wincap.has_lseek_bug () && get_check_win95_lseek_bug ())
+  else if (get_did_lseek ())
     {
-      /* Note: this bug doesn't happen on NT4, even though the documentation
-        for WriteFile() says that it *may* happen on any OS. */
-      int actual_length, current_position;
-      set_check_win95_lseek_bug (0); /* don't do it again */
-      actual_length = GetFileSize (get_handle (), NULL);
-      current_position = SetFilePointer (get_handle (), 0, 0, FILE_CURRENT);
+      _off64_t actual_length, current_position;
+      DWORD size_high = 0;
+      LONG pos_high = 0;
+
+      set_did_lseek (0); /* don't do it again */
+
+      actual_length = GetFileSize (get_handle (), &size_high);
+      actual_length += ((_off64_t) size_high) << 32;
+
+      current_position = SetFilePointer (get_handle (), 0, &pos_high,
+                                        FILE_CURRENT);
+      current_position += ((_off64_t) pos_high) << 32;
+
       if (current_position > actual_length)
        {
-         /* Oops, this is the bug case - Win95 uses whatever is on the disk
-            instead of some known (safe) value, so we must seek back and
-            fill in the gap with zeros. - DJ */
-         char zeros[512];
-         int number_of_zeros_to_write = current_position - actual_length;
-         memset (zeros, 0, 512);
-         SetFilePointer (get_handle (), 0, 0, FILE_END);
-         while (number_of_zeros_to_write > 0)
+         if ((get_fs_flags (FILE_SUPPORTS_SPARSE_FILES))
+             && current_position >= actual_length + (64 * 1024))
            {
-             DWORD zeros_this_time = (number_of_zeros_to_write > 512
-                                    ? 512 : number_of_zeros_to_write);
-             DWORD written;
-             if (!WriteFile (get_handle (), zeros, zeros_this_time, &written,
-                             NULL))
-               {
-                 __seterrno ();
-                 if (get_errno () == EPIPE)
-                   raise (SIGPIPE);
-                 /* This might fail, but it's the best we can hope for */
-                 SetFilePointer (get_handle (), current_position, 0, FILE_BEGIN);
-                 return -1;
-
-               }
-             if (written < zeros_this_time) /* just in case */
+             /* If the file systemn supports sparse files and the application
+                is writing after a long seek beyond EOF, convert the file to
+                a sparse file. */
+             DWORD dw;
+             HANDLE h = get_handle ();
+             BOOL r = DeviceIoControl (h, FSCTL_SET_SPARSE, NULL, 0, NULL,
+                                       0, &dw, NULL);
+             syscall_printf ("%d = DeviceIoControl(0x%x, FSCTL_SET_SPARSE, "
+                             "NULL, 0, NULL, 0, &dw, NULL)", r, h);
+           }
+         else if (wincap.has_lseek_bug ())
+           {
+             /* Oops, this is the bug case - Win95 uses whatever is on the
+                disk instead of some known (safe) value, so we must seek
+                back and fill in the gap with zeros. - DJ
+                Note: this bug doesn't happen on NT4, even though the
+                documentation for WriteFile() says that it *may* happen
+                on any OS. */
+             char zeros[512];
+             int number_of_zeros_to_write = current_position - actual_length;
+             memset (zeros, 0, 512);
+             SetFilePointer (get_handle (), 0, NULL, FILE_END);
+             while (number_of_zeros_to_write > 0)
                {
-                 set_errno (ENOSPC);
-                 /* This might fail, but it's the best we can hope for */
-                 SetFilePointer (get_handle (), current_position, 0, FILE_BEGIN);
-                 return -1;
+                 DWORD zeros_this_time = (number_of_zeros_to_write > 512
+                                        ? 512 : number_of_zeros_to_write);
+                 DWORD written;
+                 if (!WriteFile (get_handle (), zeros, zeros_this_time,
+                                 &written, NULL))
+                   {
+                     __seterrno ();
+                     if (get_errno () == EPIPE)
+                       raise (SIGPIPE);
+                     /* This might fail, but it's the best we can hope for */
+                     SetFilePointer (get_handle (), current_position, NULL,
+                                     FILE_BEGIN);
+                     return -1;
+
+                   }
+                 if (written < zeros_this_time) /* just in case */
+                   {
+                     set_errno (ENOSPC);
+                     /* This might fail, but it's the best we can hope for */
+                     SetFilePointer (get_handle (), current_position, NULL,
+                                     FILE_BEGIN);
+                     return -1;
+                   }
+                 number_of_zeros_to_write -= written;
                }
-             number_of_zeros_to_write -= written;
            }
        }
     }
@@ -876,7 +905,7 @@ fhandler_base::lseek (_off64_t offset, int whence)
     {
       /* When next we write(), we will check to see if *this* seek went beyond
         the end of the file, and back-seek and fill with zeros if so - DJ */
-      set_check_win95_lseek_bug ();
+      set_did_lseek ();
 
       /* If this was a SEEK_CUR with offset 0, we still might have
         readahead that we have to take into account when calculating
@@ -1165,6 +1194,7 @@ fhandler_base::fhandler_base (DWORD devtype, int unit):
   unix_path_name (NULL),
   win32_path_name (NULL),
   open_status (0),
+  fs_flags (0),
   read_state (NULL)
 {
 }
index 8138d1d..ae3becc 100644 (file)
@@ -28,9 +28,10 @@ enum
   FH_SYMLINK   = 0x00100000,   /* is a symlink */
   FH_EXECABL   = 0x00200000,   /* file looked like it would run:
                                 * ends in .exe or .bat or begins with #! */
-  FH_W95LSBUG  = 0x00400000,   /* set when lseek is called as a flag that
+  FH_LSEEKED   = 0x00400000,   /* set when lseek is called as a flag that
                                 * _write should check if we've moved beyond
-                                * EOF, zero filling if so. */
+                                * EOF, zero filling or making file sparse
+                                  if so. */
   FH_NOHANDLE  = 0x00800000,   /* No handle associated with fhandler. */
   FH_NOEINTR   = 0x01000000,   /* Set if I/O should be uninterruptible. */
   FH_FFIXUP    = 0x02000000,   /* Set if need to fixup after fork. */
@@ -167,6 +168,7 @@ class fhandler_base
   const char *unix_path_name;
   const char *win32_path_name;
   DWORD open_status;
+  DWORD fs_flags;
   HANDLE read_state;
 
  public:
@@ -234,8 +236,8 @@ class fhandler_base
       return get_close_on_exec () ? &sec_none_nih : &sec_none;
   }
 
-  void set_check_win95_lseek_bug (int b = 1) { FHCONDSETF (b, W95LSBUG); }
-  bool get_check_win95_lseek_bug () { return FHISSETF (W95LSBUG); }
+  void set_did_lseek (int b = 1) { FHCONDSETF (b, LSEEKED); }
+  bool get_did_lseek () { return FHISSETF (LSEEKED); }
 
   bool get_need_fork_fixup () { return FHISSETF (FFIXUP); }
   void set_need_fork_fixup () { FHSETF (FFIXUP); }
@@ -268,6 +270,10 @@ class fhandler_base
   void set_append_p (int val) { FHCONDSETF (val, APPEND); }
   void set_append_p () { FHSETF (APPEND); }
 
+  void set_fs_flags (DWORD flags) { fs_flags = flags; }
+  bool get_fs_flags (DWORD flagval = 0xffffffffUL)
+    { return (fs_flags & (flagval)); }
+
   bool get_query_open () { return FHISSETF (QUERYOPEN); }
   void set_query_open (bool val) { FHCONDSETF (val, QUERYOPEN); }
 
index 98d1531..64e1a73 100644 (file)
@@ -26,7 +26,6 @@ details. */
 #include "pinfo.h"
 #include <assert.h>
 #include <ctype.h>
-#include <winioctl.h>
 
 #define _COMPILING_NEWLIB
 #include <dirent.h>
@@ -395,19 +394,7 @@ fhandler_disk_file::open (path_conv *real_path, int flags, mode_t mode)
       && !allow_ntsec && allow_ntea)
     set_file_attribute (has_acls (), get_win32_name (), mode);
 
-  /* Set newly created and truncated files as sparse files. */
-  if ((real_path->fs_flags () & FILE_SUPPORTS_SPARSE_FILES)
-      && (get_access () & GENERIC_WRITE) == GENERIC_WRITE
-      && (get_flags () & (O_CREAT | O_TRUNC)))
-    {
-      DWORD dw;
-      HANDLE h = get_handle ();
-      BOOL r = DeviceIoControl (h , FSCTL_SET_SPARSE, NULL, 0,         NULL, 0, &dw,
-                               NULL);
-      syscall_printf ("%d = DeviceIoControl(0x%x, FSCTL_SET_SPARSE, NULL, 0, "
-                     "NULL, 0, &dw, NULL)", r, h);
-    }
-
+  set_fs_flags (real_path->fs_flags ());
   set_symlink_p (real_path->issymlink ());
   set_execable_p (real_path->exec_state ());
   set_socket_p (real_path->issocket ());