lkml.org 
[lkml]   [1997]   [Dec]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Conditional SymLinks
Hello,

I have labored to produce another "proof of concept" patch. This time
environment variables are symlinks in the /proc filesystem. This looks
nicer, but is unfortunately actually less usefull than my previous proof of
concept. Much less actually. I didn't know what the hell I was talking
about in my last message on the subject. Can I claim temporary stupidity? =)

Anyway this 4-5 hour waste of time is yours to peruse. It makes a new
directory in the /proc/<pid> directories called "env", where all the
environment variables are symlinks to the data, so you get nice links like:

> tree /proc/12/env/
/proc/12/env
|-- AUTOBOOT -> YES
|-- BOOT_IMAGE -> Linux
|-- CONSOLE -> /dev/console
|-- HOME -> /
|-- HOSTTYPE -> i386
|-- INIT_VERSION -> sysvinit-2.69
|-- OSTYPE -> Linux
|-- PATH -> /sbin:/usr/sbin:/bin:/usr/bin
|-- PREVLEVEL -> N
|-- RUNLEVEL -> S
|-- SHELL -> /bin/tcsh
|-- SHLVL -> 1
|-- TERM -> linux
`-- _ -> /sbin/update

Nice, but pretty useless. A /cond filesystem wouldn't work very well,
unless a special case were made for sym-links entering /cond, where /cond
essentually expands links much the same way my previous patch did.

You can at least do:

/tmp -> /proc/self/env/HOME/tmp

and expect it to work reasonably well, except in the cases where HOME
isn't defined, points to /, etc...

I guess the only real way to do it would be the way my first proof of
concept worked, but cleaned up and expanded upon I suppose. It also means
that conditional sym-links haven't got a chance of getting in the kernel.

Oh, one final note. The /proc/<pid>/* directory uses 8 bits when it only
really needs 4, those extra 4 bits would let you display up to 4096 file
descriptors in the /proc/<pid>/fd directory instead of 256. If there is a
case for 48 or 64 bit inodes, /proc is it. That and inodeless filesystems.

- Steve

.------------------------------------------------. # * # # # # # #
| Steve Baker | Barely Working | # ## # # # # #
| ice@mama.indstate.edu | System Administrator | # # # # # # # #
| Red-Hat Rulz! | Will work for hardware | # # # ## # # # #
`-- SYS-ADMIN FOR HIRE, HAVE UNIX, WILL TRAVEL --' #### # # # ## # #


diff -u -N --recursive linux-2.0.32/fs/proc/Makefile linux/fs/proc/Makefile
--- linux-2.0.32/fs/proc/Makefile Thu Jan 18 00:06:17 1996
+++ linux/fs/proc/Makefile Tue Dec 16 13:31:55 1997
@@ -8,7 +8,7 @@
# Note 2! The CFLAGS definitions are now in the main makefile...

O_TARGET := proc.o
-O_OBJS := inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o scsi.o
+O_OBJS := inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o scsi.o env.o
OX_OBJS := procfs_syms.o
M_OBJS := $(O_TARGET)

diff -u -N --recursive linux-2.0.32/fs/proc/array.c linux/fs/proc/array.c
--- linux-2.0.32/fs/proc/array.c Sun Aug 3 15:59:07 1997
+++ linux/fs/proc/array.c Wed Dec 17 14:26:48 1997
@@ -332,7 +332,7 @@
return NULL;
}

-static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
+unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr)
{
pgd_t *page_dir;
pmd_t *page_middle;
@@ -362,7 +362,7 @@
return pte_page(pte) + (ptr & ~PAGE_MASK);
}

