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