Reorganize some directories

servers/hgfs/hgfs_server => servers/hgfs
servers/hgfs/libhgfs => lib/libhgfs
servers/rs/service => commands/service
drivers/memory/memory_driver => drivers/memory
drivers/memory/ramdisk => drivers/ramdisk
This commit is contained in:
Arun Thomas
2010-05-26 22:49:57 +00:00
parent 007104d60e
commit b48b037fbe
66 changed files with 141 additions and 174 deletions

View File

@@ -1,7 +1,7 @@
.include <minix.own.mk>
SUBDIR= csu libc libcurses libdriver libnetdriver libend libedit libm libsys \
libtimers libutil libbz2 libl
libtimers libutil libbz2 libl libhgfs
.if ${COMPILER_TYPE} == "ack"
SUBDIR+= ack/libd ack/libe ack/libfp ack/liby

7
lib/libhgfs/Makefile Normal file
View File

@@ -0,0 +1,7 @@
# Makefile for HGFS library
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
.include <minix.lib.mk>

86
lib/libhgfs/attr.c Normal file
View File

@@ -0,0 +1,86 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
#include <sys/stat.h>
/*===========================================================================*
* attr_get *
*===========================================================================*/
PUBLIC void attr_get(attr)
struct hgfs_attr *attr;
{
/* Get attribute information from the RPC buffer, storing the requested parts
* in the given attr structure.
*/
mode_t mode;
u32_t size_lo, size_hi;
mode = (RPC_NEXT32) ? S_IFDIR : S_IFREG;
size_lo = RPC_NEXT32;
size_hi = RPC_NEXT32;
if (attr->a_mask & HGFS_ATTR_SIZE)
attr->a_size = make64(size_lo, size_hi);
time_get((attr->a_mask & HGFS_ATTR_CRTIME) ? &attr->a_crtime : NULL);
time_get((attr->a_mask & HGFS_ATTR_ATIME) ? &attr->a_atime : NULL);
time_get((attr->a_mask & HGFS_ATTR_MTIME) ? &attr->a_mtime : NULL);
time_get((attr->a_mask & HGFS_ATTR_CTIME) ? &attr->a_ctime : NULL);
mode |= HGFS_PERM_TO_MODE(RPC_NEXT8);
if (attr->a_mask & HGFS_ATTR_MODE) attr->a_mode = mode;
}
/*===========================================================================*
* hgfs_getattr *
*===========================================================================*/
PUBLIC int hgfs_getattr(path, attr)
char *path;
struct hgfs_attr *attr;
{
/* Get selected attributes of a file by path name.
*/
int r;
RPC_REQUEST(HGFS_REQ_GETATTR);
path_put(path);
if ((r = rpc_query()) != OK)
return r;
attr_get(attr);
return OK;
}
/*===========================================================================*
* hgfs_setattr *
*===========================================================================*/
PUBLIC int hgfs_setattr(path, attr)
char *path;
struct hgfs_attr *attr;
{
/* Set selected attributes of a file by path name.
*/
RPC_REQUEST(HGFS_REQ_SETATTR);
RPC_NEXT8 = (attr->a_mask & HGFS_ATTR_ALL);
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) ? &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);
path_put(path);
return rpc_query();
}

106
lib/libhgfs/backdoor.S Normal file
View File

