From b8fd6756e28a27224c90d3e82ce9dc93af5951c2 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Wed, 24 Mar 2004 03:54:16 +0000 Subject: [PATCH] Allow unlink/rename of files open by another process on Win32, using a special Win32 open flag FILE_SHARE_DELETE. Claudio Natoli --- configure | 1 + configure.in | 3 +- src/include/port.h | 7 ++- src/interfaces/libpq/Makefile | 6 +-- src/interfaces/libpq/win32.h | 2 +- src/port/open.c | 97 +++++++++++++++++++++++++++++++++++ 6 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 src/port/open.c diff --git a/configure b/configure index 072e851db7..9629ef2602 100755 --- 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 diff --git a/configure.in b/configure.in index 0a2a719cfb..92756c5b95 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/src/include/port.h b/src/include/port.h index 4f52075308..70f2b5f3fe 100644 --- a/src/include/port.h +++ b/src/include/port.h @@ -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 */ diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile index 4149f9a696..f9031e79b2 100644 --- a/src/interfaces/libpq/Makefile +++ b/src/interfaces/libpq/Makefile @@ -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/% diff --git a/src/interfaces/libpq/win32.h b/src/interfaces/libpq/win32.h index 468e786dcc..9d4557fc0d 100644 --- a/src/interfaces/libpq/win32.h +++ b/src/interfaces/libpq/win32.h @@ -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 index 0000000000..ccd2a15b1d --- /dev/null +++ b/src/port/open.c @@ -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