xref: /minix3/minix/lib/libvboxfs/handle.c (revision 94e65446c4f963450ea94b8becc02cec062675cd)
1433d6423SLionel Sambuc /* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
2433d6423SLionel Sambuc 
3433d6423SLionel Sambuc #include "inc.h"
4433d6423SLionel Sambuc 
5433d6423SLionel Sambuc /*
6433d6423SLionel Sambuc  * Create or open a file or directory.
7433d6423SLionel Sambuc  */
8433d6423SLionel Sambuc int
vboxfs_open_file(const char * path,int flags,int mode,vboxfs_handle_t * handlep,vboxfs_objinfo_t * infop)9*94e65446SDavid van Moolenbroek vboxfs_open_file(const char *path, int flags, int mode,
10*94e65446SDavid van Moolenbroek 	vboxfs_handle_t *handlep, vboxfs_objinfo_t *infop)
11433d6423SLionel Sambuc {
12433d6423SLionel Sambuc 	vbox_param_t param[3];
13433d6423SLionel Sambuc 	vboxfs_path_t pathbuf;
14433d6423SLionel Sambuc 	vboxfs_crinfo_t crinfo;
15433d6423SLionel Sambuc 	int r, dir, rflag, wflag;
16433d6423SLionel Sambuc 
17433d6423SLionel Sambuc 	if ((r = vboxfs_set_path(&pathbuf, path)) != OK)
18433d6423SLionel Sambuc 		return r;
19433d6423SLionel Sambuc 
20433d6423SLionel Sambuc 	memset(&crinfo, 0, sizeof(crinfo));
21433d6423SLionel Sambuc 
22433d6423SLionel Sambuc 	/*
23433d6423SLionel Sambuc 	 * Note that the mode may not be set at all.  If no new file may be
24433d6423SLionel Sambuc 	 * created, this is not a problem.  The following test succeeds only if
25433d6423SLionel Sambuc 	 * the caller explicitly specified that a directory is involved.
26433d6423SLionel Sambuc 	 */
27433d6423SLionel Sambuc 	dir = S_ISDIR(mode);
28433d6423SLionel Sambuc 
29433d6423SLionel Sambuc 	/* Convert open(2) flags to VirtualBox creation flags. */
30433d6423SLionel Sambuc 	if (flags & O_APPEND)
31433d6423SLionel Sambuc 		return EINVAL;	/* not supported at this time */
32433d6423SLionel Sambuc 
33433d6423SLionel Sambuc 	if (flags & O_CREAT) {
34433d6423SLionel Sambuc 		crinfo.flags = VBOXFS_CRFLAG_CREATE_IF_NEW;
35433d6423SLionel Sambuc 
36433d6423SLionel Sambuc 		if (flags & O_EXCL)
37433d6423SLionel Sambuc 			crinfo.flags |= VBOXFS_CRFLAG_FAIL_IF_EXISTS;
38433d6423SLionel Sambuc 		else if (flags & O_TRUNC)
39433d6423SLionel Sambuc 			crinfo.flags |= VBOXFS_CRFLAG_TRUNC_IF_EXISTS;
40433d6423SLionel Sambuc 		else
41433d6423SLionel Sambuc 			crinfo.flags |= VBOXFS_CRFLAG_OPEN_IF_EXISTS;
42433d6423SLionel Sambuc 	} else {
43433d6423SLionel Sambuc 		crinfo.flags = VBOXFS_CRFLAG_FAIL_IF_NEW;
44433d6423SLionel Sambuc 
45433d6423SLionel Sambuc 		if (flags & O_TRUNC)
46433d6423SLionel Sambuc 			crinfo.flags |= VBOXFS_CRFLAG_TRUNC_IF_EXISTS;
47433d6423SLionel Sambuc 		else
48433d6423SLionel Sambuc 			crinfo.flags |= VBOXFS_CRFLAG_OPEN_IF_EXISTS;
49433d6423SLionel Sambuc 	}
50433d6423SLionel Sambuc 
51433d6423SLionel Sambuc 	/*
52433d6423SLionel Sambuc 	 * If an object information structure is given, open the file only to
53433d6423SLionel Sambuc 	 * retrieve or change its attributes.
54433d6423SLionel Sambuc 	 */
55433d6423SLionel Sambuc 	if (infop != NULL) {
56433d6423SLionel Sambuc 		rflag = VBOXFS_CRFLAG_READ_ATTR;
57433d6423SLionel Sambuc 		wflag = VBOXFS_CRFLAG_WRITE_ATTR;
58433d6423SLionel Sambuc 	} else {
59433d6423SLionel Sambuc 		rflag = VBOXFS_CRFLAG_READ;
60433d6423SLionel Sambuc 		wflag = VBOXFS_CRFLAG_WRITE;
61433d6423SLionel Sambuc 	}
62433d6423SLionel Sambuc 
63433d6423SLionel Sambuc 	switch (flags & O_ACCMODE) {
64433d6423SLionel Sambuc 	case O_RDONLY:	crinfo.flags |= rflag;		break;
65433d6423SLionel Sambuc 	case O_WRONLY:	crinfo.flags |= wflag;		break;
66433d6423SLionel Sambuc 	case O_RDWR:	crinfo.flags |= rflag | wflag;	break;
67433d6423SLionel Sambuc 	default:	return EINVAL;
68433d6423SLionel Sambuc 	}
69433d6423SLionel Sambuc 
70433d6423SLionel Sambuc 	if (S_ISDIR(mode))
71433d6423SLionel Sambuc 		crinfo.flags |= VBOXFS_CRFLAG_DIRECTORY;
72433d6423SLionel Sambuc 
73433d6423SLionel Sambuc 	crinfo.info.attr.mode = VBOXFS_SET_MODE(dir ? S_IFDIR : S_IFREG, mode);
74433d6423SLionel Sambuc 	crinfo.info.attr.add = VBOXFS_OBJATTR_ADD_NONE;
75433d6423SLionel Sambuc 
76433d6423SLionel Sambuc 	vbox_set_u32(&param[0], vboxfs_root);
77433d6423SLionel Sambuc 	vbox_set_ptr(&param[1], &pathbuf, vboxfs_get_path_size(&pathbuf),
78433d6423SLionel Sambuc 	    VBOX_DIR_OUT);
79433d6423SLionel Sambuc 	vbox_set_ptr(&param[2], &crinfo, sizeof(crinfo), VBOX_DIR_INOUT);
80433d6423SLionel Sambuc 
81433d6423SLionel Sambuc 	r = vbox_call(vboxfs_conn, VBOXFS_CALL_CREATE, param, 3, NULL);
82433d6423SLionel Sambuc 	if (r != OK)
83433d6423SLionel Sambuc 		return r;
84433d6423SLionel Sambuc 
85433d6423SLionel Sambuc 	if (crinfo.handle == VBOXFS_INVALID_HANDLE) {
86433d6423SLionel Sambuc 		switch (crinfo.result) {
87433d6423SLionel Sambuc 		case VBOXFS_PATH_NOT_FOUND:
88433d6423SLionel Sambuc 			/*
89433d6423SLionel Sambuc 			 * This could also mean ENOTDIR, but there does not
90433d6423SLionel Sambuc 			 * appear to be any way to distinguish that case.
91433d6423SLionel Sambuc 			 * Verifying with extra lookups seems overkill.
92433d6423SLionel Sambuc 			 */
93433d6423SLionel Sambuc 		case VBOXFS_FILE_NOT_FOUND:
94433d6423SLionel Sambuc 			return ENOENT;
95433d6423SLionel Sambuc 		case VBOXFS_FILE_EXISTS:
96433d6423SLionel Sambuc 			return EEXIST;
97433d6423SLionel Sambuc 		default:
98433d6423SLionel Sambuc 			return EIO;		/* should never happen */
99433d6423SLionel Sambuc 		}
100433d6423SLionel Sambuc 	}
101433d6423SLionel Sambuc 
102433d6423SLionel Sambuc 	*handlep = crinfo.handle;
103433d6423SLionel Sambuc 	if (infop != NULL)
104433d6423SLionel Sambuc 		*infop = crinfo.info;
105433d6423SLionel Sambuc 	return OK;
106433d6423SLionel Sambuc }
107433d6423SLionel Sambuc 
108433d6423SLionel Sambuc /*
109433d6423SLionel Sambuc  * Close an open file handle.
110433d6423SLionel Sambuc  */
111433d6423SLionel Sambuc void
vboxfs_close_file(vboxfs_handle_t handle)112433d6423SLionel Sambuc vboxfs_close_file(vboxfs_handle_t handle)
113433d6423SLionel Sambuc {
114433d6423SLionel Sambuc 	vbox_param_t param[2];
115433d6423SLionel Sambuc 
116433d6423SLionel Sambuc 	vbox_set_u32(&param[0], vboxfs_root);
117433d6423SLionel Sambuc 	vbox_set_u64(&param[1], handle);
118433d6423SLionel Sambuc 
119433d6423SLionel Sambuc 	/* Ignore errors here. We cannot do anything with them anyway. */
120433d6423SLionel Sambuc 	(void) vbox_call(vboxfs_conn, VBOXFS_CALL_CLOSE, param, 2, NULL);
121433d6423SLionel Sambuc }
122