Allow unlink/rename of files open by another process on Win32, using a
authorBruce Momjian <bruce@momjian.us>
Wed, 24 Mar 2004 03:54:16 +0000 (03:54 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 24 Mar 2004 03:54:16 +0000 (03:54 +0000)
special Win32 open flag FILE_SHARE_DELETE.

Claudio Natoli

configure
configure.in
src/include/port.h
src/interfaces/libpq/Makefile
src/interfaces/libpq/win32.h
src/port/open.c [new file with mode: 0644]

index 072e851db7d2f17937fbd100dbedd6ff33d33b96..9629ef2602a9d2071d57061639f66db2fbd6c69e 100755 (executable)
--- a/configure
+++ b/configure
@@ -12079,6 +12079,7 @@ esac
 case $host_os in mingw*)
 LIBOBJS="$LIBOBJS copydir.$ac_objext"
 LIBOBJS="$LIBOBJS gettimeofday.$ac_objext"
+LIBOBJS="$LIBOBJS open.$ac_objext"
 LIBOBJS="$LIBOBJS pipe.$ac_objext"
 LIBOBJS="$LIBOBJS rand.$ac_objext" ;;
 esac
index 0a2a719cfb6da59e909cda945b5961041485acab..92756c5b958dc2f9d8771862b1071b97a2fb5836 100644 (file)
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-dnl $PostgreSQL: pgsql/configure.in,v 1.321 2004/03/20 16:11:22 momjian Exp $
+dnl $PostgreSQL: pgsql/configure.in,v 1.322 2004/03/24 03:54:16 momjian Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
@@ -907,6 +907,7 @@ esac
 case $host_os in mingw*)
 AC_LIBOBJ(copydir)
 AC_LIBOBJ(gettimeofday)
+AC_LIBOBJ(open)
 AC_LIBOBJ(pipe)
 AC_LIBOBJ(rand) ;;
 esac
index 4f52075308a3caa849d179ef280af62b7cd11373..70f2b5f3fe5aa0e6ae9f26e9839a206f54ff6d06 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/port.h,v 1.22 2004/03/10 21:12:46 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/port.h,v 1.23 2004/03/24 03:54:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,6 +50,11 @@ extern int   pgunlink(const char *path);
 #endif
 
 #ifdef WIN32
+
+/* open() replacement to allow delete of held files */
+extern int     win32_open(const char*,int,...);
+#define        open(a,b,...)   win32_open(a,b,##__VA_ARGS__)
+
 extern int     copydir(char *fromdir, char *todir);
 
 /* Missing rand functions */
index 4149f9a69616dde98700601b0b8aa49447cb5311..f9031e79b2553bb459dde9bd3ce44ad3eca89894 100644 (file)
@@ -4,7 +4,7 @@
 #
 # Copyright (c) 1994, Regents of the University of California
 #
-# $PostgreSQL: pgsql/src/interfaces/libpq/Makefile,v 1.99 2004/03/12 04:33:41 momjian Exp $
+# $PostgreSQL: pgsql/src/interfaces/libpq/Makefile,v 1.100 2004/03/24 03:54:16 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -23,7 +23,7 @@ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) $(THREAD_CPPFLAGS) -DFRONTEND -DSYS
 OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
       fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o \
       dllist.o md5.o ip.o wchar.o encnames.o \
-      $(filter crypt.o getaddrinfo.o inet_aton.o noblock.o snprintf.o strerror.o path.o thread.o, $(LIBOBJS))
+      $(filter crypt.o getaddrinfo.o inet_aton.o noblock.o snprintf.o strerror.o open.o path.o thread.o, $(LIBOBJS))
 ifeq ($(PORTNAME), win32)
 OBJS+=win32.o
 endif
@@ -52,7 +52,7 @@ backend_src = $(top_srcdir)/src/backend
 # For port modules, this only happens if configure decides the module
 # is needed (see filter hack in OBJS, above).
 
-crypt.c getaddrinfo.c inet_aton.c noblock.c snprintf.c strerror.c path.c thread.c: % : $(top_srcdir)/src/port/%
+crypt.c getaddrinfo.c inet_aton.c noblock.c snprintf.c strerror.c open.c path.c thread.c: % : $(top_srcdir)/src/port/%
        rm -f $@ && $(LN_S) $< .
 
 md5.c ip.c: % : $(backend_src)/libpq/%
index 468e786dccc905f7cf91aa34b70cd5953a3b85da..9d4557fc0d51d8e52468fdc15fa0f08915ae0c81 100644 (file)
@@ -16,7 +16,7 @@
 #define _strnicmp(a,b,c) strnicmp(a,b,c)
 #define _errno errno
 #else
