Import 2.3.9pre5
[davej-history.git] / fs / proc / sysvipc.c
blob7fff0ed0320818c31867270528b1bdcfebe9241c
1 /*
2 * linux/fs/proc/sysvipc.c
4 * Copyright (c) 1999 Dragos Acostachioaie
6 * This code is derived from linux/fs/proc/generic.c,
7 * which is Copyright (C) 1991, 1992 Linus Torvalds.
9 * /proc/sysvipc directory handling functions
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/proc_fs.h>
14 #include <linux/stat.h>
15 #include <linux/mm.h>
17 #include <asm/uaccess.h>
19 #ifndef MIN
20 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
21 #endif
23 /* 4K page size but our output routines use some slack for overruns */
24 #define PROC_BLOCK_SIZE (3*1024)
26 static ssize_t
27 proc_sysvipc_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
29 struct inode * inode = file->f_dentry->d_inode;
30 char *page;
31 ssize_t retval=0;
32 int eof=0;
33 ssize_t n, count;
34 char *start;
35 struct proc_dir_entry * dp;
37 dp = (struct proc_dir_entry *) inode->u.generic_ip;
38 if (!(page = (char*) __get_free_page(GFP_KERNEL)))
39 return -ENOMEM;
41 while ((nbytes > 0) && !eof)
43 count = MIN(PROC_BLOCK_SIZE, nbytes);
45 start = NULL;
46 if (dp->get_info) {
48 * Handle backwards compatibility with the old net
49 * routines.
51 * XXX What gives with the file->f_flags & O_ACCMODE
52 * test? Seems stupid to me....
54 n = dp->get_info(page, &start, *ppos, count,
55 (file->f_flags & O_ACCMODE) == O_RDWR);
56 if (n < count)
57 eof = 1;
58 } else if (dp->read_proc) {
59 n = dp->read_proc(page, &start, *ppos,
60 count, &eof, dp->data);
61 } else
62 break;
64 if (!start) {
66 * For proc files that are less than 4k
68 start = page + *ppos;
69 n -= *ppos;
70 if (n <= 0)
71 break;
72 if (n > count)
73 n = count;
75 if (n == 0)
76 break; /* End of file */
77 if (n < 0) {
78 if (retval == 0)
79 retval = n;
80 break;
83 /* This is a hack to allow mangling of file pos independent
84 * of actual bytes read. Simply place the data at page,
85 * return the bytes, and set `start' to the desired offset
86 * as an unsigned int. - Paul.Russell@rustcorp.com.au
88 n -= copy_to_user(buf, start < page ? page : start, n);
89 if (n == 0) {
90 if (retval == 0)
91 retval = -EFAULT;
92 break;
95 *ppos += start < page ? (long)start : n; /* Move down the file */
96 nbytes -= n;
97 buf += n;
98 retval += n;
100 free_page((unsigned long) page);
101 return retval;
104 static struct file_operations proc_sysvipc_operations = {
105 NULL, /* lseek */
106 proc_sysvipc_read, /* read */
107 NULL, /* write */
108 NULL, /* readdir */
109 NULL, /* poll */
110 NULL, /* ioctl */
111 NULL, /* mmap */
112 NULL, /* no special open code */
113 NULL, /* no special release code */
114 NULL /* can't fsync */
118 * proc directories can do almost nothing..
120 struct inode_operations proc_sysvipc_inode_operations = {
121 &proc_sysvipc_operations, /* default net file-ops */
122 NULL, /* create */
123 NULL, /* lookup */
124 NULL, /* link */
125 NULL, /* unlink */
126 NULL, /* symlink */
127 NULL, /* mkdir */
128 NULL, /* rmdir */
129 NULL, /* mknod */
130 NULL, /* rename */
131 NULL, /* readlink */
132 NULL, /* follow_link */
133 NULL, /* get_block */
134 NULL, /* readpage */
135 NULL, /* writepage */
136 NULL, /* flushpage */
137 NULL, /* truncate */
138 NULL, /* permission */
139 NULL, /* smap */
140 NULL /* revalidate */