#include "pixie-file.h" #if defined(WIN32) #include #include #include #define access _access #else #include #include #endif int pixie_fopen_shareable(FILE **in_fp, const char *filename, unsigned is_append) { FILE *fp; *in_fp = NULL; #if defined(WIN32) /* PORTABILITY: WINDOWS * This bit of code deals with the fact that on Windows, fopen() opens * a file so that it can't be moved. This code opens it a different * way so that we can move it. * * NOTE: this is probably overkill, it appears that there is a better * API _fsopen() that does what I want without all this nonsense. */ { HANDLE hFile; int fd; /* The normal POSIX C functions lock the file */ /* int fd = open(filename, O_RDWR | O_CREAT, _S_IREAD | _S_IWRITE); */ /* Fails */ /* int fd = _sopen(filename, O_RDWR | O_CREAT, _SH_DENYNO, _S_IREAD | _S_IWRITE); */ /* Also fails */ /* We need to use WINAPI + _open_osfhandle to be able to use file descriptors (instead of WINAPI handles) */ hFile = CreateFileA( filename, GENERIC_WRITE | (is_append?FILE_APPEND_DATA:0), FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); if (hFile == INVALID_HANDLE_VALUE) { return -1; } fd = _open_osfhandle((intptr_t)hFile, _O_CREAT | _O_RDONLY | _O_TEMPORARY); if (fd == -1) { perror("_open_osfhandle"); return -1; } fp = _fdopen(fd, "w"); } #else fp = fopen(filename, is_append?"a":"w"); if (fp == NULL) return errno; #endif *in_fp = fp; return 0; }