From fd47c1834c2bcb8772f7a320ab088d802b1ca649 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 23 Aug 2020 19:37:17 +0200 Subject: [PATCH] supersede: Avoid a failure when writing to /dev/null in Solaris zones. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reported by Jörg Sonnenberger via Thomas Klausner in . * lib/supersede.c (open_supersede): When opening an existing non-regular file on Solaris, use O_CREAT although it should not be necessary. --- ChangeLog | 9 +++++++++ lib/supersede.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 33d4dc0f7a..8ab706ac4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2020-08-23 Bruno Haible + + supersede: Avoid a failure when writing to /dev/null in Solaris zones. + Reported by Jörg Sonnenberger + via Thomas Klausner in + . + * lib/supersede.c (open_supersede): When opening an existing non-regular + file on Solaris, use O_CREAT although it should not be necessary. + 2020-08-23 Bruno Haible verify: Make assume work on bit field expressions (regr. 2020-08-22). diff --git a/lib/supersede.c b/lib/supersede.c index 92317f2fc7..a03cc6d13d 100644 --- a/lib/supersede.c +++ b/lib/supersede.c @@ -78,6 +78,16 @@ open_supersede (const char *filename, int flags, mode_t mode, struct supersede_final_action *action) { int fd; + /* Extra flags for existing devices. */ + int extra_flags = + #if defined __sun + /* open ("/dev/null", O_TRUNC | O_WRONLY) fails with error EINVAL on Solaris + zones. See . As a workaround, add + the O_CREAT flag, although it ought not to be necessary. */ + O_CREAT; + #else + 0; + #endif if (supersede_if_exists) { @@ -89,7 +99,7 @@ open_supersede (const char *filename, int flags, mode_t mode, && ! S_ISREG (statbuf.st_mode) /* The file exists and is possibly a character device, socket, or something like that. */ - && ((fd = open (filename, flags, mode)) >= 0 + && ((fd = open (filename, flags | extra_flags, mode)) >= 0 || errno != ENOENT)) { if (fd >= 0) @@ -167,7 +177,7 @@ open_supersede (const char *filename, int flags, mode_t mode, { /* It is possibly a character device, socket, or something like that. */ - fd = open (canon_filename, flags, mode); + fd = open (canon_filename, flags | extra_flags, mode); if (fd >= 0) { free (canon_filename); @@ -197,6 +207,28 @@ open_supersede (const char *filename, int flags, mode_t mode, action->final_rename_temp = NULL; action->final_rename_dest = NULL; } + #if defined __sun + /* Work around . */ + else if (errno == EINVAL) + { + struct stat statbuf; + + if (stat (filename, &statbuf) >= 0 + && ! S_ISREG (statbuf.st_mode)) + { + /* The file exists and is possibly a character device, socket, + or something like that. As a workaround, add the O_CREAT + flag, although it ought not to be necessary.*/ + fd = open (filename, flags | extra_flags, mode); + if (fd >= 0) + { + /* The file exists. */ + action->final_rename_temp = NULL; + action->final_rename_dest = NULL; + } + } + } + #endif else if (errno == ENOENT) { /* The file does not exist. Use a temporary file. */ -- 2.39.5