HGFS: move all VMware-specific code into libhgfs

This commit is contained in:
David van Moolenbroek
2012-04-09 17:17:42 +02:00
parent 060399d9dd
commit 09b327b042
17 changed files with 117 additions and 114 deletions

View File

@@ -2,6 +2,6 @@
LIB= hgfs
SRCS= backdoor.S attr.c channel.c dir.c error.c file.c \
link.c misc.c path.c rpc.c time.c
info.c link.c misc.c path.c rpc.c time.c
.include <bsd.lib.mk>

View File

@@ -64,18 +64,34 @@ struct hgfs_attr *attr;
{
/* Set selected attributes of a file by path name.
*/
u8_t mask;
RPC_REQUEST(HGFS_REQ_SETATTR);
RPC_NEXT8 = (attr->a_mask & HGFS_ATTR_ALL);
/* This library implements the HGFS v1 protocol, which is largely
* path-oriented. This is the only method to set the file size, and thus,
* truncating a deleted file is not possible. This has been fixed in later
* HGFS protocol version (v2/v3).
*/
mask = 0;
if (attr->a_mask & HGFS_ATTR_MODE) mask |= HGFS_ATTR_MODE;
if (attr->a_mask & HGFS_ATTR_SIZE) mask |= HGFS_ATTR_SIZE;
if (attr->a_mask & HGFS_ATTR_CRTIME) mask |= HGFS_ATTR_CRTIME;
if (attr->a_mask & HGFS_ATTR_ATIME)
mask |= HGFS_ATTR_ATIME | HGFS_ATTR_ATIME_SET;
if (attr->a_mask & HGFS_ATTR_MTIME)
mask |= HGFS_ATTR_MTIME | HGFS_ATTR_MTIME_SET;
if (attr->a_mask & HGFS_ATTR_CTIME) mask |= HGFS_ATTR_CTIME;
RPC_NEXT8 = mask;
RPC_NEXT32 = !!(S_ISDIR(attr->a_mode));
RPC_NEXT32 = ex64lo(attr->a_size);
RPC_NEXT32 = ex64hi(attr->a_size);
time_put((attr->a_mask & HGFS_ATTR_CRTIME) ? &attr->a_crtime : NULL);
time_put((attr->a_mask & HGFS_ATTR_ATIME_SET) ? &attr->a_atime : NULL);
time_put((attr->a_mask & HGFS_ATTR_MTIME_SET) ? &attr->a_mtime : NULL);
time_put((attr->a_mask & HGFS_ATTR_ATIME) ? &attr->a_atime : NULL);
time_put((attr->a_mask & HGFS_ATTR_MTIME) ? &attr->a_mtime : NULL);
time_put((attr->a_mask & HGFS_ATTR_CTIME) ? &attr->a_ctime : NULL);
RPC_NEXT8 = HGFS_MODE_TO_PERM(attr->a_mode);

View File

@@ -60,3 +60,13 @@ enum {
/* HGFS mode/perms conversion macros */
#define HGFS_MODE_TO_PERM(m) (((m) & S_IRWXU) >> 6)
#define HGFS_PERM_TO_MODE(p) (((p) << 6) & S_IRWXU)
/* HGFS attribute flags */
#define HGFS_ATTR_SIZE 0x01 /* get/set file size */
#define HGFS_ATTR_CRTIME 0x02 /* get/set file creation time */
#define HGFS_ATTR_ATIME 0x04 /* get/set file access time */
#define HGFS_ATTR_MTIME 0x08 /* get/set file modification time */
#define HGFS_ATTR_CTIME 0x10 /* get/set file change time */
#define HGFS_ATTR_MODE 0x20 /* get/set file mode */
#define HGFS_ATTR_ATIME_SET 0x40 /* set specific file access time */
#define HGFS_ATTR_MTIME_SET 0x80 /* set specific file modify time */

View File

@@ -39,7 +39,7 @@ struct hgfs_attr *attr;
* number. Upon success, the resulting path name is stored in the given buffer
* and the given attribute structure is filled selectively as requested. Upon
* error, the contents of the path buffer and attribute structure are
* undefined.
* undefined. ENOENT is returned upon end of directory.
*/
int r;
@@ -47,12 +47,20 @@ struct hgfs_attr *attr;
RPC_NEXT32 = (u32_t)handle;
RPC_NEXT32 = index;
/* EINVAL signifies end of directory. */
if ((r = rpc_query()) != OK)
return r;
return (r == EINVAL) ? ENOENT : OK;
attr_get(attr);
return path_get(buf, size);
if ((r = path_get(buf, size)) != OK)
return r;
/* VMware Player 3 returns an empty name, instead of EINVAL, when reading
* from an EOF position right after opening the directory handle. Seems to be
* a newly introduced bug..
*/
return (!buf[0]) ? ENOENT : OK;
}
/*===========================================================================*

View File

@@ -74,8 +74,8 @@ u64_t off; /* file offset */
len = RPC_NEXT32;
if (len > max) len = max; /* sanity check */
/* Only copy out data if we're requested to do so. */
if (buf != NULL)
/* Only copy out data if we're not operating directly on the RPC buffer. */
if (buf != RPC_PTR)
memcpy(buf, RPC_PTR, len);
return len;
@@ -84,12 +84,11 @@ u64_t off; /* file offset */
/*===========================================================================*
* hgfs_write *
*===========================================================================*/
int hgfs_write(handle, buf, len, off, append)
int hgfs_write(handle, buf, len, off)
hgfs_file_t handle; /* handle to open file */
const char *buf; /* data buffer or NULL */
char *buf; /* data buffer or NULL */
size_t len; /* number of bytes to write */
u64_t off; /* file offset */
int append; /* if set, append to file (ignore offset) */
{
/* Write to an open file. Upon success, return the number of bytes written.
*/
@@ -97,22 +96,13 @@ int append; /* if set, append to file (ignore offset) */
RPC_REQUEST(HGFS_REQ_WRITE);
RPC_NEXT32 = (u32_t)handle;
if (append) {
RPC_NEXT8 = 1;
RPC_NEXT32 = 0;
RPC_NEXT32 = 0;
}
else {
RPC_NEXT8 = 0;
RPC_NEXT32 = ex64lo(off);
RPC_NEXT32 = ex64hi(off);
}
RPC_NEXT8 = 0; /* append flag */
RPC_NEXT32 = ex64lo(off);
RPC_NEXT32 = ex64hi(off);
RPC_NEXT32 = len;
/* Only copy in data if we're requested to do so. */
if (buf != NULL)
/* Only copy in data if we're not operating directly on the RPC buffer. */
if (RPC_PTR != buf)
memcpy(RPC_PTR, buf, len);
RPC_ADVANCE(len);

38
lib/libhgfs/info.c Normal file
View File

@@ -0,0 +1,38 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
/*===========================================================================*
* hgfs_queryvol *
*===========================================================================*/
int hgfs_queryvol(path, free, total)
char *path;
u64_t *free;
u64_t *total;
{
/* Retrieve information about available and total volume space associated with
* a given path.
*/
u32_t lo, hi;
int r;
RPC_REQUEST(HGFS_REQ_QUERYVOL);
path_put(path);
/* It appears that this call always fails with EACCES ("permission denied")
* on read-only folders. As far as I can tell, this is a VMware bug.
*/
if ((r = rpc_query()) != OK)
return r;
lo = RPC_NEXT32;
hi = RPC_NEXT32;
*free = make64(lo, hi);
lo = RPC_NEXT32;
hi = RPC_NEXT32;
*total = make64(lo, hi);
return OK;
}

View File

@@ -8,8 +8,7 @@
int hgfs_init()
{
/* Initialize the library. Return OK on success, or a negative error code
* otherwise. If EAGAIN is returned, shared folders are disabled; in that
* case, other operations may be tried (and possibly succeed).
* otherwise. If EAGAIN is returned, shared folders are disabled.
*/
time_init();
@@ -27,47 +26,3 @@ void hgfs_cleanup()
rpc_close();
}
/*===========================================================================*
* hgfs_enabled *
*===========================================================================*/
int hgfs_enabled()
{
/* Check if shared folders are enabled. Return OK if so, EAGAIN if not, and
* another negative error code on error.
*/
return rpc_test();
}
/*===========================================================================*
* hgfs_queryvol *
*===========================================================================*/
int hgfs_queryvol(path, free, total)
char *path;
u64_t *free;
u64_t *total;
{
/* Retrieve information about available and total volume space associated with
* a given path.
*/
u32_t lo, hi;
int r;
RPC_REQUEST(HGFS_REQ_QUERYVOL);
path_put(path);
if ((r = rpc_query()) != OK)
return r;
lo = RPC_NEXT32;
hi = RPC_NEXT32;
*free = make64(lo, hi);
lo = RPC_NEXT32;
hi = RPC_NEXT32;
*total = make64(lo, hi);
return OK;
}

View File

@@ -13,7 +13,8 @@ static struct channel rpc_chan;
int rpc_open()
{
/* Open a HGFS RPC backdoor channel to the VMware host, and make sure that it
* is working. Return OK upon success, or a negative error code otherwise.
* is working. Return OK upon success, or a negative error code otherwise; in
* particular, return EAGAIN if shared folders are disabled.
*/
int r;
@@ -22,7 +23,7 @@ int rpc_open()
r = rpc_test();
if (r != OK && r != EAGAIN)
if (r != OK)
channel_close(&rpc_chan);
return r;