Statistics
| Branch: | Revision:

root / util / osdep.c @ cb77d192

History | View | Annotate | Download (10.1 kB)

1
/*
2
 * QEMU low level functions
3
 *
4
 * Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <stdbool.h>
28
#include <string.h>
29
#include <errno.h>
30
#include <unistd.h>
31
#include <fcntl.h>
32

    
33
/* Needed early for CONFIG_BSD etc. */
34
#include "config-host.h"
35

    
36
#if defined(CONFIG_MADVISE) || defined(CONFIG_POSIX_MADVISE)
37
#include <sys/mman.h>
38
#endif
39

    
40
#ifdef CONFIG_SOLARIS
41
#include <sys/types.h>
42
#include <sys/statvfs.h>
43
/* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
44
   discussion about Solaris header problems */
45
extern int madvise(caddr_t, size_t, int);
46
#endif
47

    
48
#include "qemu-common.h"
49
#include "trace.h"
50
#include "qemu/sockets.h"
51
#include "monitor/monitor.h"
52

    
53
static bool fips_enabled = false;
54

    
55
static const char *qemu_version = QEMU_VERSION;
56

    
57
int socket_set_cork(int fd, int v)
58
{
59
#if defined(SOL_TCP) && defined(TCP_CORK)
60
    return qemu_setsockopt(fd, SOL_TCP, TCP_CORK, &v, sizeof(v));
61
#else
62
    return 0;
63
#endif
64
}
65

    
66
int socket_set_nodelay(int fd)
67
{
68
    int v = 1;
69
    return qemu_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
70
}
71

    
72
int qemu_madvise(void *addr, size_t len, int advice)
73
{
74
    if (advice == QEMU_MADV_INVALID) {
75
        errno = EINVAL;
76
        return -1;
77
    }
78
#if defined(CONFIG_MADVISE)
79
    return madvise(addr, len, advice);
80
#elif defined(CONFIG_POSIX_MADVISE)
81
    return posix_madvise(addr, len, advice);
82
#else
83
    errno = EINVAL;
84
    return -1;
85
#endif
86
}
87

    
88
#ifndef _WIN32
89
/*
90
 * Dups an fd and sets the flags
91
 */
92
static int qemu_dup_flags(int fd, int flags)
93
{
94
    int ret;
95
    int serrno;
96
    int dup_flags;
97

    
98
#ifdef F_DUPFD_CLOEXEC
99
    ret = fcntl(fd, F_DUPFD_CLOEXEC, 0);
100
#else
101
    ret = dup(fd);
102
    if (ret != -1) {
103
        qemu_set_cloexec(ret);
104
    }
105
#endif
106
    if (ret == -1) {
107
        goto fail;
108
    }
109

    
110
    dup_flags = fcntl(ret, F_GETFL);
111
    if (dup_flags == -1) {
112
        goto fail;
113
    }
114

    
115
    if ((flags & O_SYNC) != (dup_flags & O_SYNC)) {
116
        errno = EINVAL;
117
        goto fail;
118
    }
119

    
120
    /* Set/unset flags that we can with fcntl */
121
    if (fcntl(ret, F_SETFL, flags) == -1) {
122
        goto fail;
123
    }
124

    
125
    /* Truncate the file in the cases that open() would truncate it */
126
    if (flags & O_TRUNC ||
127
            ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))) {
128
        if (ftruncate(ret, 0) == -1) {
129
            goto fail;
130
        }
131
    }
132

    
133
    return ret;
134

    
135
fail:
136
    serrno = errno;
137
    if (ret != -1) {
138
        close(ret);
139
    }
140
    errno = serrno;
141
    return -1;
142
}
143

    
144
static int qemu_parse_fdset(const char *param)
145
{
146
    return qemu_parse_fd(param);
147
}
148
#endif
149

    
150
/*
151
 * Opens a file with FD_CLOEXEC set
152
 */
