/* * - 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_DSYNC | (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), /* These flags allow concurrent rename/unlink */ (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) | ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 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; }
/* * - file attribute setting, based on fileMode? */ int pgwin32_open(const char *fileName, int fileFlags,...) { int fd; HANDLE h = INVALID_HANDLE_VALUE; SECURITY_ATTRIBUTES sa; int loops = 0; /* 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_DSYNC | O_DIRECT | (O_CREAT | O_TRUNC | O_EXCL) | (O_TEXT | O_BINARY))) == fileFlags); sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; while ((h = CreateFile(fileName, /* cannot use O_RDONLY, as it == 0 */ (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) : ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ), /* These flags allow concurrent rename/unlink */ (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) | ((fileFlags & O_DIRECT) ? FILE_FLAG_NO_BUFFERING : 0) | ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0), NULL)) == INVALID_HANDLE_VALUE) { /* * Sharing violation or locking error can indicate antivirus, backup * or similar software that's locking the file. Try again for 30 seconds * before giving up. */ DWORD err = GetLastError(); if (err == ERROR_SHARING_VIOLATION || err == ERROR_LOCK_VIOLATION) { pg_usleep(100000); loops++; #ifndef FRONTEND if (loops == 50) ereport(LOG, (errmsg("could not open file \"%s\": %s", fileName, (err == ERROR_SHARING_VIOLATION)?_("sharing violation"):_("lock violation")), errdetail("Continuing to retry for 30 seconds."), errhint("You might have antivirus, backup, or similar software interfering with the database system."))); #endif if (loops < 300) continue; } _dosmaperr(err); return -1; } /* _open_osfhandle will, on error, set errno accordingly */ if ((fd = _open_osfhandle((long) h, fileFlags & O_APPEND)) < 0) CloseHandle(h); /* will not affect errno */ else if (fileFlags & (O_TEXT | O_BINARY) && _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0) { _close(fd); return -1; } return fd; }