qemu-ga patch queue for 2.6
* fix w32 build breakage when VSS enabled * fix up wchar handling in guest-set-user-password * fix re-install handling for w32 MSI installer * add w32 support for guest-get-vcpus * add support for enums in guest-file-seek SEEK params instead of relying on platform-specific integer values -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJWzzLhAAoJEDNTyc7xCLWE6gIH/2INKPuMEjKea5EFY5K7L7ux xbBfW9eDX1yhoBTUzEMT7Wuh0j59tlGlmubEJ+SwoHCC6otHMCbIjFI3/x+FubbY yNBLca2gEbIe+ojujTJRHLp5Zr6AwjuD5AH08Po29zWBeTUUVZb5SvmqIMk5Awr9 wyLMKErC1XOQz3PAOn0ifZCWflzqZOhBd/XnDmOu0Yi9dOlvsOUjo3ZXQqNwItu6 ta0CEumxkE8rV6xLq7R+iaj0jjZdIK54VKp2FgPsSSwnV+zcnkx5yfHpmwvIQ6DD OT11hDldcPd6/Kj6oSQVh7Z2Qfzw3E9vCkKR0Vu9/2nq4lcZ7oyVwllKqX5TfDg= =1xjV -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mdroth/tags/qga-pull-2016-02-25-tag' into staging qemu-ga patch queue for 2.6 * fix w32 build breakage when VSS enabled * fix up wchar handling in guest-set-user-password * fix re-install handling for w32 MSI installer * add w32 support for guest-get-vcpus * add support for enums in guest-file-seek SEEK params instead of relying on platform-specific integer values # gpg: Signature made Thu 25 Feb 2016 16:59:13 GMT using RSA key ID F108B584 # gpg: Good signature from "Michael Roth <flukshun@gmail.com>" # gpg: aka "Michael Roth <mdroth@utexas.edu>" # gpg: aka "Michael Roth <mdroth@linux.vnet.ibm.com>" * remotes/mdroth/tags/qga-pull-2016-02-25-tag: qga: fix w32 breakage due to missing osdep.h includes qga: check utf8-to-utf16 conversion qga: fix off-by-one length check qga: use wide-chars constants for wchar_t comparisons qga: use size_t for wcslen() return value qga: use more idiomatic qemu-style eol operators qga: implement the guest-get-vcpus for windows qemu-ga: Fixed minor version switch issue qga: Support enum names in guest-file-seek Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
67ef811ed1
@ -550,31 +550,24 @@ GuestFileWrite *qmp_guest_file_write(int64_t handle, const char *buf_b64,
|
||||
}
|
||||
|
||||
struct GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
|
||||
int64_t whence_code, Error **errp)
|
||||
GuestFileWhence *whence_code,
|
||||
Error **errp)
|
||||
{
|
||||
GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
|
||||
GuestFileSeek *seek_data = NULL;
|
||||
FILE *fh;
|
||||
int ret;
|
||||
int whence;
|
||||
Error *err = NULL;
|
||||
|
||||
if (!gfh) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We stupidly exposed 'whence':'int' in our qapi */
|
||||
switch (whence_code) {
|
||||
case QGA_SEEK_SET:
|
||||
whence = SEEK_SET;
|
||||
break;
|
||||
case QGA_SEEK_CUR:
|
||||
whence = SEEK_CUR;
|
||||
break;
|
||||
case QGA_SEEK_END:
|
||||
whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "invalid whence code %"PRId64, whence_code);
|
||||
whence = ga_parse_whence(whence_code, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -385,7 +385,8 @@ done:
|
||||
}
|
||||
|
||||
GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
|
||||
int64_t whence_code, Error **errp)
|
||||
GuestFileWhence *whence_code,
|
||||
Error **errp)
|
||||
{
|
||||
GuestFileHandle *gfh;
|
||||
GuestFileSeek *seek_data;
|
||||
@ -394,6 +395,7 @@ GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
|
||||
off_pos.QuadPart = offset;
|
||||
BOOL res;
|
||||
int whence;
|
||||
Error *err = NULL;
|
||||
|
||||
gfh = guest_file_handle_find(handle, errp);
|
||||
if (!gfh) {
|
||||
@ -401,18 +403,9 @@ GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
|
||||
}
|
||||
|
||||
/* We stupidly exposed 'whence':'int' in our qapi */
|
||||
switch (whence_code) {
|
||||
case QGA_SEEK_SET:
|
||||
whence = SEEK_SET;
|
||||
break;
|
||||
case QGA_SEEK_CUR:
|
||||
whence = SEEK_CUR;
|
||||
break;
|
||||
case QGA_SEEK_END:
|
||||
whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "invalid whence code %"PRId64, whence_code);
|
||||
whence = ga_parse_whence(whence_code, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1230,7 +1223,71 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns, Error **errp)
|
||||
|
||||
GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
|
||||
{
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pslpi, ptr;
|
||||
DWORD length;
|
||||
GuestLogicalProcessorList *head, **link;
|
||||
Error *local_err = NULL;
|
||||
int64_t current;
|
||||
|
||||
ptr = pslpi = NULL;
|
||||
length = 0;
|
||||
current = 0;
|
||||
head = NULL;
|
||||
link = &head;
|
||||
|
||||
if ((GetLogicalProcessorInformation(pslpi, &length) == FALSE) &&
|
||||
(GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
|
||||
(length > sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION))) {
|
||||
ptr = pslpi = g_malloc0(length);
|
||||
if (GetLogicalProcessorInformation(pslpi, &length) == FALSE) {
|
||||
error_setg(&local_err, "Failed to get processor information: %d",
|
||||
(int)GetLastError());
|
||||
}
|
||||
} else {
|
||||
error_setg(&local_err,
|
||||
"Failed to get processor information buffer length: %d",
|
||||
(int)GetLastError());
|
||||
}
|
||||
|
||||
while ((local_err == NULL) && (length > 0)) {
|
||||
if (pslpi->Relationship == RelationProcessorCore) {
|
||||
ULONG_PTR cpu_bits = pslpi->ProcessorMask;
|
||||
|
||||
while (cpu_bits > 0) {
|
||||
if (!!(cpu_bits & 1)) {
|
||||
GuestLogicalProcessor *vcpu;
|
||||
GuestLogicalProcessorList *entry;
|
||||
|
||||
vcpu = g_malloc0(sizeof *vcpu);
|
||||
vcpu->logical_id = current++;
|
||||
vcpu->online = true;
|
||||
vcpu->has_can_offline = false;
|
||||
|
||||
entry = g_malloc0(sizeof *entry);
|
||||
entry->value = vcpu;
|
||||
|
||||
*link = entry;
|
||||
link = &entry->next;
|
||||
}
|
||||
cpu_bits >>= 1;
|
||||
}
|
||||
}
|
||||
length -= sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
|
||||
pslpi++; /* next entry */
|
||||
}
|
||||
|
||||
g_free(ptr);
|
||||
|
||||
if (local_err == NULL) {
|
||||
if (head != NULL) {
|
||||
return head;
|
||||
}
|
||||
/* there's no guest with zero VCPUs */
|
||||
error_setg(&local_err, "Guest reported zero VCPUs");
|
||||
}
|
||||
|
||||
qapi_free_GuestLogicalProcessorList(head);
|
||||
error_propagate(errp, local_err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1246,11 +1303,12 @@ get_net_error_message(gint error)
|
||||
HMODULE module = NULL;
|
||||
gchar *retval = NULL;
|
||||
wchar_t *msg = NULL;
|
||||
int flags, nchars;
|
||||
int flags;
|
||||
size_t nchars;
|
||||
|
||||
flags = FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
|FORMAT_MESSAGE_IGNORE_INSERTS
|
||||
|FORMAT_MESSAGE_FROM_SYSTEM;
|
||||
flags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM;
|
||||
|
||||
if (error >= NERR_BASE && error <= MAX_NERR) {
|
||||
module = LoadLibraryExW(L"netmsg.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
|
||||
@ -1265,8 +1323,10 @@ get_net_error_message(gint error)
|
||||
if (msg != NULL) {
|
||||
nchars = wcslen(msg);
|
||||
|
||||
if (nchars > 2 && msg[nchars-1] == '\n' && msg[nchars-2] == '\r') {
|
||||
msg[nchars-2] = '\0';
|
||||
if (nchars >= 2 &&
|
||||
msg[nchars - 1] == L'\n' &&
|
||||
msg[nchars - 2] == L'\r') {
|
||||
msg[nchars - 2] = L'\0';
|
||||
}
|
||||
|
||||
retval = g_utf16_to_utf8(msg, -1, NULL, NULL, NULL);
|
||||
@ -1289,8 +1349,9 @@ void qmp_guest_set_user_password(const char *username,
|
||||
NET_API_STATUS nas;
|
||||
char *rawpasswddata = NULL;
|
||||
size_t rawpasswdlen;
|
||||
wchar_t *user, *wpass;
|
||||
wchar_t *user = NULL, *wpass = NULL;
|
||||
USER_INFO_1003 pi1003 = { 0, };
|
||||
GError *gerr = NULL;
|
||||
|
||||
if (crypted) {
|
||||
error_setg(errp, QERR_UNSUPPORTED);
|
||||
@ -1304,8 +1365,15 @@ void qmp_guest_set_user_password(const char *username,
|
||||
rawpasswddata = g_renew(char, rawpasswddata, rawpasswdlen + 1);
|
||||
rawpasswddata[rawpasswdlen] = '\0';
|
||||
|
||||
user = g_utf8_to_utf16(username, -1, NULL, NULL, NULL);
|
||||
wpass = g_utf8_to_utf16(rawpasswddata, -1, NULL, NULL, NULL);
|
||||
user = g_utf8_to_utf16(username, -1, NULL, NULL, &gerr);
|
||||
if (!user) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
wpass = g_utf8_to_utf16(rawpasswddata, -1, NULL, NULL, &gerr);
|
||||
if (!wpass) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
pi1003.usri1003_password = wpass;
|
||||
nas = NetUserSetInfo(NULL, user,
|
||||
@ -1318,6 +1386,11 @@ void qmp_guest_set_user_password(const char *username,
|
||||
g_free(msg);
|
||||
}
|
||||
|
||||
done:
|
||||
if (gerr) {
|
||||
error_setg(errp, QERR_QGA_COMMAND_FAILED, gerr->message);
|
||||
g_error_free(gerr);
|
||||
}
|
||||
g_free(user);
|
||||
g_free(wpass);
|
||||
g_free(rawpasswddata);
|
||||
@ -1347,7 +1420,7 @@ GList *ga_command_blacklist_init(GList *blacklist)
|
||||
{
|
||||
const char *list_unsupported[] = {
|
||||
"guest-suspend-hybrid",
|
||||
"guest-get-vcpus", "guest-set-vcpus",
|
||||
"guest-set-vcpus",
|
||||
"guest-get-memory-blocks", "guest-set-memory-blocks",
|
||||
"guest-get-memory-block-size",
|
||||
"guest-fsfreeze-freeze-list",
|
||||
|
@ -473,3 +473,24 @@ done:
|
||||
|
||||
return ge;
|
||||
}
|
||||
|
||||
/* Convert GuestFileWhence (either a raw integer or an enum value) into
|
||||
* the guest's SEEK_ constants. */
|
||||
int ga_parse_whence(GuestFileWhence *whence, Error **errp)
|
||||
{
|
||||
/* Exploit the fact that we picked values to match QGA_SEEK_*. */
|
||||
if (whence->type == QTYPE_QSTRING) {
|
||||
whence->type = QTYPE_QINT;
|
||||
whence->u.value = whence->u.name;
|
||||
}
|
||||
switch (whence->u.value) {
|
||||
case QGA_SEEK_SET:
|
||||
return SEEK_SET;
|
||||
case QGA_SEEK_CUR:
|
||||
return SEEK_CUR;
|
||||
case QGA_SEEK_END:
|
||||
return SEEK_END;
|
||||
}
|
||||
error_setg(errp, "invalid whence code %"PRId64, whence->u.value);
|
||||
return -1;
|
||||
}
|
||||
|
@ -12,16 +12,10 @@
|
||||
*/
|
||||
#include "qapi/qmp/dispatch.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qga-qmp-commands.h"
|
||||
|
||||
#define QGA_READ_COUNT_DEFAULT 4096
|
||||
|
||||
/* Mapping of whence codes used by guest-file-seek. */
|
||||
enum {
|
||||
QGA_SEEK_SET = 0,
|
||||
QGA_SEEK_CUR = 1,
|
||||
QGA_SEEK_END = 2,
|
||||
};
|
||||
|
||||
typedef struct GAState GAState;
|
||||
typedef struct GACommandState GACommandState;
|
||||
extern GAState *ga_state;
|
||||
@ -44,6 +38,7 @@ void ga_set_frozen(GAState *s);
|
||||
void ga_unset_frozen(GAState *s);
|
||||
const char *ga_fsfreeze_hook(GAState *s);
|
||||
int64_t ga_get_fd_handle(GAState *s, Error **errp);
|
||||
int ga_parse_whence(GuestFileWhence *whence, Error **errp);
|
||||
|
||||
#ifndef _WIN32
|
||||
void reopen_fd_to_null(int fd);
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
<Product
|
||||
Name="QEMU guest agent"
|
||||
Id="*"
|
||||
Id="{DF9974AD-E41A-4304-81AD-69AA8F299766}"
|
||||
UpgradeCode="{EB6B8302-C06E-4BEC-ADAC-932C68A3A98D}"
|
||||
Manufacturer="$(env.QEMU_GA_MANUFACTURER)"
|
||||
Version="$(env.QEMU_GA_VERSION)"
|
||||
|
@ -313,6 +313,34 @@
|
||||
{ 'struct': 'GuestFileSeek',
|
||||
'data': { 'position': 'int', 'eof': 'bool' } }
|
||||
|
||||
##
|
||||
# @QGASeek:
|
||||
#
|
||||
# Symbolic names for use in @guest-file-seek
|
||||
#
|
||||
# @set: Set to the specified offset (same effect as 'whence':0)
|
||||
# @cur: Add offset to the current location (same effect as 'whence':1)
|
||||
# @end: Add offset to the end of the file (same effect as 'whence':2)
|
||||
#
|
||||
# Since: 2.6
|
||||
##
|
||||
{ 'enum': 'QGASeek', 'data': [ 'set', 'cur', 'end' ] }
|
||||
|
||||
##
|
||||
# @GuestFileWhence:
|
||||
#
|
||||
# Controls the meaning of offset to @guest-file-seek.
|
||||
#
|
||||
# @value: Integral value (0 for set, 1 for cur, 2 for end), available
|
||||
# for historical reasons, and might differ from the host's or
|
||||
# guest's SEEK_* values (since: 0.15)
|
||||
# @name: Symbolic name, and preferred interface
|
||||
#
|
||||
# Since: 2.6
|
||||
##
|
||||
{ 'alternate': 'GuestFileWhence',
|
||||
'data': { 'value': 'int', 'name': 'QGASeek' } }
|
||||
|
||||
##
|
||||
# @guest-file-seek:
|
||||
#
|
||||
@ -324,14 +352,15 @@
|
||||
#
|
||||
# @offset: bytes to skip over in the file stream
|
||||
#
|
||||
# @whence: 0 for SEEK_SET, 1 for SEEK_CUR, or 2 for SEEK_END
|
||||
# @whence: Symbolic or numeric code for interpreting offset
|
||||
#
|
||||
# Returns: @GuestFileSeek on success.
|
||||
#
|
||||
# Since: 0.15.0
|
||||
##
|
||||
{ 'command': 'guest-file-seek',
|
||||
'data': { 'handle': 'int', 'offset': 'int', 'whence': 'int' },
|
||||
'data': { 'handle': 'int', 'offset': 'int',
|
||||
'whence': 'GuestFileWhence' },
|
||||
'returns': 'GuestFileSeek' }
|
||||
|
||||
##
|
||||
|
@ -150,7 +150,7 @@ void qga_vss_fsfreeze(int *nr_volume, Error **errp, bool freeze)
|
||||
const char *func_name = freeze ? "requester_freeze" : "requester_thaw";
|
||||
QGAVSSRequesterFunc func;
|
||||
ErrorSet errset = {
|
||||
.error_setg_win32 = error_setg_win32_internal,
|
||||
.error_setg_win32_wrapper = error_setg_win32_internal,
|
||||
.errp = errp,
|
||||
};
|
||||
|
||||
|
@ -10,8 +10,7 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "vss-common.h"
|
||||
#include "inc/win2003/vscoordint.h"
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "qemu/osdep.h"
|
||||
#include "vss-common.h"
|
||||
#include "inc/win2003/vscoordint.h"
|
||||
#include "inc/win2003/vsprov.h"
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "qemu/osdep.h"
|
||||
#include "vss-common.h"
|
||||
#include "requester.h"
|
||||
#include "assert.h"
|
||||
@ -23,9 +23,9 @@
|
||||
/* Call QueryStatus every 10 ms while waiting for frozen event */
|
||||
#define VSS_TIMEOUT_EVENT_MSEC 10
|
||||
|
||||
#define err_set(e, err, fmt, ...) \
|
||||
((e)->error_setg_win32((e)->errp, __FILE__, __LINE__, __func__, \
|
||||
err, fmt, ## __VA_ARGS__))
|
||||
#define err_set(e, err, fmt, ...) \
|
||||
((e)->error_setg_win32_wrapper((e)->errp, __FILE__, __LINE__, __func__, \
|
||||
err, fmt, ## __VA_ARGS__))
|
||||
/* Bad idea, works only when (e)->errp != NULL: */
|
||||
#define err_is_set(e) ((e)->errp && *(e)->errp)
|
||||
/* To lift this restriction, error_propagate(), like we do in QEMU code */
|
||||
|
@ -27,7 +27,7 @@ typedef void (*ErrorSetFunc)(struct Error **errp,
|
||||
int win32_err, const char *fmt, ...)
|
||||
GCC_FMT_ATTR(6, 7);
|
||||
typedef struct ErrorSet {
|
||||
ErrorSetFunc error_setg_win32;
|
||||
ErrorSetFunc error_setg_win32_wrapper;
|
||||
struct Error **errp; /* restriction: must not be null */
|
||||
} ErrorSet;
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "libqtest.h"
|
||||
#include "qga/guest-agent-core.h"
|
||||
|
||||
typedef struct {
|
||||
char *test_dir;
|
||||
@ -450,8 +449,8 @@ static void test_qga_file_ops(gconstpointer fix)
|
||||
/* seek */
|
||||
cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
|
||||
" 'arguments': { 'handle': %" PRId64 ", "
|
||||
" 'offset': %d, 'whence': %d } }",
|
||||
id, 6, QGA_SEEK_SET);
|
||||
" 'offset': %d, 'whence': '%s' } }",
|
||||
id, 6, "set");
|
||||
ret = qmp_fd(fixture->fd, cmd);
|
||||
qmp_assert_no_error(ret);
|
||||
val = qdict_get_qdict(ret, "return");
|
||||
@ -543,8 +542,8 @@ static void test_qga_file_write_read(gconstpointer fix)
|
||||
/* seek to 0 */
|
||||
cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
|
||||
" 'arguments': { 'handle': %" PRId64 ", "
|
||||
" 'offset': %d, 'whence': %d } }",
|
||||
id, 0, QGA_SEEK_SET);
|
||||
" 'offset': %d, 'whence': '%s' } }",
|
||||
id, 0, "set");
|
||||
ret = qmp_fd(fixture->fd, cmd);
|
||||
qmp_assert_no_error(ret);
|
||||
val = qdict_get_qdict(ret, "return");
|
||||
|
Loading…
Reference in New Issue
Block a user