OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [kernel/] [sysctl.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * sysctl.c: General linux system control interface
3
 *
4
 * Begun 24 March 1995, Stephen Tweedie
5
 * Added /proc support, Dec 1995
6
 * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas.
7
 * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver.
8
 * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver.
9
 * Dynamic registration fixes, Stephen Tweedie.
10
 * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn.
11
 * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris
12
 *  Horn.
13
 * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer.
14
 * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer.
15
 * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill
16
 *  Wendling.
17
 * The list_for_each() macro wasn't appropriate for the sysctl loop.
18
 *  Removed it and replaced it with older style, 03/23/00, Bill Wendling
19
 */
20
 
21
#include <linux/config.h>
22
#include <linux/slab.h>
23
#include <linux/sysctl.h>
24
#include <linux/swapctl.h>
25
#include <linux/proc_fs.h>
26
#include <linux/ctype.h>
27
#include <linux/utsname.h>
28
#include <linux/capability.h>
29
#include <linux/smp_lock.h>
30
#include <linux/init.h>
31
#include <linux/sysrq.h>
32
#include <linux/highuid.h>
33
#include <linux/swap.h>
34
 
35
#include <asm/uaccess.h>
36
 
37
#ifdef CONFIG_ROOT_NFS
38
#include <linux/nfs_fs.h>
39
#endif
40
 
41
#if defined(CONFIG_SYSCTL)
42
 
43
/* External variables not in a header file. */
44
extern int panic_timeout;
45
extern int C_A_D;
46
extern int bdf_prm[], bdflush_min[], bdflush_max[];
47
extern int sysctl_overcommit_memory;
48
extern int max_threads;
49
extern atomic_t nr_queued_signals;
50
extern int max_queued_signals;
51
extern int sysrq_enabled;
52
extern int core_uses_pid;
53
extern int core_setuid_ok;
54
extern char core_pattern[];
55
extern int cad_pid;
56
extern int laptop_mode;
57
extern int block_dump;
58
 
59
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
60
static int maxolduid = 65535;
61
static int minolduid;
62
 
63
#ifdef CONFIG_KMOD
64
extern char modprobe_path[];
65
#endif
66
#ifdef CONFIG_HOTPLUG
67
extern char hotplug_path[];
68
#endif
69
#ifdef CONFIG_CHR_DEV_SG
70
extern int sg_big_buff;
71
#endif
72
#ifdef CONFIG_SYSVIPC
73
extern size_t shm_ctlmax;
74
extern size_t shm_ctlall;
75
extern int shm_ctlmni;
76
extern int msg_ctlmax;
77
extern int msg_ctlmnb;
78
extern int msg_ctlmni;
79
extern int sem_ctls[];
80
#endif
81
 
82
extern int exception_trace;
83
 
84
#ifdef __sparc__
85
extern char reboot_command [];
86
extern int stop_a_enabled;
87
#endif
88
 
89
#ifdef CONFIG_ARCH_S390
90
#ifdef CONFIG_MATHEMU
91
extern int sysctl_ieee_emulation_warnings;
92
#endif
93
extern int sysctl_userprocess_debug;
94
#endif
95
 
96
#ifdef CONFIG_PPC32
97
extern unsigned long zero_paged_on, powersave_nap;
98
int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
99
                void *buffer, size_t *lenp);
100
int proc_dol3crvec(ctl_table *table, int write, struct file *filp,
101
                void *buffer, size_t *lenp);
102
#endif
103
 
104
#ifdef CONFIG_BSD_PROCESS_ACCT
105
extern int acct_parm[];
106
#endif
107
 
108
extern int pgt_cache_water[];
109
 
110
static int parse_table(int *, int, void *, size_t *, void *, size_t,
111
                       ctl_table *, void **);
112
static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
113
                  void *buffer, size_t *lenp);
114
 
