diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 14:08:29 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 14:08:29 +0000 |
commit | 57d569635c05dc4ea9b9f1f8dcec69b9ddc989b2 (patch) | |
tree | 1f703abf7d95dcd50ee52da3b96eb1b4b2b4ea53 /fs/proc | |
parent | 59223edaa18759982db0a8aced0e77457d10c68e (diff) |
The rest of 2.3.6.
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/sysvipc.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/fs/proc/sysvipc.c b/fs/proc/sysvipc.c new file mode 100644 index 000000000..eab3e3186 --- /dev/null +++ b/fs/proc/sysvipc.c @@ -0,0 +1,138 @@ +/* + * linux/fs/proc/sysvipc.c + * + * Copyright (c) 1999 Dragos Acostachioaie + * + * This code is derived from linux/fs/proc/generic.c, + * which is Copyright (C) 1991, 1992 Linus Torvalds. + * + * /proc/sysvipc directory handling functions + */ +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/proc_fs.h> +#include <linux/stat.h> +#include <linux/mm.h> + +#include <asm/uaccess.h> + +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +/* 4K page size but our output routines use some slack for overruns */ +#define PROC_BLOCK_SIZE (3*1024) + +static ssize_t +proc_sysvipc_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) +{ + struct inode * inode = file->f_dentry->d_inode; + char *page; + ssize_t retval=0; + int eof=0; + ssize_t n, count; + char *start; + struct proc_dir_entry * dp; + + dp = (struct proc_dir_entry *) inode->u.generic_ip; + if (!(page = (char*) __get_free_page(GFP_KERNEL))) + return -ENOMEM; + + while ((nbytes > 0) && !eof) + { + count = MIN(PROC_BLOCK_SIZE, nbytes); + + start = NULL; + if (dp->get_info) { + /* + * Handle backwards compatibility with the old net + * routines. + * + * XXX What gives with the file->f_flags & O_ACCMODE + * test? Seems stupid to me.... + */ + n = dp->get_info(page, &start, *ppos, count, + (file->f_flags & O_ACCMODE) == O_RDWR); + if (n < count) + eof = 1; + } else if (dp->read_proc) { + n = dp->read_proc(page, &start, *ppos, + count, &eof, dp->data); + } else + break; + + if (!start) { + /* + * For proc files that are less than 4k + */ + start = page + *ppos; + n -= *ppos; + if (n <= 0) + break; + if (n > count) + n = count; + } + if (n == 0) + break; /* End of file */ + if (n < 0) { + if (retval == 0) + retval = n; + break; + } + + /* This is a hack to allow mangling of file pos independent + * of actual bytes read. Simply place the data at page, + * return the bytes, and set `start' to the desired offset + * as an unsigned int. - Paul.Russell@rustcorp.com.au + */ + n -= copy_to_user(buf, start < page ? page : start, n); + if (n == 0) { + if (retval == 0) + retval = -EFAULT; + break; + } + + *ppos += start < page ? (long)start : n; /* Move down the file */ + nbytes -= n; + buf += n; + retval += n; + } + free_page((unsigned long) page); + return retval; +} + +static struct file_operations proc_sysvipc_operations = { + NULL, /* lseek */ + proc_sysvipc_read, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + 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_sysvipc_inode_operations = { + &proc_sysvipc_operations, /* default net file-ops */ + NULL, /* create */ + NULL, /* 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 */ +}; |