153
int qemu_open(const char *name, int flags, ...)
154
{
155
    int ret;
156
    int mode = 0;
157

    
158
#ifndef _WIN32
159
    const char *fdset_id_str;
160

    
161
    /* Attempt dup of fd from fd set */
162
    if (strstart(name, "/dev/fdset/", &fdset_id_str)) {
163
        int64_t fdset_id;
164
        int fd, dupfd;
165

    
166
        fdset_id = qemu_parse_fdset(fdset_id_str);
167
        if (fdset_id == -1) {
168
            errno = EINVAL;
169
            return -1;
170
        }
171

    
172
        fd = monitor_fdset_get_fd(fdset_id, flags);
173
        if (fd == -1) {
174
            return -1;
175
        }
176

    
177
        dupfd = qemu_dup_flags(fd, flags);
178
        if (dupfd == -1) {
179
            return -1;
180
        }
181

    
182
        ret = monitor_fdset_dup_fd_add(fdset_id, dupfd);
183
        if (ret == -1) {
184
            close(dupfd);
185
            errno = EINVAL;
186
            return -1;
187
        }
188

    
189
        return dupfd;
190
    }
191
#endif
192

    
193
    if (flags & O_CREAT) {
194
        va_list ap;
195

    
196
        va_start(ap, flags);
197
        mode = va_arg(ap, int);
198
        va_end(ap);
199
    }
200

    
201
#ifdef O_CLOEXEC
202
    ret = open(name, flags | O_CLOEXEC, mode);
203
#else
204
    ret = open(name, flags, mode);
205
    if (ret >= 0) {
206
        qemu_set_cloexec(ret);
207
    }
208
#endif
209

    
210
    return ret;
211
}
212

    
213
int qemu_close(int fd)
214
{
215
    int64_t fdset_id;
216

    
217
    /* Close fd that was dup'd from an fdset */
218
    fdset_id = monitor_fdset_dup_fd_find(fd);
219
    if (fdset_id != -1) {
220
        int ret;
221

    
222
        ret = close(fd);
223
        if (ret == 0) {
224
            monitor_fdset_dup_fd_remove(fd);
225
        }
226

    
227
        return ret;
228
    }
229

    
230
    return close(fd);
231
}
232

    
233
/*
234
 * A variant of write(2) which handles partial write.
235
 *
236
 * Return the number of bytes transferred.
237
 * Set errno if fewer than `count' bytes are written.
238
 *
239
 * This function don't work with non-blocking fd's.
240
 * Any of the possibilities with non-bloking fd's is bad:
241
 *   - return a short write (then name is wrong)
242
 *   - busy wait adding (errno == EAGAIN) to the loop
243
 */
244
ssize_t qemu_write_full(int fd, const void *buf, size_t count)
245
{
246
    ssize_t ret = 0;
247
    ssize_t total = 0;
248

    
249
    while (count) {
250
        ret = write(fd, buf, count);
251
        if (ret < 0) {
252
            if (errno == EINTR)
253
                continue;
254
            break;
255
        }
256

    
257
        count -= ret;
258
        buf += ret;
259
        total += ret;
260
    }
261

    
262
    return total;
263
}
264

    
265
/*
266
 * Opens a socket with FD_CLOEXEC set
267
 */
268
int qemu_socket(int domain, int type, int protocol)
269
{
270
    int ret;
271

    
272
#ifdef SOCK_CLOEXEC
273
    ret = socket(domain, type | SOCK_CLOEXEC, protocol);
274
    if (ret != -1 || errno != EINVAL) {
275
        return ret;
276
    }
277
#endif
278
    ret = socket(domain, type, protocol);
279
    if (ret >= 0) {
280
        qemu_set_cloexec(ret);
281
    }
282

    
283
    return ret;
284
}
285

    
286
/*
287
 * Accept a connection and set FD_CLOEXEC
288
 */
289
int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
290
{
291
    int ret;
292

    
293
#ifdef CONFIG_ACCEPT4
294
    ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
295
    if (ret != -1 || errno != ENOSYS) {
296
        return ret;
297
    }
298
#endif
299
    ret = accept(s, addr, addrlen);
300
    if (ret >= 0) {
301
        qemu_set_cloexec(ret);
302
    }
303

    
304
    return ret;
305
}
306

    
307
/*
308
 * A variant of send(2) which handles partial write.
309
 *
310
 * Return the number of bytes transferred, which is only
311
 * smaller than `count' if there is an error.
312
 *
313
 * This function won't work with non-blocking fd's.
314
 * Any of the possibilities with non-bloking fd's is bad:
315
 *   - return a short write (then name is wrong)
316
 *   - busy wait adding (errno == EAGAIN) to the loop
317
 */