115
static ctl_table root_table[];
116
static struct ctl_table_header root_table_header =
117
        { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
118
 
119
static ctl_table kern_table[];
120
static ctl_table vm_table[];
121
#ifdef CONFIG_NET
122
extern ctl_table net_table[];
123
#endif
124
static ctl_table proc_table[];
125
static ctl_table fs_table[];
126
static ctl_table debug_table[];
127
static ctl_table dev_table[];
128
extern ctl_table random_table[];
129
 
130
/* /proc declarations: */
131
 
132
#ifdef CONFIG_PROC_FS
133
 
134
static ssize_t proc_readsys(struct file *, char *, size_t, loff_t *);
135
static ssize_t proc_writesys(struct file *, const char *, size_t, loff_t *);
136
static int proc_sys_permission(struct inode *, int);
137
 
138
struct file_operations proc_sys_file_operations = {
139
        read:           proc_readsys,
140
        write:          proc_writesys,
141
};
142
 
143
static struct inode_operations proc_sys_inode_operations = {
144
        permission:     proc_sys_permission,
145
};
146
 
147
extern struct proc_dir_entry *proc_sys_root;
148
 
149
static void register_proc_table(ctl_table *, struct proc_dir_entry *);
150
static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
151
#endif
152
 
153
/* The default sysctl tables: */
154
 
155
static ctl_table root_table[] = {
156
        {CTL_KERN, "kernel", NULL, 0, 0555, kern_table},
157
        {CTL_VM, "vm", NULL, 0, 0555, vm_table},
158
#ifdef CONFIG_NET
159
        {CTL_NET, "net", NULL, 0, 0555, net_table},
160
#endif
161
        {CTL_PROC, "proc", NULL, 0, 0555, proc_table},
162
        {CTL_FS, "fs", NULL, 0, 0555, fs_table},
163
        {CTL_DEBUG, "debug", NULL, 0, 0555, debug_table},
164
        {CTL_DEV, "dev", NULL, 0, 0555, dev_table},
165
        {0}
166
};
167
 
168
static ctl_table kern_table[] = {
169
        {KERN_OSTYPE, "ostype", system_utsname.sysname, 64,
170
         0444, NULL, &proc_doutsstring, &sysctl_string},
171
        {KERN_OSRELEASE, "osrelease", system_utsname.release, 64,
172
         0444, NULL, &proc_doutsstring, &sysctl_string},
173
        {KERN_VERSION, "version", system_utsname.version, 64,
174
         0444, NULL, &proc_doutsstring, &sysctl_string},
175
        {KERN_NODENAME, "hostname", system_utsname.nodename, 64,
176
         0644, NULL, &proc_doutsstring, &sysctl_string},
177
        {KERN_DOMAINNAME, "domainname", system_utsname.domainname, 64,
178
         0644, NULL, &proc_doutsstring, &sysctl_string},
179
        {KERN_PANIC, "panic", &panic_timeout, sizeof(int),
180
         0644, NULL, &proc_dointvec},
181
        {KERN_CORE_USES_PID, "core_uses_pid", &core_uses_pid, sizeof(int),
182
         0644, NULL, &proc_dointvec},
183
        {KERN_CORE_SETUID, "core_setuid_ok", &core_setuid_ok, sizeof(int),
184
        0644, NULL, &proc_dointvec},
185
        {KERN_CORE_PATTERN, "core_pattern", core_pattern, 64,
186
         0644, NULL, &proc_dostring, &sysctl_string},
187
        {KERN_TAINTED, "tainted", &tainted, sizeof(int),
188
         0644, NULL, &proc_dointvec},
189
        {KERN_CAP_BSET, "cap-bound", &cap_bset, sizeof(kernel_cap_t),
190
         0600, NULL, &proc_dointvec_bset},
191
#ifdef CONFIG_BLK_DEV_INITRD
192
        {KERN_REALROOTDEV, "real-root-dev", &real_root_dev, sizeof(int),
193
         0644, NULL, &proc_dointvec},
194
#endif
195
#ifdef __sparc__
196
        {KERN_SPARC_REBOOT, "reboot-cmd", reboot_command,
197
         256, 0644, NULL, &proc_dostring, &sysctl_string },
198
        {KERN_SPARC_STOP_A, "stop-a", &stop_a_enabled, sizeof (int),
199
         0644, NULL, &proc_dointvec},
200
#endif
201
#ifdef CONFIG_PPC32
202
        {KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on, sizeof(int),
203
         0644, NULL, &proc_dointvec},
204
        {KERN_PPC_POWERSAVE_NAP, "powersave-nap", &powersave_nap, sizeof(int),
205
         0644, NULL, &proc_dointvec},
206
        {KERN_PPC_L2CR, "l2cr", NULL, 0,
207
         0644, NULL, &proc_dol2crvec},
208
        {KERN_PPC_L3CR, "l3cr", NULL, 0,
209
         0644, NULL, &proc_dol3crvec},
210
#endif
211
        {KERN_CTLALTDEL, "ctrl-alt-del", &C_A_D, sizeof(int),
212
         0644, NULL, &proc_dointvec},
213
        {KERN_PRINTK, "printk", &console_loglevel, 4*sizeof(int),
214
         0644, NULL, &proc_dointvec},
215
#ifdef CONFIG_KMOD
216
        {KERN_MODPROBE, "modprobe", &modprobe_path, 256,
217
         0644, NULL, &proc_dostring, &sysctl_string },
218
#endif
219
#ifdef CONFIG_HOTPLUG
220
        {KERN_HOTPLUG, "hotplug", &hotplug_path, 256,
221
         0644, NULL, &proc_dostring, &sysctl_string },
222
#endif
223
#ifdef CONFIG_CHR_DEV_SG
224
        {KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff, sizeof (int),
225
         0444, NULL, &proc_dointvec},
226
#endif
227
#ifdef CONFIG_BSD_PROCESS_ACCT
228
        {KERN_ACCT, "acct", &acct_parm, 3*sizeof(int),
229
        0644, NULL, &proc_dointvec},
230
#endif
231
        {KERN_RTSIGNR, "rtsig-nr", &nr_queued_signals, sizeof(int),
232
         0444, NULL, &proc_dointvec},
233
        {KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int),
234
         0644, NULL, &proc_dointvec},
235
#ifdef CONFIG_SYSVIPC
236
        {KERN_SHMMAX, "shmmax", &shm_ctlmax, sizeof (size_t),
237
         0644, NULL, &proc_doulongvec_minmax},
238
        {KERN_SHMALL, "shmall", &shm_ctlall, sizeof (size_t),
239
         0644, NULL, &proc_doulongvec_minmax},
240
        {KERN_SHMMNI, "shmmni", &shm_ctlmni, sizeof (int),
241
         0644, NULL, &proc_dointvec},
242
        {KERN_MSGMAX, "msgmax", &msg_ctlmax, sizeof (int),
243
         0644, NULL, &proc_dointvec},
244
        {KERN_MSGMNI, "msgmni", &msg_ctlmni, sizeof (int),
245
         0644, NULL, &proc_dointvec},
246
        {KERN_MSGMNB, "msgmnb", &msg_ctlmnb, sizeof (int),
247
         0644, NULL, &proc_dointvec},
248
        {KERN_SEM, "sem", &sem_ctls, 4*sizeof (int),
249
         0644, NULL, &proc_dointvec},
250
#endif
251
#ifdef CONFIG_MAGIC_SYSRQ
252
        {KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int),
253
         0644, NULL, &proc_dointvec},
254
#endif   
255
        {KERN_CADPID, "cad_pid", &cad_pid, sizeof (int),
256
         0600, NULL, &proc_dointvec},
257
        {KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int),
258
         0644, NULL, &proc_dointvec},
259
        {KERN_RANDOM, "random", NULL, 0, 0555, random_table},
260
        {KERN_OVERFLOWUID, "overflowuid", &overflowuid, sizeof(int), 0644, NULL,
261
         &proc_dointvec_minmax, &sysctl_intvec, NULL,
262
         &minolduid, &maxolduid},
263
        {KERN_OVERFLOWGID, "overflowgid", &overflowgid, sizeof(int), 0644, NULL,
264
         &proc_dointvec_minmax, &sysctl_intvec, NULL,
265
         &minolduid, &maxolduid},
266
#ifdef CONFIG_ARCH_S390
267
#ifdef CONFIG_MATHEMU
268
        {KERN_IEEE_EMULATION_WARNINGS,"ieee_emulation_warnings",
269
         &sysctl_ieee_emulation_warnings,sizeof(int),0644,NULL,&proc_dointvec},
270
#endif
271
        {KERN_S390_USER_DEBUG_LOGGING,"userprocess_debug",
272
         &sysctl_userprocess_debug,sizeof(int),0644,NULL,&proc_dointvec},
273
#endif
274
#ifdef __x86_64__
275
        {KERN_EXCEPTION_TRACE,"exception-trace",
276
         &exception_trace,sizeof(int),0644,NULL,&proc_dointvec},
277
#endif  
278
        {0}
279
};
280
 
