122 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Part of libvboxfs - (c) 2012, D.C. van Moolenbroek */
 | |
| 
 | |
| #include "inc.h"
 | |
| 
 | |
| /*
 | |
|  * Create or open a file or directory.
 | |
|  */
 | |
| int
 | |
| vboxfs_open_file(char *path, int flags, int mode, vboxfs_handle_t *handlep,
 | |
| 	vboxfs_objinfo_t *infop)
 | |
| {
 | |
| 	vbox_param_t param[3];
 | |
| 	vboxfs_path_t pathbuf;
 | |
| 	vboxfs_crinfo_t crinfo;
 | |
| 	int r, dir, rflag, wflag;
 | |
| 
 | |
| 	if ((r = vboxfs_set_path(&pathbuf, path)) != OK)
 | |
| 		return r;
 | |
| 
 | |
| 	memset(&crinfo, 0, sizeof(crinfo));
 | |
| 
 | |
| 	/*
 | |
| 	 * Note that the mode may not be set at all.  If no new file may be
 | |
| 	 * created, this is not a problem.  The following test succeeds only if
 | |
| 	 * the caller explicitly specified that a directory is involved.
 | |
| 	 */
 | |
| 	dir = S_ISDIR(mode);
 | |
| 
 | |
| 	/* Convert open(2) flags to VirtualBox creation flags. */
 | |
| 	if (flags & O_APPEND)
 | |
| 		return EINVAL;	/* not supported at this time */
 | |
| 
 | |
| 	if (flags & O_CREAT) {
 | |
| 		crinfo.flags = VBOXFS_CRFLAG_CREATE_IF_NEW;
 | |
| 
 | |
| 		if (flags & O_EXCL)
 | |
| 			crinfo.flags |= VBOXFS_CRFLAG_FAIL_IF_EXISTS;
 | |
| 		else if (flags & O_TRUNC)
 | |
| 			crinfo.flags |= VBOXFS_CRFLAG_TRUNC_IF_EXISTS;
 | |
| 		else
 | |
| 			crinfo.flags |= VBOXFS_CRFLAG_OPEN_IF_EXISTS;
 | |
| 	} else {
 | |
| 		crinfo.flags = VBOXFS_CRFLAG_FAIL_IF_NEW;
 | |
| 
 | |
| 		if (flags & O_TRUNC)
 | |
| 			crinfo.flags |= VBOXFS_CRFLAG_TRUNC_IF_EXISTS;
 | |
| 		else
 | |
| 			crinfo.flags |= VBOXFS_CRFLAG_OPEN_IF_EXISTS;
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * If an object information structure is given, open the file only to
 | |
| 	 * retrieve or change its attributes.
 | |
| 	 */
 | |
| 	if (infop != NULL) {
 | |
| 		rflag = VBOXFS_CRFLAG_READ_ATTR;
 | |
| 		wflag = VBOXFS_CRFLAG_WRITE_ATTR;
 | |
| 	} else {
 | |
| 		rflag = VBOXFS_CRFLAG_READ;
 | |
| 		wflag = VBOXFS_CRFLAG_WRITE;
 | |
| 	}
 | |
| 
 | |
| 	switch (flags & O_ACCMODE) {
 | |
| 	case O_RDONLY:	crinfo.flags |= rflag;		break;
 | |
| 	case O_WRONLY:	crinfo.flags |= wflag;		break;
 | |
| 	case O_RDWR:	crinfo.flags |= rflag | wflag;	break;
 | |
| 	default:	return EINVAL;
 | |
| 	}
 | |
| 
 | |
| 	if (S_ISDIR(mode))
 | |
| 		crinfo.flags |= VBOXFS_CRFLAG_DIRECTORY;
 | |
| 
 | |
| 	crinfo.info.attr.mode = VBOXFS_SET_MODE(dir ? S_IFDIR : S_IFREG, mode);
 | |
| 	crinfo.info.attr.add = VBOXFS_OBJATTR_ADD_NONE;
 | |
| 
 | |
| 	vbox_set_u32(¶m[0], vboxfs_root);
 | |
| 	vbox_set_ptr(¶m[1], &pathbuf, vboxfs_get_path_size(&pathbuf),
 | |
| 	    VBOX_DIR_OUT);
 | |
| 	vbox_set_ptr(¶m[2], &crinfo, sizeof(crinfo), VBOX_DIR_INOUT);
 | |
| 
 | |
| 	r = vbox_call(vboxfs_conn, VBOXFS_CALL_CREATE, param, 3, NULL);
 | |
| 	if (r != OK)
 | |
| 		return r;
 | |
| 
 | |
| 	if (crinfo.handle == VBOXFS_INVALID_HANDLE) {
 | |
| 		switch (crinfo.result) {
 | |
| 		case VBOXFS_PATH_NOT_FOUND:
 | |
| 			/*
 | |
| 			 * This could also mean ENOTDIR, but there does not
 | |
| 			 * appear to be any way to distinguish that case.
 | |
| 			 * Verifying with extra lookups seems overkill.
 | |
| 			 */
 | |
| 		case VBOXFS_FILE_NOT_FOUND:
 | |
| 			return ENOENT;
 | |
| 		case VBOXFS_FILE_EXISTS:
 | |
| 			return EEXIST;
 | |
| 		default:
 | |
| 			return EIO;		/* should never happen */
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	*handlep = crinfo.handle;
 | |
| 	if (infop != NULL)
 | |
| 		*infop = crinfo.info;
 | |
| 	return OK;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Close an open file handle.
 | |
|  */
 | |
| void
 | |
| vboxfs_close_file(vboxfs_handle_t handle)
 | |
| {
 | |
| 	vbox_param_t param[2];
 | |
| 
 | |
| 	vbox_set_u32(¶m[0], vboxfs_root);
 | |
| 	vbox_set_u64(¶m[1], handle);
 | |
| 
 | |
| 	/* Ignore errors here. We cannot do anything with them anyway. */
 | |
| 	(void) vbox_call(vboxfs_conn, VBOXFS_CALL_CLOSE, param, 2, NULL);
 | |
| }
 | 
