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);
 | 
						|
}
 |