@@ -0,0 +1,106 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
.globl ___libhgfs_backdoor
.globl ___libhgfs_backdoor_in
.globl ___libhgfs_backdoor_out
.text
MAGIC = 0x564D5868
BD_PORT = 0x5658
IO_PORT = 0x5659
.balign 16
___libhgfs_backdoor:
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
movl 4+16(%esp), %ebp
movl $MAGIC, %eax
movl 4(%ebp), %ebx
movl 8(%ebp), %ecx
movl 12(%ebp), %edx
movw $BD_PORT, %dx
movl 16(%ebp), %esi
movl 20(%ebp), %edi
inl %dx
movl %eax, (%ebp)
movl %ebx, 4(%ebp)
movl %ecx, 8(%ebp)
movl %edx, 12(%ebp)
movl %esi, 16(%ebp)
movl %edi, 20(%ebp)
popl %ebp
popl %edi
popl %esi
popl %ebx
ret
.balign 16
___libhgfs_backdoor_in:
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
movl 4+16(%esp), %eax
movl 4(%eax), %ebx
movl 8(%eax), %ecx
movl 12(%eax), %edx
movw $IO_PORT, %dx
movl 16(%eax), %esi
movl 20(%eax), %edi
movl 24(%eax), %ebp
movl $MAGIC, %eax
cld
repe; insb
pushl %eax
movl 4+20(%esp), %eax
movl %ebx, 4(%eax)
movl %ecx, 8(%eax)
movl %edx, 12(%eax)
movl %esi, 16(%eax)
movl %edi, 20(%eax)
movl %ebp, 24(%eax)
popl %ebx
movl %ebx, (%eax)
movl (%eax), %eax
popl %ebp
popl %edi
popl %esi
popl %ebx
ret
.balign 16
___libhgfs_backdoor_out:
pushl %ebx
pushl %esi
pushl %edi
pushl %ebp
movl 4+16(%esp), %eax
movl 4(%eax), %ebx
movl 8(%eax), %ecx
movl 12(%eax), %edx
movw $IO_PORT, %dx
movl 16(%eax), %esi
movl 20(%eax), %edi
movl 24(%eax), %ebp
movl $MAGIC, %eax
cld
repe; outsb
pushl %eax
movl 4+20(%esp), %eax
movl %ebx, 4(%eax)
movl %ecx, 8(%eax)
movl %edx, 12(%eax)
movl %esi, 16(%eax)
movl %edi, 20(%eax)
movl %ebp, 24(%eax)
popl %ebx
movl %ebx, (%eax)
movl (%eax), %eax
popl %ebp
popl %edi
popl %esi
popl %ebx
ret

146
lib/libhgfs/channel.c Normal file
View File

