]>
Commit | Line | Data |
---|---|---|
0fd16957 HG |
1 | // SPDX-License-Identifier: MIT |
2 | /* | |
3 | * Wrapper functions for the shfl host calls. | |
4 | * | |
5 | * Copyright (C) 2006-2018 Oracle Corporation | |
6 | */ | |
7 | ||
8 | #include <linux/mm.h> | |
9 | #include <linux/slab.h> | |
10 | #include <linux/vbox_err.h> | |
11 | #include <linux/vbox_utils.h> | |
12 | #include "vfsmod.h" | |
13 | ||
14 | #define SHFL_REQUEST \ | |
15 | (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER | \ | |
16 | VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN) | |
17 | ||
18 | static u32 vboxsf_client_id; | |
19 | ||
20 | int vboxsf_connect(void) | |
21 | { | |
22 | struct vbg_dev *gdev; | |
23 | struct vmmdev_hgcm_service_location loc; | |
24 | int err, vbox_status; | |
25 | ||
26 | loc.type = VMMDEV_HGCM_LOC_LOCALHOST_EXISTING; | |
27 | strcpy(loc.u.localhost.service_name, "VBoxSharedFolders"); | |
28 | ||
29 | gdev = vbg_get_gdev(); | |
30 | if (IS_ERR(gdev)) | |
31 | return -ENODEV; /* No guest-device */ | |
32 | ||
33 | err = vbg_hgcm_connect(gdev, SHFL_REQUEST, &loc, | |
34 | &vboxsf_client_id, &vbox_status); | |
35 | vbg_put_gdev(gdev); | |
36 | ||
37 | return err ? err : vbg_status_code_to_errno(vbox_status); | |
38 | } | |
39 | ||
40 | void vboxsf_disconnect(void) | |
41 | { | |
42 | struct vbg_dev *gdev; | |
43 | int vbox_status; | |
44 | ||
45 | gdev = vbg_get_gdev(); | |
46 | if (IS_ERR(gdev)) | |
47 | return; /* guest-device is gone, already disconnected */ | |
48 | ||
49 | vbg_hgcm_disconnect(gdev, SHFL_REQUEST, vboxsf_client_id, &vbox_status); | |
50 | vbg_put_gdev(gdev); | |
51 | } | |
52 | ||
53 | static int vboxsf_call(u32 function, void *parms, u32 parm_count, int *status) | |
54 | { | |
55 | struct vbg_dev *gdev; | |
56 | int err, vbox_status; | |
57 | ||
58 | gdev = vbg_get_gdev(); | |
59 | if (IS_ERR(gdev)) | |
60 | return -ESHUTDOWN; /* guest-dev removed underneath us */ | |
61 | ||
62 | err = vbg_hgcm_call(gdev, SHFL_REQUEST, vboxsf_client_id, function, | |
63 | U32_MAX, parms, parm_count, &vbox_status); | |
64 | vbg_put_gdev(gdev); | |
65 | ||
66 | if (err < 0) | |
67 | return err; | |
68 | ||
69 | if (status) | |
70 | *status = vbox_status; | |
71 | ||
72 | return vbg_status_code_to_errno(vbox_status); | |
73 | } | |
74 | ||
75 | int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root) | |
76 | { | |
77 | struct shfl_map_folder parms; | |
78 | int err, status; | |
79 | ||
80 | parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; | |
81 | parms.path.u.pointer.size = shfl_string_buf_size(folder_name); | |
82 | parms.path.u.pointer.u.linear_addr = (uintptr_t)folder_name; | |
83 | ||
84 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
85 | parms.root.u.value32 = 0; | |
86 | ||
87 | parms.delimiter.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
88 | parms.delimiter.u.value32 = '/'; | |
89 | ||
90 | parms.case_sensitive.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
91 | parms.case_sensitive.u.value32 = 1; | |
92 | ||
93 | err = vboxsf_call(SHFL_FN_MAP_FOLDER, &parms, SHFL_CPARMS_MAP_FOLDER, | |
94 | &status); | |
95 | if (err == -ENOSYS && status == VERR_NOT_IMPLEMENTED) | |
96 | vbg_err("%s: Error host is too old\n", __func__); | |
97 | ||
98 | *root = parms.root.u.value32; | |
99 | return err; | |
100 | } | |
101 | ||
102 | int vboxsf_unmap_folder(u32 root) | |
103 | { | |
104 | struct shfl_unmap_folder parms; | |
105 | ||
106 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
107 | parms.root.u.value32 = root; | |
108 | ||
109 | return vboxsf_call(SHFL_FN_UNMAP_FOLDER, &parms, | |
110 | SHFL_CPARMS_UNMAP_FOLDER, NULL); | |
111 | } | |
112 | ||
113 | /** | |
114 | * vboxsf_create - Create a new file or folder | |
115 | * @root: Root of the shared folder in which to create the file | |
116 | * @parsed_path: The path of the file or folder relative to the shared folder | |
117 | * @param: create_parms Parameters for file/folder creation. | |
118 | * | |
119 | * Create a new file or folder or open an existing one in a shared folder. | |
120 | * Note this function always returns 0 / success unless an exceptional condition | |
121 | * occurs - out of memory, invalid arguments, etc. If the file or folder could | |
122 | * not be opened or created, create_parms->handle will be set to | |
123 | * SHFL_HANDLE_NIL on return. In this case the value in create_parms->result | |
124 | * provides information as to why (e.g. SHFL_FILE_EXISTS), create_parms->result | |
125 | * is also set on success as additional information. | |
126 | * | |
127 | * Returns: | |
128 | * 0 or negative errno value. | |
129 | */ | |
130 | int vboxsf_create(u32 root, struct shfl_string *parsed_path, | |
131 | struct shfl_createparms *create_parms) | |
132 | { | |
133 | struct shfl_create parms; | |
134 | ||
135 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
136 | parms.root.u.value32 = root; | |
137 | ||
138 | parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; | |
139 | parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); | |
140 | parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; | |
141 | ||
142 | parms.parms.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; | |
143 | parms.parms.u.pointer.size = sizeof(struct shfl_createparms); | |
144 | parms.parms.u.pointer.u.linear_addr = (uintptr_t)create_parms; | |
145 | ||
146 | return vboxsf_call(SHFL_FN_CREATE, &parms, SHFL_CPARMS_CREATE, NULL); | |
147 | } | |
148 | ||
149 | int vboxsf_close(u32 root, u64 handle) | |
150 | { | |
151 | struct shfl_close parms; | |
152 | ||
153 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
154 | parms.root.u.value32 = root; | |
155 | ||
156 | parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; | |
157 | parms.handle.u.value64 = handle; | |
158 | ||
159 | return vboxsf_call(SHFL_FN_CLOSE, &parms, SHFL_CPARMS_CLOSE, NULL); | |
160 | } | |
161 | ||
162 | int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags) | |
163 | { | |
164 | struct shfl_remove parms; | |
165 | ||
166 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
167 | parms.root.u.value32 = root; | |
168 | ||
169 | parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; | |
170 | parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); | |
171 | parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; | |
172 | ||
173 | parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
174 | parms.flags.u.value32 = flags; | |
175 | ||
176 | return vboxsf_call(SHFL_FN_REMOVE, &parms, SHFL_CPARMS_REMOVE, NULL); | |
177 | } | |
178 | ||
179 | int vboxsf_rename(u32 root, struct shfl_string *src_path, | |
180 | struct shfl_string *dest_path, u32 flags) | |
181 | { | |
182 | struct shfl_rename parms; | |
183 | ||
184 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
185 | parms.root.u.value32 = root; | |
186 | ||
187 | parms.src.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; | |
188 | parms.src.u.pointer.size = shfl_string_buf_size(src_path); | |
189 | parms.src.u.pointer.u.linear_addr = (uintptr_t)src_path; | |
190 | ||
191 | parms.dest.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; | |
192 | parms.dest.u.pointer.size = shfl_string_buf_size(dest_path); | |
193 | parms.dest.u.pointer.u.linear_addr = (uintptr_t)dest_path; | |
194 | ||
195 | parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
196 | parms.flags.u.value32 = flags; | |
197 | ||
198 | return vboxsf_call(SHFL_FN_RENAME, &parms, SHFL_CPARMS_RENAME, NULL); | |
199 | } | |
200 | ||
201 | int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) | |
202 | { | |
203 | struct shfl_read parms; | |
204 | int err; | |
205 | ||
206 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
207 | parms.root.u.value32 = root; | |
208 | ||
209 | parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; | |
210 | parms.handle.u.value64 = handle; | |
211 | parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; | |
212 | parms.offset.u.value64 = offset; | |
213 | parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
214 | parms.cb.u.value32 = *buf_len; | |
215 | parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; | |
216 | parms.buffer.u.pointer.size = *buf_len; | |
217 | parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; | |
218 | ||
219 | err = vboxsf_call(SHFL_FN_READ, &parms, SHFL_CPARMS_READ, NULL); | |
220 | ||
221 | *buf_len = parms.cb.u.value32; | |
222 | return err; | |
223 | } | |
224 | ||
225 | int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) | |
226 | { | |
227 | struct shfl_write parms; | |
228 | int err; | |
229 | ||
230 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
231 | parms.root.u.value32 = root; | |
232 | ||
233 | parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; | |
234 | parms.handle.u.value64 = handle; | |
235 | parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; | |
236 | parms.offset.u.value64 = offset; | |
237 | parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
238 | parms.cb.u.value32 = *buf_len; | |
239 | parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; | |
240 | parms.buffer.u.pointer.size = *buf_len; | |
241 | parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; | |
242 | ||
243 | err = vboxsf_call(SHFL_FN_WRITE, &parms, SHFL_CPARMS_WRITE, NULL); | |
244 | ||
245 | *buf_len = parms.cb.u.value32; | |
246 | return err; | |
247 | } | |
248 | ||
249 | /* Returns 0 on success, 1 on end-of-dir, negative errno otherwise */ | |
250 | int vboxsf_dirinfo(u32 root, u64 handle, | |
251 | struct shfl_string *parsed_path, u32 flags, u32 index, | |
252 | u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count) | |
253 | { | |
254 | struct shfl_list parms; | |
255 | int err, status; | |
256 | ||
257 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
258 | parms.root.u.value32 = root; | |
259 | ||
260 | parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; | |
261 | parms.handle.u.value64 = handle; | |
262 | parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
263 | parms.flags.u.value32 = flags; | |
264 | parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
265 | parms.cb.u.value32 = *buf_len; | |
266 | if (parsed_path) { | |
267 | parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; | |
268 | parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); | |
269 | parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; | |
270 | } else { | |
271 | parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_IN; | |
272 | parms.path.u.pointer.size = 0; | |
273 | parms.path.u.pointer.u.linear_addr = 0; | |
274 | } | |
275 | ||
276 | parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; | |
277 | parms.buffer.u.pointer.size = *buf_len; | |
278 | parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; | |
279 | ||
280 | parms.resume_point.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
281 | parms.resume_point.u.value32 = index; | |
282 | parms.file_count.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
283 | parms.file_count.u.value32 = 0; /* out parameter only */ | |
284 | ||
285 | err = vboxsf_call(SHFL_FN_LIST, &parms, SHFL_CPARMS_LIST, &status); | |
286 | if (err == -ENODATA && status == VERR_NO_MORE_FILES) | |
287 | err = 1; | |
288 | ||
289 | *buf_len = parms.cb.u.value32; | |
290 | *file_count = parms.file_count.u.value32; | |
291 | return err; | |
292 | } | |
293 | ||
294 | int vboxsf_fsinfo(u32 root, u64 handle, u32 flags, | |
295 | u32 *buf_len, void *buf) | |
296 | { | |
297 | struct shfl_information parms; | |
298 | int err; | |
299 | ||
300 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
301 | parms.root.u.value32 = root; | |
302 | ||
303 | parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; | |
304 | parms.handle.u.value64 = handle; | |
305 | parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
306 | parms.flags.u.value32 = flags; | |
307 | parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
308 | parms.cb.u.value32 = *buf_len; | |
309 | parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; | |
310 | parms.info.u.pointer.size = *buf_len; | |
311 | parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; | |
312 | ||
313 | err = vboxsf_call(SHFL_FN_INFORMATION, &parms, SHFL_CPARMS_INFORMATION, | |
314 | NULL); | |
315 | ||
316 | *buf_len = parms.cb.u.value32; | |
317 | return err; | |
318 | } | |
319 | ||
320 | int vboxsf_readlink(u32 root, struct shfl_string *parsed_path, | |
321 | u32 buf_len, u8 *buf) | |
322 | { | |
323 | struct shfl_readLink parms; | |
324 | ||
325 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
326 | parms.root.u.value32 = root; | |
327 | ||
328 | parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; | |
329 | parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); | |
330 | parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; | |
331 | ||
332 | parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; | |
333 | parms.buffer.u.pointer.size = buf_len; | |
334 | parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; | |
335 | ||
336 | return vboxsf_call(SHFL_FN_READLINK, &parms, SHFL_CPARMS_READLINK, | |
337 | NULL); | |
338 | } | |
339 | ||
340 | int vboxsf_symlink(u32 root, struct shfl_string *new_path, | |
341 | struct shfl_string *old_path, struct shfl_fsobjinfo *buf) | |
342 | { | |
343 | struct shfl_symlink parms; | |
344 | ||
345 | parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; | |
346 | parms.root.u.value32 = root; | |
347 | ||
348 | parms.new_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; | |
349 | parms.new_path.u.pointer.size = shfl_string_buf_size(new_path); | |
350 | parms.new_path.u.pointer.u.linear_addr = (uintptr_t)new_path; | |
351 | ||
352 | parms.old_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; | |
353 | parms.old_path.u.pointer.size = shfl_string_buf_size(old_path); | |
354 | parms.old_path.u.pointer.u.linear_addr = (uintptr_t)old_path; | |
355 | ||
356 | parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; | |
357 | parms.info.u.pointer.size = sizeof(struct shfl_fsobjinfo); | |
358 | parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; | |
359 | ||
360 | return vboxsf_call(SHFL_FN_SYMLINK, &parms, SHFL_CPARMS_SYMLINK, NULL); | |
361 | } | |
362 | ||
363 | int vboxsf_set_utf8(void) | |
364 | { | |
365 | return vboxsf_call(SHFL_FN_SET_UTF8, NULL, 0, NULL); | |
366 | } | |
367 | ||
368 | int vboxsf_set_symlinks(void) | |
369 | { | |
370 | return vboxsf_call(SHFL_FN_SET_SYMLINKS, NULL, 0, NULL); | |
371 | } |