-#define open(a,b,c) _open(a,b,c)
+/* open provided elsewhere */
 #define close(a) _close(a)
 #define read(a,b,c) _read(a,b,c)
 #define write(a,b,c) _write(a,b,c)
diff --git a/src/port/open.c b/src/port/open.c
new file mode 100644 (file)
index 0000000..ccd2a15
--- /dev/null
@@ -0,0 +1,97 @@
+/*-------------------------------------------------------------------------
+ *
+ * open.c
+ *        Win32 open() replacement
+ *
+ *
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ *
+ * $PostgreSQL: pgsql/src/port/open.c,v 1.1 2004/03/24 03:54:16 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef WIN32
+
+#include <windows.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <assert.h>
+
+int openFlagsToCreateFileFlags(int openFlags)
+{
+       switch (openFlags & (O_CREAT|O_TRUNC|O_EXCL))
+       {
+               case 0:
+               case O_EXCL:    return OPEN_EXISTING;
+
+               case O_CREAT:   return OPEN_ALWAYS;
+
+               case O_TRUNC:
+               case O_TRUNC|O_EXCL:    return TRUNCATE_EXISTING;
+
+               case O_CREAT|O_TRUNC:   return CREATE_ALWAYS;
+
+               case O_CREAT|O_EXCL:
+               case O_CREAT|O_TRUNC|O_EXCL:    return CREATE_NEW;
+       }
+
+       /* will never get here */
+       return 0;
+}
+
+/*
+ *   - file attribute setting, based on fileMode?
+ *   - handle other flags? (eg FILE_FLAG_NO_BUFFERING/FILE_FLAG_WRITE_THROUGH)
+ */
+int win32_open(const char* fileName, int fileFlags, ...)
+{
+       int fd;
+       HANDLE h;
+       SECURITY_ATTRIBUTES sa;
+
+       /* Check that we can handle the request */
+       assert((fileFlags & ((O_RDONLY|O_WRONLY|O_RDWR) | O_APPEND      |
+                                                (O_RANDOM|O_SEQUENTIAL|O_TEMPORARY)    |
+                                                _O_SHORT_LIVED                                                 |
+                                                (O_CREAT|O_TRUNC|O_EXCL) | (O_TEXT|O_BINARY))) == fileFlags);
+
+       sa.nLength=sizeof(sa);
+       sa.bInheritHandle=TRUE;
+       sa.lpSecurityDescriptor=NULL;
+
+       if ((h = CreateFile(fileName,
+                                               /* cannot use O_RDONLY, as it == 0 */
+                                               (fileFlags & O_RDWR)     ? (GENERIC_WRITE | GENERIC_READ) :
+                                               ((fileFlags &  O_WRONLY) ?  GENERIC_WRITE : GENERIC_READ),
+                                               (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE),
+                                               &sa,
+                                               openFlagsToCreateFileFlags(fileFlags),
+                                               FILE_ATTRIBUTE_NORMAL   |
+                                               ((fileFlags &  O_RANDOM)                ? FILE_FLAG_RANDOM_ACCESS       : 0) |
+                                               ((fileFlags &  O_SEQUENTIAL)    ? FILE_FLAG_SEQUENTIAL_SCAN     : 0) |
+                                               ((fileFlags & _O_SHORT_LIVED)   ? FILE_ATTRIBUTE_TEMPORARY      : 0) |
+                                               ((fileFlags &  O_TEMPORARY)             ? FILE_FLAG_DELETE_ON_CLOSE     : 0),
+                                               NULL)) == INVALID_HANDLE_VALUE)
+       {
+               switch (GetLastError())
+               {
+                       /* EMFILE, ENFILE should not occur from CreateFile. */
+                       case ERROR_PATH_NOT_FOUND:
+                       case ERROR_FILE_NOT_FOUND:      errno = ENOENT; break;
+                       case ERROR_FILE_EXISTS:         errno = EEXIST; break;
+                       case ERROR_ACCESS_DENIED:       errno = EACCES; break;
+                       default:
+                               errno = EINVAL;
+               }
+               return -1;
+       }
+
+       /* _open_osfhandle will, on error, set errno accordingly */
+       if ((fd = _open_osfhandle((long)h,fileFlags&O_APPEND)) < 0 ||
+               (fileFlags&(O_TEXT|O_BINARY) && (_setmode(fd,fileFlags&(O_TEXT|O_BINARY)) < 0)))
+               CloseHandle(h); /* will not affect errno */
+       return fd;
+}
+
+#endif