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