From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39035) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YIkor-0002LZ-Kn for qemu-devel@nongnu.org; Tue, 03 Feb 2015 16:15:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YIkon-00005j-JX for qemu-devel@nongnu.org; Tue, 03 Feb 2015 16:15:37 -0500 Received: from e32.co.us.ibm.com ([32.97.110.150]:39605) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YIkon-00005a-BR for qemu-devel@nongnu.org; Tue, 03 Feb 2015 16:15:33 -0500 Received: from /spool/local by e32.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 3 Feb 2015 14:15:32 -0700 Received: from b03cxnp08028.gho.boulder.ibm.com (b03cxnp08028.gho.boulder.ibm.com [9.17.130.20]) by d03dlp02.boulder.ibm.com (Postfix) with ESMTP id BEA333E40030 for ; Tue, 3 Feb 2015 14:15:28 -0700 (MST) Received: from d03av05.boulder.ibm.com (d03av05.boulder.ibm.com [9.17.195.85]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t13LFZaM38338726 for ; Tue, 3 Feb 2015 14:15:35 -0700 Received: from d03av05.boulder.ibm.com (localhost [127.0.0.1]) by d03av05.boulder.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t13LFSJb008148 for ; Tue, 3 Feb 2015 14:15:28 -0700 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Michael Roth In-Reply-To: <1420031214-6053-3-git-send-email-den@openvz.org> References: <1420031214-6053-1-git-send-email-den@openvz.org> <1420031214-6053-3-git-send-email-den@openvz.org> Message-ID: <20150203211520.6410.51074@loki> Date: Tue, 03 Feb 2015 15:15:20 -0600 Subject: Re: [Qemu-devel] [PATCH 2/8] qga: implement file commands for Windows guest List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "Denis V. Lunev" Cc: Olga Krishtal , qemu-devel@nongnu.org Quoting Denis V. Lunev (2014-12-31 07:06:48) > From: Olga Krishtal > = > The following commands are implemented: > - guest_file_open > - guest_file_close > - guest_file_write > - guest_file_read > - guest_file_seek > - guest_file_flush > = > Motivation is quite simple: Windows guests should be supported with the > same set of features as Linux one. Also this patch is a prerequisite for > Windows guest-exec command support. > = > Signed-off-by: Olga Krishtal > Signed-off-by: Denis V. Lunev > CC: Michael Roth > --- > qga/commands-win32.c | 271 +++++++++++++++++++++++++++++++++++++++++++++= ++---- > 1 file changed, 250 insertions(+), 21 deletions(-) > = > diff --git a/qga/commands-win32.c b/qga/commands-win32.c > index 3bcbeae..5db96ef 100644 > --- a/qga/commands-win32.c > +++ b/qga/commands-win32.c > @@ -14,10 +14,13 @@ > #include > #include > #include > +#include > +#include > #include "qga/guest-agent-core.h" > #include "qga/vss-win32.h" > #include "qga-qmp-commands.h" > #include "qapi/qmp/qerror.h" > +#include "qemu/queue.h" > = > #ifndef SHTDN_REASON_FLAG_PLANNED > #define SHTDN_REASON_FLAG_PLANNED 0x80000000 > @@ -29,6 +32,146 @@ > (365 * (1970 - 1601) + \ > (1970 - 1601) / 4 - 3)) > = > +#define INVALID_SET_FILE_POINTER ((DWORD)-1) > + > +typedef struct GuestFileHandle { > + int64_t id; > + HANDLE fh; > + QTAILQ_ENTRY(GuestFileHandle) next; > +} GuestFileHandle; > + > +static struct { > + QTAILQ_HEAD(, GuestFileHandle) filehandles; > +} guest_file_state; > + > + > +typedef struct OpenFlags { > + const char *forms; > + DWORD desired_access; > + DWORD creation_disposition; > +} OpenFlags; > +static OpenFlags guest_file_open_modes[] =3D { > + {"r", GENERIC_READ, OPEN_EXISTING}, > + {"rb", GENERIC_READ, OPEN_EXISTING}, > + {"w", GENERIC_WRITE, CREATE_ALWAYS}, > + {"wb", GENERIC_WRITE, CREATE_ALWAYS}, > + {"a", GENERIC_WRITE, OPEN_ALWAYS }, > + {"r+", GENERIC_WRITE|GENERIC_READ, OPEN_EXISTING}, > + {"rb+", GENERIC_WRITE|GENERIC_READ, OPEN_EXISTING}, > + {"r+b", GENERIC_WRITE|GENERIC_READ, OPEN_EXISTING}, > + {"w+", GENERIC_WRITE|GENERIC_READ, CREATE_ALWAYS}, > + {"wb+", GENERIC_WRITE|GENERIC_READ, CREATE_ALWAYS}, > + {"w+b", GENERIC_WRITE|GENERIC_READ, CREATE_ALWAYS}, > + {"a+", GENERIC_WRITE|GENERIC_READ, OPEN_ALWAYS }, > + {"ab+", GENERIC_WRITE|GENERIC_READ, OPEN_ALWAYS }, > + {"a+b", GENERIC_WRITE|GENERIC_READ, OPEN_ALWAYS } > +}; > + > +static OpenFlags *find_open_flag(const char *mode_str) > +{ > + int mode; > + Error **errp =3D NULL; > + > + for (mode =3D 0; mode < ARRAY_SIZE(guest_file_open_modes); ++mode) { > + OpenFlags *flags =3D guest_file_open_modes + mode; > + > + if (strcmp(flags->forms, mode_str) =3D=3D 0) { > + return flags; > + } > + } > + > + error_setg(errp, "invalid file open mode '%s'", mode_str); > + return NULL; > +} > + > +static int64_t guest_file_handle_add(HANDLE fh, Error **errp) > +{ > + GuestFileHandle *gfh; > + int64_t handle; > + > + handle =3D ga_get_fd_handle(ga_state, errp); > + if (handle < 0) { > + return -1; > + } > + gfh =3D g_malloc0(sizeof(GuestFileHandle)); > + gfh->id =3D handle; > + gfh->fh =3D fh; > + QTAILQ_INSERT_TAIL(&guest_file_state.filehandles, gfh, next); > + > + return handle; > +} > + > +static GuestFileHandle *guest_file_handle_find(int64_t id, Error **errp) > +{ > + GuestFileHandle *gfh; > + QTAILQ_FOREACH(gfh, &guest_file_state.filehandles, next) { > + if (gfh->id =3D=3D id) { > + return gfh; > + } > + } > + error_setg(errp, "handle '%" PRId64 "' has not been found", id); > + return NULL; > +} > + > +int64_t qmp_guest_file_open(const char *path, bool has_mode, > + const char *mode, Error **errp) > +{ > + int64_t fd; > + HANDLE fh; > + HANDLE templ_file =3D NULL; > + DWORD share_mode =3D FILE_SHARE_READ; > + DWORD flags_and_attr =3D FILE_ATTRIBUTE_NORMAL; > + LPSECURITY_ATTRIBUTES sa_attr =3D NULL; > + OpenFlags *guest_flags; > + > + if (!has_mode) { > + mode =3D "r"; > + } > + slog("guest-file-open called, filepath: %s, mode: %s", path, mode); > + guest_flags =3D find_open_flag(mode); > + if (guest_flags =3D=3D NULL) { > + error_setg(errp, "invalid file open mode"); > + return -1; > + } > + > + fh =3D CreateFile(path, guest_flags->desired_access, share_mode, sa_= attr, > + guest_flags->creation_disposition, flags_and_attr, > + templ_file); > + if (fh =3D=3D INVALID_HANDLE_VALUE) { > + error_setg_errno(errp, GetLastError(), "failed to open file '%s'= ", > + path); For working with GetLastError() I think error_setg_win32() is what you want. Same for all the other occurrences.