0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/mm.h>
0009 #include <linux/slab.h>
0010 #include <linux/vbox_err.h>
0011 #include <linux/vbox_utils.h>
0012 #include "vfsmod.h"
0013
0014 #define SHFL_REQUEST \
0015 (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER | \
0016 VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN)
0017
0018 static u32 vboxsf_client_id;
0019
0020 int vboxsf_connect(void)
0021 {
0022 struct vbg_dev *gdev;
0023 struct vmmdev_hgcm_service_location loc;
0024 int err, vbox_status;
0025
0026 loc.type = VMMDEV_HGCM_LOC_LOCALHOST_EXISTING;
0027 strcpy(loc.u.localhost.service_name, "VBoxSharedFolders");
0028
0029 gdev = vbg_get_gdev();
0030 if (IS_ERR(gdev))
0031 return -ENODEV;
0032
0033 err = vbg_hgcm_connect(gdev, SHFL_REQUEST, &loc,
0034 &vboxsf_client_id, &vbox_status);
0035 vbg_put_gdev(gdev);
0036
0037 return err ? err : vbg_status_code_to_errno(vbox_status);
0038 }
0039
0040 void vboxsf_disconnect(void)
0041 {
0042 struct vbg_dev *gdev;
0043 int vbox_status;
0044
0045 gdev = vbg_get_gdev();
0046 if (IS_ERR(gdev))
0047 return;
0048
0049 vbg_hgcm_disconnect(gdev, SHFL_REQUEST, vboxsf_client_id, &vbox_status);
0050 vbg_put_gdev(gdev);
0051 }
0052
0053 static int vboxsf_call(u32 function, void *parms, u32 parm_count, int *status)
0054 {
0055 struct vbg_dev *gdev;
0056 int err, vbox_status;
0057
0058 gdev = vbg_get_gdev();
0059 if (IS_ERR(gdev))
0060 return -ESHUTDOWN;
0061
0062 err = vbg_hgcm_call(gdev, SHFL_REQUEST, vboxsf_client_id, function,
0063 U32_MAX, parms, parm_count, &vbox_status);
0064 vbg_put_gdev(gdev);
0065
0066 if (err < 0)
0067 return err;
0068
0069 if (status)
0070 *status = vbox_status;
0071
0072 return vbg_status_code_to_errno(vbox_status);
0073 }
0074
0075 int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root)
0076 {
0077 struct shfl_map_folder parms;
0078 int err, status;
0079
0080 parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
0081 parms.path.u.pointer.size = shfl_string_buf_size(folder_name);
0082 parms.path.u.pointer.u.linear_addr = (uintptr_t)folder_name;
0083
0084 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0085 parms.root.u.value32 = 0;
0086
0087 parms.delimiter.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0088 parms.delimiter.u.value32 = '/';
0089
0090 parms.case_sensitive.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0091 parms.case_sensitive.u.value32 = 1;
0092
0093 err = vboxsf_call(SHFL_FN_MAP_FOLDER, &parms, SHFL_CPARMS_MAP_FOLDER,
0094 &status);
0095 if (err == -ENOSYS && status == VERR_NOT_IMPLEMENTED)
0096 vbg_err("%s: Error host is too old\n", __func__);
0097
0098 *root = parms.root.u.value32;
0099 return err;
0100 }
0101
0102 int vboxsf_unmap_folder(u32 root)
0103 {
0104 struct shfl_unmap_folder parms;
0105
0106 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0107 parms.root.u.value32 = root;
0108
0109 return vboxsf_call(SHFL_FN_UNMAP_FOLDER, &parms,
0110 SHFL_CPARMS_UNMAP_FOLDER, NULL);
0111 }
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 int vboxsf_create(u32 root, struct shfl_string *parsed_path,
0131 struct shfl_createparms *create_parms)
0132 {
0133 struct shfl_create parms;
0134
0135 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0136 parms.root.u.value32 = root;
0137
0138 parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
0139 parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
0140 parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
0141
0142 parms.parms.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
0143 parms.parms.u.pointer.size = sizeof(struct shfl_createparms);
0144 parms.parms.u.pointer.u.linear_addr = (uintptr_t)create_parms;
0145
0146 return vboxsf_call(SHFL_FN_CREATE, &parms, SHFL_CPARMS_CREATE, NULL);
0147 }
0148
0149 int vboxsf_close(u32 root, u64 handle)
0150 {
0151 struct shfl_close parms;
0152
0153 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0154 parms.root.u.value32 = root;
0155
0156 parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0157 parms.handle.u.value64 = handle;
0158
0159 return vboxsf_call(SHFL_FN_CLOSE, &parms, SHFL_CPARMS_CLOSE, NULL);
0160 }
0161
0162 int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags)
0163 {
0164 struct shfl_remove parms;
0165
0166 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0167 parms.root.u.value32 = root;
0168
0169 parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0170 parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
0171 parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
0172
0173 parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0174 parms.flags.u.value32 = flags;
0175
0176 return vboxsf_call(SHFL_FN_REMOVE, &parms, SHFL_CPARMS_REMOVE, NULL);
0177 }
0178
0179 int vboxsf_rename(u32 root, struct shfl_string *src_path,
0180 struct shfl_string *dest_path, u32 flags)
0181 {
0182 struct shfl_rename parms;
0183
0184 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0185 parms.root.u.value32 = root;
0186
0187 parms.src.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0188 parms.src.u.pointer.size = shfl_string_buf_size(src_path);
0189 parms.src.u.pointer.u.linear_addr = (uintptr_t)src_path;
0190
0191 parms.dest.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0192 parms.dest.u.pointer.size = shfl_string_buf_size(dest_path);
0193 parms.dest.u.pointer.u.linear_addr = (uintptr_t)dest_path;
0194
0195 parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0196 parms.flags.u.value32 = flags;
0197
0198 return vboxsf_call(SHFL_FN_RENAME, &parms, SHFL_CPARMS_RENAME, NULL);
0199 }
0200
0201 int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf)
0202 {
0203 struct shfl_read parms;
0204 int err;
0205
0206 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0207 parms.root.u.value32 = root;
0208
0209 parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0210 parms.handle.u.value64 = handle;
0211 parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0212 parms.offset.u.value64 = offset;
0213 parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0214 parms.cb.u.value32 = *buf_len;
0215 parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
0216 parms.buffer.u.pointer.size = *buf_len;
0217 parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
0218
0219 err = vboxsf_call(SHFL_FN_READ, &parms, SHFL_CPARMS_READ, NULL);
0220
0221 *buf_len = parms.cb.u.value32;
0222 return err;
0223 }
0224
0225 int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf)
0226 {
0227 struct shfl_write parms;
0228 int err;
0229
0230 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0231 parms.root.u.value32 = root;
0232
0233 parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0234 parms.handle.u.value64 = handle;
0235 parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0236 parms.offset.u.value64 = offset;
0237 parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0238 parms.cb.u.value32 = *buf_len;
0239 parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0240 parms.buffer.u.pointer.size = *buf_len;
0241 parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
0242
0243 err = vboxsf_call(SHFL_FN_WRITE, &parms, SHFL_CPARMS_WRITE, NULL);
0244
0245 *buf_len = parms.cb.u.value32;
0246 return err;
0247 }
0248
0249
0250 int vboxsf_dirinfo(u32 root, u64 handle,
0251 struct shfl_string *parsed_path, u32 flags, u32 index,
0252 u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count)
0253 {
0254 struct shfl_list parms;
0255 int err, status;
0256
0257 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0258 parms.root.u.value32 = root;
0259
0260 parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0261 parms.handle.u.value64 = handle;
0262 parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0263 parms.flags.u.value32 = flags;
0264 parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0265 parms.cb.u.value32 = *buf_len;
0266 if (parsed_path) {
0267 parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0268 parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
0269 parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
0270 } else {
0271 parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_IN;
0272 parms.path.u.pointer.size = 0;
0273 parms.path.u.pointer.u.linear_addr = 0;
0274 }
0275
0276 parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
0277 parms.buffer.u.pointer.size = *buf_len;
0278 parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
0279
0280 parms.resume_point.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0281 parms.resume_point.u.value32 = index;
0282 parms.file_count.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0283 parms.file_count.u.value32 = 0;
0284
0285 err = vboxsf_call(SHFL_FN_LIST, &parms, SHFL_CPARMS_LIST, &status);
0286 if (err == -ENODATA && status == VERR_NO_MORE_FILES)
0287 err = 1;
0288
0289 *buf_len = parms.cb.u.value32;
0290 *file_count = parms.file_count.u.value32;
0291 return err;
0292 }
0293
0294 int vboxsf_fsinfo(u32 root, u64 handle, u32 flags,
0295 u32 *buf_len, void *buf)
0296 {
0297 struct shfl_information parms;
0298 int err;
0299
0300 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0301 parms.root.u.value32 = root;
0302
0303 parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0304 parms.handle.u.value64 = handle;
0305 parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0306 parms.flags.u.value32 = flags;
0307 parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0308 parms.cb.u.value32 = *buf_len;
0309 parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
0310 parms.info.u.pointer.size = *buf_len;
0311 parms.info.u.pointer.u.linear_addr = (uintptr_t)buf;
0312
0313 err = vboxsf_call(SHFL_FN_INFORMATION, &parms, SHFL_CPARMS_INFORMATION,
0314 NULL);
0315
0316 *buf_len = parms.cb.u.value32;
0317 return err;
0318 }
0319
0320 int vboxsf_readlink(u32 root, struct shfl_string *parsed_path,
0321 u32 buf_len, u8 *buf)
0322 {
0323 struct shfl_readLink parms;
0324
0325 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0326 parms.root.u.value32 = root;
0327
0328 parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0329 parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
0330 parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
0331
0332 parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
0333 parms.buffer.u.pointer.size = buf_len;
0334 parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
0335
0336 return vboxsf_call(SHFL_FN_READLINK, &parms, SHFL_CPARMS_READLINK,
0337 NULL);
0338 }
0339
0340 int vboxsf_symlink(u32 root, struct shfl_string *new_path,
0341 struct shfl_string *old_path, struct shfl_fsobjinfo *buf)
0342 {
0343 struct shfl_symlink parms;
0344
0345 parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0346 parms.root.u.value32 = root;
0347
0348 parms.new_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0349 parms.new_path.u.pointer.size = shfl_string_buf_size(new_path);
0350 parms.new_path.u.pointer.u.linear_addr = (uintptr_t)new_path;
0351
0352 parms.old_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0353 parms.old_path.u.pointer.size = shfl_string_buf_size(old_path);
0354 parms.old_path.u.pointer.u.linear_addr = (uintptr_t)old_path;
0355
0356 parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
0357 parms.info.u.pointer.size = sizeof(struct shfl_fsobjinfo);
0358 parms.info.u.pointer.u.linear_addr = (uintptr_t)buf;
0359
0360 return vboxsf_call(SHFL_FN_SYMLINK, &parms, SHFL_CPARMS_SYMLINK, NULL);
0361 }
0362
0363 int vboxsf_set_utf8(void)
0364 {
0365 return vboxsf_call(SHFL_FN_SET_UTF8, NULL, 0, NULL);
0366 }
0367
0368 int vboxsf_set_symlinks(void)
0369 {
0370 return vboxsf_call(SHFL_FN_SET_SYMLINKS, NULL, 0, NULL);
0371 }