sysctl.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:37k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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