bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: fix inadequate Windows implementation of tmpfile


From: Bruno Haible
Subject: Re: fix inadequate Windows implementation of tmpfile
Date: Fri, 16 Feb 2007 04:03:34 +0100
User-agent: KMail/1.5.4

Ben Pfaff wrote:
> There seems to be some kind of problem with
> FILE_FLAG_DELETE_ON_CLOSE, with which _O_TEMPORARY is presumably
> implemented, under Windows 95:
>         http://cygwin.com/ml/cygwin-cvs/2003-q4/msg00025.html
> 
> In fact, it appears that FILE_FLAG_DELETE_ON_CLOSE works on NT
> derivatives, not on the older Windows systems, based on the
> has_delete_on_close definitions here (sorry about citing a patch
> when a source file would probably be better, this is based on a
> very quick search):
>         http://www.cygwin.com/ml/cygwin-patches/2003-q1/msg00170.html
> 
> Where it works, it appears to be implemented such that it always
> works, even if a program is terminated abruptly, based on what
> I've read on the web.

Thanks for these explanations. It appears worth to use this in the
clean-temp module.

2007-02-15  Bruno Haible  <address@hidden>

        * lib/clean-temp.c [WIN32 && !CYGWIN]: Include <windows.h>.
        (supports_delete_on_close): New function.
        (open_temp, fopen_temp): Use _O_TEMPORARY when supported.

*** lib/clean-temp.c    14 Jan 2007 11:32:10 -0000      1.11
--- lib/clean-temp.c    16 Feb 2007 02:38:34 -0000
***************
*** 1,5 ****
  /* Temporary directories and temporary files with automatic cleanup.
!    Copyright (C) 2001, 2003, 2006 Free Software Foundation, Inc.
     Written by Bruno Haible <address@hidden>, 2006.
  
     This program is free software; you can redistribute it and/or modify
--- 1,5 ----
  /* Temporary directories and temporary files with automatic cleanup.
!    Copyright (C) 2001, 2003, 2006-2007 Free Software Foundation, Inc.
     Written by Bruno Haible <address@hidden>, 2006.
  
     This program is free software; you can redistribute it and/or modify
***************
*** 30,35 ****
--- 30,40 ----
  #include <string.h>
  #include <unistd.h>
  
+ #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+ # include <windows.h>
+ #endif
+ 
  #include "error.h"
  #include "fatal-signal.h"
  #include "pathmax.h"
***************
*** 563,568 ****
--- 568,600 ----
  }
  
  
+ #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ 
+ /* On Windows, opening a file with _O_TEMPORARY has the effect of passing
+    the FILE_FLAG_DELETE_ON_CLOSE flag to CreateFile(), which has the effect
+    of deleting the file when it is closed - even when the program crashes.
+    But (according to the Cygwin sources) it works only on Windows NT or newer.
+    So we cache the info whether we are running on Windows NT or newer.  */
+ 
+ static bool
+ supports_delete_on_close ()
+ {
+   static int known; /* 1 = yes, -1 = no, 0 = unknown */
+   if (!known)
+     {
+       OSVERSIONINFO v;
+ 
+       if (GetVersionEx (&v))
+       known = (v.dwPlatformId == VER_PLATFORM_WIN32_NT ? 1 : -1);
+       else
+       known = -1;
+     }
+   return (known > 0);
+ }
+ 
+ #endif
+ 
+ 
  /* Register a file descriptor to be closed.  */
  static void
  register_fd (int fd)
***************
*** 598,604 ****
    int saved_errno;
  
    block_fatal_signals ();
!   fd = open (file_name, flags, mode); /* actually open or open_safer */
    saved_errno = errno;
    if (fd >= 0)
      register_fd (fd);
--- 630,644 ----
    int saved_errno;
  
    block_fatal_signals ();
!   /* Note: 'open' here is actually open() or open_safer().  */
! #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
!   /* Use _O_TEMPORARY when possible, to increase the chances that the
!      temporary file is removed when the process crashes.  */
!   if (supports_delete_on_close ())
!     fd = open (file_name, flags | _O_TEMPORARY, mode);
!   else
! #endif
!     fd = open (file_name, flags, mode);
    saved_errno = errno;
    if (fd >= 0)
      register_fd (fd);
***************
*** 616,623 ****
    int saved_errno;
  
    block_fatal_signals ();
!   fp = fopen (file_name, mode); /* actually fopen or fopen_safer */
!   saved_errno = errno;
    if (fp != NULL)
      {
        /* It is sufficient to register fileno (fp) instead of the entire fp,
--- 656,683 ----
    int saved_errno;
  
    block_fatal_signals ();
!   /* Note: 'fopen' here is actually fopen() or fopen_safer().  */
! #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
!   /* Use _O_TEMPORARY when possible, to increase the chances that the
!      temporary file is removed when the process crashes.  */
!   if (supports_delete_on_close ())
!     {
!       size_t mode_len = strlen (mode);
!       char *augmented_mode = (char *) xallocsa (mode_len + 2);
!       memcpy (augmented_mode, mode, mode_len);
!       memcpy (augmented_mode + mode_len, "D", 2);
! 
!       fp = fopen (file_name, augmented_mode);
!       saved_errno = errno;
! 
!       freesa (augmented_mode);
!     }
!   else
! #endif
!     {
!       fp = fopen (file_name, mode);
!       saved_errno = errno;
!     }
    if (fp != NULL)
      {
        /* It is sufficient to register fileno (fp) instead of the entire fp,





reply via email to

[Prev in Thread] Current Thread [Next in Thread]