+2020-08-23 Bruno Haible <bruno@clisp.org>
+
+ supersede: Avoid a failure when writing to /dev/null in Solaris zones.
+ Reported by Jörg Sonnenberger <joerg@netbsd.org>
+ via Thomas Klausner <tk@giga.or.at> in
+ <https://pkgsrc.se/files.php?messageId=20200812233110.30230FB28@cvs.NetBSD.org>.
+ * 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 <bruno@clisp.org>
verify: Make assume work on bit field expressions (regr. 2020-08-22).
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 <https://www.illumos.org/issues/13035>. As a workaround, add
+ the O_CREAT flag, although it ought not to be necessary. */
+ O_CREAT;
+ #else
+ 0;
+ #endif
if (supersede_if_exists)
{
&& ! 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)
{
/* 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);
action->final_rename_temp = NULL;
action->final_rename_dest = NULL;
}
+ #if defined __sun
+ /* Work around <https://www.illumos.org/issues/13035>. */
+ 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. */