281
static ctl_table vm_table[] = {
282
        {VM_GFP_DEBUG, "vm_gfp_debug",
283
         &vm_gfp_debug, sizeof(int), 0644, NULL, &proc_dointvec},
284
        {VM_VFS_SCAN_RATIO, "vm_vfs_scan_ratio",
285
         &vm_vfs_scan_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
286
        {VM_CACHE_SCAN_RATIO, "vm_cache_scan_ratio",
287
         &vm_cache_scan_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
288
        {VM_MAPPED_RATIO, "vm_mapped_ratio",
289
         &vm_mapped_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
290
        {VM_LRU_BALANCE_RATIO, "vm_lru_balance_ratio",
291
         &vm_lru_balance_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
292
        {VM_PASSES, "vm_passes",
293
         &vm_passes, sizeof(int), 0644, NULL, &proc_dointvec},
294
        {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0644, NULL,
295
         &proc_dointvec_minmax, &sysctl_intvec, NULL,
296
         &bdflush_min, &bdflush_max},
297
        {VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory,
298
         sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec},
299
        {VM_PAGERDAEMON, "kswapd",
300
         &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
301
        {VM_PGT_CACHE, "pagetable_cache",
302
         &pgt_cache_water, 2*sizeof(int), 0644, NULL, &proc_dointvec},
303
        {VM_PAGE_CLUSTER, "page-cluster",
304
         &page_cluster, sizeof(int), 0644, NULL, &proc_dointvec},
305
        {VM_MIN_READAHEAD, "min-readahead",
306
        &vm_min_readahead,sizeof(int), 0644, NULL, &proc_dointvec},
307
        {VM_MAX_READAHEAD, "max-readahead",
308
        &vm_max_readahead,sizeof(int), 0644, NULL, &proc_dointvec},
309
        {VM_MAX_MAP_COUNT, "max_map_count",
310
         &max_map_count, sizeof(int), 0644, NULL, &proc_dointvec},
311
        {VM_LAPTOP_MODE, "laptop_mode",
312
         &laptop_mode, sizeof(int), 0644, NULL, &proc_dointvec},
313
        {VM_BLOCK_DUMP, "block_dump",
314
         &block_dump, sizeof(int), 0644, NULL, &proc_dointvec},
315
        {0}
316
};
317
 
318
static ctl_table proc_table[] = {
319
        {0}
320
};
321
 
322
static ctl_table fs_table[] = {
323
        {FS_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int),
324
         0444, NULL, &proc_dointvec},
325
        {FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int),
326
         0444, NULL, &proc_dointvec},
327
        {FS_NRFILE, "file-nr", &files_stat, 3*sizeof(int),
328
         0444, NULL, &proc_dointvec},
329
        {FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int),
330
         0644, NULL, &proc_dointvec},
331
        {FS_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int),
332
         0444, NULL, &proc_dointvec},
333
        {FS_OVERFLOWUID, "overflowuid", &fs_overflowuid, sizeof(int), 0644, NULL,
334
         &proc_dointvec_minmax, &sysctl_intvec, NULL,
335
         &minolduid, &maxolduid},
336
        {FS_OVERFLOWGID, "overflowgid", &fs_overflowgid, sizeof(int), 0644, NULL,
337
         &proc_dointvec_minmax, &sysctl_intvec, NULL,
338
         &minolduid, &maxolduid},
339
        {FS_LEASES, "leases-enable", &leases_enable, sizeof(int),
340
         0644, NULL, &proc_dointvec},
341
        {FS_DIR_NOTIFY, "dir-notify-enable", &dir_notify_enable,
342
         sizeof(int), 0644, NULL, &proc_dointvec},
343
        {FS_LEASE_TIME, "lease-break-time", &lease_break_time, sizeof(int),
344
         0644, NULL, &proc_dointvec},
345
        {0}
346
};
347
 
348
static ctl_table debug_table[] = {
349
        {0}
350
};
351
 
352
static ctl_table dev_table[] = {
353
        {0}
354
};
355
 
356
extern void init_irq_proc (void);
357
 
358
void __init sysctl_init(void)
359
{
360
#ifdef CONFIG_PROC_FS
361
        register_proc_table(root_table, proc_sys_root);
362
        init_irq_proc();
363
#endif
364
}
365
 
366
int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
367
               void *newval, size_t newlen)
368
{
369
        struct list_head *tmp;
370
 
371
        if (nlen <= 0 || nlen >= CTL_MAXNAME)
372
                return -ENOTDIR;
373
        if (oldval) {
374
                int old_len;
375
                if (!oldlenp || get_user(old_len, oldlenp))
376
                        return -EFAULT;
377
        }
378
        tmp = &root_table_header.ctl_entry;
379
        do {
380
                struct ctl_table_header *head =
381
                        list_entry(tmp, struct ctl_table_header, ctl_entry);
382
                void *context = NULL;
383
                int error = parse_table(name, nlen, oldval, oldlenp,
384
                                        newval, newlen, head->ctl_table,
385
                                        &context);
386
                if (context)
387
                        kfree(context);
388
                if (error != -ENOTDIR)
389
                        return error;
390
                tmp = tmp->next;
391
        } while (tmp != &root_table_header.ctl_entry);
392
        return -ENOTDIR;
393
}
394
 
395
extern asmlinkage long sys_sysctl(struct __sysctl_args *args)
396
{
397
        struct __sysctl_args tmp;
398
        int error;
399
 
400
        if (copy_from_user(&tmp, args, sizeof(tmp)))
401
                return -EFAULT;
402
 
403
        lock_kernel();
404
        error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp,
405
                          tmp.newval, tmp.newlen);
406
        unlock_kernel();
407
        return error;
408
}
409
 
410
/*
411
 * ctl_perm does NOT grant the superuser all rights automatically, because
412
 * some sysctl variables are readonly even to root.
413
 */
414
 
415
static int test_perm(int mode, int op)
416
{
417
        if (!current->euid)
418
                mode >>= 6;
419
        else if (in_egroup_p(0))
420
                mode >>= 3;
421
        if ((mode & op & 0007) == op)
422
                return 0;
423
        return -EACCES;
424
}
425
 
426
static inline int ctl_perm(ctl_table *table, int op)
427
{
428
        return test_perm(table->mode, op);
429
}
430
 
431
static int parse_table(int *name, int nlen,
432
                       void *oldval, size_t *oldlenp,
433
                       void *newval, size_t newlen,
434
                       ctl_table *table, void **context)
435
{
436
        int n;
437
repeat:
438
        if (!nlen)
439
                return -ENOTDIR;
440
        if (get_user(n, name))
441
                return -EFAULT;
442
        for ( ; table->ctl_name; table++) {
443
                if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
444
                        int error;
445
                        if (table->child) {
446
                                if (ctl_perm(table, 001))
447
                                        return -EPERM;
448
                                if (table->strategy) {
449
                                        error = table->strategy(
450
                                                table, name, nlen,
451
                                                oldval, oldlenp,
452
                                                newval, newlen, context);
453
                                        if (error)
454
                                                return error;
455
                                }
456
                                name++;
457
                                nlen--;
458
                                table = table->child;
459
                                goto repeat;
460
                        }
461
                        error = do_sysctl_strategy(table, name, nlen,
462
                                                   oldval, oldlenp,
463
                                                   newval, newlen, context);
464
                        return error;
465
                }
466
        }
467
        return -ENOTDIR;
468
}
469
 
470
/* Perform the actual read/write of a sysctl table entry. */
471
int do_sysctl_strategy (ctl_table *table,
472
                        int *name, int nlen,
473
                        void *oldval, size_t *oldlenp,
474
                        void *newval, size_t newlen, void **context)