@@ -0,0 +1,146 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
#define CMD_XFER 0x1E /* vmware backdoor transfer command */
enum {
XFER_OPEN, /* open transfer channel */
XFER_SENDLEN, /* specify length of data to send */
XFER_SEND, /* send data */
XFER_RECVLEN, /* get length of data to receive */
XFER_RECV, /* receive data */
XFER_RECVACK, /* acknowledge receipt of data */
XFER_CLOSE /* close transfer channel */
};
#define STATUS(p) (HIWORD((p)[2]) & 0xff)
/*===========================================================================*
* channel_open *
*===========================================================================*/
PUBLIC int channel_open(ch, type)
struct channel *ch; /* struct describing the new channel */
u32_t type; /* channel type: CH_IN or CH_OUT */
{
/* Open a new backdoor channel. Upon success, the given channel structure will
* be filled with information and can be used in subsequent channel calls.
* Return OK on success, or a negative error code on error.
*/
u32_t ptr[6];
ptr[1] = type | 0x80000000;
ptr[2] = MAKELONG(CMD_XFER, XFER_OPEN);
backdoor(ptr);
if ((STATUS(ptr) & 1) == 0) return EIO;
ch->id = HIWORD(ptr[3]);
ch->cookie1 = ptr[4];
ch->cookie2 = ptr[5];
return OK;
}
/*===========================================================================*
* channel_close *
*===========================================================================*/
PUBLIC void channel_close(ch)
struct channel *ch; /* backdoor channel to close */
{
/* Close a previously opened backdoor channel.
*/
u32_t ptr[6];
ptr[2] = MAKELONG(CMD_XFER, XFER_CLOSE);
ptr[3] = MAKELONG(0, ch->id);
ptr[4] = ch->cookie1;
ptr[5] = ch->cookie2;
backdoor(ptr);
}
/*===========================================================================*
* channel_send *
*===========================================================================*/
PUBLIC int channel_send(ch, buf, len)
struct channel *ch; /* backdoor channel to send to */
char *buf; /* buffer to send data from */
int len; /* size of the data to send */
{
/* Receive data over a backdoor channel. Return OK on success, or a negative
* error code on error.
*/
u32_t ptr[7];
ptr[1] = len;
ptr[2] = MAKELONG(CMD_XFER, XFER_SENDLEN);
ptr[3] = MAKELONG(0, ch->id);
ptr[4] = ch->cookie1;
ptr[5] = ch->cookie2;
backdoor(ptr);
if ((STATUS(ptr) & 1) == 0) return EIO;
if (len == 0) return OK;
ptr[1] = MAKELONG(0, 1);
ptr[2] = len;
ptr[3] = MAKELONG(0, ch->id);
ptr[4] = (u32_t)buf;
ptr[5] = ch->cookie2;
ptr[6] = ch->cookie1;
backdoor_out(ptr);
return OK;
}
/*===========================================================================*
* channel_recv *
*===========================================================================*/
PUBLIC int channel_recv(ch, buf, max)
struct channel *ch; /* backdoor channel to receive from */
char *buf; /* buffer to receive data into */
int max; /* size of the buffer */
{
/* Receive data on a backdoor channel. Return the number of bytes received, or
* a negative error code on error.
*/
u32_t ptr[7];
int len;
ptr[2] = MAKELONG(CMD_XFER, XFER_RECVLEN);
ptr[3] = MAKELONG(0, ch->id);
ptr[4] = ch->cookie1;
ptr[5] = ch->cookie2;
backdoor(ptr);
if ((STATUS(ptr) & 0x81) == 0) return EIO;
if ((len = ptr[1]) == 0 || (STATUS(ptr) & 3) == 1) return 0;
if (len > max) return E2BIG;
ptr[1] = MAKELONG(0, 1);
ptr[2] = len;
ptr[3] = MAKELONG(0, ch->id);
ptr[4] = ch->cookie1;
ptr[5] = (u32_t)buf;
ptr[6] = ch->cookie2;
backdoor_in(ptr);
ptr[1] = 1;
ptr[2] = MAKELONG(CMD_XFER, XFER_RECVACK);
ptr[3] = MAKELONG(0, ch->id);
ptr[4] = ch->cookie1;
ptr[5] = ch->cookie2;
backdoor(ptr);
return len;
}

62
lib/libhgfs/const.h Normal file
View File

