[Envfs-commits] CVS: envfs/fs/envfs Makefile,NONE,1.1 dir.c,NONE,1.1 file.c,NONE,1.1 inode.c,NONE,1.
Status: Pre-Alpha
Brought to you by:
lethal
From: Paul M. <le...@us...> - 2001-09-19 03:01:47
|
Update of /cvsroot/envfs/envfs/fs/envfs In directory usw-pr-cvs1:/tmp/cvs-serv4903/fs/envfs Added Files: Makefile dir.c file.c inode.c super.c Log Message: Initial import of envfs sources, against 2.4.7. --- NEW FILE: Makefile --- # # Makefile for the Linux envfs filesystem routines. # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (not a .c file). # # Note 2! The CFLAGS definitions are now in the main makefile. O_TARGET := envfs.o obj-y := super.o inode.o dir.o file.o obj-m := $(O_TARGET) include $(TOPDIR)/Rules.make --- NEW FILE: dir.c --- /* * fs/envfs/dir.c * * envfs directory operations * * Copyright (C) 2001 Paul Mundt <le...@ch...> * * Released under the terms of the GNU GPL v2.0. * */ #include <linux/envfs_fs.h> static struct dentry *envfs_lookup(struct inode *dir, struct dentry *dentry) { envfs_debug("entering\n"); if (!dentry) goto out; if (!dentry->d_name.name) goto out; envfs_debug("dir->i_ino == %d\n", dir->i_ino); envfs_debug("dentry->d_name.name == %s\n", dentry->d_name.name); dentry->d_inode = envfs_get_inode(dir->i_sb, 0644 | S_IFREG, dir->i_dev); out: envfs_debug("leaving\n"); return NULL; } static int envfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev) { struct inode *inode = envfs_get_inode(dir->i_sb, mode, dev); envfs_debug("entering\n"); if (!inode) return -ENOSPC; dentry->d_inode = inode; envfs_debug("inode == %d\n", dentry->d_inode->i_ino); dentry->d_inode = inode; dget(dentry); envfs_debug("leaving\n"); return 0; } static int envfs_create(struct inode *dir, struct dentry *dentry, int mode) { envfs_debug("entering\n"); envfs_debug("dir->i_ino == %d\n", dir->i_ino); envfs_debug("leaving\n"); return envfs_mknod(dir, dentry, mode | S_IFREG, 0); } int envfs_create_by_name(const char *name, mode_t mode, struct dentry *parent, struct dentry **dentry) { struct qstr qstr; struct dentry *pdentry = parent; char *tmp; int ret = 0; envfs_debug("entering\n"); qstr.name = name; qstr.len = strlen(qstr.name); qstr.hash = full_name_hash(qstr.name, qstr.len); /* * FIXME: This is a hack.. for some odd reason, we get garbage * in the name when new environment variables are set. * * This check is just to ensure that we have a valid environment * variable before allocating an inode and setting up the dentry. */ tmp = envfs_getenv(qstr.name); if (!tmp) { ret = -EINVAL; goto out; } if (!pdentry) pdentry = envfs_find_sb_dentry(); if (!d_lookup(pdentry, &qstr)) { *dentry = d_alloc(pdentry, &qstr); ret = envfs_mknod(pdentry->d_inode, *dentry, mode, 0); } kfree(tmp); out: envfs_debug("leaving\n"); return ret; } static int envfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { struct dentry *dentry = filp->f_dentry; envfs_debug("entering\n"); envfs_debug("filp->f_pos == %d\n", filp->f_pos); if (!dentry) goto out; if (!dentry->d_inode || !dentry->d_parent) goto out; switch ((unsigned int)filp->f_pos) { case 0: if (filldir(dirent, ".", 1, filp->f_pos, dentry->d_inode->i_ino, DT_DIR) < 0) { break; } filp->f_pos++; case 1: if (filldir(dirent, "..", 2, filp->f_pos, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { break; } filp->f_pos++; default: envfs_getenv_vars(filp, dirent, filldir); break; } out: envfs_debug("leaving\n"); return 0; } struct file_operations envfs_dops = { read: generic_read_dir, readdir: envfs_readdir, }; struct inode_operations envfs_diops = { create: envfs_create, lookup: envfs_lookup, mknod: envfs_mknod, }; --- NEW FILE: file.c --- /* * fs/envfs/file.c * * envfs file operations * * Copyright (C) 2001 Paul Mundt <le...@ch...> * * Released under the terms of the GNU GPL v2.0. * */ #include <linux/slab.h> #include <linux/envfs_fs.h> #include <asm/uaccess.h> char *envfs_getenv_vars(struct file *filp, void *dirent, filldir_t filldir) { unsigned long currkey; struct dentry *dentry; char *buf, *opt; int i = 0; envfs_debug("entering\n"); buf = kmalloc(current->mm->env_end - current->mm->env_start, GFP_KERNEL); for (currkey = current->mm->env_start; currkey < current->mm->env_end; currkey++) { get_user(buf[i], (char *)currkey); if (buf[i] == ' '|| !buf[i] || buf[i] == '\t') buf[i] = '|'; i++; } for (i = 0; i < filp->f_pos - 2; i++) { strsep(&buf, "|"); } opt = strsep(&buf, "="); if (!*opt) goto out; if (envfs_create_by_name(opt, 0755 | S_IFREG, NULL, &dentry) == -EINVAL) goto out; if (filldir(dirent, dentry->d_name.name, dentry->d_name.len, filp->f_pos, dentry->d_inode->i_ino, DT_UNKNOWN) < 0) goto out; filp->f_pos++; out: kfree(buf); envfs_debug("leaving\n"); return NULL; } char *envfs_getenv(const char *key) { unsigned long currkey; char *buf, c; int i, match, len; envfs_debug("entering\n"); i = 1; match = 0; len = strlen(key) + 1; buf = kmalloc(ENVFS_MAX_ENVLEN, GFP_KERNEL); for (currkey = current->mm->env_start; currkey < current->mm->env_end; currkey++) { get_user(c, (char *)currkey); if (match) { if (i == (ENVFS_MAX_ENVLEN - 1)) c = '\0'; buf[i] = c; if (!c || c == ' ' || c == '\t') { if (i) { buf[i] = '\n'; buf[i+1] = '\0'; envfs_debug("leaving: 0\n"); return ++buf; } i = 0; } else { i++; } if (!c) break; continue; } if ((!i && !c) || (i && c == key[i - 1])) { i++; } else { i = 0; } if (i == len) { match = 1; i = 0; } } kfree(buf); envfs_debug("leaving: 1\n"); return NULL; } static ssize_t envfs_read_file(struct file *filp, char *buf, size_t count, loff_t *ppos) { char *tmpbuf; envfs_debug("entering\n"); tmpbuf = envfs_getenv((char *)filp->f_dentry->d_name.name); if (!tmpbuf) { kfree(tmpbuf); envfs_debug("leaving\n"); return 0; } if (count + *ppos > strlen(tmpbuf)) count = strlen(tmpbuf) - *ppos; copy_to_user(buf, tmpbuf + *ppos, count); *ppos += count; kfree(tmpbuf); envfs_debug("leaving\n"); return count; } struct file_operations envfs_fops = { read: envfs_read_file, mmap: generic_file_mmap, }; --- NEW FILE: inode.c --- /* * fs/envfs/inode.c * * envfs inode operations * * Copyright (C) 2001 Paul Mundt <le...@ch...> * * Released under the terms of the GNU GPL v2.0. * */ #include <linux/locks.h> #include <linux/envfs_fs.h> void envfs_read_inode(struct inode *inode) { inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; } struct inode *envfs_get_inode(struct super_block *sb, int mode, int dev) { struct inode *inode = new_inode(sb); envfs_debug("entering\n"); if (!inode) return NULL; inode->i_mode = mode; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; inode->i_rdev = NODEV; inode->i_mapping->a_ops = &envfs_aops; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; /* * FIXME: This is a hack to force everything into a read-only state. * Since we don't currently support writing to or creating new * environment variables. */ inode->i_flags |= S_IMMUTABLE; switch (mode & S_IFMT) { case S_IFREG: inode->i_fop = &envfs_fops; break; case S_IFDIR: inode->i_op = &envfs_diops; inode->i_fop = &envfs_dops; break; default: init_special_inode(inode, mode, dev); break; } envfs_debug("leaving\n"); return inode; } struct address_space_operations envfs_aops = { /* Left empty intentionally */ }; --- NEW FILE: super.c --- /* * fs/envfs/super.c * * envfs superblock operations * * Copyright (C) 2001 Paul Mundt <le...@ch...> * * Released under the terms of the GNU GPL v2.0. * */ #include <linux/module.h> #include <linux/init.h> #include <linux/pagemap.h> #include <linux/envfs_fs.h> static struct vfsmount *envfs_mnt; static int envfs_statfs(struct super_block *sb, struct statfs *buf) { envfs_debug("entering\n"); buf->f_type = ENVFS_SUPER_MAGIC; buf->f_bsize = PAGE_CACHE_SIZE; buf->f_namelen = NAME_MAX; envfs_debug("leaving\n"); return 0; } struct dentry *envfs_find_sb_dentry(void) { struct super_block *sb; struct list_head *list; envfs_debug("entering\n"); list_for_each(list, &super_blocks) { sb = sb_entry(list); if (sb->s_magic == ENVFS_SUPER_MAGIC) { envfs_debug("leaving: 0\n"); return sb->s_root; } } envfs_debug("leaving: 1\n"); return NULL; } static struct super_operations envfs_sops = { statfs: envfs_statfs, put_inode: force_delete, read_inode: envfs_read_inode, }; static struct super_block *envfs_read_super(struct super_block *sb, void *data, int silent) { struct inode *root_inode; envfs_debug("entering\n"); sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = ENVFS_SUPER_MAGIC; sb->s_op = &envfs_sops; root_inode = envfs_get_inode(sb, S_IFDIR | 0755, 0); if (!root_inode) return NULL; sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) { iput(root_inode); return NULL; } envfs_debug("leaving\n"); return sb; } static DECLARE_FSTYPE(envfs_fs_type, "envfs", envfs_read_super, FS_SINGLE); static int __init init_envfs_fs(void) { int ret = register_filesystem(&envfs_fs_type); if (!ret) { envfs_mnt = kern_mount(&envfs_fs_type); ret = PTR_ERR(envfs_mnt); if (!IS_ERR(envfs_mnt)) ret = 0; } return ret; } static void __exit exit_envfs_fs(void) { kern_umount(envfs_mnt); unregister_filesystem(&envfs_fs_type); } EXPORT_NO_SYMBOLS; MODULE_AUTHOR("Paul Mundt <le...@ch...>"); MODULE_DESCRIPTION("/env file system"); module_init(init_envfs_fs); module_exit(exit_envfs_fs); |