qemu/chardev/char-file.c
<<
>>
Prefs
   1/*
   2 * QEMU System Emulator
   3 *
   4 * Copyright (c) 2003-2008 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
  25#include "qemu/osdep.h"
  26#include "qapi/error.h"
  27#include "qemu/option.h"
  28#include "chardev/char.h"
  29
  30#ifdef _WIN32
  31#include "chardev/char-win.h"
  32#else
  33#include "chardev/char-fd.h"
  34#endif
  35
  36static void qmp_chardev_open_file(Chardev *chr,
  37                                  ChardevBackend *backend,
  38                                  bool *be_opened,
  39                                  Error **errp)
  40{
  41    ChardevFile *file = backend->u.file.data;
  42#ifdef _WIN32
  43    HANDLE out;
  44    DWORD accessmode;
  45    DWORD flags;
  46
  47    if (file->has_in) {
  48        error_setg(errp, "input file not supported");
  49        return;
  50    }
  51
  52    if (file->has_append && file->append) {
  53        /* Append to file if it already exists. */
  54        accessmode = FILE_GENERIC_WRITE & ~FILE_WRITE_DATA;
  55        flags = OPEN_ALWAYS;
  56    } else {
  57        /* Truncate file if it already exists. */
  58        accessmode = GENERIC_WRITE;
  59        flags = CREATE_ALWAYS;
  60    }
  61
  62    out = CreateFile(file->out, accessmode, FILE_SHARE_READ, NULL, flags,
  63                     FILE_ATTRIBUTE_NORMAL, NULL);
  64    if (out == INVALID_HANDLE_VALUE) {
  65        error_setg(errp, "open %s failed", file->out);
  66        return;
  67    }
  68
  69    win_chr_set_file(chr, out, false);
  70#else
  71    int flags, in = -1, out;
  72
  73    flags = O_WRONLY | O_CREAT | O_BINARY;
  74    if (file->has_append && file->append) {
  75        flags |= O_APPEND;
  76    } else {
  77        flags |= O_TRUNC;
  78    }
  79
  80    out = qmp_chardev_open_file_source(file->out, flags, errp);
  81    if (out < 0) {
  82        return;
  83    }
  84
  85    if (file->has_in) {
  86        flags = O_RDONLY;
  87        in = qmp_chardev_open_file_source(file->in, flags, errp);
  88        if (in < 0) {
  89            qemu_close(out);
  90            return;
  91        }
  92    }
  93
  94    qemu_chr_open_fd(chr, in, out);
  95#endif
  96}
  97
  98static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
  99                                    Error **errp)
 100{
 101    const char *path = qemu_opt_get(opts, "path");
 102    ChardevFile *file;
 103
 104    backend->type = CHARDEV_BACKEND_KIND_FILE;
 105    if (path == NULL) {
 106        error_setg(errp, "chardev: file: no filename given");
 107        return;
 108    }
 109    file = backend->u.file.data = g_new0(ChardevFile, 1);
 110    qemu_chr_parse_common(opts, qapi_ChardevFile_base(file));
 111    file->out = g_strdup(path);
 112
 113    file->has_append = true;
 114    file->append = qemu_opt_get_bool(opts, "append", false);
 115}
 116
 117static void char_file_class_init(ObjectClass *oc, void *data)
 118{
 119    ChardevClass *cc = CHARDEV_CLASS(oc);
 120
 121    cc->parse = qemu_chr_parse_file_out;
 122    cc->open = qmp_chardev_open_file;
 123}
 124
 125static const TypeInfo char_file_type_info = {
 126    .name = TYPE_CHARDEV_FILE,
 127#ifdef _WIN32
 128    .parent = TYPE_CHARDEV_WIN,
 129#else
 130    .parent = TYPE_CHARDEV_FD,
 131#endif
 132    .class_init = char_file_class_init,
 133};
 134
 135static void register_types(void)
 136{
 137    type_register_static(&char_file_type_info);
 138}
 139
 140type_init(register_types);
 141