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