@@ -0,0 +1,62 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
/* Various macros used here and there */
#define MAKELONG(a,b) ((a) | ((b) << 16))
#define HIWORD(d) ((d) >> 16)
#define LOWORD(d) ((d) & 0xffff)
#define BYTES(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
/* Valid channel types for channel_open() */
#define CH_IN BYTES('T', 'C', 'L', 'O')
#define CH_OUT BYTES('R', 'P', 'C', 'I')
/* RPC constants */
#define RPC_BUF_SIZE 6134 /* max size of RPC request */
#define RPC_HDR_SIZE 10 /* RPC HGFS header size */
/* RPC macros. These NEED NOT be portable. VMware only does x86(-64) anyway. */
/* ..all this because ACK can't pack structures :( */
#define RPC_NEXT8 *(((u8_t*)(++rpc_ptr))-1) /* get/set next byte */
#define RPC_NEXT16 *(((u16_t*)(rpc_ptr+=2))-1) /* get/set next short */
#define RPC_NEXT32 *(((u32_t*)(rpc_ptr+=4))-1) /* get/set next long */
#define RPC_LEN (rpc_ptr - rpc_buf) /* request length thus far */
#define RPC_ADVANCE(n) rpc_ptr += n /* skip n bytes in buffer */
#define RPC_PTR (rpc_ptr) /* pointer to next data */
#define RPC_RESET rpc_ptr = rpc_buf /* start at beginning */
#define RPC_REQUEST(r) \
RPC_RESET; \
RPC_NEXT8 = 'f'; \
RPC_NEXT8 = ' '; \
RPC_NEXT32 = 0; \
RPC_NEXT32 = r; /* start a RPC request */
/* HGFS requests */
enum {
HGFS_REQ_OPEN,
HGFS_REQ_READ,
HGFS_REQ_WRITE,
HGFS_REQ_CLOSE,
HGFS_REQ_OPENDIR,
HGFS_REQ_READDIR,
HGFS_REQ_CLOSEDIR,
HGFS_REQ_GETATTR,
HGFS_REQ_SETATTR,
HGFS_REQ_MKDIR,
HGFS_REQ_UNLINK,
HGFS_REQ_RMDIR,
HGFS_REQ_RENAME,
HGFS_REQ_QUERYVOL
};
/* HGFS open types */
enum {
HGFS_OPEN_TYPE_O,
HGFS_OPEN_TYPE_OT,
HGFS_OPEN_TYPE_CO,
HGFS_OPEN_TYPE_C,
HGFS_OPEN_TYPE_COT
};
/* 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)

71
lib/libhgfs/dir.c Normal file
View File

@@ -0,0 +1,71 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
/*===========================================================================*
* hgfs_opendir *
*===========================================================================*/
PUBLIC int hgfs_opendir(path, handle)
char *path;
hgfs_dir_t *handle;
{
/* Open a directory. Store a directory handle upon success.
*/
int r;
RPC_REQUEST(HGFS_REQ_OPENDIR);
path_put(path);
if ((r = rpc_query()) != OK)
return r;
*handle = (hgfs_dir_t)RPC_NEXT32;
return OK;
}
/*===========================================================================*
* hgfs_readdir *
*===========================================================================*/
PUBLIC int hgfs_readdir(handle, index, buf, size, attr)
hgfs_dir_t handle;
unsigned int index;
char *buf;
size_t size;
struct hgfs_attr *attr;
{
/* Read a directory entry from an open directory, using a zero-based index
* 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.
*/
int r;
RPC_REQUEST(HGFS_REQ_READDIR);
RPC_NEXT32 = (u32_t)handle;
RPC_NEXT32 = index;
if ((r = rpc_query()) != OK)
return r;
attr_get(attr);
return path_get(buf, size);
}
/*===========================================================================*
* hgfs_closedir *
*===========================================================================*/
PUBLIC int hgfs_closedir(handle)
hgfs_dir_t handle;
{
/* Close an open directory.
*/
RPC_REQUEST(HGFS_REQ_CLOSEDIR);
RPC_NEXT32 = (u32_t)handle;
return rpc_query();
}

40
lib/libhgfs/error.c Normal file
View File

@@ -0,0 +1,40 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
/* Not sure if all of these occur in the HGFS v1 protocol, but at least some
* that weren't in the original protocol, are being returned now.
*/
#define NERRS 16
PRIVATE int error_map[NERRS] = {
OK, /* no error */
ENOENT, /* no such file/directory */
EBADF, /* invalid handle */
EPERM, /* operation not permitted */
EEXIST, /* file already exists */
ENOTDIR, /* not a directory */
ENOTEMPTY, /* directory not empty */
EIO, /* protocol error */
EACCES, /* access denied */
EINVAL, /* invalid name */
EIO, /* generic error */
EIO, /* sharing violation */
ENOSPC, /* no space */
ENOSYS, /* operation not supported */
ENAMETOOLONG, /* name too long */
EINVAL, /* invalid parameter */
};
/*===========================================================================*
* error_convert *
*===========================================================================*/
PUBLIC int error_convert(err)
int err;
{
/* Convert a HGFS error into an errno error code.
*/
if (err < 0 || err >= NERRS) return EIO;
return error_map[err];
}

182
lib/libhgfs/file.c Normal file
View File

