1 /* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
2
3 #include "inc.h"
4
5 #include <fcntl.h>
6 #include <sys/stat.h>
7
8 /*===========================================================================*
9 * hgfs_open *
10 *===========================================================================*/
hgfs_open(const char * path,int flags,int mode,sffs_file_t * handle)11 int hgfs_open(
12 const char *path, /* path name to open */
13 int flags, /* open flags to use */
14 int mode, /* mode to create (user bits only) */
15 sffs_file_t *handle /* place to store resulting handle */
16 )
17 {
18 /* Open a file. Store a file handle upon success.
19 */
20 int r, type;
21
22 /* We could implement this, but that means we would have to start tracking
23 * open files in order to associate data with them. Rather not.
24 */
25 if (flags & O_APPEND) return EINVAL;
26
27 if (flags & O_CREAT) {
28 if (flags & O_EXCL) type = HGFS_OPEN_TYPE_C;
29 else if (flags & O_TRUNC) type = HGFS_OPEN_TYPE_COT;
30 else type = HGFS_OPEN_TYPE_CO;
31 } else {
32 if (flags & O_TRUNC) type = HGFS_OPEN_TYPE_OT;
33 else type = HGFS_OPEN_TYPE_O;
34 }
35
36 RPC_REQUEST(HGFS_REQ_OPEN);
37 RPC_NEXT32 = (flags & O_ACCMODE);
38 RPC_NEXT32 = type;
39 RPC_NEXT8 = HGFS_MODE_TO_PERM(mode);
40
41 path_put(path);
42
43 if ((r = rpc_query()) != OK)
44 return r;
45
46 *handle = (sffs_file_t)RPC_NEXT32;
47
48 return OK;
49 }
50
51 /*===========================================================================*
52 * hgfs_read *
53 *===========================================================================*/
hgfs_read(sffs_file_t handle,char * buf,size_t size,u64_t off)54 ssize_t hgfs_read(
55 sffs_file_t handle, /* handle to open file */
56 char *buf, /* data buffer or NULL */
57 size_t size, /* maximum number of bytes to read */
58 u64_t off /* file offset */
59 )
60 {
61 /* Read from an open file. Upon success, return the number of bytes read.
62 */
63 size_t len, max;
64 int r;
65
66 RPC_REQUEST(HGFS_REQ_READ);
67 RPC_NEXT32 = (u32_t)handle;
68 RPC_NEXT32 = ex64lo(off);
69 RPC_NEXT32 = ex64hi(off);
70
71 max = RPC_BUF_SIZE - RPC_LEN - sizeof(u32_t);
72 RPC_NEXT32 = (size < max) ? size : max;
73
74 if ((r = rpc_query()) != OK)
75 return r;
76
77 len = RPC_NEXT32;
78 if (len > max) len = max; /* sanity check */
79
80 /* Only copy out data if we're not operating directly on the RPC buffer. */
81 if (buf != RPC_PTR)
82 memcpy(buf, RPC_PTR, len);
83
84 return len;
85 }
86
87 /*===========================================================================*
88 * hgfs_write *
89 *===========================================================================*/
hgfs_write(sffs_file_t handle,char * buf,size_t len,u64_t off)90 ssize_t hgfs_write(
91 sffs_file_t handle, /* handle to open file */
92 char *buf, /* data buffer or NULL */
93 size_t len, /* number of bytes to write */
94 u64_t off /* file offset */
95 )
96 {
97 /* Write to an open file. Upon success, return the number of bytes written.
98 */
99 int r;
100
101 RPC_REQUEST(HGFS_REQ_WRITE);
102 RPC_NEXT32 = (u32_t)handle;
103 RPC_NEXT8 = 0; /* append flag */
104 RPC_NEXT32 = ex64lo(off);
105 RPC_NEXT32 = ex64hi(off);
106 RPC_NEXT32 = len;
107
108 /* Only copy in data if we're not operating directly on the RPC buffer. */
109 if (RPC_PTR != buf)
110 memcpy(RPC_PTR, buf, len);
111 RPC_ADVANCE(len);
112
113 if ((r = rpc_query()) != OK)
114 return r;
115
116 return RPC_NEXT32;
117 }
118
119 /*===========================================================================*
120 * hgfs_close *
121 *===========================================================================*/
hgfs_close(sffs_file_t handle)122 int hgfs_close(
123 sffs_file_t handle /* handle to open file */
124 )
125 {
126 /* Close an open file.
127 */
128
129 RPC_REQUEST(HGFS_REQ_CLOSE);
130 RPC_NEXT32 = (u32_t)handle;
131
132 return rpc_query();
133 }
134
135 /*===========================================================================*
136 * hgfs_readbuf *
137 *===========================================================================*/
hgfs_readbuf(char ** ptr)138 size_t hgfs_readbuf(char **ptr)
139 {
140 /* Return information about the read buffer, for zero-copy purposes. Store a
141 * pointer to the first byte of the read buffer, and return the maximum data
142 * size. The results are static, but must only be used directly prior to a
143 * hgfs_read() call (with a NULL data buffer address).
144 */
145 u32_t off;
146
147 off = RPC_HDR_SIZE + sizeof(u32_t);
148
149 RPC_RESET;
150 RPC_ADVANCE(off);
151 *ptr = RPC_PTR;
152
153 return RPC_BUF_SIZE - off;
154 }
155
156 /*===========================================================================*
157 * hgfs_writebuf *
158 *===========================================================================*/
hgfs_writebuf(char ** ptr)159 size_t hgfs_writebuf(char **ptr)
160 {
161 /* Return information about the write buffer, for zero-copy purposes. Store a
162 * pointer to the first byte of the write buffer, and return the maximum data
163 * size. The results are static, but must only be used immediately after a
164 * hgfs_write() call (with a NULL data buffer address).
165 */
166 u32_t off;
167
168 off = RPC_HDR_SIZE + sizeof(u32_t) + sizeof(u8_t) + sizeof(u32_t) * 3;
169
170 RPC_RESET;
171 RPC_ADVANCE(off);
172 *ptr = RPC_PTR;
173
174 return RPC_BUF_SIZE - off;
175 }
176