1*433d6423SLionel Sambuc /* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */ 2*433d6423SLionel Sambuc 3*433d6423SLionel Sambuc #include "inc.h" 4*433d6423SLionel Sambuc 5*433d6423SLionel Sambuc /* 6*433d6423SLionel Sambuc * We perform all file I/O using a local, intermediate buffer. While in theory 7*433d6423SLionel Sambuc * it would be possible to perform direct DMA from/to the user process, this 8*433d6423SLionel Sambuc * does not work in practice: on short reads, VirtualBox copies back the entire 9*433d6423SLionel Sambuc * provided buffer rather than only the part actually filled, resulting in the 10*433d6423SLionel Sambuc * unused part of the buffer being clobbered. Marking the buffer as bi- 11*433d6423SLionel Sambuc * directional would solve this, except it would also eliminate all the 12*433d6423SLionel Sambuc * zero-copy benefits for reads; in addition, it is prevented by the protection 13*433d6423SLionel Sambuc * set on the given grant. 14*433d6423SLionel Sambuc */ 15*433d6423SLionel Sambuc 16*433d6423SLionel Sambuc #define VBOXFS_MAX_FILEIO 65536 /* maximum I/O chunk size */ 17*433d6423SLionel Sambuc 18*433d6423SLionel Sambuc static char iobuf[VBOXFS_MAX_FILEIO]; 19*433d6423SLionel Sambuc 20*433d6423SLionel Sambuc /* 21*433d6423SLionel Sambuc * Open a file. 22*433d6423SLionel Sambuc */ 23*433d6423SLionel Sambuc int 24*433d6423SLionel Sambuc vboxfs_open(char *path, int flags, int mode, sffs_file_t *handle) 25*433d6423SLionel Sambuc { 26*433d6423SLionel Sambuc vboxfs_handle_t *handlep; 27*433d6423SLionel Sambuc int r; 28*433d6423SLionel Sambuc 29*433d6423SLionel Sambuc handlep = (vboxfs_handle_t *) malloc(sizeof(*handlep)); 30*433d6423SLionel Sambuc 31*433d6423SLionel Sambuc if ((r = vboxfs_open_file(path, flags, mode, handlep, NULL)) != OK) { 32*433d6423SLionel Sambuc free(handlep); 33*433d6423SLionel Sambuc 34*433d6423SLionel Sambuc return r; 35*433d6423SLionel Sambuc } 36*433d6423SLionel Sambuc 37*433d6423SLionel Sambuc *handle = (sffs_file_t) handlep; 38*433d6423SLionel Sambuc 39*433d6423SLionel Sambuc return OK; 40*433d6423SLionel Sambuc } 41*433d6423SLionel Sambuc 42*433d6423SLionel Sambuc /* 43*433d6423SLionel Sambuc * Read or write a chunk from or to a file. 44*433d6423SLionel Sambuc */ 45*433d6423SLionel Sambuc static ssize_t 46*433d6423SLionel Sambuc read_write(vboxfs_handle_t handle, char *buf, size_t size, u64_t pos, 47*433d6423SLionel Sambuc int write) 48*433d6423SLionel Sambuc { 49*433d6423SLionel Sambuc vbox_param_t param[5]; 50*433d6423SLionel Sambuc int r, dir, call; 51*433d6423SLionel Sambuc 52*433d6423SLionel Sambuc dir = write ? VBOX_DIR_OUT : VBOX_DIR_IN; 53*433d6423SLionel Sambuc call = write ? VBOXFS_CALL_WRITE : VBOXFS_CALL_READ; 54*433d6423SLionel Sambuc 55*433d6423SLionel Sambuc vbox_set_u32(¶m[0], vboxfs_root); 56*433d6423SLionel Sambuc vbox_set_u64(¶m[1], handle); 57*433d6423SLionel Sambuc vbox_set_u64(¶m[2], pos); 58*433d6423SLionel Sambuc vbox_set_u32(¶m[3], size); 59*433d6423SLionel Sambuc vbox_set_ptr(¶m[4], buf, size, dir); 60*433d6423SLionel Sambuc 61*433d6423SLionel Sambuc if ((r = vbox_call(vboxfs_conn, call, param, 5, NULL)) != OK) 62*433d6423SLionel Sambuc return r; 63*433d6423SLionel Sambuc 64*433d6423SLionel Sambuc return vbox_get_u32(¶m[3]); 65*433d6423SLionel Sambuc } 66*433d6423SLionel Sambuc 67*433d6423SLionel Sambuc /* 68*433d6423SLionel Sambuc * Read from a file. 69*433d6423SLionel Sambuc */ 70*433d6423SLionel Sambuc ssize_t 71*433d6423SLionel Sambuc vboxfs_read(sffs_file_t handle, char *buf, size_t size, u64_t pos) 72*433d6423SLionel Sambuc { 73*433d6423SLionel Sambuc vboxfs_handle_t *handlep; 74*433d6423SLionel Sambuc 75*433d6423SLionel Sambuc handlep = (vboxfs_handle_t *) handle; 76*433d6423SLionel Sambuc 77*433d6423SLionel Sambuc return read_write(*handlep, buf, size, pos, FALSE /*write*/); 78*433d6423SLionel Sambuc } 79*433d6423SLionel Sambuc 80*433d6423SLionel Sambuc /* 81*433d6423SLionel Sambuc * Write to a file. 82*433d6423SLionel Sambuc */ 83*433d6423SLionel Sambuc ssize_t 84*433d6423SLionel Sambuc vboxfs_write(sffs_file_t handle, char *buf, size_t len, u64_t pos) 85*433d6423SLionel Sambuc { 86*433d6423SLionel Sambuc vboxfs_handle_t *handlep; 87*433d6423SLionel Sambuc 88*433d6423SLionel Sambuc handlep = (vboxfs_handle_t *) handle; 89*433d6423SLionel Sambuc 90*433d6423SLionel Sambuc return read_write(*handlep, buf, len, pos, TRUE /*write*/); 91*433d6423SLionel Sambuc } 92*433d6423SLionel Sambuc 93*433d6423SLionel Sambuc /* 94*433d6423SLionel Sambuc * Close a file handle. 95*433d6423SLionel Sambuc */ 96*433d6423SLionel Sambuc int 97*433d6423SLionel Sambuc vboxfs_close(sffs_file_t handle) 98*433d6423SLionel Sambuc { 99*433d6423SLionel Sambuc vboxfs_handle_t *handlep; 100*433d6423SLionel Sambuc 101*433d6423SLionel Sambuc handlep = (vboxfs_handle_t *) handle; 102*433d6423SLionel Sambuc 103*433d6423SLionel Sambuc vboxfs_close_file(*handlep); 104*433d6423SLionel Sambuc 105*433d6423SLionel Sambuc free(handlep); 106*433d6423SLionel Sambuc 107*433d6423SLionel Sambuc return OK; 108*433d6423SLionel Sambuc } 109*433d6423SLionel Sambuc 110*433d6423SLionel Sambuc /* 111*433d6423SLionel Sambuc * Return an internal buffer address and size for I/O operations. 112*433d6423SLionel Sambuc */ 113*433d6423SLionel Sambuc size_t 114*433d6423SLionel Sambuc vboxfs_buffer(char **ptr) 115*433d6423SLionel Sambuc { 116*433d6423SLionel Sambuc 117*433d6423SLionel Sambuc *ptr = iobuf; 118*433d6423SLionel Sambuc return sizeof(iobuf); 119*433d6423SLionel Sambuc } 120