@@ -0,0 +1,182 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
#include <fcntl.h>
#include <sys/stat.h>
/*===========================================================================*
* hgfs_open *
*===========================================================================*/
PUBLIC int hgfs_open(path, flags, mode, handle)
char *path; /* path name to open */
int flags; /* open flags to use */
int mode; /* mode to create (user bits only) */
hgfs_file_t *handle; /* place to store resulting handle */
{
/* Open a file. Store a file handle upon success.
*/
int r, type;
/* We could implement this, but that means we would have to start tracking
* open files in order to associate data with them. Rather not.
*/
if (flags & O_APPEND) return EINVAL;
if (flags & O_CREAT) {
if (flags & O_EXCL) type = HGFS_OPEN_TYPE_C;
else if (flags & O_TRUNC) type = HGFS_OPEN_TYPE_COT;
else type = HGFS_OPEN_TYPE_CO;
} else {
if (flags & O_TRUNC) type = HGFS_OPEN_TYPE_OT;
else type = HGFS_OPEN_TYPE_O;
}
RPC_REQUEST(HGFS_REQ_OPEN);
RPC_NEXT32 = (flags & O_ACCMODE);
RPC_NEXT32 = type;
RPC_NEXT8 = HGFS_MODE_TO_PERM(mode);
path_put(path);
if ((r = rpc_query()) != OK)
return r;
*handle = (hgfs_file_t)RPC_NEXT32;
return OK;
}
/*===========================================================================*
* hgfs_read *
*===========================================================================*/
PUBLIC int hgfs_read(handle, buf, size, off)
hgfs_file_t handle; /* handle to open file */
char *buf; /* data buffer or NULL */
size_t size; /* maximum number of bytes to read */
u64_t off; /* file offset */
{
/* Read from an open file. Upon success, return the number of bytes read.
*/
int r, len, max;
RPC_REQUEST(HGFS_REQ_READ);
RPC_NEXT32 = (u32_t)handle;
RPC_NEXT32 = ex64lo(off);
RPC_NEXT32 = ex64hi(off);
max = RPC_BUF_SIZE - RPC_LEN - sizeof(u32_t);
RPC_NEXT32 = (size < max) ? size : max;
if ((r = rpc_query()) != OK)
return r;
len = RPC_NEXT32;
if (len > max) len = max; /* sanity check */
/* Only copy out data if we're requested to do so. */
if (buf != NULL)
memcpy(buf, RPC_PTR, len);
return len;
}
/*===========================================================================*
* hgfs_write *
*===========================================================================*/
PUBLIC int hgfs_write(handle, buf, len, off, append)
hgfs_file_t handle; /* handle to open file */
const 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.
*/
int r;
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_NEXT32 = len;
/* Only copy in data if we're requested to do so. */
if (buf != NULL)
memcpy(RPC_PTR, buf, len);
RPC_ADVANCE(len);
if ((r = rpc_query()) != OK)
return r;
return RPC_NEXT32;
}
/*===========================================================================*
* hgfs_close *
*===========================================================================*/
PUBLIC int hgfs_close(handle)
hgfs_file_t handle; /* handle to open file */
{
/* Close an open file.
*/
RPC_REQUEST(HGFS_REQ_CLOSE);
RPC_NEXT32 = (u32_t)handle;
return rpc_query();
}
/*===========================================================================*
* hgfs_readbuf *
*===========================================================================*/
PUBLIC size_t hgfs_readbuf(ptr)
char **ptr;
{
/* Return information about the read buffer, for zero-copy purposes. Store a
* pointer to the first byte of the read buffer, and return the maximum data
* size. The results are static, but must only be used directly prior to a
* hgfs_read() call (with a NULL data buffer address).
*/
u32_t off;
off = RPC_HDR_SIZE + sizeof(u32_t);
RPC_RESET;
RPC_ADVANCE(off);
*ptr = RPC_PTR;
return RPC_BUF_SIZE - off;
}
/*===========================================================================*
* hgfs_writebuf *
*===========================================================================*/
PUBLIC size_t hgfs_writebuf(ptr)
char **ptr;
{
/* Return information about the write buffer, for zero-copy purposes. Store a
* pointer to the first byte of the write buffer, and return the maximum data
* size. The results are static, but must only be used immediately after a
* hgfs_write() call (with a NULL data buffer address).
*/
u32_t off;
off = RPC_HDR_SIZE + sizeof(u32_t) + sizeof(u8_t) + sizeof(u32_t) * 3;
RPC_RESET;
RPC_ADVANCE(off);
*ptr = RPC_PTR;
return RPC_BUF_SIZE - off;
}

