/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/dcache.h>
#include <linux/statfs.h>
#include <asm/uaccess.h>
#include <asm/fcntl.h>
#include "os.h"
static int init_inode(struct inode *inode, struct dentry *dentry);
struct hppfs_data {
struct list_head list;
char contents[PAGE_SIZE - sizeof(struct list_head)];
};
struct hppfs_private {
struct file *proc_file;
int host_fd;
loff_t len;
struct hppfs_data *contents;
};
struct hppfs_inode_info {
struct dentry *proc_dentry;
struct inode vfs_inode;
};
static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode)
{
return container_of(inode, struct hppfs_inode_info, vfs_inode);
}
#define HPPFS_SUPER_MAGIC 0xb00000ee
static struct super_operations hppfs_sbops;
static int is_pid(struct dentry *dentry)
{
struct super_block *sb;
int i;
sb = dentry->d_sb;
if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root))
return(0);
for(i = 0; i < dentry->d_name.len; i++){
if(!isdigit(dentry->d_name.name[i]))
return(0);
}
return(1);
}
static char *dentry_name(struct dentry *dentry, int extra)
{
struct dentry *parent;
char *root, *name;
const char *seg_name;
int len, seg_len;
len = 0;
parent = dentry;
while(parent->d_parent != parent){
if(is_pid(parent))
len += strlen("pid") + 1;
else len += parent->d_name.len + 1;
parent = parent->d_parent;
}
root = "proc";
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){
if(is_pid(parent)){
seg_name = "pid";
seg_len = strlen("pid");
}
else {
seg_name = parent->d_name.name;
seg_len = parent->d_name.len;
}
len -= seg_len + 1;
name[len] = '/';
strncpy(&name[len + 1], seg_name, seg_len);
parent = parent->d_parent;
}
strncpy(name, root, strlen(root));
return(name);
}
struct dentry_operations hppfs_dentry_ops = {
};
static int file_removed(struct dentry *dentry, const char *file)
{
char *host_file;
int extra, fd;
extra = 0;
if(file != NULL) extra += strlen(file) + 1;
host_file = dentry_name(dentry, extra + strlen("/remove"));
if(host_file == NULL){
printk("file_removed : allocation failed\n");
return(-ENOMEM);
}
if(file != NULL){
strcat(host_file, "/");
strcat(host_file, file);
}
strcat(host_file, "/remove");
fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
kfree(host_file);
if(fd > 0){
os_close_file(fd);
return(1);
}
return(0);
}
static void hppfs_read_inode(struct inode *ino)
{
struct inode *proc_ino;
if(HPPFS_I(ino)->proc_dentry == NULL)
return;
proc_ino = HPPFS_I(ino)->proc_dentry->d_inode;
ino->i_uid = proc_ino->i_uid;
ino->i_gid = proc_ino->i_gid;
ino->i_atime = proc_ino->i_atime;
ino->i_mtime = proc_ino->i_mtime;
ino->i_ctime = proc_ino->i_ctime;
ino->i_ino = proc_ino->i_ino;
ino->i_mode = proc_ino->i_mode;
ino->i_nlink = proc_ino->i_nlink;
ino->i_size = proc_ino->i_size;
ino->i_blksize = proc_ino->i_blksize;
ino->i_blocks = proc_ino->i_blocks;
}
static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
struct nameidata *nd)
{
struct dentry *proc_dentry, *new, *parent;
struct inode *inode;
int err, deleted;
deleted = file_removed(dentry, NULL);
if(deleted < 0)
return(ERR_PTR(deleted));
else if(deleted)
return(