linux/fs/vboxsf/vboxsf_wrappers.c
<<
>>
Prefs
   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
  18static u32 vboxsf_client_id;
  19
  20int 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
  40void 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
  53static 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
  75int 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
 102int 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 */
 130int 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
 149int 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
 162int 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
 179int 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
 201int 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
 225int 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 */
 250int 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
 294int 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
 320int 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
 340int 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
 363int vboxsf_set_utf8(void)
 364{
 365        return vboxsf_call(SHFL_FN_SET_UTF8, NULL, 0, NULL);
 366}
 367
 368int vboxsf_set_symlinks(void)
 369{
 370        return vboxsf_call(SHFL_FN_SET_SYMLINKS, NULL, 0, NULL);
 371}
 372