/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*
* Ported the filesystem routines to 2.5.
* 2003-02-10 Petr Baudis <pasky@ucw.cz>
*/
#include <linux/stddef.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
#include <linux/blkdev.h>
#include <linux/list.h>
#include <linux/statfs.h>
#include <linux/kdev_t.h>
#include <asm/uaccess.h>
#include "hostfs.h"
#include "kern_util.h"
#include "kern.h"
#include "user_util.h"
#include "init.h"
struct hostfs_inode_info {
char *host_filename;
int fd;
int mode;
struct inode vfs_inode;
};
static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode)
{
return(list_entry(inode, struct hostfs_inode_info, vfs_inode));
}
#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_path.dentry->d_inode)
int hostfs_d_delete(struct dentry *dentry)
{
return(1);
}
struct dentry_operations hostfs_dentry_ops = {
.d_delete = hostfs_d_delete,
};
/* Changed in hostfs_args before the kernel starts running */
static char *root_ino = "/";
static int append = 0;
#define HOSTFS_SUPER_MAGIC 0x00c0ffee
static struct inode_operations hostfs_iops;
static struct inode_operations hostfs_dir_iops;
static const struct address_space_operations hostfs_link_aops;
#ifndef MODULE
static int __init hostfs_args(char *options, int *add)
{
char *ptr;
ptr = strchr(options, ',');
if(ptr != NULL)
*ptr++ = '\0';
if(*options != '\0')
root_ino = options;
options = ptr;
while(options){
ptr = strchr(options, ',');
if(ptr != NULL)
*ptr++ = '\0';
if(*options != '\0'){
if(!strcmp(options, "append"))
append = 1;
else printf("hostfs_args - unsupported option - %s\n",
options);
}
options = ptr;
}
return(0);
}
__uml_setup("hostfs=", hostfs_args,
"hostfs=<root dir>,<flags>,...\n"
" This is used to set hostfs parameters. The root directory argument\n"
" is used to confine all hostfs mounts to within the specified directory\n"
" tree on the host. If this isn't specified, then a user inside UML can\n"
" mount anything on the host that's accessible to the user that's running\n"
" it.\n"
" The only flag currently supported is 'append', which specifies that all\n"
" files opened by hostfs will be opened in append mode.\n\n"
);
#endif
static char *dentry_name(struct dentry *dentry, int extra)
{
struct dentry *parent;
char *root, *name;
int len;
len = 0;
parent = dentry;
while(parent->d_parent != parent){
len += parent->d_name.len + 1;
parent = parent->d_parent;
}
root = HOSTFS_I(parent->d_inode)->host_filename;
len += strlen(root);
name = kmalloc(len + extra + 1, GFP_KERNEL);
if(name == NULL) return(NULL);
name[len] = '\0';
parent = dentry;
while(parent->d_parent != parent){
len -= parent->d_name.len + 1;
name[len] = '/';
strncpy(&name[len + 1], parent->d_name.name,
parent->d_name.len);
parent = parent->d_parent;
}
strncpy(name, root, strlen(root));
return(name);
}
static char *inode_name(struct inode *ino, int extra)
{
struct dentry *dentry;
dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias);
return(dentry_name(dentry, extra));
}
static int read_name(struct inode *ino, char *name)
{
/* The non-int inode fields are copied into ints by stat_file and
* then copied into the inode because passing the actual pointers
* in and having them treated as int * breaks on big-endian machines
*/
int err;
int i_mode, i_nlink, i_blksize;
unsigned long long i_size;
unsigned