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,
 | 
			
		||||
                                          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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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' }
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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