475
{
476
        int op = 0, rc;
477
        size_t len;
478
 
479
        if (oldval)
480
                op |= 004;
481
        if (newval)
482
                op |= 002;
483
        if (ctl_perm(table, op))
484
                return -EPERM;
485
 
486
        if (table->strategy) {
487
                rc = table->strategy(table, name, nlen, oldval, oldlenp,
488
                                     newval, newlen, context);
489
                if (rc < 0)
490
                        return rc;
491
                if (rc > 0)
492
                        return 0;
493
        }
494
 
495
        /* If there is no strategy routine, or if the strategy returns
496
         * zero, proceed with automatic r/w */
497
        if (table->data && table->maxlen) {
498
                if (oldval && oldlenp) {
499
                        if (get_user(len, oldlenp))
500
                                return -EFAULT;
501
                        if (len) {
502
                                if (len > table->maxlen)
503
                                        len = table->maxlen;
504
                                if(copy_to_user(oldval, table->data, len))
505
                                        return -EFAULT;
506
                                if(put_user(len, oldlenp))
507
                                        return -EFAULT;
508
                        }
509
                }
510
                if (newval && newlen) {
511
                        len = newlen;
512
                        if (len > table->maxlen)
513
                                len = table->maxlen;
514
                        if(copy_from_user(table->data, newval, len))
515
                                return -EFAULT;
516
                }
517
        }
518
        return 0;
519
}
520
 
521
/**
522
 * register_sysctl_table - register a sysctl hierarchy
523
 * @table: the top-level table structure
524
 * @insert_at_head: whether the entry should be inserted in front or at the end
525
 *
526
 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
527
 * array. An entry with a ctl_name of 0 terminates the table.
528
 *
529
 * The members of the &ctl_table structure are used as follows:
530
 *
531
 * ctl_name - This is the numeric sysctl value used by sysctl(2). The number
532
 *            must be unique within that level of sysctl
533
 *
534
 * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
535
 *            enter a sysctl file
536
 *
537
 * data - a pointer to data for use by proc_handler
538
 *
539
 * maxlen - the maximum size in bytes of the data
540
 *
541
 * mode - the file permissions for the /proc/sys file, and for sysctl(2)
542
 *
543
 * child - a pointer to the child sysctl table if this entry is a directory, or
544
 *         %NULL.
545
 *
546
 * proc_handler - the text handler routine (described below)
547
 *
548
 * strategy - the strategy routine (described below)
549
 *
550
 * de - for internal use by the sysctl routines
551
 *
552
 * extra1, extra2 - extra pointers usable by the proc handler routines
553
 *
554
 * Leaf nodes in the sysctl tree will be represented by a single file
555
 * under /proc; non-leaf nodes will be represented by directories.
556
 *
557
 * sysctl(2) can automatically manage read and write requests through
558
 * the sysctl table.  The data and maxlen fields of the ctl_table
559
 * struct enable minimal validation of the values being written to be
560
 * performed, and the mode field allows minimal authentication.
561
 *
562
 * More sophisticated management can be enabled by the provision of a
563
 * strategy routine with the table entry.  This will be called before
564
 * any automatic read or write of the data is performed.
565
 *
566
 * The strategy routine may return
567
 *
568
 * < 0 - Error occurred (error is passed to user process)
569
 *
570
 * 0   - OK - proceed with automatic read or write.
571
 *
572
 * > 0 - OK - read or write has been done by the strategy routine, so
573
 *       return immediately.
574
 *
575
 * There must be a proc_handler routine for any terminal nodes
576
 * mirrored under /proc/sys (non-terminals are handled by a built-in
577
 * directory handler).  Several default handlers are available to
578
 * cover common cases -
579
 *
580
 * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
581
 * proc_dointvec_minmax(), proc_doulongvec_ms_jiffies_minmax(),
582
 * proc_doulongvec_minmax()
583
 *
584
 * It is the handler's job to read the input buffer from user memory
585
 * and process it. The handler should return 0 on success.
586
 *
587
 * This routine returns %NULL on a failure to register, and a pointer
588
 * to the table header on success.
589
 */
590
struct ctl_table_header *register_sysctl_table(ctl_table * table,
591
                                               int insert_at_head)
592
{
593
        struct ctl_table_header *tmp;
594
        tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
595
        if (!tmp)
596
                return NULL;
597
        tmp->ctl_table = table;
598
        INIT_LIST_HEAD(&tmp->ctl_entry);
599
        if (insert_at_head)
600
                list_add(&tmp->ctl_entry, &root_table_header.ctl_entry);
601
        else
602
                list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
603
#ifdef CONFIG_PROC_FS
604
        register_proc_table(table, proc_sys_root);
605
#endif
606
        return tmp;
607
}
608
 
609
/**
610
 * unregister_sysctl_table - unregister a sysctl table hierarchy
611
 * @header: the header returned from register_sysctl_table
612
 *
613
 * Unregisters the sysctl table and all children. proc entries may not
614
 * actually be removed until they are no longer used by anyone.
615
 */
616
void unregister_sysctl_table(struct ctl_table_header * header)
617
{
618
        list_del(&header->ctl_entry);
619
#ifdef CONFIG_PROC_FS
620
        unregister_proc_table(header->ctl_table, proc_sys_root);
621
#endif
622
        kfree(header);
623
}
624
 
625
/*
626
 * /proc/sys support
627
 */
628
 
629
#ifdef CONFIG_PROC_FS
630
 
631
/* Scan the sysctl entries in table and add them all into /proc */
632
static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
633
{
634
        struct proc_dir_entry *de;
635
        int len;
636
        mode_t mode;
637
 
638
        for (; table->ctl_name; table++) {
639
                /* Can't do anything without a proc name. */
640
                if (!table->procname)
641
                        continue;
642
                /* Maybe we can't do anything with it... */
643
                if (!table->proc_handler && !table->child) {
644
                        printk(KERN_WARNING "SYSCTL: Can't register %s\n",
645
                                table->procname);
646
                        continue;
647
                }
648
 
649
                len = strlen(table->procname);
650
                mode = table->mode;
651
 
652
                de = NULL;
653
                if (table->proc_handler)
654
                        mode |= S_IFREG;
655
                else {
656
                        mode |= S_IFDIR;
657
                        for (de = root->subdir; de; de = de->next) {
658
                                if (proc_match(len, table->procname, de))
659
                                        break;
660
                        }
661
                        /* If the subdir exists already, de is non-NULL */
662
                }
663
 
664
                if (!de) {
665
                        de = create_proc_entry(table->procname, mode, root);
666
                        if (!de)
667
                                continue;
668
                        de->data = (void *) table;
669
                        if (table->proc_handler) {
670
                                de->proc_fops = &proc_sys_file_operations;
671
                                de->proc_iops = &proc_sys_inode_operations;
672
                        }
673
                }
674
                table->de = de;
675
                if (de->mode & S_IFDIR)
676
                        register_proc_table(table->child, de);
677
        }
678
}
679
 
