minix/lib/libhgfs/file.c
David van Moolenbroek ef7b484e5c Create SFFS library out of HGFS
This Shared Folders File System library (libsffs) now contains all the
file system logic originally in HGFS. The actual HGFS server code is
now a stub that passes on all the work to libsffs. The libhgfs library
is changed accordingly.
2012-04-09 18:08:26 +02:00

172 lines
4.7 KiB
C

/* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
#include "inc.h"
#include <fcntl.h>
#include <sys/stat.h>
/*===========================================================================*
* hgfs_open *
*===========================================================================*/
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) */
sffs_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 = (sffs_file_t)RPC_NEXT32;
return OK;
}
/*===========================================================================*
* hgfs_read *
*===========================================================================*/
ssize_t hgfs_read(handle, buf, size, off)
sffs_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 not operating directly on the RPC buffer. */
if (buf != RPC_PTR)
memcpy(buf, RPC_PTR, len);
return len;
}
/*===========================================================================*
* hgfs_write *
*===========================================================================*/
ssize_t hgfs_write(handle, buf, len, off)
sffs_file_t handle; /* handle to open file */
char *buf; /* data buffer or NULL */
size_t len; /* number of bytes to write */
u64_t off; /* file 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;
RPC_NEXT8 = 0; /* append flag */
RPC_NEXT32 = ex64lo(off);
RPC_NEXT32 = ex64hi(off);
RPC_NEXT32 = len;
/* 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);
if ((r = rpc_query()) != OK)
return r;
return RPC_NEXT32;
}
/*===========================================================================*
* hgfs_close *
*===========================================================================*/
int hgfs_close(handle)
sffs_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 *
*===========================================================================*/
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 *
*===========================================================================*/
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;
}