2 * proc/fs/generic.c --- generic routines for the proc-fs
4 * This file contains generic proc-fs routines for handling
5 * directories and files.
7 * Copyright (C) 1991, 1992 Linus Torvalds.
8 * Copyright (C) 1997 Theodore Ts'o
11 #include <asm/uaccess.h>
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/proc_fs.h>
16 #include <linux/stat.h>
17 #include <asm/bitops.h>
19 extern struct inode_operations proc_dyna_dir_inode_operations
;
21 static ssize_t
proc_file_read(struct file
* file
, char * buf
,
22 size_t nbytes
, loff_t
*ppos
);
23 static ssize_t
proc_file_write(struct file
* file
, const char * buffer
,
24 size_t count
, loff_t
*ppos
);
25 static long long proc_file_lseek(struct file
*, long long, int);
27 int proc_match(int len
, const char *name
,struct proc_dir_entry
* de
)
29 if (!de
|| !de
->low_ino
)
31 if (de
->namelen
!= len
)
33 return !memcmp(name
, de
->name
, len
);
36 static struct file_operations proc_file_operations
= {
37 proc_file_lseek
, /* lseek */
38 proc_file_read
, /* read */
39 proc_file_write
, /* write */
44 NULL
, /* no special open code */
46 NULL
, /* no special release code */
47 NULL
/* can't fsync */
50 struct inode_operations proc_file_inode_operations
= {
51 &proc_file_operations
, /* default proc file-ops */
62 NULL
, /* follow_link */
71 * compatibility to replace fs/proc/net.c
73 struct inode_operations proc_net_inode_operations
= {
74 &proc_file_operations
, /* default net file-ops */
85 NULL
, /* follow_link */
95 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
98 /* 4K page size but our output routines use some slack for overruns */
99 #define PROC_BLOCK_SIZE (3*1024)
102 proc_file_read(struct file
* file
, char * buf
, size_t nbytes
, loff_t
*ppos
)
104 struct inode
* inode
= file
->f_dentry
->d_inode
;
110 struct proc_dir_entry
* dp
;
112 dp
= (struct proc_dir_entry
*) inode
->u
.generic_ip
;
113 if (!(page
= (char*) __get_free_page(GFP_KERNEL
)))
116 while ((nbytes
> 0) && !eof
)
118 count
= MIN(PROC_BLOCK_SIZE
, nbytes
);
123 * Handle backwards compatibility with the old net
126 * XXX What gives with the file->f_flags & O_ACCMODE
127 * test? Seems stupid to me....
129 n
= dp
->get_info(page
, &start
, *ppos
, count
,
130 (file
->f_flags
& O_ACCMODE
) == O_RDWR
);
133 } else if (dp
->read_proc
) {
134 n
= dp
->read_proc(page
, &start
, *ppos
,
135 count
, &eof
, dp
->data
);
141 * For proc files that are less than 4k
143 start
= page
+ *ppos
;
151 break; /* End of file */
158 /* This is a hack to allow mangling of file pos independent
159 * of actual bytes read. Simply place the data at page,
160 * return the bytes, and set `start' to the desired offset
161 * as an unsigned int. - Paul.Russell@rustcorp.com.au
163 n
-= copy_to_user(buf
, start
< page
? page
: start
, n
);
170 *ppos
+= start
< page
? (long)start
: n
; /* Move down the file */
175 free_page((unsigned long) page
);
180 proc_file_write(struct file
* file
, const char * buffer
,
181 size_t count
, loff_t
*ppos
)
183 struct inode
*inode
= file
->f_dentry
->d_inode
;
184 struct proc_dir_entry
* dp
;
186 dp
= (struct proc_dir_entry
*) inode
->u
.generic_ip
;
191 /* FIXME: does this routine need ppos? probably... */
192 return dp
->write_proc(file
, buffer
, count
, dp
->data
);
197 proc_file_lseek(struct file
* file
, long long offset
, int orig
)
201 file
->f_pos
= offset
;
204 file
->f_pos
+= offset
;
214 * This function parses a name such as "tty/driver/serial", and
215 * returns the struct proc_dir_entry for "/proc/tty/driver", and
216 * returns "serial" in residual.
218 static int xlate_proc_name(const char *name
,
219 struct proc_dir_entry
**ret
, const char **residual
)
221 const char *cp
= name
, *next
;
222 struct proc_dir_entry
*de
;
227 next
= strchr(cp
, '/');
232 for (de
= de
->subdir
; de
; de
= de
->next
) {
233 if (proc_match(len
, cp
, de
))
245 struct proc_dir_entry
*create_proc_entry(const char *name
, mode_t mode
,
246 struct proc_dir_entry
*parent
)
248 struct proc_dir_entry
*ent
= NULL
;
249 const char *fn
= name
;
252 if (!parent
&& xlate_proc_name(name
, &parent
, &fn
) != 0)
256 ent
= kmalloc(sizeof(struct proc_dir_entry
) + len
+ 1, GFP_KERNEL
);
259 memset(ent
, 0, sizeof(struct proc_dir_entry
));
260 memcpy(((char *) ent
) + sizeof(*ent
), fn
, len
+ 1);
261 ent
->name
= ((char *) ent
) + sizeof(*ent
);
265 if ((mode
& S_IALLUGO
) == 0)
266 mode
|= S_IRUGO
| S_IXUGO
;
267 ent
->ops
= &proc_dyna_dir_inode_operations
;
270 if ((mode
& S_IFMT
) == 0)
272 if ((mode
& S_IALLUGO
) == 0)
278 proc_register(parent
, ent
);
284 extern void free_proc_entry(struct proc_dir_entry
*);
285 void free_proc_entry(struct proc_dir_entry
*de
)
287 int ino
= de
->low_ino
;
289 if (ino
>= PROC_DYNAMIC_FIRST
&&
290 ino
< PROC_DYNAMIC_FIRST
+PROC_NDYNAMIC
)
295 * Remove a /proc entry and free it if it's not currently in use.
296 * If it is in use, we set the 'deleted' flag.
298 void remove_proc_entry(const char *name
, struct proc_dir_entry
*parent
)
300 struct proc_dir_entry
*de
;
301 const char *fn
= name
;
304 if (!parent
&& xlate_proc_name(name
, &parent
, &fn
) != 0)
308 for (de
= parent
->subdir
; de
; de
= de
->next
) {
309 if (proc_match(len
, fn
, de
))
314 proc_unregister(parent
, de
->low_ino
);
320 printk("remove_proc_entry: %s/%s busy, count=%d\n",
321 parent
->name
, de
->name
, de
->count
);