680
/*
681
 * Unregister a /proc sysctl table and any subdirectories.
682
 */
683
static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
684
{
685
        struct proc_dir_entry *de;
686
        for (; table->ctl_name; table++) {
687
                if (!(de = table->de))
688
                        continue;
689
                if (de->mode & S_IFDIR) {
690
                        if (!table->child) {
691
                                printk (KERN_ALERT "Help - malformed sysctl tree on free\n");
692
                                continue;
693
                        }
694
                        unregister_proc_table(table->child, de);
695
 
696
                        /* Don't unregister directories which still have entries.. */
697
                        if (de->subdir)
698
                                continue;
699
                }
700
 
701
                /* Don't unregister proc entries that are still being used.. */
702
                if (atomic_read(&de->count))
703
                        continue;
704
 
705
                table->de = NULL;
706
                remove_proc_entry(table->procname, root);
707
        }
708
}
709
 
710
static ssize_t do_rw_proc(int write, struct file * file, char * buf,
711
                          size_t count, loff_t *ppos)
712
{
713
        int op;
714
        struct proc_dir_entry *de;
715
        struct ctl_table *table;
716
        size_t res;
717
        ssize_t error;
718
 
719
        de = (struct proc_dir_entry*) file->f_dentry->d_inode->u.generic_ip;
720
        if (!de || !de->data)
721
                return -ENOTDIR;
722
        table = (struct ctl_table *) de->data;
723
        if (!table || !table->proc_handler)
724
                return -ENOTDIR;
725
        op = (write ? 002 : 004);
726
        if (ctl_perm(table, op))
727
                return -EPERM;
728
 
729
        res = count;
730
 
731
        /*
732
         * FIXME: we need to pass on ppos to the handler.
733
         */
734
 
735
        error = (*table->proc_handler) (table, write, file, buf, &res);
736
        if (error)
737
                return error;
738
        return res;
739
}
740
 
741
static ssize_t proc_readsys(struct file * file, char * buf,
742
                            size_t count, loff_t *ppos)
743
{
744
        return do_rw_proc(0, file, buf, count, ppos);
745
}
746
 
747
static ssize_t proc_writesys(struct file * file, const char * buf,
748
                             size_t count, loff_t *ppos)
749
{
750
        return do_rw_proc(1, file, (char *) buf, count, ppos);
751
}
752
 
753
static int proc_sys_permission(struct inode *inode, int op)
754
{
755
        return test_perm(inode->i_mode, op);
756
}
757
 
758
/**
759
 * proc_dostring - read a string sysctl
760
 * @table: the sysctl table
761
 * @write: %TRUE if this is a write to the sysctl file
762
 * @filp: the file structure
763
 * @buffer: the user buffer
764
 * @lenp: the size of the user buffer
765
 *
766
 * Reads/writes a string from/to the user buffer. If the kernel
767
 * buffer provided is not large enough to hold the string, the
768
 * string is truncated. The copied string is %NULL-terminated.
769
 * If the string is being read by the user process, it is copied
770
 * and a newline '\n' is added. It is truncated if the buffer is
771
 * not large enough.
772
 *
773
 * Returns 0 on success.
774
 */
775
int proc_dostring(ctl_table *table, int write, struct file *filp,
776
                  void *buffer, size_t *lenp)
777
{
778
        size_t len;
779
        char *p, c;
780
 
781
        if (!table->data || !table->maxlen || !*lenp ||
782
            (filp->f_pos && !write)) {
783
                *lenp = 0;
784
                return 0;
785
        }
786
 
787
        if (write) {
788
                len = 0;
789
                p = buffer;
790
                while (len < *lenp) {
791
                        if (get_user(c, p++))
792
                                return -EFAULT;
793
                        if (c == 0 || c == '\n')
794
                                break;
795
                        len++;
796
                }
797
                if (len >= table->maxlen)
798
                        len = table->maxlen-1;
799
                if(copy_from_user(table->data, buffer, len))
800
                        return -EFAULT;
801
                ((char *) table->data)[len] = 0;
802
                filp->f_pos += *lenp;
803
        } else {
804
                len = strlen(table->data);
805
                if (len > table->maxlen)
806
                        len = table->maxlen;
807
                if (len > *lenp)
808
                        len = *lenp;
809
                if (len)
810
                        if(copy_to_user(buffer, table->data, len))
811
                                return -EFAULT;
812
                if (len < *lenp) {
813
                        if(put_user('\n', ((char *) buffer) + len))
814
                                return -EFAULT;
815
                        len++;
816
                }
817
                *lenp = len;
818
                filp->f_pos += len;
819
        }
820
        return 0;
821
}
822
 
823
/*
824
 *      Special case of dostring for the UTS structure. This has locks
825
 *      to observe. Should this be in kernel/sys.c ????
826
 */
827
 
828
static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
829
                  void *buffer, size_t *lenp)
830
{
831
        int r;
832
 
833
        if (!write) {
834
                down_read(&uts_sem);
835
                r=proc_dostring(table,0,filp,buffer,lenp);
836
                up_read(&uts_sem);
837
        } else {
838
                down_write(&uts_sem);
839
                r=proc_dostring(table,1,filp,buffer,lenp);
840
                up_write(&uts_sem);
841
        }
842
        return r;
843
}
844
 
845
#define OP_SET  0
846
#define OP_AND  1
847
#define OP_OR   2
848
#define OP_MAX  3
849
#define OP_MIN  4
850
 
851
static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
852
                  void *buffer, size_t *lenp, int conv, int op)