318
ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags)
319
{
320
    ssize_t ret = 0;
321
    ssize_t total = 0;
322

    
323
    while (count) {
324
        ret = send(fd, buf, count, flags);
325
        if (ret < 0) {
326
            if (errno == EINTR) {
327
                continue;
328
            }
329
            break;
330
        }
331

    
332
        count -= ret;
333
        buf += ret;
334
        total += ret;
335
    }
336

    
337
    return total;
338
}
339

    
340
/*
341
 * A variant of recv(2) which handles partial write.
342
 *
343
 * Return the number of bytes transferred, which is only
344
 * smaller than `count' if there is an error.
345
 *
346
 * This function won't work with non-blocking fd's.
347
 * Any of the possibilities with non-bloking fd's is bad:
348
 *   - return a short write (then name is wrong)
349
 *   - busy wait adding (errno == EAGAIN) to the loop
350
 */
351
ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags)
352
{
353
    ssize_t ret = 0;
354
    ssize_t total = 0;
355

    
356
    while (count) {
357
        ret = qemu_recv(fd, buf, count, flags);
358
        if (ret <= 0) {
359
            if (ret < 0 && errno == EINTR) {
360
                continue;
361
            }
362
            break;
363
        }
364

    
365
        count -= ret;
366
        buf += ret;
367
        total += ret;
368
    }
369

    
370
    return total;
371
}
372

    
373
void qemu_set_version(const char *version)
374
{
375
    qemu_version = version;
376
}
377

    
378
const char *qemu_get_version(void)
379
{
380
    return qemu_version;
381
}
382

    
383
void fips_set_state(bool requested)
384
{
385
#ifdef __linux__
386
    if (requested) {
387
        FILE *fds = fopen("/proc/sys/crypto/fips_enabled", "r");
388
        if (fds != NULL) {
389
            fips_enabled = (fgetc(fds) == '1');
390
            fclose(fds);
391
        }
392
    }
393
#else
394
    fips_enabled = false;
395
#endif /* __linux__ */
396

    
397
#ifdef _FIPS_DEBUG
398
    fprintf(stderr, "FIPS mode %s (requested %s)\n",
399
            (fips_enabled ? "enabled" : "disabled"),
400
            (requested ? "enabled" : "disabled"));
401
#endif
402
}
403

    
404
bool fips_get_state(void)
405
{
406
    return fips_enabled;
407
}
408

    
409
#ifdef _WIN32
410
static void socket_cleanup(void)
411
{
412
    WSACleanup();
413
}
414
#endif
415

    
416
int socket_init(void)
417
{
418
#ifdef _WIN32
419
    WSADATA Data;
420
    int ret, err;
421

    
422
    ret = WSAStartup(MAKEWORD(2, 2), &Data);
423
    if (ret != 0) {
424
        err = WSAGetLastError();
425
        fprintf(stderr, "WSAStartup: %d\n", err);
426
        return -1;
427
    }
428
    atexit(socket_cleanup);
429
#endif
430
    return 0;
431
}
432

    
433
#ifndef CONFIG_IOVEC
434
/* helper function for iov_send_recv() */
435
static ssize_t
436
readv_writev(int fd, const struct iovec *iov, int iov_cnt, bool do_write)
437
{
438
    unsigned i = 0;
439
    ssize_t ret = 0;
440
    while (i < iov_cnt) {
441
        ssize_t r = do_write
442
            ? write(fd, iov[i].iov_base, iov[i].iov_len)
443
            : read(fd, iov[i].iov_base, iov[i].iov_len);
444
        if (r > 0) {
445
            ret += r;
446
        } else if (!r) {
447
            break;
448
        } else if (errno == EINTR) {
449
            continue;
450
        } else {
451
            /* else it is some "other" error,
452
             * only return if there was no data processed. */
453
            if (ret == 0) {
454
                ret = -1;
455
            }
456
            break;
457
        }
458
        i++;
459
    }
460
    return ret;
461
}
462

    
463
ssize_t
464
readv(int fd, const struct iovec *iov, int iov_cnt)
465
{
466
    return readv_writev(fd, iov, iov_cnt, false);
467
}
468

    
469
ssize_t
470
writev(int fd, const struct iovec *iov, int iov_cnt)
471
{
472
    return readv_writev(fd, iov, iov_cnt, true);
473
}
474
#endif