4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 #include <sys/types.h>
42 #ifdef HAVE_SYS_SOCKET_H
43 #include <sys/socket.h>
46 #ifdef HAVE_SYS_WAIT_H
50 #include <nbdkit-plugin.h>
52 #include "windows-compat.h"
56 /* Convert exit status to nbd_error. If the exit status was nonzero
57 * or another failure then -1 is returned.
60 exit_status_to_nbd_error (int status
, const char *cmd
)
62 if (WIFEXITED (status
) && WEXITSTATUS (status
) != 0) {
63 nbdkit_error ("%s: command failed with exit code %d",
64 cmd
, WEXITSTATUS (status
));
67 else if (WIFSIGNALED (status
)) {
68 nbdkit_error ("%s: command was killed by signal %d",
69 cmd
, WTERMSIG (status
));
72 else if (WIFSTOPPED (status
)) {
73 nbdkit_error ("%s: command was stopped by signal %d",
74 cmd
, WSTOPSIG (status
));
83 /* This assumes we're using Win32 system(). See:
84 * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/system-wsystem?view=vs-2019
87 exit_status_to_nbd_error (int status
, const char *cmd
)
92 nbdkit_error ("%s: command failed: errno = %d", cmd
, errno
);
100 /* Set the FD_CLOEXEC flag on the given fd, if it is non-negative.
101 * On failure, close fd and return -1; on success, return fd.
103 * Note that this function should ONLY be used on platforms that lack
104 * atomic CLOEXEC support during fd creation (such as Haiku in 2019);
105 * when using it as a fallback path, you must also consider how to
106 * prevent fd leaks to plugins that want to fork().
111 #if (defined SOCK_CLOEXEC && defined HAVE_MKOSTEMP && defined HAVE_PIPE2 && \
112 defined HAVE_ACCEPT4)
113 nbdkit_error ("prefer creating fds with CLOEXEC atomically set");
118 # if !defined __APPLE__ && \
119 (defined SOCK_CLOEXEC || defined HAVE_MKOSTEMP || defined HAVE_PIPE2 || \
120 defined HAVE_ACCEPT4)
121 # error "Unexpected: your system has incomplete atomic CLOEXEC support"
129 f
= fcntl (fd
, F_GETFD
);
130 if (f
== -1 || fcntl (fd
, F_SETFD
, f
| FD_CLOEXEC
) == -1) {
132 nbdkit_error ("fcntl: %m");
153 /* Set the O_NONBLOCK flag on the given fd, if it is non-negative.
154 * On failure, close fd and return -1; on success, return fd.
157 set_nonblock (int fd
)
165 f
= fcntl (fd
, F_GETFL
);
166 if (f
== -1 || fcntl (fd
, F_SETFL
, f
| O_NONBLOCK
) == -1) {
168 nbdkit_error ("fcntl: %m");
179 set_nonblock (int fd
)
189 make_temporary_directory (void)
191 char template[] = "/tmp/nbdkitXXXXXX";
193 if (mkdtemp (template) == NULL
)
196 return strdup (template);
202 make_temporary_directory (void)
204 char tmppath
[MAX_PATH
];
205 char tmpname
[MAX_PATH
];
208 ret
= GetTempPath (MAX_PATH
, tmppath
);
209 if (ret
> MAX_PATH
|| ret
== 0) {
210 fprintf (stderr
, "mkdtemp: GetTempPath: %lu\n", GetLastError ());
214 ret
= GetTempFileName (tmppath
, TEXT ("nbdkit"), 0, tmpname
);
216 fprintf (stderr
, "mkdtemp: GetTempFileName: %lu\n", GetLastError ());
220 /* The above function actually creates the file, so we must remove
221 * it before creating the directory. Not ideal because it leaves a
222 * small window for exploitation (XXX).
226 if (mkdir (tmpname
) == -1) {
227 fprintf (stderr
, "mkdtemp: mkdir: %s: %lu\n", tmpname
, GetLastError ());
231 return strdup (tmpname
);