minix/lib/libhgfs/file.c
Arun Thomas b48b037fbe 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
2010-05-26 22:49:57 +00:00

183 lines
4.8 KiB
C

/* 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;
}