From: Jack Lange <jacklange@cs.pitt.edu>
Date: Thu, 27 Oct 2011 21:35:51 +0000 (-0400)
Subject: added directory creation to the file interface
X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=c4beaffa640916f82593013a1b272ce09ee1cfbd;p=palacios.git

added directory creation to the file interface
---

diff --git a/linux_module/iface-file.c b/linux_module/iface-file.c
index 965023a..3d8ab4d 100644
--- a/linux_module/iface-file.c
+++ b/linux_module/iface-file.c
@@ -4,6 +4,8 @@
 
 
 #include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/version.h>
 #include <linux/file.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
@@ -16,6 +18,7 @@
 
 static struct list_head global_files;
 
+#define isprint(a) ((a >= ' ') && (a <= '~'))
 
 struct palacios_file {
     struct file * filp;
@@ -39,6 +42,120 @@ struct vm_file_state {
 
 
 
+static int palacios_file_mkdir(const char * pathname, unsigned short perms, int recurse);
+
+static int mkdir_recursive(const char * path, unsigned short perms) {
+    char * tmp_str = NULL;
+    char * dirname_ptr;
+    char * tmp_iter;
+
+    tmp_str = kmalloc(strlen(path) + 1, GFP_KERNEL);
+    memset(tmp_str, 0, strlen(path) + 1);
+    strncpy(tmp_str, path, strlen(path));
+
+    dirname_ptr = tmp_str;
+    tmp_iter = tmp_str;
+
+    // parse path string, call palacios_file_mkdir recursively.
+
+
+    while (dirname_ptr != NULL) {
+	int done = 0;
+
+	while ((*tmp_iter != '/') && 
+	       (*tmp_iter != '\0')) {
+
+	    if ( (!isprint(*tmp_iter))) {
+		printk("Invalid character in path name (%d)\n", *tmp_iter);
+		return -1;
+	    } else {
+		tmp_iter++;
+	    }
+	}
+
+	if (*tmp_iter == '/') {
+	    *tmp_iter = '\0';
+	} else {
+	    done = 1;
+	}
+
+	// Ignore empty directories
+	if ((tmp_iter - dirname_ptr) > 1) {
+	    palacios_file_mkdir(tmp_str, perms, 0);
+	}
+
+	if (done) {
+	    break;
+	} else {
+	    *tmp_iter = '/';
+	}
+	
+	tmp_iter++;
+
+	dirname_ptr = tmp_iter;
+    }
+    
+    kfree(tmp_str);
+
+    return 0;
+}
+
+static int palacios_file_mkdir(const char * pathname, unsigned short perms, int recurse) {
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
+    /* DO NOT REFERENCE THIS VARIABLE */
+    /* It only exists to provide version compatibility */
+    struct path tmp_path; 
+#endif
+
+    struct path * path_ptr = NULL;
+    struct dentry * dentry;
+    int ret = 0;
+
+
+
+    if (recurse != 0) {
+	return mkdir_recursive(pathname, perms);
+    } 
+
+    /* Before Linux 3.1 this was somewhat more difficult */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
+    {
+	struct nameidata nd;
+	ret = kern_path_parent(pathname, &nd);
+
+	if (ret != 0) {
+	    printk("%s:%d - Error: kern_path_parent() returned error for (%s)\n", __FILE__, __LINE__, 
+		   pathname);
+	    return -1;
+	}
+	
+	dentry = lookup_create(&nd, 1);
+	path_ptr = &(nd.path);
+    }
+#else 
+    {
+	dentry = kern_path_create(AT_FDCWD, pathname, &tmp_path, 1);
+	
+	if (IS_ERR(dentry)) {
+	    return -1;
+	}
+	
+	path_ptr = &tmp_path;
+    }
+#endif    
+
+
+    if (!IS_ERR(dentry)) {
+	ret = vfs_mkdir(path_ptr->dentry->d_inode, dentry, perms);
+    }
+
+    mutex_unlock(&(path_ptr->dentry->d_inode->i_mutex));
+    path_put(path_ptr);
+    return ret;
+}
+
+
 static void * palacios_file_open(const char * path, int mode, void * private_data) {
     struct v3_guest * guest = (struct v3_guest *)private_data;
     struct palacios_file * pfile = NULL;	
@@ -170,6 +287,7 @@ static struct v3_file_hooks palacios_file_hooks = {
 	.read		= palacios_file_read,
 	.write		= palacios_file_write,
 	.size		= palacios_file_size,
+	.mkdir          = palacios_file_mkdir,
 };
 
 
diff --git a/palacios/include/interfaces/vmm_file.h b/palacios/include/interfaces/vmm_file.h
index 46b89b1..69b78d8 100644
--- a/palacios/include/interfaces/vmm_file.h
+++ b/palacios/include/interfaces/vmm_file.h
@@ -27,6 +27,8 @@
 #ifdef __V3VEE__
 typedef void * v3_file_t;
 
+int v3_mkdir(char * path, uint16_t permissions, uint8_t recursive);
+
 
 v3_file_t v3_file_open(struct v3_vm_info * vm, char * path, uint8_t mode);
 int v3_file_close(v3_file_t file);
@@ -42,6 +44,7 @@ uint64_t v3_file_write(v3_file_t file, uint8_t * buf, uint64_t len, uint64_t off
 #define FILE_OPEN_MODE_CREATE        (1 << 2)
 
 struct v3_file_hooks {
+    int (*mkdir)(const char * path, unsigned short perms, int recursive);
 
     void * (*open)(const char * path, int mode, void * host_data);
     int (*close)(void * fd);
diff --git a/palacios/src/interfaces/vmm_file.c b/palacios/src/interfaces/vmm_file.c
index c22267a..c4d3f28 100644
--- a/palacios/src/interfaces/vmm_file.c
+++ b/palacios/src/interfaces/vmm_file.c
@@ -34,6 +34,13 @@ void V3_Init_File(struct v3_file_hooks * hooks) {
 }
 
 
+int v3_mkdir(char * path, uint16_t permissions, uint8_t recursive) {
+    V3_ASSERT(file_hooks);
+    V3_ASSERT(file_hooks->mkdir);
+    
+    return file_hooks->mkdir(path, permissions, recursive);
+}
+
 v3_file_t v3_file_open(struct v3_vm_info * vm, char * path, uint8_t mode) {
     void * priv_data = NULL;
     V3_ASSERT(file_hooks);