root / os-posix.c @ 93148aa5
History | View | Annotate | Download (8.2 kB)
1 | 86b645e7 | Jes Sorensen | /*
|
---|---|---|---|
2 | 86b645e7 | Jes Sorensen | * os-posix.c
|
3 | 86b645e7 | Jes Sorensen | *
|
4 | 86b645e7 | Jes Sorensen | * Copyright (c) 2003-2008 Fabrice Bellard
|
5 | 86b645e7 | Jes Sorensen | * Copyright (c) 2010 Red Hat, Inc.
|
6 | 86b645e7 | Jes Sorensen | *
|
7 | 86b645e7 | Jes Sorensen | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
8 | 86b645e7 | Jes Sorensen | * of this software and associated documentation files (the "Software"), to deal
|
9 | 86b645e7 | Jes Sorensen | * in the Software without restriction, including without limitation the rights
|
10 | 86b645e7 | Jes Sorensen | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11 | 86b645e7 | Jes Sorensen | * copies of the Software, and to permit persons to whom the Software is
|
12 | 86b645e7 | Jes Sorensen | * furnished to do so, subject to the following conditions:
|
13 | 86b645e7 | Jes Sorensen | *
|
14 | 86b645e7 | Jes Sorensen | * The above copyright notice and this permission notice shall be included in
|
15 | 86b645e7 | Jes Sorensen | * all copies or substantial portions of the Software.
|
16 | 86b645e7 | Jes Sorensen | *
|
17 | 86b645e7 | Jes Sorensen | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18 | 86b645e7 | Jes Sorensen | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19 | 86b645e7 | Jes Sorensen | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
20 | 86b645e7 | Jes Sorensen | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21 | 86b645e7 | Jes Sorensen | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22 | 86b645e7 | Jes Sorensen | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23 | 86b645e7 | Jes Sorensen | * THE SOFTWARE.
|
24 | 86b645e7 | Jes Sorensen | */
|
25 | 86b645e7 | Jes Sorensen | |
26 | 86b645e7 | Jes Sorensen | #include <unistd.h> |
27 | 86b645e7 | Jes Sorensen | #include <fcntl.h> |
28 | 86b645e7 | Jes Sorensen | #include <signal.h> |
29 | 8d963e6a | Jes Sorensen | #include <sys/types.h> |
30 | 8d963e6a | Jes Sorensen | #include <sys/wait.h> |
31 | 69e8b162 | Jes Sorensen | /*needed for MAP_POPULATE before including qemu-options.h */
|
32 | 69e8b162 | Jes Sorensen | #include <sys/mman.h> |
33 | 8847cfe8 | Jes Sorensen | #include <pwd.h> |
34 | cc4662f9 | Stefan Hajnoczi | #include <grp.h> |
35 | 6170540b | Jes Sorensen | #include <libgen.h> |
36 | 86b645e7 | Jes Sorensen | |
37 | 86b645e7 | Jes Sorensen | /* Needed early for CONFIG_BSD etc. */
|
38 | 86b645e7 | Jes Sorensen | #include "config-host.h" |
39 | 86b645e7 | Jes Sorensen | #include "sysemu.h" |
40 | 59a5264b | Jes Sorensen | #include "net/slirp.h" |
41 | 59a5264b | Jes Sorensen | #include "qemu-options.h" |
42 | 86b645e7 | Jes Sorensen | |
43 | ce798cf2 | Jes Sorensen | #ifdef CONFIG_LINUX
|
44 | ce798cf2 | Jes Sorensen | #include <sys/prctl.h> |
45 | 949d31e6 | Jes Sorensen | #endif
|
46 | 949d31e6 | Jes Sorensen | |
47 | 8847cfe8 | Jes Sorensen | static struct passwd *user_pwd; |
48 | 0766379d | Jes Sorensen | static const char *chroot_dir; |
49 | eb505be1 | Jes Sorensen | static int daemonize; |
50 | eb505be1 | Jes Sorensen | static int fds[2]; |
51 | 8847cfe8 | Jes Sorensen | |
52 | fe98ac14 | Jes Sorensen | void os_setup_early_signal_handling(void) |
53 | 86b645e7 | Jes Sorensen | { |
54 | 86b645e7 | Jes Sorensen | struct sigaction act;
|
55 | 86b645e7 | Jes Sorensen | sigfillset(&act.sa_mask); |
56 | 86b645e7 | Jes Sorensen | act.sa_flags = 0;
|
57 | 86b645e7 | Jes Sorensen | act.sa_handler = SIG_IGN; |
58 | 86b645e7 | Jes Sorensen | sigaction(SIGPIPE, &act, NULL);
|
59 | 86b645e7 | Jes Sorensen | } |
60 | 8d963e6a | Jes Sorensen | |
61 | f64622c4 | Gleb Natapov | static void termsig_handler(int signal, siginfo_t *info, void *c) |
62 | 8d963e6a | Jes Sorensen | { |
63 | f64622c4 | Gleb Natapov | qemu_system_killed(info->si_signo, info->si_pid); |
64 | 8d963e6a | Jes Sorensen | } |
65 | 8d963e6a | Jes Sorensen | |
66 | 8d963e6a | Jes Sorensen | void os_setup_signal_handling(void) |
67 | 8d963e6a | Jes Sorensen | { |
68 | 8d963e6a | Jes Sorensen | struct sigaction act;
|
69 | 8d963e6a | Jes Sorensen | |
70 | 8d963e6a | Jes Sorensen | memset(&act, 0, sizeof(act)); |
71 | f64622c4 | Gleb Natapov | act.sa_sigaction = termsig_handler; |
72 | f64622c4 | Gleb Natapov | act.sa_flags = SA_SIGINFO; |
73 | 8d963e6a | Jes Sorensen | sigaction(SIGINT, &act, NULL);
|
74 | 8d963e6a | Jes Sorensen | sigaction(SIGHUP, &act, NULL);
|
75 | 8d963e6a | Jes Sorensen | sigaction(SIGTERM, &act, NULL);
|
76 | 8d963e6a | Jes Sorensen | } |
77 | 6170540b | Jes Sorensen | |
78 | 6170540b | Jes Sorensen | /* Find a likely location for support files using the location of the binary.
|
79 | 6170540b | Jes Sorensen | For installed binaries this will be "$bindir/../share/qemu". When
|
80 | 6170540b | Jes Sorensen | running from the build tree this will be "$bindir/../pc-bios". */
|
81 | 6170540b | Jes Sorensen | #define SHARE_SUFFIX "/share/qemu" |
82 | 6170540b | Jes Sorensen | #define BUILD_SUFFIX "/pc-bios" |
83 | 6170540b | Jes Sorensen | char *os_find_datadir(const char *argv0) |
84 | 6170540b | Jes Sorensen | { |
85 | 6170540b | Jes Sorensen | char *dir;
|
86 | 6170540b | Jes Sorensen | char *p = NULL; |
87 | 6170540b | Jes Sorensen | char *res;
|
88 | 6170540b | Jes Sorensen | char buf[PATH_MAX];
|
89 | 6170540b | Jes Sorensen | size_t max_len; |
90 | 6170540b | Jes Sorensen | |
91 | 6170540b | Jes Sorensen | #if defined(__linux__)
|
92 | 6170540b | Jes Sorensen | { |
93 | 6170540b | Jes Sorensen | int len;
|
94 | 6170540b | Jes Sorensen | len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); |
95 | 6170540b | Jes Sorensen | if (len > 0) { |
96 | 6170540b | Jes Sorensen | buf[len] = 0;
|
97 | 6170540b | Jes Sorensen | p = buf; |
98 | 6170540b | Jes Sorensen | } |
99 | 6170540b | Jes Sorensen | } |
100 | 6170540b | Jes Sorensen | #elif defined(__FreeBSD__)
|
101 | 6170540b | Jes Sorensen | { |
102 | 6170540b | Jes Sorensen | static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; |
103 | 6170540b | Jes Sorensen | size_t len = sizeof(buf) - 1; |
104 | 6170540b | Jes Sorensen | |
105 | 6170540b | Jes Sorensen | *buf = '\0';
|
106 | 66fe09ee | Blue Swirl | if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) && |
107 | 6170540b | Jes Sorensen | *buf) { |
108 | 6170540b | Jes Sorensen | buf[sizeof(buf) - 1] = '\0'; |
109 | 6170540b | Jes Sorensen | p = buf; |
110 | 6170540b | Jes Sorensen | } |
111 | 6170540b | Jes Sorensen | } |
112 | 6170540b | Jes Sorensen | #endif
|
113 | 6170540b | Jes Sorensen | /* If we don't have any way of figuring out the actual executable
|
114 | 6170540b | Jes Sorensen | location then try argv[0]. */
|
115 | 6170540b | Jes Sorensen | if (!p) {
|
116 | 6170540b | Jes Sorensen | p = realpath(argv0, buf); |
117 | 6170540b | Jes Sorensen | if (!p) {
|
118 | 6170540b | Jes Sorensen | return NULL; |
119 | 6170540b | Jes Sorensen | } |
120 | 6170540b | Jes Sorensen | } |
121 | 6170540b | Jes Sorensen | dir = dirname(p); |
122 | 6170540b | Jes Sorensen | dir = dirname(dir); |
123 | 6170540b | Jes Sorensen | |
124 | 6170540b | Jes Sorensen | max_len = strlen(dir) + |
125 | 6170540b | Jes Sorensen | MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
|
126 | 7267c094 | Anthony Liguori | res = g_malloc0(max_len); |
127 | 6170540b | Jes Sorensen | snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
|
128 | 6170540b | Jes Sorensen | if (access(res, R_OK)) {
|
129 | 6170540b | Jes Sorensen | snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
|
130 | 6170540b | Jes Sorensen | if (access(res, R_OK)) {
|
131 | 7267c094 | Anthony Liguori | g_free(res); |
132 | 6170540b | Jes Sorensen | res = NULL;
|
133 | 6170540b | Jes Sorensen | } |
134 | 6170540b | Jes Sorensen | } |
135 | 6170540b | Jes Sorensen | |
136 | 6170540b | Jes Sorensen | return res;
|
137 | 6170540b | Jes Sorensen | } |
138 | 6170540b | Jes Sorensen | #undef SHARE_SUFFIX
|
139 | 6170540b | Jes Sorensen | #undef BUILD_SUFFIX
|
140 | 59a5264b | Jes Sorensen | |
141 | ce798cf2 | Jes Sorensen | void os_set_proc_name(const char *s) |
142 | ce798cf2 | Jes Sorensen | { |
143 | ce798cf2 | Jes Sorensen | #if defined(PR_SET_NAME)
|
144 | ce798cf2 | Jes Sorensen | char name[16]; |
145 | ce798cf2 | Jes Sorensen | if (!s)
|
146 | ce798cf2 | Jes Sorensen | return;
|
147 | ce798cf2 | Jes Sorensen | name[sizeof(name) - 1] = 0; |
148 | ce798cf2 | Jes Sorensen | strncpy(name, s, sizeof(name));
|
149 | ce798cf2 | Jes Sorensen | /* Could rewrite argv[0] too, but that's a bit more complicated.
|
150 | ce798cf2 | Jes Sorensen | This simple way is enough for `top'. */
|
151 | ce798cf2 | Jes Sorensen | if (prctl(PR_SET_NAME, name)) {
|
152 | ce798cf2 | Jes Sorensen | perror("unable to change process name");
|
153 | ce798cf2 | Jes Sorensen | exit(1);
|
154 | ce798cf2 | Jes Sorensen | } |
155 | ce798cf2 | Jes Sorensen | #else
|
156 | ce798cf2 | Jes Sorensen | fprintf(stderr, "Change of process name not supported by your OS\n");
|
157 | ce798cf2 | Jes Sorensen | exit(1);
|
158 | ce798cf2 | Jes Sorensen | #endif
|
159 | ce798cf2 | Jes Sorensen | } |
160 | ce798cf2 | Jes Sorensen | |
161 | 59a5264b | Jes Sorensen | /*
|
162 | 59a5264b | Jes Sorensen | * Parse OS specific command line options.
|
163 | 59a5264b | Jes Sorensen | * return 0 if option handled, -1 otherwise
|
164 | 59a5264b | Jes Sorensen | */
|
165 | 59a5264b | Jes Sorensen | void os_parse_cmd_args(int index, const char *optarg) |
166 | 59a5264b | Jes Sorensen | { |
167 | 59a5264b | Jes Sorensen | switch (index) {
|
168 | 59a5264b | Jes Sorensen | #ifdef CONFIG_SLIRP
|
169 | 59a5264b | Jes Sorensen | case QEMU_OPTION_smb:
|
170 | 59a5264b | Jes Sorensen | if (net_slirp_smb(optarg) < 0) |
171 | 59a5264b | Jes Sorensen | exit(1);
|
172 | 59a5264b | Jes Sorensen | break;
|
173 | 59a5264b | Jes Sorensen | #endif
|
174 | 8847cfe8 | Jes Sorensen | case QEMU_OPTION_runas:
|
175 | 8847cfe8 | Jes Sorensen | user_pwd = getpwnam(optarg); |
176 | 8847cfe8 | Jes Sorensen | if (!user_pwd) {
|
177 | 8847cfe8 | Jes Sorensen | fprintf(stderr, "User \"%s\" doesn't exist\n", optarg);
|
178 | 8847cfe8 | Jes Sorensen | exit(1);
|
179 | 8847cfe8 | Jes Sorensen | } |
180 | 8847cfe8 | Jes Sorensen | break;
|
181 | 0766379d | Jes Sorensen | case QEMU_OPTION_chroot:
|
182 | 0766379d | Jes Sorensen | chroot_dir = optarg; |
183 | 0766379d | Jes Sorensen | break;
|
184 | eb505be1 | Jes Sorensen | case QEMU_OPTION_daemonize:
|
185 | eb505be1 | Jes Sorensen | daemonize = 1;
|
186 | eb505be1 | Jes Sorensen | break;
|
187 | 59a5264b | Jes Sorensen | } |
188 | 59a5264b | Jes Sorensen | return;
|
189 | 59a5264b | Jes Sorensen | } |
190 | 8847cfe8 | Jes Sorensen | |
191 | e06eb601 | Jes Sorensen | static void change_process_uid(void) |
192 | 8847cfe8 | Jes Sorensen | { |
193 | 8847cfe8 | Jes Sorensen | if (user_pwd) {
|
194 | 8847cfe8 | Jes Sorensen | if (setgid(user_pwd->pw_gid) < 0) { |
195 | 8847cfe8 | Jes Sorensen | fprintf(stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid);
|
196 | 8847cfe8 | Jes Sorensen | exit(1);
|
197 | 8847cfe8 | Jes Sorensen | } |
198 | cc4662f9 | Stefan Hajnoczi | if (initgroups(user_pwd->pw_name, user_pwd->pw_gid) < 0) { |
199 | cc4662f9 | Stefan Hajnoczi | fprintf(stderr, "Failed to initgroups(\"%s\", %d)\n",
|
200 | cc4662f9 | Stefan Hajnoczi | user_pwd->pw_name, user_pwd->pw_gid); |
201 | cc4662f9 | Stefan Hajnoczi | exit(1);
|
202 | cc4662f9 | Stefan Hajnoczi | } |
203 | 8847cfe8 | Jes Sorensen | if (setuid(user_pwd->pw_uid) < 0) { |
204 | 8847cfe8 | Jes Sorensen | fprintf(stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid);
|
205 | 8847cfe8 | Jes Sorensen | exit(1);
|
206 | 8847cfe8 | Jes Sorensen | } |
207 | 8847cfe8 | Jes Sorensen | if (setuid(0) != -1) { |
208 | 8847cfe8 | Jes Sorensen | fprintf(stderr, "Dropping privileges failed\n");
|
209 | 8847cfe8 | Jes Sorensen | exit(1);
|
210 | 8847cfe8 | Jes Sorensen | } |
211 | 8847cfe8 | Jes Sorensen | } |
212 | 8847cfe8 | Jes Sorensen | } |
213 | 0766379d | Jes Sorensen | |
214 | e06eb601 | Jes Sorensen | static void change_root(void) |
215 | 0766379d | Jes Sorensen | { |
216 | 0766379d | Jes Sorensen | if (chroot_dir) {
|
217 | 0766379d | Jes Sorensen | if (chroot(chroot_dir) < 0) { |
218 | 0766379d | Jes Sorensen | fprintf(stderr, "chroot failed\n");
|
219 | 0766379d | Jes Sorensen | exit(1);
|
220 | 0766379d | Jes Sorensen | } |
221 | 0766379d | Jes Sorensen | if (chdir("/")) { |
222 | 0766379d | Jes Sorensen | perror("not able to chdir to /");
|
223 | 0766379d | Jes Sorensen | exit(1);
|
224 | 0766379d | Jes Sorensen | } |
225 | 0766379d | Jes Sorensen | } |
226 | 0766379d | Jes Sorensen | |
227 | 0766379d | Jes Sorensen | } |
228 | eb505be1 | Jes Sorensen | |
229 | eb505be1 | Jes Sorensen | void os_daemonize(void) |
230 | eb505be1 | Jes Sorensen | { |
231 | eb505be1 | Jes Sorensen | if (daemonize) {
|
232 | eb505be1 | Jes Sorensen | pid_t pid; |
233 | eb505be1 | Jes Sorensen | |
234 | eb505be1 | Jes Sorensen | if (pipe(fds) == -1) |
235 | eb505be1 | Jes Sorensen | exit(1);
|
236 | eb505be1 | Jes Sorensen | |
237 | eb505be1 | Jes Sorensen | pid = fork(); |
238 | eb505be1 | Jes Sorensen | if (pid > 0) { |
239 | eb505be1 | Jes Sorensen | uint8_t status; |
240 | eb505be1 | Jes Sorensen | ssize_t len; |
241 | eb505be1 | Jes Sorensen | |
242 | eb505be1 | Jes Sorensen | close(fds[1]);
|
243 | eb505be1 | Jes Sorensen | |
244 | eb505be1 | Jes Sorensen | again:
|
245 | eb505be1 | Jes Sorensen | len = read(fds[0], &status, 1); |
246 | eb505be1 | Jes Sorensen | if (len == -1 && (errno == EINTR)) |
247 | eb505be1 | Jes Sorensen | goto again;
|
248 | eb505be1 | Jes Sorensen | |
249 | eb505be1 | Jes Sorensen | if (len != 1) |
250 | eb505be1 | Jes Sorensen | exit(1);
|
251 | eb505be1 | Jes Sorensen | else if (status == 1) { |
252 | eb505be1 | Jes Sorensen | fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno));
|
253 | eb505be1 | Jes Sorensen | exit(1);
|
254 | eb505be1 | Jes Sorensen | } else
|
255 | eb505be1 | Jes Sorensen | exit(0);
|
256 | eb505be1 | Jes Sorensen | } else if (pid < 0) |
257 | eb505be1 | Jes Sorensen | exit(1);
|
258 | eb505be1 | Jes Sorensen | |
259 | eb505be1 | Jes Sorensen | close(fds[0]);
|
260 | eb505be1 | Jes Sorensen | qemu_set_cloexec(fds[1]);
|
261 | eb505be1 | Jes Sorensen | |
262 | eb505be1 | Jes Sorensen | setsid(); |
263 | eb505be1 | Jes Sorensen | |
264 | eb505be1 | Jes Sorensen | pid = fork(); |
265 | eb505be1 | Jes Sorensen | if (pid > 0) |
266 | eb505be1 | Jes Sorensen | exit(0);
|
267 | eb505be1 | Jes Sorensen | else if (pid < 0) |
268 | eb505be1 | Jes Sorensen | exit(1);
|
269 | eb505be1 | Jes Sorensen | |
270 | eb505be1 | Jes Sorensen | umask(027);
|
271 | eb505be1 | Jes Sorensen | |
272 | eb505be1 | Jes Sorensen | signal(SIGTSTP, SIG_IGN); |
273 | eb505be1 | Jes Sorensen | signal(SIGTTOU, SIG_IGN); |
274 | eb505be1 | Jes Sorensen | signal(SIGTTIN, SIG_IGN); |
275 | eb505be1 | Jes Sorensen | } |
276 | eb505be1 | Jes Sorensen | } |
277 | eb505be1 | Jes Sorensen | |
278 | eb505be1 | Jes Sorensen | void os_setup_post(void) |
279 | eb505be1 | Jes Sorensen | { |
280 | eb505be1 | Jes Sorensen | int fd = 0; |
281 | eb505be1 | Jes Sorensen | |
282 | eb505be1 | Jes Sorensen | if (daemonize) {
|
283 | eb505be1 | Jes Sorensen | uint8_t status = 0;
|
284 | eb505be1 | Jes Sorensen | ssize_t len; |
285 | eb505be1 | Jes Sorensen | |
286 | eb505be1 | Jes Sorensen | again1:
|
287 | eb505be1 | Jes Sorensen | len = write(fds[1], &status, 1); |
288 | eb505be1 | Jes Sorensen | if (len == -1 && (errno == EINTR)) |
289 | eb505be1 | Jes Sorensen | goto again1;
|
290 | eb505be1 | Jes Sorensen | |
291 | eb505be1 | Jes Sorensen | if (len != 1) |
292 | eb505be1 | Jes Sorensen | exit(1);
|
293 | eb505be1 | Jes Sorensen | |
294 | eb505be1 | Jes Sorensen | if (chdir("/")) { |
295 | eb505be1 | Jes Sorensen | perror("not able to chdir to /");
|
296 | eb505be1 | Jes Sorensen | exit(1);
|
297 | eb505be1 | Jes Sorensen | } |
298 | eb505be1 | Jes Sorensen | TFR(fd = qemu_open("/dev/null", O_RDWR));
|
299 | eb505be1 | Jes Sorensen | if (fd == -1) |
300 | eb505be1 | Jes Sorensen | exit(1);
|
301 | eb505be1 | Jes Sorensen | } |
302 | eb505be1 | Jes Sorensen | |
303 | e06eb601 | Jes Sorensen | change_root(); |
304 | e06eb601 | Jes Sorensen | change_process_uid(); |
305 | eb505be1 | Jes Sorensen | |
306 | eb505be1 | Jes Sorensen | if (daemonize) {
|
307 | eb505be1 | Jes Sorensen | dup2(fd, 0);
|
308 | eb505be1 | Jes Sorensen | dup2(fd, 1);
|
309 | eb505be1 | Jes Sorensen | dup2(fd, 2);
|
310 | eb505be1 | Jes Sorensen | |
311 | eb505be1 | Jes Sorensen | close(fd); |
312 | eb505be1 | Jes Sorensen | } |
313 | eb505be1 | Jes Sorensen | } |
314 | eb505be1 | Jes Sorensen | |
315 | eb505be1 | Jes Sorensen | void os_pidfile_error(void) |
316 | eb505be1 | Jes Sorensen | { |
317 | eb505be1 | Jes Sorensen | if (daemonize) {
|
318 | eb505be1 | Jes Sorensen | uint8_t status = 1;
|
319 | eb505be1 | Jes Sorensen | if (write(fds[1], &status, 1) != 1) { |
320 | eb505be1 | Jes Sorensen | perror("daemonize. Writing to pipe\n");
|
321 | eb505be1 | Jes Sorensen | } |
322 | eb505be1 | Jes Sorensen | } else
|
323 | eb505be1 | Jes Sorensen | fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
|
324 | eb505be1 | Jes Sorensen | } |
325 | 9156d763 | Jes Sorensen | |
326 | 9156d763 | Jes Sorensen | void os_set_line_buffering(void) |
327 | 9156d763 | Jes Sorensen | { |
328 | 9156d763 | Jes Sorensen | setvbuf(stdout, NULL, _IOLBF, 0); |
329 | 9156d763 | Jes Sorensen | } |
330 | 949d31e6 | Jes Sorensen | |
331 | bc4a957c | Jes Sorensen | int qemu_create_pidfile(const char *filename) |
332 | bc4a957c | Jes Sorensen | { |
333 | bc4a957c | Jes Sorensen | char buffer[128]; |
334 | bc4a957c | Jes Sorensen | int len;
|
335 | bc4a957c | Jes Sorensen | int fd;
|
336 | bc4a957c | Jes Sorensen | |
337 | bc4a957c | Jes Sorensen | fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
|
338 | bc4a957c | Jes Sorensen | if (fd == -1) { |
339 | bc4a957c | Jes Sorensen | return -1; |
340 | bc4a957c | Jes Sorensen | } |
341 | bc4a957c | Jes Sorensen | if (lockf(fd, F_TLOCK, 0) == -1) { |
342 | 1bbd1592 | Markus Armbruster | close(fd); |
343 | bc4a957c | Jes Sorensen | return -1; |
344 | bc4a957c | Jes Sorensen | } |
345 | 953ffe0f | Andreas Färber | len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", getpid()); |
346 | bc4a957c | Jes Sorensen | if (write(fd, buffer, len) != len) {
|
347 | 1bbd1592 | Markus Armbruster | close(fd); |
348 | bc4a957c | Jes Sorensen | return -1; |
349 | bc4a957c | Jes Sorensen | } |
350 | bc4a957c | Jes Sorensen | |
351 | 93dd748b | Laszlo Ersek | /* keep pidfile open & locked forever */
|
352 | bc4a957c | Jes Sorensen | return 0; |
353 | bc4a957c | Jes Sorensen | } |