853
{
854
        int *i, vleft, first=1, neg, val;
855
        size_t left, len;
856
 
857
        #define TMPBUFLEN 20
858
        char buf[TMPBUFLEN], *p;
859
 
860
        if (!table->data || !table->maxlen || !*lenp ||
861
            (filp->f_pos && !write)) {
862
                *lenp = 0;
863
                return 0;
864
        }
865
 
866
        i = (int *) table->data;
867
        vleft = table->maxlen / sizeof(int);
868
        left = *lenp;
869
 
870
        for (; left && vleft--; i++, first=0) {
871
                if (write) {
872
                        while (left) {
873
                                char c;
874
                                if (get_user(c, (char *) buffer))
875
                                        return -EFAULT;
876
                                if (!isspace(c))
877
                                        break;
878
                                left--;
879
                                ((char *) buffer)++;
880
                        }
881
                        if (!left)
882
                                break;
883
                        neg = 0;
884
                        len = left;
885
                        if (len > TMPBUFLEN-1)
886
                                len = TMPBUFLEN-1;
887
                        if(copy_from_user(buf, buffer, len))
888
                                return -EFAULT;
889
                        buf[len] = 0;
890
                        p = buf;
891
                        if (*p == '-' && left > 1) {
892
                                neg = 1;
893
                                left--, p++;
894
                        }
895
                        if (*p < '0' || *p > '9')
896
                                break;
897
                        val = simple_strtoul(p, &p, 0) * conv;
898
                        len = p-buf;
899
                        if ((len < left) && *p && !isspace(*p))
900
                                break;
901
                        if (neg)
902
                                val = -val;
903
                        buffer += len;
904
                        left -= len;
905
                        switch(op) {
906
                        case OP_SET:    *i = val; break;
907
                        case OP_AND:    *i &= val; break;
908
                        case OP_OR:     *i |= val; break;
909
                        case OP_MAX:    if(*i < val)
910
                                                *i = val;
911
                                        break;
912
                        case OP_MIN:    if(*i > val)
913
                                                *i = val;
914
                                        break;
915
                        }
916
                } else {
917
                        p = buf;
918
                        if (!first)
919
                                *p++ = '\t';
920
                        sprintf(p, "%d", (*i) / conv);
921
                        len = strlen(buf);
922
                        if (len > left)
923
                                len = left;
924
                        if(copy_to_user(buffer, buf, len))
925
                                return -EFAULT;
926
                        left -= len;
927
                        buffer += len;
928
                }
929
        }
930
 
931
        if (!write && !first && left) {
932
                if(put_user('\n', (char *) buffer))
933
                        return -EFAULT;
934
                left--, buffer++;
935
        }
936
        if (write) {
937
                p = (char *) buffer;
938
                while (left) {
939
                        char c;
940
                        if (get_user(c, p++))
941
                                return -EFAULT;
942
                        if (!isspace(c))
943
                                break;
944
                        left--;
945
                }
946
        }
947
        if (write && first)
948
                return -EINVAL;
949
        *lenp -= left;
950
        filp->f_pos += *lenp;
951
        return 0;
952
}
953
 
954
/**
955
 * proc_dointvec - read a vector of integers
956
 * @table: the sysctl table
957
 * @write: %TRUE if this is a write to the sysctl file
958
 * @filp: the file structure
959
 * @buffer: the user buffer
960
 * @lenp: the size of the user buffer
961
 *
962
 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
963
 * values from/to the user buffer, treated as an ASCII string.
964
 *
965
 * Returns 0 on success.
966
 */
967
int proc_dointvec(ctl_table *table, int write, struct file *filp,
968
                     void *buffer, size_t *lenp)
969
{
970
    return do_proc_dointvec(table,write,filp,buffer,lenp,1,OP_SET);
971
}
972
 
973
/*
974
 *      init may raise the set.
975
 */
976
 
977
int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
978
                        void *buffer, size_t *lenp)
979
{
980
        if (!capable(CAP_SYS_MODULE)) {
981
                return -EPERM;
982
        }
983
        return do_proc_dointvec(table,write,filp,buffer,lenp,1,
984
                                (current->pid == 1) ? OP_SET : OP_AND);
985
}
986
 
987
/**
988
 * proc_dointvec_minmax - read a vector of integers with min/max values
989
 * @table: the sysctl table
990
 * @write: %TRUE if this is a write to the sysctl file
991
 * @filp: the file structure
992
 * @buffer: the user buffer
993
 * @lenp: the size of the user buffer
994
 *
995
 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
996
 * values from/to the user buffer, treated as an ASCII string.
997
 *
998
 * This routine will ensure the values are within the range specified by
999
 * table->extra1 (min) and table->extra2 (max).
1000
 *
1001
 * Returns 0 on success.
1002
 */
1003
int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
1004
                  void *buffer, size_t *lenp)
1005
{
1006
        int *i, *min, *max, vleft, first=1, neg, val;
1007
        size_t len, left;
1008
        #define TMPBUFLEN 20
1009
        char buf[TMPBUFLEN], *p;
1010
 
1011
        if (!table->data || !table->maxlen || !*lenp ||
1012
            (filp->f_pos && !write)) {
1013
                *lenp = 0;
1014
                return 0;
1015
        }
1016
 
1017
        i = (int *) table->data;
1018
        min = (int *) table->extra1;
1019
        max = (int *) table->extra2;
1020
        vleft = table->maxlen / sizeof(int);
1021
        left = *lenp;
1022
 
1023
        for (; left && vleft--; i++, min++, max++, first=0) {
1024
                if (write) {
1025
                        while (left) {
1026
                                char c;
1027
                                if (get_user(c, (char *) buffer))
1028
                                        return -EFAULT;
1029
                                if (!isspace(c))
1030
                                        break;
1031
                                left--;
1032
                                ((char *) buffer)++;
1033
                        }
1034
                        if (!left)
1035
                                break;
1036
                        neg = 0;
1037
                        len = left;
1038
                        if (len > TMPBUFLEN-1)
1039
                                len = TMPBUFLEN-1;
1040
                        if(copy_from_user(buf, buffer, len))
1041
                                return -EFAULT;
1042
                        buf[len] = 0;
1043
                        p = buf;
1044
                        if (*p == '-' && left > 1) {
1045
                                neg = 1;
1046
                                left--, p++;
1047
                        }
1048
                        if (*p < '0' || *p > '9')
1049
                                break;
1050
                        val = simple_strtoul(p, &p, 0);
1051
                        len = p-buf;
1052
                        if ((len < left) && *p && !isspace(*p))
1053
                                break;
1054
                        if (neg)
1055
                                val = -val;
1056
                        buffer += len;
1057
                        left -= len;
1058
 
1059
                        if ((min && val < *min) || (max && val > *max))
1060
                                continue;
1061
                        *i = val;
1062
                } else {
1063
                        p = buf;
1064
                        if (!first)
1065
                                *p++ = '\t';
1066
                        sprintf(p, "%d", *i);
1067
                        len = strlen(buf);
1068
                        if (len > left)
1069
                                len = left;
1070
                        if(copy_to_user(buffer, buf, len))
1071
                                return -EFAULT;
1072
                        left -= len;
1073
                        buffer += len;
1074
                }
1075
        }
1076
 
1077
        if (!write && !first && left) {
1078
                if(put_user('\n', (char *) buffer))
1079
                        return -EFAULT;
1080
                left--, buffer++;
1081
        }
1082
        if (write) {
1083
                p = (char *) buffer;
1084
                while (left) {
1085
                        char c;
1086
                        if (get_user(c, p++))
1087
                                return -EFAULT;
1088
                        if (!isspace(c))
1089
                                break;
1090
                        left--;
1091
                }
1092
        }
1093
        if (write && first)
1094
                return -EINVAL;
1095
        *lenp -= left;
1096
        filp->f_pos += *lenp;
1097
        return 0;
1098
}
1099
 
1100
static int do_proc_doulongvec_minmax(ctl_table *table, int write,
1101
                                     struct file *filp,
1102
                                     void *buffer, size_t *lenp,
1103
                                     unsigned long convmul,
1104
                                     unsigned long convdiv)