-static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
+int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
{
unsigned long addr;
int size = 0, result = 0;
diff -u -N --recursive linux-2.0.32/fs/proc/base.c linux/fs/proc/base.c
--- linux-2.0.32/fs/proc/base.c Wed Feb 21 04:26:09 1996
+++ linux/fs/proc/base.c Tue Dec 16 13:26:37 1997
@@ -125,6 +125,12 @@
NULL, proc_pid_fill_inode,
});
proc_register(&proc_pid, &(struct proc_dir_entry) {
+ PROC_PID_ENV, 3, "env",
+ S_IFDIR | S_IRUSR | S_IXUSR, 1, 0, 0,
+ 0, &proc_env_inode_operations,
+ NULL, proc_pid_fill_inode,
+ });
+ proc_register(&proc_pid, &(struct proc_dir_entry) {
PROC_PID_CMDLINE, 7, "cmdline",
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations,
diff -u -N --recursive linux-2.0.32/fs/proc/env.c linux/fs/proc/env.c
--- linux-2.0.32/fs/proc/env.c Wed Dec 31 18:00:00 1969
+++ linux/fs/proc/env.c Thu Dec 18 13:06:09 1997
@@ -0,0 +1,361 @@
+/*
+ * linux/fs/proc/env.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * proc env directory handling functions
+ */
+
+#include <asm/segment.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+
+
+static int proc_readenv(struct inode *, struct file *, void *, filldir_t);
+static int proc_lookupenv(struct inode *,const char *,int,struct inode **);
+static int proc_env_followlink(struct inode *, struct inode *, int, int,
+ struct inode **);
+static int proc_env_readlink(struct inode *, char *, int);
+
+unsigned long get_phys_addr(struct task_struct *, unsigned long);
+int get_array(struct task_struct **, unsigned long, unsigned long, char *);
+
+
+static struct file_operations proc_env_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read - bad */
+ NULL, /* write - bad */
+ proc_readenv, /* readdir */
+ NULL, /* select - default */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+struct inode_operations proc_env_inode_operations = {
+ &proc_env_operations, /* default base directory file-ops */
+ NULL, /* create */
+ proc_lookupenv, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
+
+static struct file_operations proc_env_link_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read - bad */
+ NULL, /* write - bad */
+ NULL, /* readdir */
+ NULL, /* select - default */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+};
+
+struct inode_operations proc_env_link_inode_operations = {
+ &proc_env_link_operations, /* default base directory file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ proc_env_readlink, /* readlink */
+ proc_env_followlink, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
+
+static int proc_lookupenv(struct inode * dir, const char * name, int len,
+ struct inode ** result)
+{
+ char *env_buf, *env_end, *es, *ee;
+ unsigned int ino, pid, ep, envlen;
+ struct task_struct * p;
+ struct super_block * sb;
+ int i;
+
+ *result = NULL;
+ ino = dir->i_ino;
+ pid = ino >> 16;
+ ino &= 0x0000ffff;
+ if (!dir)
+ return -ENOENT;
+ sb = dir->i_sb;
+ if (!pid || ino != PROC_PID_ENV || !S_ISDIR(dir->i_mode)) {
+ iput(dir);
+ return -ENOENT;
+ }
+ if (!len || (name[0] == '.' && (len == 1 ||
+ (name[1] == '.' && len == 2)))) {
+ if (len < 2) {
+ *result = dir;
+ return 0;
+ }
+ if (!(*result = proc_get_inode(sb, (pid << 16)+PROC_PID_INO, &proc_pid))) {
+ iput(dir);
+ return -ENOENT;
+ }
+ iput(dir);
+ return 0;
+ }
+ iput(dir);
+
+ for (i = 0 ; i < NR_TASKS ; i++)
+ if ((p = task[i]) && p->pid == pid)
+ break;
+ if (!pid || i >= NR_TASKS)
+ return -ENOENT;
+
+ ep = 0;
+ env_buf = vmalloc((p->mm->env_end - p->mm->env_start) +1);
+ if (!env_buf) return -ENOENT;
+ envlen = get_array(&p,p->mm->env_start,p->mm->env_end,env_buf);
+ if (!envlen) {
+ vfree(env_buf);
+ return -ENOENT;
+ }
+ env_end = env_buf+envlen;
+
+ for(ep=0, es=env_buf; es < env_end; ep++,es++) {
+ for(ee=es+1; ee < env_end && *ee != '=' && *ee; ee++);
+
+ if (!*ee || ee >= env_end) {
+ vfree(env_buf);
+ return -ENOENT;
+ }
+ if (!strncmp(name,es,ee-es)) break;
+
+ for(es=ee+1;es < env_end && *es; es++);
+ }
+ vfree(env_buf);
+
+ ino = (pid << 16) + (PROC_PID_ENV_DIR << 8) + ep;
+
+ if (!(*result = proc_get_inode(sb, ino, NULL)))
+ return -ENOENT;
+ return 0;
+}
+
+static int proc_readenv(struct inode * inode, struct file * filp,
+ void * dirent, filldir_t filldir)
+{
+ char *env_buf, *env_end, *es, *ee;
+ int task_nr;
+ struct task_struct * p;
+ unsigned int envlen, ep, pid, ino, i;
+
+ if (!inode || !S_ISDIR(inode->i_mode))
+ return -EBADF;
+ ino = inode->i_ino;
+ pid = ino >> 16;
+ ino &= 0x0000ffff;
+ if (ino != PROC_PID_ENV)
+ return 0;
+
+ for (ep = filp->f_pos; ep < 2; ep++, filp->f_pos++) {
+ unsigned long ino = inode->i_ino;
+ if (ep)
+ ino = (ino & 0xffff0000) | PROC_PID_INO;
+ if (filldir(dirent, "..", ep+1, ep, ino) < 0)
+ return 0;
+ }
+
+ task_nr = 1;
+ for (;;) {
+ if ((p = task[task_nr]) && p->pid == pid)
+ break;
+ if (++task_nr >= NR_TASKS)
+ return 0;
+ }
+
+ env_buf = vmalloc((p->mm->env_end - p->mm->env_start) +1);
+ if (!env_buf) return 0;
+ envlen = get_array(&p,p->mm->env_start,p->mm->env_end,env_buf);
+ if (!envlen) {
+ vfree(env_buf);
+ return 0;
+ }
+ env_end = env_buf+envlen;
+
+ for (es=env_buf, ep -= 2, i=0; es < env_end && i < ep; i++, es++) {
+ while(es < env_end && es) es++;
+ }
+ if (es >= env_end) return 0;
+
+ for (; es < env_end; ep++, filp->f_pos++, es++) {
+ for(ee=es+1; ee < env_end && *ee != '=' && *ee; ee++);
+
+ if (!*ee || ee >= env_end) break;
+
+ ino = (pid << 16) + (PROC_PID_ENV_DIR << 8) + ep;
+ if (filldir(dirent, es, ee-es, ep+2, ino) < 0)
+ break;
+
+ /* filldir() might have slept, so we must re-validate "p" */
+ if (p != task[task_nr] || p->pid != pid)
+ break;
+
+ for(es=ee+1; es < env_end && *es; es++);
+ }
+ if (env_buf) vfree(env_buf);
+ return 0;
+}
+
+static int proc_env_followlink(struct inode * dir, struct inode * inode,
+ int flag, int mode, struct inode ** res_inode)
+{
+ int error, task_nr;
+ unsigned int ino, pid, envlen;
+ char * link, *env_buf, *env_end, *es, *ee;
+ struct task_struct * p;
+
+ *res_inode = NULL;
+ if (!dir) {
+ dir = current->fs->root;
+ dir->i_count++;
+ }
+ if (!inode) {
+ iput (dir);
+ return -ENOENT;
+ }
+
+ ino = inode->i_ino;
+ pid = ino >> 16;
+ ino &= 0x0000ffff;
+ if (ino>>8 != PROC_PID_ENV_DIR) return -ENOENT;
+ ino &= 0x000000ff;
+
+ if (current->link_count > 5) {
+ iput (dir);
+ iput (inode);
+ return -ELOOP;
+ }
+
+ task_nr = 1;
+ for (;;) {
+ if ((p = task[task_nr]) && p->pid == pid)
+ break;
+ if (++task_nr >= NR_TASKS)
+ return -ENOENT;
+ }
+
+ env_buf = vmalloc((p->mm->env_end - p->mm->env_start) +1);
+ if (!env_buf) return -ENOENT;
+ envlen = get_array(&p,p->mm->env_start,p->mm->env_end,env_buf);
+ if (!envlen) {
+ vfree(env_buf);
+ return -ENOENT;
+ }
+ env_end = env_buf+envlen;
+
+ for(es=env_buf;es < env_end && ino; ino--, es++) {
+ while(es < env_end && *es) es++;
+ }
+
+ while(es < env_end && *es != '=' && *es) es++;
+
+ if (es >= env_end || !*es) {
+ vfree(env_buf);
+ return -ENOENT;
+ }
+
+ for(ee=++es; ee<env_end && *ee; ee++);
+
+ link = vmalloc((ee-es)+2);
+ strncpy(link,es,(ee-es));
+ link[ee-es] = 0;
+
+ current->link_count++;
+ error = open_namei (link, flag, mode, res_inode, dir);
+ current->link_count--;
+ iput (inode);
+ vfree(link);
+ vfree(env_buf);
+ return error;
+}
+
+static int proc_env_readlink(struct inode * inode, char * buffer, int buflen)
+{
+ int len, task_nr;
+ unsigned int ino, pid, envlen;
+ char *env_buf, *env_end, *es, *ee;
+ struct task_struct * p;
+
+ iput(inode);
+
+ ino = inode->i_ino;
+ pid = ino >> 16;
+ ino &= 0x0000ffff;
+ if (ino>>8 != PROC_PID_ENV_DIR) return -EINVAL;
+ ino &= 0x000000ff;
+
+ task_nr = 1;
+ for (;;) {
+ if ((p = task[task_nr]) && p->pid == pid)
+ break;
+ if (++task_nr >= NR_TASKS)
+ return -ENOENT;
+ }
+
+ env_buf = vmalloc((p->mm->env_end - p->mm->env_start) +1);
+ if (!env_buf) return -ENOENT;
+ envlen = get_array(&p,p->mm->env_start,p->mm->env_end,env_buf);
+ if (!envlen) {
+ vfree(env_buf);
+ return -EINVAL;
+ }
+ env_end = env_buf+envlen;
+
+ for(es=env_buf;(es < env_end) && ino; ino--, es++)
+ while(es < env_end && *es) es++;
+
+ while(es < env_end && *es != '=' && *es) es++;
+
+ if (es >= env_end || !*es) {
+ vfree(env_buf);
+ return -ENOENT;
+ }
+
+ for(ee=++es; ee<env_end && *ee; ee++);
+
+ len = (ee-es)+1;
+ if (buflen > len) buflen = len;
+
+ for(;buflen && es < ee;buflen--,es++)
+ put_user(*es,buffer++);
+
+ if (buflen) put_user(0,buffer);
+
+ vfree(env_buf);
+ return len;
+}
diff -u -N --recursive linux-2.0.32/fs/proc/inode.c linux/fs/proc/inode.c
--- linux-2.0.32/fs/proc/inode.c Sat Nov 1 15:31:17 1997
+++ linux/fs/proc/inode.c Thu Dec 18 11:07:38 1997
@@ -221,6 +221,11 @@
inode->i_mode = S_IFREG | S_IRUSR;
inode->i_op = &proc_array_inode_operations;
return;
+ case PROC_PID_ENV:
+ inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
+ inode->i_op = &proc_env_inode_operations;
+ inode->i_nlink = 2;
+ return;
case PROC_PID_CMDLINE:
case PROC_PID_STATUS:
case PROC_PID_STAT:
@@ -245,6 +250,13 @@
inode->i_mode |= S_IRUSR | S_IXUSR;
if (p->files->fd[ino]->f_mode & 2)
inode->i_mode |= S_IWUSR | S_IXUSR;
+ return;
+ case PROC_PID_ENV_DIR:
+ ino &= 0xff;
+ if (ino > 254) return;
+ inode->i_op = &proc_env_link_inode_operations;
+ inode->i_size = 1024;
+ inode->i_mode = S_IFLNK | S_IRUSR | S_IXUSR;
return;
}
return;
diff -u -N --recursive linux-2.0.32/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- linux-2.0.32/include/linux/proc_fs.h Thu Nov 13 19:12:35 1997
+++ linux/include/linux/proc_fs.h Wed Dec 17 16:14:48 1997
@@ -58,11 +58,13 @@
PROC_PID_CMDLINE,
PROC_PID_STAT,
PROC_PID_STATM,
- PROC_PID_MAPS
+ PROC_PID_MAPS,
+ PROC_PID_ENV
};

enum pid_subdirectory_inos {
- PROC_PID_FD_DIR = 1
+ PROC_PID_FD_DIR = 1,
+ PROC_PID_ENV_DIR
};

enum net_directory_inos {
@@ -283,5 +285,6 @@
extern struct inode_operations proc_kmsg_inode_operations;
extern struct inode_operations proc_link_inode_operations;
extern struct inode_operations proc_fd_inode_operations;
-
+extern struct inode_operations proc_env_inode_operations;
+extern struct inode_operations proc_env_link_inode_operations;
#endif
\
 
 \ /
  Last update: 2005-03-22 13:40    [W:0.459 / U:0.076 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site