Merge branch 'cloexec' into 'master'

Set CLOEXEC when opening files

Closes #213

See merge request cairo/cairo!563
This commit is contained in:
Adrian Johnson 2024-06-08 22:20:17 +00:00
commit a308881018
3 changed files with 90 additions and 17 deletions

View file

@ -48,6 +48,9 @@
#ifdef HAVE_XLOCALE_H
#include <xlocale.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
COMPILE_TIME_ASSERT ((int)CAIRO_STATUS_LAST_STATUS < (int)CAIRO_INT_STATUS_UNSUPPORTED);
COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127);
@ -956,14 +959,40 @@ _cairo_fopen (const char *filename, const char *mode, FILE **file_out)
return status;
}
result = _wfopen(filename_w, mode_w);
result = _wfopen (filename_w, mode_w);
free (filename_w);
free (mode_w);
#else /* Use fopen directly */
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)
/* Glibc 2.7 supports the "e" mode flag that opens the file with O_CLOEXEC.
* this avoid the race condition in the fcntl fallback below. */
char new_mode[20];
snprintf (new_mode, sizeof (new_mode), "%s%s", mode, "e");
result = fopen (filename, new_mode);
#else /* fopen "e" not available */
result = fopen (filename, mode);
#endif
#if defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
/* Manually set CLOEXEC */
if (result != NULL) {
int fd = fileno (result);
if (fd != -1) {
int flags = fcntl (fd, F_GETFD);
if (flags >= 0)
flags = fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
}
}
#endif /* defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) */
#endif /* fopen "e" not available */
#endif /* !_WIN32 */
*file_out = result;
@ -971,18 +1000,15 @@ _cairo_fopen (const char *filename, const char *mode, FILE **file_out)
}
#ifdef _WIN32
#include <windows.h>
#include <io.h>
#if !_WIN32_WCE
/* tmpfile() replacement for Windows.
*
* On Windows tmpfile() creates the file in the root directory. This
* may fail due to insufficient privileges. However, this isn't a
* problem on Windows CE so we don't use it there.
* may fail due to insufficient privileges.
*/
FILE *
static FILE *
_cairo_win32_tmpfile (void)
{
DWORD path_len;
@ -996,7 +1022,7 @@ _cairo_win32_tmpfile (void)
if (path_len <= 0 || path_len >= MAX_PATH)
return NULL;
if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0)
if (GetTempFileNameW (path_name, L"cairo_", 0, file_name) == 0)
return NULL;
handle = CreateFileW (file_name,
@ -1025,10 +1051,60 @@ _cairo_win32_tmpfile (void)
return fp;
}
#endif /* !_WIN32_WCE */
#endif /* _WIN32 */
/**
* _cairo_tmpfile:
*
* Exactly like the C library function. On platforms that support
* O_CLOEXEC, the file will be opened with this flag. On Windows, the
* file is opened in the temp directory instead of the root directory.
*
* Return value: a file handle or NULL on error.
**/
FILE *
_cairo_tmpfile (void)
{
#ifdef _WIN32
return _cairo_win32_tmpfile ();
#else /* !_WIN32 */
int fd;
FILE *file;
int flags;
#ifdef O_TMPFILE
fd = open(P_tmpdir,
O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC,
0600);
if (fd == -1 && errno == ENOENT) {
fd = open("/tmp",
O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC,
0600);
}
if (fd != -1)
return fdopen (fd, "wb+");
/* Fallback */
#endif /* O_TMPFILE */
file = tmpfile();
#if defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC)
/* Manually set CLOEXEC */
if (file != NULL) {
fd = fileno(file);
if (fd != -1) {
flags = fcntl(fd, F_GETFD);
if (flags >= 0 && !(flags & FD_CLOEXEC))
fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
}
}
#endif /* defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) */
return file;
#endif /* !_WIN32 */
}
typedef struct _cairo_intern_string {
cairo_hash_entry_t hash_entry;
int len;

View file

@ -1115,7 +1115,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->final_stream = stream;
surface->tmpfile = tmpfile ();
surface->tmpfile = _cairo_tmpfile ();
if (surface->tmpfile == NULL) {
switch (errno) {
case ENOMEM:

View file

@ -89,12 +89,6 @@
CAIRO_BEGIN_DECLS
#if _WIN32 && !_WIN32_WCE /* Permissions on WinCE? No worries! */
cairo_private FILE *
_cairo_win32_tmpfile (void);
#define tmpfile() _cairo_win32_tmpfile()
#endif
#undef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
@ -1962,6 +1956,9 @@ _cairo_observers_notify (cairo_list_t *observers, void *arg);
cairo_private cairo_status_t
_cairo_fopen (const char *filename, const char *mode, FILE **file_out);
cairo_private FILE *
_cairo_tmpfile (void);
#include "cairo-mutex-private.h"
#include "cairo-fixed-private.h"
#include "cairo-wideint-private.h"