1433d6423SLionel Sambuc /* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
2433d6423SLionel Sambuc
3433d6423SLionel Sambuc #include "inc.h"
4433d6423SLionel Sambuc
5433d6423SLionel Sambuc #include <fcntl.h>
6433d6423SLionel Sambuc #include <sys/stat.h>
7433d6423SLionel Sambuc
8433d6423SLionel Sambuc /*===========================================================================*
9433d6423SLionel Sambuc * hgfs_open *
10433d6423SLionel Sambuc *===========================================================================*/
hgfs_open(const char * path,int flags,int mode,sffs_file_t * handle)11433d6423SLionel Sambuc int hgfs_open(
12*94e65446SDavid van Moolenbroek const char *path, /* path name to open */
13433d6423SLionel Sambuc int flags, /* open flags to use */
14433d6423SLionel Sambuc int mode, /* mode to create (user bits only) */
15433d6423SLionel Sambuc sffs_file_t *handle /* place to store resulting handle */
16433d6423SLionel Sambuc )
17433d6423SLionel Sambuc {
18433d6423SLionel Sambuc /* Open a file. Store a file handle upon success.
19433d6423SLionel Sambuc */
20433d6423SLionel Sambuc int r, type;
21433d6423SLionel Sambuc
22433d6423SLionel Sambuc /* We could implement this, but that means we would have to start tracking
23433d6423SLionel Sambuc * open files in order to associate data with them. Rather not.
24433d6423SLionel Sambuc */
25433d6423SLionel Sambuc if (flags & O_APPEND) return EINVAL;
26433d6423SLionel Sambuc
27433d6423SLionel Sambuc if (flags & O_CREAT) {
28433d6423SLionel Sambuc if (flags & O_EXCL) type = HGFS_OPEN_TYPE_C;
29433d6423SLionel Sambuc else if (flags & O_TRUNC) type = HGFS_OPEN_TYPE_COT;
30433d6423SLionel Sambuc else type = HGFS_OPEN_TYPE_CO;
31433d6423SLionel Sambuc } else {
32433d6423SLionel Sambuc if (flags & O_TRUNC) type = HGFS_OPEN_TYPE_OT;
33433d6423SLionel Sambuc else type = HGFS_OPEN_TYPE_O;
34433d6423SLionel Sambuc }
35433d6423SLionel Sambuc
36433d6423SLionel Sambuc RPC_REQUEST(HGFS_REQ_OPEN);
37433d6423SLionel Sambuc RPC_NEXT32 = (flags & O_ACCMODE);
38433d6423SLionel Sambuc RPC_NEXT32 = type;
39433d6423SLionel Sambuc RPC_NEXT8 = HGFS_MODE_TO_PERM(mode);
40433d6423SLionel Sambuc
41433d6423SLionel Sambuc path_put(path);
42433d6423SLionel Sambuc
43433d6423SLionel Sambuc if ((r = rpc_query()) != OK)
44433d6423SLionel Sambuc return r;
45433d6423SLionel Sambuc
46433d6423SLionel Sambuc *handle = (sffs_file_t)RPC_NEXT32;
47433d6423SLionel Sambuc
48433d6423SLionel Sambuc return OK;
49433d6423SLionel Sambuc }
50433d6423SLionel Sambuc
51433d6423SLionel Sambuc /*===========================================================================*
52433d6423SLionel Sambuc * hgfs_read *
53433d6423SLionel Sambuc *===========================================================================*/
hgfs_read(sffs_file_t handle,char * buf,size_t size,u64_t off)54433d6423SLionel Sambuc ssize_t hgfs_read(
55433d6423SLionel Sambuc sffs_file_t handle, /* handle to open file */
56433d6423SLionel Sambuc char *buf, /* data buffer or NULL */
57433d6423SLionel Sambuc size_t size, /* maximum number of bytes to read */
58433d6423SLionel Sambuc u64_t off /* file offset */
59433d6423SLionel Sambuc )
60433d6423SLionel Sambuc {
61433d6423SLionel Sambuc /* Read from an open file. Upon success, return the number of bytes read.
62433d6423SLionel Sambuc */
63*94e65446SDavid van Moolenbroek size_t len, max;
64*94e65446SDavid van Moolenbroek int r;
65433d6423SLionel Sambuc
66433d6423SLionel Sambuc RPC_REQUEST(HGFS_REQ_READ);
67433d6423SLionel Sambuc RPC_NEXT32 = (u32_t)handle;
68433d6423SLionel Sambuc RPC_NEXT32 = ex64lo(off);
69433d6423SLionel Sambuc RPC_NEXT32 = ex64hi(off);
70433d6423SLionel Sambuc
71433d6423SLionel Sambuc max = RPC_BUF_SIZE - RPC_LEN - sizeof(u32_t);
72433d6423SLionel Sambuc RPC_NEXT32 = (size < max) ? size : max;
73433d6423SLionel Sambuc
74433d6423SLionel Sambuc if ((r = rpc_query()) != OK)
75433d6423SLionel Sambuc return r;
76433d6423SLionel Sambuc
77433d6423SLionel Sambuc len = RPC_NEXT32;
78433d6423SLionel Sambuc if (len > max) len = max; /* sanity check */
79433d6423SLionel Sambuc
80433d6423SLionel Sambuc /* Only copy out data if we're not operating directly on the RPC buffer. */
81433d6423SLionel Sambuc if (buf != RPC_PTR)
82433d6423SLionel Sambuc memcpy(buf, RPC_PTR, len);
83433d6423SLionel Sambuc
84433d6423SLionel Sambuc return len;
85433d6423SLionel Sambuc }
86433d6423SLionel Sambuc
87433d6423SLionel Sambuc /*===========================================================================*
88433d6423SLionel Sambuc * hgfs_write *
89433d6423SLionel Sambuc *===========================================================================*/
hgfs_write(sffs_file_t handle,char * buf,size_t len,u64_t off)90433d6423SLionel Sambuc ssize_t hgfs_write(
91433d6423SLionel Sambuc sffs_file_t handle, /* handle to open file */
92433d6423SLionel Sambuc char *buf, /* data buffer or NULL */
93433d6423SLionel Sambuc size_t len, /* number of bytes to write */
94433d6423SLionel Sambuc u64_t off /* file offset */
95433d6423SLionel Sambuc )
96433d6423SLionel Sambuc {
97433d6423SLionel Sambuc /* Write to an open file. Upon success, return the number of bytes written.
98433d6423SLionel Sambuc */
99433d6423SLionel Sambuc int r;
100433d6423SLionel Sambuc
101433d6423SLionel Sambuc RPC_REQUEST(HGFS_REQ_WRITE);
102433d6423SLionel Sambuc RPC_NEXT32 = (u32_t)handle;
103433d6423SLionel Sambuc RPC_NEXT8 = 0; /* append flag */
104433d6423SLionel Sambuc RPC_NEXT32 = ex64lo(off);
105433d6423SLionel Sambuc RPC_NEXT32 = ex64hi(off);
106433d6423SLionel Sambuc RPC_NEXT32 = len;
107433d6423SLionel Sambuc
108433d6423SLionel Sambuc /* Only copy in data if we're not operating directly on the RPC buffer. */
109433d6423SLionel Sambuc if (RPC_PTR != buf)
110433d6423SLionel Sambuc memcpy(RPC_PTR, buf, len);
111433d6423SLionel Sambuc RPC_ADVANCE(len);
112433d6423SLionel Sambuc
113433d6423SLionel Sambuc if ((r = rpc_query()) != OK)
114433d6423SLionel Sambuc return r;
115433d6423SLionel Sambuc
116433d6423SLionel Sambuc return RPC_NEXT32;
117433d6423SLionel Sambuc }
118433d6423SLionel Sambuc
119433d6423SLionel Sambuc /*===========================================================================*
120433d6423SLionel Sambuc * hgfs_close *
121433d6423SLionel Sambuc *===========================================================================*/
hgfs_close(sffs_file_t handle)122433d6423SLionel Sambuc int hgfs_close(
123433d6423SLionel Sambuc sffs_file_t handle /* handle to open file */
124433d6423SLionel Sambuc )
125433d6423SLionel Sambuc {
126433d6423SLionel Sambuc /* Close an open file.
127433d6423SLionel Sambuc */
128433d6423SLionel Sambuc
129433d6423SLionel Sambuc RPC_REQUEST(HGFS_REQ_CLOSE);
130433d6423SLionel Sambuc RPC_NEXT32 = (u32_t)handle;
131433d6423SLionel Sambuc
132433d6423SLionel Sambuc return rpc_query();
133433d6423SLionel Sambuc }
134433d6423SLionel Sambuc
135433d6423SLionel Sambuc /*===========================================================================*
136433d6423SLionel Sambuc * hgfs_readbuf *
137433d6423SLionel Sambuc *===========================================================================*/
hgfs_readbuf(char ** ptr)138433d6423SLionel Sambuc size_t hgfs_readbuf(char **ptr)
139433d6423SLionel Sambuc {
140433d6423SLionel Sambuc /* Return information about the read buffer, for zero-copy purposes. Store a
141433d6423SLionel Sambuc * pointer to the first byte of the read buffer, and return the maximum data
142433d6423SLionel Sambuc * size. The results are static, but must only be used directly prior to a
143433d6423SLionel Sambuc * hgfs_read() call (with a NULL data buffer address).
144433d6423SLionel Sambuc */
145433d6423SLionel Sambuc u32_t off;
146433d6423SLionel Sambuc
147433d6423SLionel Sambuc off = RPC_HDR_SIZE + sizeof(u32_t);
148433d6423SLionel Sambuc
149433d6423SLionel Sambuc RPC_RESET;
150433d6423SLionel Sambuc RPC_ADVANCE(off);
151433d6423SLionel Sambuc *ptr = RPC_PTR;
152433d6423SLionel Sambuc
153433d6423SLionel Sambuc return RPC_BUF_SIZE - off;
154433d6423SLionel Sambuc }
155433d6423SLionel Sambuc
156433d6423SLionel Sambuc /*===========================================================================*
157433d6423SLionel Sambuc * hgfs_writebuf *
158433d6423SLionel Sambuc *===========================================================================*/
hgfs_writebuf(char ** ptr)159433d6423SLionel Sambuc size_t hgfs_writebuf(char **ptr)
160433d6423SLionel Sambuc {
161433d6423SLionel Sambuc /* Return information about the write buffer, for zero-copy purposes. Store a
162433d6423SLionel Sambuc * pointer to the first byte of the write buffer, and return the maximum data
163433d6423SLionel Sambuc * size. The results are static, but must only be used immediately after a
164433d6423SLionel Sambuc * hgfs_write() call (with a NULL data buffer address).
165433d6423SLionel Sambuc */
166433d6423SLionel Sambuc u32_t off;
167433d6423SLionel Sambuc
168433d6423SLionel Sambuc off = RPC_HDR_SIZE + sizeof(u32_t) + sizeof(u8_t) + sizeof(u32_t) * 3;
169433d6423SLionel Sambuc
170433d6423SLionel Sambuc RPC_RESET;
171433d6423SLionel Sambuc RPC_ADVANCE(off);
172433d6423SLionel Sambuc *ptr = RPC_PTR;
173433d6423SLionel Sambuc
174433d6423SLionel Sambuc return RPC_BUF_SIZE - off;
175433d6423SLionel Sambuc }
176