6
lib/libhgfs/glo.h Normal file
View File

@@ -0,0 +1,6 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#define rpc_buf PREFIX(rpc_buf)
#define rpc_ptr PREFIX(rpc_ptr)
extern char rpc_buf[RPC_BUF_SIZE];
extern char *rpc_ptr;

19
lib/libhgfs/inc.h Normal file
View File

@@ -0,0 +1,19 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#define _POSIX_SOURCE 1 /* need PATH_MAX */
#define _SYSTEM 1 /* need negative error codes */
#include <minix/config.h>
#include <minix/const.h>
#include <string.h>
#include <errno.h>
#include "hgfs.h"
#define PREFIX(x) __libhgfs_##x
#include "type.h"
#include "const.h"
#include "proto.h"
#include "glo.h"

73
lib/libhgfs/link.c Normal file
View File

@@ -0,0 +1,73 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
#include <sys/stat.h>
/*===========================================================================*
* hgfs_mkdir *
*===========================================================================*/
PUBLIC int hgfs_mkdir(path, mode)
char *path;
int mode;
{
/* Create a new directory.
*/
RPC_REQUEST(HGFS_REQ_MKDIR);
RPC_NEXT8 = HGFS_MODE_TO_PERM(mode);
path_put(path);
return rpc_query();
}
/*===========================================================================*
* hgfs_unlink *
*===========================================================================*/
PUBLIC int hgfs_unlink(path)
char *path;
{
/* Delete a file.
*/
RPC_REQUEST(HGFS_REQ_UNLINK);
path_put(path);
return rpc_query();
}
/*===========================================================================*
* hgfs_rmdir *
*===========================================================================*/
PUBLIC int hgfs_rmdir(path)
char *path;
{
/* Remove an empty directory.
*/
RPC_REQUEST(HGFS_REQ_RMDIR);
path_put(path);
return rpc_query();
}
/*===========================================================================*
* hgfs_rename *
*===========================================================================*/
PUBLIC int hgfs_rename(opath, npath)
char *opath;
char *npath;
{
/* Rename a file or directory.
*/
RPC_REQUEST(HGFS_REQ_RENAME);
path_put(opath);
path_put(npath);
return rpc_query();
}

73
lib/libhgfs/misc.c Normal file
View File

@@ -0,0 +1,73 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
/*===========================================================================*
* hgfs_init *
*===========================================================================*/
PUBLIC 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).
*/
time_init();
return rpc_open();
}
/*===========================================================================*
* hgfs_cleanup *
*===========================================================================*/
PUBLIC void hgfs_cleanup()
{
/* Clean up state.
*/
rpc_close();
}
/*===========================================================================*
* hgfs_enabled *
*===========================================================================*/
PUBLIC 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 *
*===========================================================================*/
PUBLIC 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;
}

73
lib/libhgfs/path.c Normal file
View File

