Allow unlink/rename of files open by another process on Win32, using a
authorBruce Momjian
Wed, 24 Mar 2004 03:54:16 +0000 (03:54 +0000)
committerBruce Momjian
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 
+#include 
+#include 
+#include 
+
+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