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 */
68 NULL
, /* permission */
74 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
77 /* 4K page size but our output routines use some slack for overruns */
78 #define PROC_BLOCK_SIZE (3*1024)
81 proc_file_read(struct file
* file
, char * buf
, size_t nbytes
, loff_t
*ppos
)
83 struct inode
* inode
= file
->f_dentry
->d_inode
;
89 struct proc_dir_entry
* dp
;
91 dp
= (struct proc_dir_entry
*) inode
->u
.generic_ip
;
92 if (!(page
= (char*) __get_free_page(GFP_KERNEL
)))
95 while ((nbytes
> 0) && !eof
)
97 count
= MIN(PROC_BLOCK_SIZE
, nbytes
);
102 * Handle backwards compatibility with the old net
105 * XXX What gives with the file->f_flags & O_ACCMODE
106 * test? Seems stupid to me....
108 n
= dp
->get_info(page
, &start
, *ppos
, count
,
109 (file
->f_flags
& O_ACCMODE
) == O_RDWR
);
112 } else if (dp
->read_proc
) {
113 n
= dp
->read_proc(page
, &start
, *ppos
,
114 count
, &eof
, dp
->data
);
120 * For proc files that are less than 4k
122 start
= page
+ *ppos
;
130 break; /* End of file */
137 /* This is a hack to allow mangling of file pos independent
138 * of actual bytes read. Simply place the data at page,
139 * return the bytes, and set `start' to the desired offset
140 * as an unsigned int. - Paul.Russell@rustcorp.com.au
142 n
-= copy_to_user(buf
, start
< page
? page
: start
, n
);
149 *ppos
+= start
< page
? (long)start
: n
; /* Move down the file */
154 free_page((unsigned long) page
);
159 proc_file_write(struct file
* file
, const char * buffer
,
160 size_t count
, loff_t
*ppos
)
162 struct inode
*inode
= file
->f_dentry
->d_inode
;
163 struct proc_dir_entry
* dp
;
165 dp
= (struct proc_dir_entry
*) inode
->u
.generic_ip
;
170 /* FIXME: does this routine need ppos? probably... */
171 return dp
->write_proc(file
, buffer
, count
, dp
->data
);
176 proc_file_lseek(struct file
* file
, long long offset
, int orig
)
180 file
->f_pos
= offset
;
183 file
->f_pos
+= offset
;
193 * This function parses a name such as "tty/driver/serial", and
194 * returns the struct proc_dir_entry for "/proc/tty/driver", and
195 * returns "serial" in residual.
197 static int xlate_proc_name(const char *name
,
198 struct proc_dir_entry
**ret
, const char **residual
)
200 const char *cp
= name
, *next
;
201 struct proc_dir_entry
*de
;
206 next
= strchr(cp
, '/');
211 for (de
= de
->subdir
; de
; de
= de
->next
) {
212 if (proc_match(len
, cp
, de
))
224 struct proc_dir_entry
*create_proc_entry(const char *name
, mode_t mode
,
225 struct proc_dir_entry
*parent
)
227 struct proc_dir_entry
*ent
= NULL
;
228 const char *fn
= name
;
231 if (!parent
&& xlate_proc_name(name
, &parent
, &fn
) != 0)
235 ent
= kmalloc(sizeof(struct proc_dir_entry
) + len
+ 1, GFP_KERNEL
);
238 memset(ent
, 0, sizeof(struct proc_dir_entry
));
239 memcpy(((char *) ent
) + sizeof(*ent
), fn
, len
+ 1);
240 ent
->name
= ((char *) ent
) + sizeof(*ent
);
244 if ((mode
& S_IALLUGO
) == 0)
245 mode
|= S_IRUGO
| S_IXUGO
;
246 ent
->ops
= &proc_dyna_dir_inode_operations
;
249 if ((mode
& S_IFMT
) == 0)
251 if ((mode
& S_IALLUGO
) == 0)
257 proc_register(parent
, ent
);
263 extern void free_proc_entry(struct proc_dir_entry
*);
264 void free_proc_entry(struct proc_dir_entry
*de
)
266 int ino
= de
->low_ino
;
268 if (ino
>= PROC_DYNAMIC_FIRST
&&
269 ino
< PROC_DYNAMIC_FIRST
+PROC_NDYNAMIC
)
274 * Remove a /proc entry and free it if it's not currently in use.
275 * If it is in use, we set the 'deleted' flag.
277 void remove_proc_entry(const char *name
, struct proc_dir_entry
*parent
)
279 struct proc_dir_entry
*de
;
280 const char *fn
= name
;
283 if (!parent
&& xlate_proc_name(name
, &parent
, &fn
) != 0)
287 for (de
= parent
->subdir
; de
; de
= de
->next
) {
288 if (proc_match(len
, fn
, de
))
293 proc_unregister(parent
, de
->low_ino
);
299 printk("remove_proc_entry: %s/%s busy, count=%d\n",
300 parent
->name
, de
->name
, de
->count
);