1105
{
1106
#define TMPBUFLEN 20
1107
        unsigned long *i, *min, *max, val;
1108
        int vleft, first=1, neg;
1109
        size_t len, left;
1110
        char buf[TMPBUFLEN], *p;
1111
 
1112
        if (!table->data || !table->maxlen || !*lenp ||
1113
            (filp->f_pos && !write)) {
1114
                *lenp = 0;
1115
                return 0;
1116
        }
1117
 
1118
        i = (unsigned long *) table->data;
1119
        min = (unsigned long *) table->extra1;
1120
        max = (unsigned long *) table->extra2;
1121
        vleft = table->maxlen / sizeof(unsigned long);
1122
        left = *lenp;
1123
 
1124
        for (; left && vleft--; i++, first=0) {
1125
                if (write) {
1126
                        while (left) {
1127
                                char c;
1128
                                if (get_user(c, (char *) buffer))
1129
                                        return -EFAULT;
1130
                                if (!isspace(c))
1131
                                        break;
1132
                                left--;
1133
                                ((char *) buffer)++;
1134
                        }
1135
                        if (!left)
1136
                                break;
1137
                        neg = 0;
1138
                        len = left;
1139
                        if (len > TMPBUFLEN-1)
1140
                                len = TMPBUFLEN-1;
1141
                        if(copy_from_user(buf, buffer, len))
1142
                                return -EFAULT;
1143
                        buf[len] = 0;
1144
                        p = buf;
1145
                        if (*p == '-' && left > 1) {
1146
                                neg = 1;
1147
                                left--, p++;
1148
                        }
1149
                        if (*p < '0' || *p > '9')
1150
                                break;
1151
                        val = simple_strtoul(p, &p, 0) * convmul / convdiv ;
1152
                        len = p-buf;
1153
                        if ((len < left) && *p && !isspace(*p))
1154
                                break;
1155
                        if (neg)
1156
                                val = -val;
1157
                        buffer += len;
1158
                        left -= len;
1159
 
1160
                        if(neg)
1161
                                continue;
1162
                        if (min && val < *min++)
1163
                                continue;
1164
                        if (max && val > *max++)
1165
                                continue;
1166
                        *i = val;
1167
                } else {
1168
                        p = buf;
1169
                        if (!first)
1170
                                *p++ = '\t';
1171
                        sprintf(p, "%lu", convdiv * (*i) / convmul);
1172
                        len = strlen(buf);
1173
                        if (len > left)
1174
                                len = left;
1175
                        if(copy_to_user(buffer, buf, len))
1176
                                return -EFAULT;
1177
                        left -= len;
1178
                        buffer += len;
1179
                }
1180
        }
1181
 
1182
        if (!write && !first && left) {
1183
                if(put_user('\n', (char *) buffer))
1184
                        return -EFAULT;
1185
                left--, buffer++;
1186
        }
1187
        if (write) {
1188
                p = (char *) buffer;
1189
                while (left) {
1190
                        char c;
1191
                        if (get_user(c, p++))
1192
                                return -EFAULT;
1193
                        if (!isspace(c))
1194
                                break;
1195
                        left--;
1196
                }
1197
        }
1198
        if (write && first)
1199
                return -EINVAL;
1200
        *lenp -= left;
1201
        filp->f_pos += *lenp;
1202
        return 0;
1203
#undef TMPBUFLEN
1204
}
1205
 
1206
/**
1207
 * proc_doulongvec_minmax - read a vector of long integers with min/max values
1208
 * @table: the sysctl table
1209
 * @write: %TRUE if this is a write to the sysctl file
1210
 * @filp: the file structure
1211
 * @buffer: the user buffer
1212
 * @lenp: the size of the user buffer
1213
 *
1214
 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1215
 * values from/to the user buffer, treated as an ASCII string.
1216
 *
1217
 * This routine will ensure the values are within the range specified by
1218
 * table->extra1 (min) and table->extra2 (max).
1219
 *
1220
 * Returns 0 on success.
1221
 */
1222
int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
1223
                           void *buffer, size_t *lenp)
1224
{
1225
    return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, 1l, 1l);
1226
}
1227
 
1228
/**
1229
 * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
1230
 * @table: the sysctl table
1231
 * @write: %TRUE if this is a write to the sysctl file
1232
 * @filp: the file structure
1233
 * @buffer: the user buffer
1234
 * @lenp: the size of the user buffer
1235
 *
1236
 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
1237
 * values from/to the user buffer, treated as an ASCII string. The values
1238
 * are treated as milliseconds, and converted to jiffies when they are stored.
1239
 *
1240
 * This routine will ensure the values are within the range specified by
1241
 * table->extra1 (min) and table->extra2 (max).
1242
 *
1243
 * Returns 0 on success.
1244
 */
1245
int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
1246
                                      struct file *filp,
1247
                                      void *buffer, size_t *lenp)
1248
{
1249
    return do_proc_doulongvec_minmax(table, write, filp, buffer,
1250
                                     lenp, HZ, 1000l);
1251
}
1252
 
1253
 
1254
/**
1255
 * proc_dointvec_jiffies - read a vector of integers as seconds
1256
 * @table: the sysctl table
1257
 * @write: %TRUE if this is a write to the sysctl file
1258
 * @filp: the file structure
1259
 * @buffer: the user buffer
1260
 * @lenp: the size of the user buffer
1261
 *
1262
 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
1263
 * values from/to the user buffer, treated as an ASCII string.
1264
 * The values read are assumed to be in seconds, and are converted into
1265
 * jiffies.
1266
 *
1267
 * Returns 0 on success.
1268
 */
1269
int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
1270
                          void *buffer, size_t *lenp)
1271
{
1272
    return do_proc_dointvec(table,write,filp,buffer,lenp,HZ,OP_SET);
1273
}
1274
 
1275
#else /* CONFIG_PROC_FS */
1276
 
1277
int proc_dostring(ctl_table *table, int write, struct file *filp,
1278
                  void *buffer, size_t *lenp)
1279
{
1280
        return -ENOSYS;
1281
}
1282
 
1283
static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
1284
                            void *buffer, size_t *lenp)
1285
{
1286
        return -ENOSYS;
1287
}
1288
 
1289
int proc_dointvec(ctl_table *table, int write, struct file *filp,
1290
                  void *buffer, size_t *lenp)
1291
{
1292
        return -ENOSYS;
1293
}
1294
 
1295
int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1296
                        void *buffer, size_t *lenp)
1297
{
1298
        return -ENOSYS;
1299
}
1300
 
1301
int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
1302
                    void *buffer, size_t *lenp)
1303
{
1304
        return -ENOSYS;
1305
}
1306
 
1307
int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
1308
                    void *buffer, size_t *lenp)
1309
{
1310
        return -ENOSYS;
1311
}
1312
 
