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 * Create or open a file or directory. 7*433d6423SLionel Sambuc */ 8*433d6423SLionel Sambuc int 9*433d6423SLionel Sambuc vboxfs_open_file(char *path, int flags, int mode, vboxfs_handle_t *handlep, 10*433d6423SLionel Sambuc vboxfs_objinfo_t *infop) 11*433d6423SLionel Sambuc { 12*433d6423SLionel Sambuc vbox_param_t param[3]; 13*433d6423SLionel Sambuc vboxfs_path_t pathbuf; 14*433d6423SLionel Sambuc vboxfs_crinfo_t crinfo; 15*433d6423SLionel Sambuc int r, dir, rflag, wflag; 16*433d6423SLionel Sambuc 17*433d6423SLionel Sambuc if ((r = vboxfs_set_path(&pathbuf, path)) != OK) 18*433d6423SLionel Sambuc return r; 19*433d6423SLionel Sambuc 20*433d6423SLionel Sambuc memset(&crinfo, 0, sizeof(crinfo)); 21*433d6423SLionel Sambuc 22*433d6423SLionel Sambuc /* 23*433d6423SLionel Sambuc * Note that the mode may not be set at all. If no new file may be 24*433d6423SLionel Sambuc * created, this is not a problem. The following test succeeds only if 25*433d6423SLionel Sambuc * the caller explicitly specified that a directory is involved. 26*433d6423SLionel Sambuc */ 27*433d6423SLionel Sambuc dir = S_ISDIR(mode); 28*433d6423SLionel Sambuc 29*433d6423SLionel Sambuc /* Convert open(2) flags to VirtualBox creation flags. */ 30*433d6423SLionel Sambuc if (flags & O_APPEND) 31*433d6423SLionel Sambuc return EINVAL; /* not supported at this time */ 32*433d6423SLionel Sambuc 33*433d6423SLionel Sambuc if (flags & O_CREAT) { 34*433d6423SLionel Sambuc crinfo.flags = VBOXFS_CRFLAG_CREATE_IF_NEW; 35*433d6423SLionel Sambuc 36*433d6423SLionel Sambuc if (flags & O_EXCL) 37*433d6423SLionel Sambuc crinfo.flags |= VBOXFS_CRFLAG_FAIL_IF_EXISTS; 38*433d6423SLionel Sambuc else if (flags & O_TRUNC) 39*433d6423SLionel Sambuc crinfo.flags |= VBOXFS_CRFLAG_TRUNC_IF_EXISTS; 40*433d6423SLionel Sambuc else 41*433d6423SLionel Sambuc crinfo.flags |= VBOXFS_CRFLAG_OPEN_IF_EXISTS; 42*433d6423SLionel Sambuc } else { 43*433d6423SLionel Sambuc crinfo.flags = VBOXFS_CRFLAG_FAIL_IF_NEW; 44*433d6423SLionel Sambuc 45*433d6423SLionel Sambuc if (flags & O_TRUNC) 46*433d6423SLionel Sambuc crinfo.flags |= VBOXFS_CRFLAG_TRUNC_IF_EXISTS; 47*433d6423SLionel Sambuc else 48*433d6423SLionel Sambuc crinfo.flags |= VBOXFS_CRFLAG_OPEN_IF_EXISTS; 49*433d6423SLionel Sambuc } 50*433d6423SLionel Sambuc 51*433d6423SLionel Sambuc /* 52*433d6423SLionel Sambuc * If an object information structure is given, open the file only to 53*433d6423SLionel Sambuc * retrieve or change its attributes. 54*433d6423SLionel Sambuc */ 55*433d6423SLionel Sambuc if (infop != NULL) { 56*433d6423SLionel Sambuc rflag = VBOXFS_CRFLAG_READ_ATTR; 57*433d6423SLionel Sambuc wflag = VBOXFS_CRFLAG_WRITE_ATTR; 58*433d6423SLionel Sambuc } else { 59*433d6423SLionel Sambuc rflag = VBOXFS_CRFLAG_READ; 60*433d6423SLionel Sambuc wflag = VBOXFS_CRFLAG_WRITE; 61*433d6423SLionel Sambuc } 62*433d6423SLionel Sambuc 63*433d6423SLionel Sambuc switch (flags & O_ACCMODE) { 64*433d6423SLionel Sambuc case O_RDONLY: crinfo.flags |= rflag; break; 65*433d6423SLionel Sambuc case O_WRONLY: crinfo.flags |= wflag; break; 66*433d6423SLionel Sambuc case O_RDWR: crinfo.flags |= rflag | wflag; break; 67*433d6423SLionel Sambuc default: return EINVAL; 68*433d6423SLionel Sambuc } 69*433d6423SLionel Sambuc 70*433d6423SLionel Sambuc if (S_ISDIR(mode)) 71*433d6423SLionel Sambuc crinfo.flags |= VBOXFS_CRFLAG_DIRECTORY; 72*433d6423SLionel Sambuc 73*433d6423SLionel Sambuc crinfo.info.attr.mode = VBOXFS_SET_MODE(dir ? S_IFDIR : S_IFREG, mode); 74*433d6423SLionel Sambuc crinfo.info.attr.add = VBOXFS_OBJATTR_ADD_NONE; 75*433d6423SLionel Sambuc 76*433d6423SLionel Sambuc vbox_set_u32(¶m[0], vboxfs_root); 77*433d6423SLionel Sambuc vbox_set_ptr(¶m[1], &pathbuf, vboxfs_get_path_size(&pathbuf), 78*433d6423SLionel Sambuc VBOX_DIR_OUT); 79*433d6423SLionel Sambuc vbox_set_ptr(¶m[2], &crinfo, sizeof(crinfo), VBOX_DIR_INOUT); 80*433d6423SLionel Sambuc 81*433d6423SLionel Sambuc r = vbox_call(vboxfs_conn, VBOXFS_CALL_CREATE, param, 3, NULL); 82*433d6423SLionel Sambuc if (r != OK) 83*433d6423SLionel Sambuc return r; 84*433d6423SLionel Sambuc 85*433d6423SLionel Sambuc if (crinfo.handle == VBOXFS_INVALID_HANDLE) { 86*433d6423SLionel Sambuc switch (crinfo.result) { 87*433d6423SLionel Sambuc case VBOXFS_PATH_NOT_FOUND: 88*433d6423SLionel Sambuc /* 89*433d6423SLionel Sambuc * This could also mean ENOTDIR, but there does not 90*433d6423SLionel Sambuc * appear to be any way to distinguish that case. 91*433d6423SLionel Sambuc * Verifying with extra lookups seems overkill. 92*433d6423SLionel Sambuc */ 93*433d6423SLionel Sambuc case VBOXFS_FILE_NOT_FOUND: 94*433d6423SLionel Sambuc return ENOENT; 95*433d6423SLionel Sambuc case VBOXFS_FILE_EXISTS: 96*433d6423SLionel Sambuc return EEXIST; 97*433d6423SLionel Sambuc default: 98*433d6423SLionel Sambuc return EIO; /* should never happen */ 99*433d6423SLionel Sambuc } 100*433d6423SLionel Sambuc } 101*433d6423SLionel Sambuc 102*433d6423SLionel Sambuc *handlep = crinfo.handle; 103*433d6423SLionel Sambuc if (infop != NULL) 104*433d6423SLionel Sambuc *infop = crinfo.info; 105*433d6423SLionel Sambuc return OK; 106*433d6423SLionel Sambuc } 107*433d6423SLionel Sambuc 108*433d6423SLionel Sambuc /* 109*433d6423SLionel Sambuc * Close an open file handle. 110*433d6423SLionel Sambuc */ 111*433d6423SLionel Sambuc void 112*433d6423SLionel Sambuc vboxfs_close_file(vboxfs_handle_t handle) 113*433d6423SLionel Sambuc { 114*433d6423SLionel Sambuc vbox_param_t param[2]; 115*433d6423SLionel Sambuc 116*433d6423SLionel Sambuc vbox_set_u32(¶m[0], vboxfs_root); 117*433d6423SLionel Sambuc vbox_set_u64(¶m[1], handle); 118*433d6423SLionel Sambuc 119*433d6423SLionel Sambuc /* Ignore errors here. We cannot do anything with them anyway. */ 120*433d6423SLionel Sambuc (void) vbox_call(vboxfs_conn, VBOXFS_CALL_CLOSE, param, 2, NULL); 121*433d6423SLionel Sambuc } 122