xref: /minix/minix/lib/libvboxfs/handle.c (revision 83133719)
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(&param[0], vboxfs_root);
77 	vbox_set_ptr(&param[1], &pathbuf, vboxfs_get_path_size(&pathbuf),
78 	    VBOX_DIR_OUT);
79 	vbox_set_ptr(&param[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(&param[0], vboxfs_root);
117 	vbox_set_u64(&param[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