1313
int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
1314
                    void *buffer, size_t *lenp)
1315
{
1316
        return -ENOSYS;
1317
}
1318
 
1319
int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
1320
                                      struct file *filp,
1321
                                      void *buffer, size_t *lenp)
1322
{
1323
    return -ENOSYS;
1324
}
1325
 
1326
 
1327
#endif /* CONFIG_PROC_FS */
1328
 
1329
 
1330
/*
1331
 * General sysctl support routines
1332
 */
1333
 
1334
/* The generic string strategy routine: */
1335
int sysctl_string(ctl_table *table, int *name, int nlen,
1336
                  void *oldval, size_t *oldlenp,
1337
                  void *newval, size_t newlen, void **context)
1338
{
1339
        size_t l, len;
1340
 
1341
        if (!table->data || !table->maxlen)
1342
                return -ENOTDIR;
1343
 
1344
        if (oldval && oldlenp) {
1345
                if (get_user(len, oldlenp))
1346
                        return -EFAULT;
1347
                if (len) {
1348
                        l = strlen(table->data);
1349
                        if (len > l) len = l;
1350
                        if (len >= table->maxlen)
1351
                                len = table->maxlen;
1352
                        if(copy_to_user(oldval, table->data, len))
1353
                                return -EFAULT;
1354
                        if(put_user(0, ((char *) oldval) + len))
1355
                                return -EFAULT;
1356
                        if(put_user(len, oldlenp))
1357
                                return -EFAULT;
1358
                }
1359
        }
1360
        if (newval && newlen) {
1361
                len = newlen;
1362
                if (len > table->maxlen)
1363
                        len = table->maxlen;
1364
                if(copy_from_user(table->data, newval, len))
1365
                        return -EFAULT;
1366
                if (len == table->maxlen)
1367
                        len--;
1368
                ((char *) table->data)[len] = 0;
1369
        }
1370
        return 0;
1371
}
1372
 
1373
/*
1374
 * This function makes sure that all of the integers in the vector
1375
 * are between the minimum and maximum values given in the arrays
1376
 * table->extra1 and table->extra2, respectively.
1377
 */
1378
int sysctl_intvec(ctl_table *table, int *name, int nlen,
1379
                void *oldval, size_t *oldlenp,
1380
                void *newval, size_t newlen, void **context)
1381
{
1382
        int i, *vec, *min, *max;
1383
        size_t length;
1384
 
1385
        if (newval && newlen) {
1386
                if (newlen % sizeof(int) != 0)
1387
                        return -EINVAL;
1388
 
1389
                if (!table->extra1 && !table->extra2)
1390
                        return 0;
1391
 
1392
                if (newlen > table->maxlen)
1393
                        newlen = table->maxlen;
1394
                length = newlen / sizeof(int);
1395
 
1396
                vec = (int *) newval;
1397
                min = (int *) table->extra1;
1398
                max = (int *) table->extra2;
1399
 
1400
                for (i = 0; i < length; i++) {
1401
                        int value;
1402
                        if (get_user(value, vec + i))
1403
                                return -EFAULT;
1404
                        if (min && value < min[i])
1405
                                return -EINVAL;
1406
                        if (max && value > max[i])
1407
                                return -EINVAL;
1408
                }
1409
        }
1410
        return 0;
1411
}
1412
 
1413
/* Strategy function to convert jiffies to seconds */
1414
int sysctl_jiffies(ctl_table *table, int *name, int nlen,
1415
                void *oldval, size_t *oldlenp,
1416
                void *newval, size_t newlen, void **context)
1417
{
1418
        if (oldval) {
1419
                size_t olen;
1420
                if (oldlenp) {
1421
                        if (get_user(olen, oldlenp))
1422
                                return -EFAULT;
1423
                        if (olen!=sizeof(int))
1424
                                return -EINVAL;
1425
                }
1426
                if (put_user(*(int *)(table->data) / HZ, (int *)oldval) ||
1427
                    (oldlenp && put_user(sizeof(int),oldlenp)))
1428
                        return -EFAULT;
1429
        }
1430
        if (newval && newlen) {
1431
                int new;
1432
                if (newlen != sizeof(int))
1433
                        return -EINVAL;
1434
                if (get_user(new, (int *)newval))
1435
                        return -EFAULT;
1436
                *(int *)(table->data) = new*HZ;
1437
        }
1438
        return 1;
1439
}
1440
 
1441
 
1442
#else /* CONFIG_SYSCTL */
1443
 
1444
 
1445
extern asmlinkage long sys_sysctl(struct __sysctl_args *args)
1446
{
1447
        return -ENOSYS;
1448
}
1449
 
1450
int sysctl_string(ctl_table *table, int *name, int nlen,
1451
                  void *oldval, size_t *oldlenp,
1452
                  void *newval, size_t newlen, void **context)
1453
{
1454
        return -ENOSYS;
1455
}
1456
 
1457
int sysctl_intvec(ctl_table *table, int *name, int nlen,
1458
                void *oldval, size_t *oldlenp,
1459
                void *newval, size_t newlen, void **context)
1460
{
1461
        return -ENOSYS;
1462
}
1463
 
1464
int sysctl_jiffies(ctl_table *table, int *name, int nlen,
1465
                void *oldval, size_t *oldlenp,
1466
                void *newval, size_t newlen, void **context)
1467
{
1468
        return -ENOSYS;
1469
}
1470
 
1471
int proc_dostring(ctl_table *table, int write, struct file *filp,
1472
                  void *buffer, size_t *lenp)
1473
{
1474
        return -ENOSYS;
1475
}
1476
 
1477
int proc_dointvec(ctl_table *table, int write, struct file *filp,
1478
                  void *buffer, size_t *lenp)
1479
{
1480
        return -ENOSYS;
1481
}
1482
 
1483
int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
1484
                        void *buffer, size_t *lenp)
1485
{
1486
        return -ENOSYS;
1487
}
1488
 
1489
int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
1490
                    void *buffer, size_t *lenp)
1491
{
1492
        return -ENOSYS;
1493
}
1494
 
1495
int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
1496
                          void *buffer, size_t *lenp)
1497
{
1498
        return -ENOSYS;
1499
}
1500
 
1501
int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
1502
                    void *buffer, size_t *lenp)
1503
{
1504
        return -ENOSYS;
1505
}
1506
 
1507
int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
1508
                                      struct file *filp,
1509
                                      void *buffer, size_t *lenp)
1510
{
1511
    return -ENOSYS;
1512
}
1513
 
1514
struct ctl_table_header * register_sysctl_table(ctl_table * table,
1515
                                                int insert_at_head)
1516
{
1517
        return 0;
1518
}
1519
 
1520
void unregister_sysctl_table(struct ctl_table_header * table)
1521
{
1522
}
1523
 
1524
#endif /* CONFIG_SYSCTL */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.