@@ -0,0 +1,73 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
#include <limits.h>
/*===========================================================================*
* path_put *
*===========================================================================*/
PUBLIC void path_put(path)
char *path;
{
/* Append the given path name in HGFS format to the RPC buffer. Truncate it
* if it is longer than PATH_MAX bytes.
*/
char *p, buf[PATH_MAX];
int len;
/* No leading slashes are allowed. */
for (p = path; *p == '/'; p++);
/* No double or tailing slashes, either. */
for (len = 0; *p && len < sizeof(buf) - 1; len++) {
if (*p == '/') {
for (p++; *p == '/'; p++);
if (!*p) break;
buf[len] = 0;
}
else buf[len] = *p++;
}
RPC_NEXT32 = len;
memcpy(RPC_PTR, buf, len);
RPC_ADVANCE(len);
RPC_NEXT8 = 0;
}
/*===========================================================================*
* path_get *
*===========================================================================*/
PUBLIC int path_get(path, max)
char *path;
int max;
{
/* Retrieve a HGFS formatted path name from the RPC buffer. Returns EINVAL if
* the path name is invalid. Returns ENAMETOOLONG if the path name is too
* long. Returns OK on success.
*/
char *p, *q;
int n, len;
n = len = RPC_NEXT32;
if (len >= max) return ENAMETOOLONG;
for (p = path, q = RPC_PTR; n--; p++, q++) {
/* We can not deal with a slash in a path component. */
if (*q == '/') return EINVAL;
if (*q == 0) *p = '/';
else *p = *q;
}
RPC_ADVANCE(len);
*p = 0;
return (RPC_NEXT8 != 0) ? EINVAL : OK;
}

51
lib/libhgfs/proto.h Normal file
View File

@@ -0,0 +1,51 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
/* attr.c */
#define attr_get PREFIX(attr_get)
_PROTOTYPE( void attr_get, (struct hgfs_attr *attr) );
/* backdoor.s */
#define backdoor PREFIX(backdoor)
#define backdoor_in PREFIX(backdoor_in)
#define backdoor_out PREFIX(backdoor_out)
_PROTOTYPE( u32_t backdoor, (u32_t ptr[6]) );
_PROTOTYPE( u32_t backdoor_in, (u32_t ptr[6]) );
_PROTOTYPE( u32_t backdoor_out, (u32_t ptr[6]) );
/* channel.c */
#define channel_open PREFIX(channel_open)
#define channel_close PREFIX(channel_close)
#define channel_send PREFIX(channel_send)
#define channel_recv PREFIX(channel_recv)
_PROTOTYPE( int channel_open, (struct channel *ch, u32_t type) );
_PROTOTYPE( void channel_close, (struct channel *ch) );
_PROTOTYPE( int channel_send, (struct channel *ch, char *buf, int len) );
_PROTOTYPE( int channel_recv, (struct channel *ch, char *buf, int max) );
/* error.c */
#define error_convert PREFIX(error_convert)
_PROTOTYPE( int error_convert, (int err) );
/* path.c */
#define path_put PREFIX(path_put)
#define path_get PREFIX(path_get)
_PROTOTYPE( void path_put, (char *path) );
_PROTOTYPE( int path_get, (char *path, int max) );
/* rpc.c */
#define rpc_open PREFIX(rpc_open)
#define rpc_query PREFIX(rpc_query)
#define rpc_test PREFIX(rpc_test)
#define rpc_close PREFIX(rpc_close)
_PROTOTYPE( int rpc_open, (void) );
_PROTOTYPE( int rpc_query, (void) );
_PROTOTYPE( int rpc_test, (void) );
_PROTOTYPE( void rpc_close, (void) );
/* time.c */
#define time_init PREFIX(time_init)
#define time_put PREFIX(time_put)
#define time_get PREFIX(time_get)
_PROTOTYPE( void time_init, (void) );
_PROTOTYPE( void time_put, (time_t *timep) );
_PROTOTYPE( void time_get, (time_t *timep) );

94
lib/libhgfs/rpc.c Normal file
View File

