X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=linux_module%2Fiface-file.c;h=3d8ab4da48e1c307399549581a28925d4c711558;hp=965023a3da02cb3374b4acfb6cf605c0ca0d35ab;hb=c4beaffa640916f82593013a1b272ce09ee1cfbd;hpb=ad468ace3ffaac55719923219920d038b3be5844 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 +#include +#include #include #include #include @@ -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, };