qga: Support enum names in guest-file-seek
Magic constants are a pain to use, especially when we run the risk that our choice of '1' for QGA_SEEK_CUR might differ from the host or guest's choice of SEEK_CUR. Better is to use an enum value, via a qapi alternate type for back-compatibility. With this, {"command":"guest-file-seek", "arguments":{"handle":1, "offset":0, "whence":"cur"}} becomes a synonym for the older {"command":"guest-file-seek", "arguments":{"handle":1, "offset":0, "whence":1}} Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com> Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
This commit is contained in:
parent
774ae4254d
commit
0b4b49387c
@ -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,
|
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);
|
GuestFileHandle *gfh = guest_file_handle_find(handle, errp);
|
||||||
GuestFileSeek *seek_data = NULL;
|
GuestFileSeek *seek_data = NULL;
|
||||||
FILE *fh;
|
FILE *fh;
|
||||||
int ret;
|
int ret;
|
||||||
int whence;
|
int whence;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
if (!gfh) {
|
if (!gfh) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We stupidly exposed 'whence':'int' in our qapi */
|
/* We stupidly exposed 'whence':'int' in our qapi */
|
||||||
switch (whence_code) {
|
whence = ga_parse_whence(whence_code, &err);
|
||||||
case QGA_SEEK_SET:
|
if (err) {
|
||||||
whence = SEEK_SET;
|
error_propagate(errp, err);
|
||||||
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);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +385,8 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
|
GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
|
||||||
int64_t whence_code, Error **errp)
|
GuestFileWhence *whence_code,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
GuestFileHandle *gfh;
|
GuestFileHandle *gfh;
|
||||||
GuestFileSeek *seek_data;
|
GuestFileSeek *seek_data;
|
||||||
@ -394,6 +395,7 @@ GuestFileSeek *qmp_guest_file_seek(int64_t handle, int64_t offset,
|
|||||||
off_pos.QuadPart = offset;
|
off_pos.QuadPart = offset;
|
||||||
BOOL res;
|
BOOL res;
|
||||||
int whence;
|
int whence;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
gfh = guest_file_handle_find(handle, errp);
|
gfh = guest_file_handle_find(handle, errp);
|
||||||
if (!gfh) {
|
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 */
|
/* We stupidly exposed 'whence':'int' in our qapi */
|
||||||
switch (whence_code) {
|
whence = ga_parse_whence(whence_code, &err);
|
||||||
case QGA_SEEK_SET:
|
if (err) {
|
||||||
whence = SEEK_SET;
|
error_propagate(errp, err);
|
||||||
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);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,3 +473,24 @@ done:
|
|||||||
|
|
||||||
return ge;
|
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 "qapi/qmp/dispatch.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
#include "qga-qmp-commands.h"
|
||||||
|
|
||||||
#define QGA_READ_COUNT_DEFAULT 4096
|
#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 GAState GAState;
|
||||||
typedef struct GACommandState GACommandState;
|
typedef struct GACommandState GACommandState;
|
||||||
extern GAState *ga_state;
|
extern GAState *ga_state;
|
||||||
@ -44,6 +38,7 @@ void ga_set_frozen(GAState *s);
|
|||||||
void ga_unset_frozen(GAState *s);
|
void ga_unset_frozen(GAState *s);
|
||||||
const char *ga_fsfreeze_hook(GAState *s);
|
const char *ga_fsfreeze_hook(GAState *s);
|
||||||
int64_t ga_get_fd_handle(GAState *s, Error **errp);
|
int64_t ga_get_fd_handle(GAState *s, Error **errp);
|
||||||
|
int ga_parse_whence(GuestFileWhence *whence, Error **errp);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
void reopen_fd_to_null(int fd);
|
void reopen_fd_to_null(int fd);
|
||||||
|
@ -313,6 +313,34 @@
|
|||||||
{ 'struct': 'GuestFileSeek',
|
{ 'struct': 'GuestFileSeek',
|
||||||
'data': { 'position': 'int', 'eof': 'bool' } }
|
'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:
|
# @guest-file-seek:
|
||||||
#
|
#
|
||||||
@ -324,14 +352,15 @@
|
|||||||
#
|
#
|
||||||
# @offset: bytes to skip over in the file stream
|
# @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.
|
# Returns: @GuestFileSeek on success.
|
||||||
#
|
#
|
||||||
# Since: 0.15.0
|
# Since: 0.15.0
|
||||||
##
|
##
|
||||||
{ 'command': 'guest-file-seek',
|
{ 'command': 'guest-file-seek',
|
||||||
'data': { 'handle': 'int', 'offset': 'int', 'whence': 'int' },
|
'data': { 'handle': 'int', 'offset': 'int',
|
||||||
|
'whence': 'GuestFileWhence' },
|
||||||
'returns': 'GuestFileSeek' }
|
'returns': 'GuestFileSeek' }
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include "libqtest.h"
|
#include "libqtest.h"
|
||||||
#include "qga/guest-agent-core.h"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char *test_dir;
|
char *test_dir;
|
||||||
@ -450,8 +449,8 @@ static void test_qga_file_ops(gconstpointer fix)
|
|||||||
/* seek */
|
/* seek */
|
||||||
cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
|
cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
|
||||||
" 'arguments': { 'handle': %" PRId64 ", "
|
" 'arguments': { 'handle': %" PRId64 ", "
|
||||||
" 'offset': %d, 'whence': %d } }",
|
" 'offset': %d, 'whence': '%s' } }",
|
||||||
id, 6, QGA_SEEK_SET);
|
id, 6, "set");
|
||||||
ret = qmp_fd(fixture->fd, cmd);
|
ret = qmp_fd(fixture->fd, cmd);
|
||||||
qmp_assert_no_error(ret);
|
qmp_assert_no_error(ret);
|
||||||
val = qdict_get_qdict(ret, "return");
|
val = qdict_get_qdict(ret, "return");
|
||||||
@ -543,8 +542,8 @@ static void test_qga_file_write_read(gconstpointer fix)
|
|||||||
/* seek to 0 */
|
/* seek to 0 */
|
||||||
cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
|
cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
|
||||||
" 'arguments': { 'handle': %" PRId64 ", "
|
" 'arguments': { 'handle': %" PRId64 ", "
|
||||||
" 'offset': %d, 'whence': %d } }",
|
" 'offset': %d, 'whence': '%s' } }",
|
||||||
id, 0, QGA_SEEK_SET);
|
id, 0, "set");
|
||||||
ret = qmp_fd(fixture->fd, cmd);
|
ret = qmp_fd(fixture->fd, cmd);
|
||||||
qmp_assert_no_error(ret);
|
qmp_assert_no_error(ret);
|
||||||
val = qdict_get_qdict(ret, "return");
|
val = qdict_get_qdict(ret, "return");
|
||||||
|
Loading…
Reference in New Issue
Block a user