@@ -0,0 +1,94 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
PUBLIC char rpc_buf[RPC_BUF_SIZE];
PUBLIC char *rpc_ptr;
PRIVATE struct channel rpc_chan;
/*===========================================================================*
* rpc_open *
*===========================================================================*/
PUBLIC 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.
*/
int r;
if ((r = channel_open(&rpc_chan, CH_OUT)) != OK)
return r;
r = rpc_test();
if (r != OK && r != EAGAIN)
channel_close(&rpc_chan);
return r;
}
/*===========================================================================*
* rpc_query *
*===========================================================================*/
PUBLIC int rpc_query()
{
/* Send a HGFS RPC query over the backdoor channel. Return OK upon success, or
* a negative error code otherwise; EAGAIN is returned if shared folders are
* disabled. In general, we make the assumption that the sender (= VMware)
* speaks the protocol correctly. Hence, the callers of this function do not
* check for lengths.
*/
int r, len, id, err;
len = RPC_LEN;
/* A more robust version of this call could reopen the channel and
* retry the request upon low-level failure.
*/
r = channel_send(&rpc_chan, rpc_buf, len);
if (r < 0) return r;
r = channel_recv(&rpc_chan, rpc_buf, sizeof(rpc_buf));
if (r < 0) return r;
if (r < 2 || (len > 2 && r < 10)) return EIO;
RPC_RESET;
if (RPC_NEXT8 != '1') return EAGAIN;
if (RPC_NEXT8 != ' ') return EAGAIN;
if (len <= 2) return OK;
id = RPC_NEXT32;
err = RPC_NEXT32;
return error_convert(err);
}
/*===========================================================================*
* rpc_test *
*===========================================================================*/
PUBLIC int rpc_test()
{
/* Test whether HGFS communication is working. Return OK on success, EAGAIN if
* shared folders are disabled, or another negative error code upon error.
*/
RPC_RESET;
RPC_NEXT8 = 'f';
RPC_NEXT8 = ' ';
return rpc_query();
}
/*===========================================================================*
* rpc_close *
*===========================================================================*/
PUBLIC void rpc_close()
{
/* Close the HGFS RPC backdoor channel.
*/
channel_close(&rpc_chan);
}

69
lib/libhgfs/time.c Normal file
View File

@@ -0,0 +1,69 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
PRIVATE u64_t time_offset;
/*===========================================================================*
* time_init *
*===========================================================================*/
PUBLIC void time_init()
{
/* Initialize the time conversion module.
*/
/* Generate a 64-bit value for the offset to use in time conversion. The
* HGFS time format uses Windows' FILETIME standard, expressing time in
* 100ns-units since Jan 1, 1601 UTC. The value that is generated is
* 116444736000000000.
*/
/* FIXME: we currently do not take into account timezones. */
time_offset = make64(3577643008UL, 27111902UL);
}
/*===========================================================================*
* time_put *
*===========================================================================*/
PUBLIC void time_put(timep)
time_t *timep;
{
/* Store a UNIX timestamp pointed to by the given pointer onto the RPC buffer,
* in HGFS timestamp format. If a NULL pointer is given, store a timestamp of
* zero instead.
*/
u64_t hgfstime;
if (timep != NULL) {
hgfstime = add64(mul64u(*timep, 10000000), time_offset);
RPC_NEXT32 = ex64lo(hgfstime);
RPC_NEXT32 = ex64hi(hgfstime);
} else {
RPC_NEXT32 = 0;
RPC_NEXT32 = 0;
}
}
/*===========================================================================*
* time_get *
*===========================================================================*/
PUBLIC void time_get(timep)
time_t *timep;
{
/* Get a HGFS timestamp from the RPC buffer, convert it into a UNIX timestamp,
* and store the result in the given time pointer. If the given pointer is
* NULL, however, simply skip over the timestamp in the RPC buffer.
*/
u64_t hgfstime;
u32_t time_lo, time_hi;
if (timep != NULL) {
time_lo = RPC_NEXT32;
time_hi = RPC_NEXT32;
hgfstime = make64(time_lo, time_hi);
*timep = div64u(sub64(hgfstime, time_offset), 10000000);
}
else RPC_ADVANCE(sizeof(u32_t) * 2);
}

7
lib/libhgfs/type.h Normal file
View File

@@ -0,0 +1,7 @@
/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
struct channel {
u16_t id;
u32_t cookie1;
u32_t cookie2;
};