netlib.narod.ru< Назад | Оглавление | Далее >

kernel/sysctl.c

30179 /*
30180  * sysctl.c: General linux system control interface
30181  *
30182  * Begun 24 March 1995, Stephen Tweedie
30183  * Added /proc support, Dec 1995
30184  * Added bdflush entry and intvec min/max checking,
30185  * 2/23/96, Tom Dyas.
30186  * Added hooks for /proc/sys/net (minor, minor patch),
30187  * 96/4/1, Mike Shaver.
30188  * Added kernel/java-{interpreter,appletviewer}, 96/5/10,
30189  * Mike Shaver.
30190  * Dynamic registration fixes, Stephen Tweedie.
30191  * Added kswapd-interval, ctrl-alt-del, printk stuff,
30192  * 1/8/97, Chris Horn.
30193  * Made sysctl support optional via CONFIG_SYSCTL,
30194  * 1/10/97, Chris Horn.  */
30195 
30196 #include <linux/config.h>
30197 #include <linux/malloc.h>
30198 #include <linux/sysctl.h>
30199 #include <linux/swapctl.h>
30200 #include <linux/proc_fs.h>
30201 #include <linux/ctype.h>
30202 #include <linux/utsname.h>
30203 #include <linux/swapctl.h>
30204 #include <linux/smp_lock.h>
30205 #include <linux/init.h>
30206 
30207 #include <asm/uaccess.h>
30208 
30209 #ifdef CONFIG_ROOT_NFS
30210 #include <linux/nfs_fs.h>
30211 #endif
30212 
30213 #if defined(CONFIG_SYSCTL)
30214 
30215 /* External variables not in a header file. */
30216 extern int panic_timeout;
30217 extern int console_loglevel, C_A_D;
30218 extern int bdf_prm[], bdflush_min[], bdflush_max[];
30219 extern char binfmt_java_interpreter[],
30220   binfmt_java_appletviewer[];
30221 extern int sysctl_overcommit_memory;
30222 extern int nr_queued_signals, max_queued_signals;
30223 
30224 #ifdef CONFIG_KMOD
30225 extern char modprobe_path[];
30226 #endif
30227 #ifdef CONFIG_CHR_DEV_SG
30228 extern int sg_big_buff;
30229 #endif
30230 #ifdef CONFIG_SYSVIPC
30231 extern int shmmax;
30232 #endif
30233 
30234 #ifdef __sparc__
30235 extern char reboot_command [];
30236 #endif
30237 #ifdef __powerpc__
30238 extern unsigned long htab_reclaim_on, zero_paged_on,
30239   powersave_nap;
30240 int proc_dol2crvec(ctl_table *table, int write,
30241   struct file *filp, void *buffer, size_t *lenp);
30242 #endif
30243 
30244 #ifdef CONFIG_BSD_PROCESS_ACCT
30245 extern int acct_parm[];
30246 #endif
30247 
30248 extern int pgt_cache_water[];
30249 
30250 static int parse_table(int *, int, void *, size_t *,
30251   void *, size_t, ctl_table *, void **);
30252 static int proc_doutsstring(ctl_table *table, int write,
30253   struct file *filp, void *buffer, size_t *lenp);
30254 
30255 static ctl_table root_table[];
30256 static struct ctl_table_header root_table_header =
30257   {root_table, DNODE_SINGLE(&root_table_header)};
30258 
30259 static ctl_table kern_table[];
30260 static ctl_table vm_table[];
30261 #ifdef CONFIG_NET
30262 extern ctl_table net_table[];
30263 #endif
30264 static ctl_table proc_table[];
30265 static ctl_table fs_table[];
30266 static ctl_table debug_table[];
30267 static ctl_table dev_table[];
30268 
30269 
30270 /* /proc declarations: */
30271 
30272 #ifdef CONFIG_PROC_FS
30273 
30274 static ssize_t proc_readsys(struct file *, char *,
30275                             size_t, loff_t *);
30276 static ssize_t proc_writesys(struct file *, const char *,
30277                              size_t, loff_t *);
30278 static int proc_sys_permission(struct inode *, int);
30279 
30280 struct file_operations proc_sys_file_operations =
30281 {
30282   NULL,           /* lseek   */
30283   proc_readsys,   /* read    */
30284   proc_writesys,  /* write   */
30285   NULL,           /* readdir */
30286   NULL,           /* poll    */
30287   NULL,           /* ioctl   */
30288   NULL,           /* mmap    */
30289   NULL,           /* no special open code    */
30290   NULL,           /* no special flush code */
30291   NULL,           /* no special release code */
30292   NULL            /* can't fsync */
30293 };
30294 
30295 struct inode_operations proc_sys_inode_operations =
30296 {
30297   &proc_sys_file_operations,
30298   NULL,           /* create */
30299   NULL,           /* lookup */
30300   NULL,           /* link */
30301   NULL,           /* unlink */
30302   NULL,           /* symlink */
30303   NULL,           /* mkdir */
30304   NULL,           /* rmdir */
30305   NULL,           /* mknod */
30306   NULL,           /* rename */
30307   NULL,           /* readlink */
30308   NULL,           /* follow_link */
30309   NULL,           /* readpage */
30310   NULL,           /* writepage */
30311   NULL,           /* bmap */
30312   NULL,           /* truncate */
30313   proc_sys_permission
30314 };
30315 
30316 extern struct proc_dir_entry proc_sys_root;
30317 
30318 static void register_proc_table(ctl_table *,
30319                                 struct proc_dir_entry *);
30320 static void unregister_proc_table(ctl_table *,
30321                                 struct proc_dir_entry *);
30322 #endif
30323 extern int inodes_stat[];
30324 extern int dentry_stat[];
30325 
30326 /* The default sysctl tables: */
30327 
30328 static ctl_table root_table[] = {
30329   {CTL_KERN, "kernel", NULL, 0, 0555, kern_table},
30330   {CTL_VM, "vm", NULL, 0, 0555, vm_table},
30331 #ifdef CONFIG_NET
30332   {CTL_NET, "net", NULL, 0, 0555, net_table},
30333 #endif
30334   {CTL_PROC, "proc", NULL, 0, 0555, proc_table},
30335   {CTL_FS, "fs", NULL, 0, 0555, fs_table},
30336   {CTL_DEBUG, "debug", NULL, 0, 0555, debug_table},
30337   {CTL_DEV, "dev", NULL, 0, 0555, dev_table},
30338   {0}
30339 };
30340 
30341 static ctl_table kern_table[] = {
30342   {KERN_OSTYPE, "ostype", system_utsname.sysname, 64,
30343    0444, NULL, &proc_doutsstring, &sysctl_string},
30344   {KERN_OSRELEASE, "osrelease", system_utsname.release,
30345    64, 0444, NULL, &proc_doutsstring, &sysctl_string},
30346   {KERN_VERSION, "version", system_utsname.version, 64,
30347    0444, NULL, &proc_doutsstring, &sysctl_string},
30348   {KERN_NODENAME, "hostname", system_utsname.nodename,
30349    64, 0644, NULL, &proc_doutsstring, &sysctl_string},
30350   {KERN_DOMAINNAME, "domainname",
30351    system_utsname.domainname, 64,
30352    0644, NULL, &proc_doutsstring, &sysctl_string},
30353   {KERN_PANIC, "panic", &panic_timeout, sizeof(int),
30354    0644, NULL, &proc_dointvec},
30355 #ifdef CONFIG_BLK_DEV_INITRD
30356   {KERN_REALROOTDEV, "real-root-dev", &real_root_dev,
30357    sizeof(int), 0644, NULL, &proc_dointvec},
30358 #endif
30359 #ifdef CONFIG_BINFMT_JAVA
30360   {KERN_JAVA_INTERPRETER, "java-interpreter",
30361    binfmt_java_interpreter,
30362    64, 0644, NULL, &proc_dostring, &sysctl_string },
30363   {KERN_JAVA_APPLETVIEWER, "java-appletviewer",
30364    binfmt_java_appletviewer,
30365    64, 0644, NULL, &proc_dostring, &sysctl_string },
30366 #endif
30367 #ifdef __sparc__
30368   {KERN_SPARC_REBOOT, "reboot-cmd", reboot_command,
30369    256, 0644, NULL, &proc_dostring, &sysctl_string },
30370 #endif
30371 #ifdef __powerpc__
30372   {KERN_PPC_HTABRECLAIM, "htab-reclaim",
30373    &htab_reclaim_on, sizeof(int),
30374    0644, NULL, &proc_dointvec},
30375   {KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on,
30376    sizeof(int), 0644, NULL, &proc_dointvec},
30377   {KERN_PPC_POWERSAVE_NAP, "powersave-nap",
30378    &powersave_nap, sizeof(int),
30379    0644, NULL, &proc_dointvec},
30380   {KERN_PPC_L2CR, "l2cr", NULL, 0,
30381    0644, NULL, &proc_dol2crvec},
30382 #endif
30383   {KERN_CTLALTDEL, "ctrl-alt-del", &C_A_D, sizeof(int),
30384    0644, NULL, &proc_dointvec},
30385   {KERN_PRINTK, "printk", &console_loglevel,
30386    4*sizeof(int), 0644, NULL, &proc_dointvec},
30387 #ifdef CONFIG_KMOD
30388   {KERN_MODPROBE, "modprobe", &modprobe_path, 256,
30389    0644, NULL, &proc_dostring, &sysctl_string },
30390 #endif
30391 #ifdef CONFIG_CHR_DEV_SG
30392   {KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff,
30393    sizeof (int), 0444, NULL, &proc_dointvec},
30394 #endif
30395 #ifdef CONFIG_BSD_PROCESS_ACCT
30396   {KERN_ACCT, "acct", &acct_parm, 3*sizeof(int),
30397   0644, NULL, &proc_dointvec},
30398 #endif
30399   {KERN_RTSIGNR, "rtsig-nr", &nr_queued_signals,
30400    sizeof(int), 0444, NULL, &proc_dointvec},
30401   {KERN_RTSIGMAX, "rtsig-max", &max_queued_signals,
30402    sizeof(int), 0644, NULL, &proc_dointvec},
30403 #ifdef CONFIG_SYSVIPC
30404   {KERN_SHMMAX, "shmmax", &shmmax, sizeof (int),
30405    0644, NULL, &proc_dointvec},
30406 #endif
30407   {0}
30408 };
30409 
30410 static ctl_table vm_table[] = {
30411   {VM_FREEPG, "freepages", &freepages,
30412    sizeof(freepages_t), 0644, NULL, &proc_dointvec},
30413   {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600,
30414    NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
30415    &bdflush_min, &bdflush_max},
30416   {VM_OVERCOMMIT_MEMORY, "overcommit_memory",
30417    &sysctl_overcommit_memory,
30418    sizeof(sysctl_overcommit_memory), 0644, NULL,
30419    &proc_dointvec},
30420   {VM_BUFFERMEM, "buffermem", &buffer_mem,
30421    sizeof(buffer_mem_t), 0644, NULL, &proc_dointvec},
30422   {VM_PAGECACHE, "pagecache", &page_cache,
30423    sizeof(buffer_mem_t), 0644, NULL, &proc_dointvec},
30424   {VM_PAGERDAEMON, "kswapd", &pager_daemon,
30425    sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
30426   {VM_PGT_CACHE, "pagetable_cache", &pgt_cache_water,
30427    2*sizeof(int), 0600, NULL, &proc_dointvec},
30428   {VM_PAGE_CLUSTER, "page-cluster", &page_cluster,
30429    sizeof(int), 0600, NULL, &proc_dointvec},
30430   {0}
30431 };
30432 
30433 static ctl_table proc_table[] = { {0} };
30434 
30435 static ctl_table fs_table[] = {
30436   {FS_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int),
30437    0444, NULL, &proc_dointvec},
30438   {FS_STATINODE, "inode-state", &inodes_stat,
30439    7*sizeof(int), 0444, NULL, &proc_dointvec},
30440   {FS_MAXINODE, "inode-max", &max_inodes, sizeof(int),
30441    0644, NULL, &proc_dointvec},
30442   {FS_NRFILE, "file-nr", &nr_files, 3*sizeof(int),
30443    0444, NULL, &proc_dointvec},
30444   {FS_MAXFILE, "file-max", &max_files, sizeof(int),
30445    0644, NULL, &proc_dointvec},
30446   {FS_NRSUPER, "super-nr", &nr_super_blocks, sizeof(int),
30447    0444, NULL, &proc_dointvec},
30448   {FS_MAXSUPER, "super-max", &max_super_blocks,
30449    sizeof(int), 0644, NULL, &proc_dointvec},
30450   {FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int),
30451    0444, NULL, &proc_dointvec},
30452   {FS_MAXDQUOT, "dquot-max", &max_dquots, sizeof(int),
30453    0644, NULL, &proc_dointvec},
30454   {FS_DENTRY, "dentry-state", &dentry_stat,
30455    6*sizeof(int), 0444, NULL, &proc_dointvec},
30456   {0}
30457 };
30458 
30459 static ctl_table debug_table[] = { {0} };
30460 
30461 static ctl_table dev_table[] = { {0} };
30462 
30463 void __init sysctl_init(void)
30464 {
30465 #ifdef CONFIG_PROC_FS
30466   register_proc_table(root_table, &proc_sys_root);
30467 #endif
30468 }
30469 
30470 
 Комментарий
30471 int do_sysctl (int *name, int nlen,
30472          void *oldval, size_t *oldlenp,
30473          void *newval, size_t newlen)
30474 {
30475   int error;
30476   struct ctl_table_header *tmp;
30477   void *context;
30478 
30479   if (nlen == 0 || nlen >= CTL_MAXNAME)
30480     return -ENOTDIR;
30481 
30482   if (oldval)
30483   {
30484     int old_len;
30485     if (!oldlenp)
30486       return -EFAULT;
30487     if(get_user(old_len, oldlenp))
30488       return -EFAULT;
30489   }
30490   tmp = &root_table_header;
30491   do {
30492     context = NULL;
30493     error = parse_table(name, nlen, oldval, oldlenp,
30494             newval, newlen, tmp->ctl_table, &context);
30495     if (context)
30496       kfree(context);
30497     if (error != -ENOTDIR)
30498       return error;
30499     tmp = tmp->DLIST_NEXT(ctl_entry);
30500   } while (tmp != &root_table_header);
30501   return -ENOTDIR;
30502 }
30503 
30504 extern asmlinkage int sys_sysctl(
30505   struct __sysctl_args *args)
30506 {
30507   struct __sysctl_args tmp;
30508   int error;
30509 
30510   if (copy_from_user(&tmp, args, sizeof(tmp)))
30511     return -EFAULT;
30512 
30513   lock_kernel();
30514   error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval,
30515                     tmp.oldlenp, tmp.newval, tmp.newlen);
30516   unlock_kernel();
30517   return error;
30518 }
30519 
30520 /* Like in_group_p, but testing against egid,
30521  * not fsgid */
30522 static int in_egroup_p(gid_t grp)
30523 {
30524   if (grp != current->egid) {
30525     int i = current->ngroups;
30526     if (i) {
30527       gid_t *groups = current->groups;
30528       do {
30529         if (*groups == grp)
30530           goto out;
30531         groups++;
30532         i--;
30533       } while (i);
30534     }
30535     return 0;
30536   }
30537 out:
30538   return 1;
30539 }
30540 
30541 /* ctl_perm does NOT grant the superuser all rights
30542  * automatically, because some sysctl variables are
30543  * readonly even to root. */
30544 static int test_perm(int mode, int op)
30545 {
30546   if (!current->euid)
30547     mode >>= 6;
30548   else if (in_egroup_p(0))
30549     mode >>= 3;
30550   if ((mode & op & 0007) == op)
30551     return 0;
30552   return -EACCES;
30553 }
30554 
30555 static inline int ctl_perm(ctl_table *table, int op)
30556 {
30557   return test_perm(table->mode, op);
30558 }
30559 
 Комментарий
30560 static int parse_table(int *name, int nlen,
30561            void *oldval, size_t *oldlenp,
30562            void *newval, size_t newlen,
30563            ctl_table *table, void **context)
30564 {
30565   int error;
30566 repeat:
30567   if (!nlen)
30568     return -ENOTDIR;
30569 
 Комментарий
30570   for ( ; table->ctl_name; table++) {
30571     int n;
30572     if(get_user(n,name))
30573       return -EFAULT;
30574     if (n == table->ctl_name ||
30575         table->ctl_name == CTL_ANY) {
30576       if (table->child) {
30577         if (ctl_perm(table, 001))
30578           return -EPERM;
30579         if (table->strategy) {
30580           error = table->strategy(
30581             table, name, nlen,
30582             oldval, oldlenp,
30583             newval, newlen, context);
30584         if (error)
30585           return error;
30586         }
30587         name++;
30588         nlen--;
30589         table = table->child;
30590         goto repeat;
30591       }
30592       error = do_sysctl_strategy(table, name, nlen,
30593                oldval, oldlenp,
30594                newval, newlen, context);
30595       return error;
30596     }
30597   };
30598   return -ENOTDIR;
30599 }
30600 
30601 /* Perform the actual read/write of a sysctl table
30602  * entry. */
 Комментарий
30603 int do_sysctl_strategy (ctl_table *table,
30604       int *name, int nlen,
30605       void *oldval, size_t *oldlenp,
30606       void *newval, size_t newlen, void **context)
30607 {
30608   int op = 0, rc, len;
30609 
30610   if (oldval)
30611     op |= 004;
30612   if (newval)
30613     op |= 002;
30614   if (ctl_perm(table, op))
30615     return -EPERM;
30616 
30617   if (table->strategy) {
30618     rc = table->strategy(table, name, nlen, oldval,
30619                        oldlenp, newval, newlen, context);
30620     if (rc < 0)
30621       return rc;
30622     if (rc > 0)
30623       return 0;
30624   }
30625 
30626   /* If there is no strategy routine, or if the strategy
30627    * returns zero, proceed with automatic r/w */
30628   if (table->data && table->maxlen) {
30629     if (oldval && oldlenp) {
30630       get_user(len, oldlenp);
30631       if (len) {
30632         if (len > table->maxlen)
30633           len = table->maxlen;
30634         if(copy_to_user(oldval, table->data, len))
30635           return -EFAULT;
30636         if(put_user(len, oldlenp))
30637           return -EFAULT;
30638       }
30639     }
30640     if (newval && newlen) {
30641       len = newlen;
30642       if (len > table->maxlen)
30643         len = table->maxlen;
30644       if(copy_from_user(table->data, newval, len))
30645         return -EFAULT;
30646     }
30647   }
30648   return 0;
30649 }
30650 
 Комментарий
30651 struct ctl_table_header *register_sysctl_table(
30652   ctl_table * table, int insert_at_head)
30653 {
30654   struct ctl_table_header *tmp;
30655   tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
30656   if (!tmp)
30657     return 0;
30658   *tmp = ((struct ctl_table_header) {table, DNODE_NULL});
30659   if (insert_at_head)
30660     DLIST_INSERT_AFTER(&root_table_header, tmp,
30661                        ctl_entry);
30662   else
30663     DLIST_INSERT_BEFORE(&root_table_header, tmp,
30664                         ctl_entry);
30665 #ifdef CONFIG_PROC_FS
30666   register_proc_table(table, &proc_sys_root);
30667 #endif
30668   return tmp;
30669 }
30670 
30671 /* Unlink and free a ctl_table. */
 Комментарий
30672 void unregister_sysctl_table(
30673   struct ctl_table_header * header)
30674 {
30675   DLIST_DELETE(header, ctl_entry);
30676 #ifdef CONFIG_PROC_FS
30677   unregister_proc_table(header->ctl_table,
30678                         &proc_sys_root);
30679 #endif
30680   kfree(header);
30681 }
30682 
30683 /* /proc/sys support */
30684 
30685 #ifdef CONFIG_PROC_FS
30686 
30687 /* Scan the sysctl entries in table and add them all into
30688  * /proc */
 Комментарий
30689 static void register_proc_table(ctl_table * table,
30690                              struct proc_dir_entry *root)
30691 {
30692   struct proc_dir_entry *de;
30693   int len;
30694   mode_t mode;
30695 
30696   for (; table->ctl_name; table++) {
30697     /* Can't do anything without a proc name. */
30698     if (!table->procname)
30699       continue;
30700     /* Maybe we can't do anything with it... */
30701     if (!table->proc_handler && !table->child) {
30702       printk(KERN_WARNING "SYSCTL: Can't register %s\n",
30703         table->procname);
30704       continue;
30705     }
30706 
30707     len = strlen(table->procname);
30708     mode = table->mode;
30709 
30710     de = NULL;
30711     if (table->proc_handler)
30712       mode |= S_IFREG;
30713     else {
30714       mode |= S_IFDIR;
30715       for (de = root->subdir; de; de = de->next) {
30716         if (proc_match(len, table->procname, de))
30717           break;
30718       }
30719       /* If the subdir exists already, de is non-NULL */
30720     }
30721 
30722     if (!de) {
30723       de = create_proc_entry(table->procname, mode,root);
30724       if (!de)
30725         continue;
30726       de->data = (void *) table;
30727       if (table->proc_handler)
30728         de->ops = &proc_sys_inode_operations;
30729 
30730     }
30731     table->de = de;
30732     if (de->mode & S_IFDIR)
30733       register_proc_table(table->child, de);
30734   }
30735 }
30736 
30737 /* Unregister a /proc sysctl table and any
30738  * subdirectories.  */
 Комментарий
30739 static void unregister_proc_table(ctl_table * table,
30740                              struct proc_dir_entry *root)
30741 {
30742   struct proc_dir_entry *de;
30743   for (; table->ctl_name; table++) {
30744     if (!(de = table->de))
30745       continue;
30746     if (de->mode & S_IFDIR) {
30747       if (!table->child) {
30748         printk(KERN_ALERT
30749                "Help - malformed sysctl tree on free\n");
30750         continue;
30751       }
30752       unregister_proc_table(table->child, de);
30753 
30754       /* Don't unregister directories which still have
30755        * entries.. */
30756       if (de->subdir)
30757         continue;
30758     }
30759 
30760     /* Don't unregister proc entries that are still being
30761      * used.. */
30762     if (de->count)
30763       continue;
30764 
30765     proc_unregister(root, de->low_ino);
30766     table->de = NULL;
30767     kfree(de);
30768   }
30769 }
30770 
 Комментарий
30771 static ssize_t do_rw_proc(int write, struct file * file,
30772   char * buf, size_t count, loff_t *ppos)
30773 {
30774   int op;
30775   struct proc_dir_entry *de;
30776   struct ctl_table *table;
30777   size_t res;
30778   ssize_t error;
30779 
30780   de = (struct proc_dir_entry *)
30781     file->f_dentry->d_inode->u.generic_ip;
30782   if (!de || !de->data)
30783     return -ENOTDIR;
30784   table = (struct ctl_table *) de->data;
30785   if (!table || !table->proc_handler)
30786     return -ENOTDIR;
30787   op = (write ? 002 : 004);
30788   if (ctl_perm(table, op))
30789     return -EPERM;
30790 
30791   res = count;
30792 
30793   /* FIXME: we need to pass on ppos to the handler. */
30794 
30795   error =
30796     (*table->proc_handler)(table, write, file, buf,&res);
30797   if (error)
30798     return error;
30799   return res;
30800 }
30801 
30802 static ssize_t proc_readsys(struct file * file,
30803   char * buf, size_t count, loff_t *ppos)
30804 {
30805   return do_rw_proc(0, file, buf, count, ppos);
30806 }
30807 
30808 static ssize_t proc_writesys(struct file * file,
30809   const char * buf, size_t count, loff_t *ppos)
30810 {
30811   return do_rw_proc(1, file, (char *) buf, count, ppos);
30812 }
30813 
30814 static int proc_sys_permission(struct inode *inode,
30815                                int op)
30816 {
30817   return test_perm(inode->i_mode, op);
30818 }
30819 
 Комментарий
30820 int proc_dostring(ctl_table *table, int write,
30821   struct file *filp, void *buffer, size_t *lenp)
30822 {
30823   int len;
30824   char *p, c;
30825 
30826   if (!table->data || !table->maxlen || !*lenp ||
30827       (filp->f_pos && !write)) {
30828     *lenp = 0;
30829     return 0;
30830   }
30831 
30832   if (write) {
30833     len = 0;
30834     p = buffer;
30835     while (len < *lenp) {
30836       if(get_user(c, p++))
30837         return -EFAULT;
30838       if (c == 0 || c == '\n')
30839         break;
30840       len++;
30841     }
30842     if (len >= table->maxlen)
30843       len = table->maxlen-1;
30844     if(copy_from_user(table->data, buffer, len))
30845       return -EFAULT;
30846     ((char *) table->data)[len] = 0;
30847     filp->f_pos += *lenp;
30848   } else {
30849     len = strlen(table->data);
30850     if (len > table->maxlen)
30851       len = table->maxlen;
30852     if (len > *lenp)
30853       len = *lenp;
30854     if (len)
30855       if(copy_to_user(buffer, table->data, len))
30856         return -EFAULT;
30857     if (len < *lenp) {
30858       if(put_user('\n', ((char *) buffer) + len))
30859         return -EFAULT;
30860       len++;
30861     }
30862     *lenp = len;
30863     filp->f_pos += len;
30864   }
30865   return 0;
30866 }
30867 
30868 /* Special case of dostring for the UTS structure. This
30869  * has locks to observe. Should this be in kernel/sys.c
30870  * ????  */
 Комментарий
30871 static int proc_doutsstring(ctl_table *table, int write,
30872   struct file *filp, void *buffer, size_t *lenp)
30873 {
30874   int r;
30875   down(&uts_sem);
30876   r=proc_dostring(table,write,filp,buffer,lenp);
30877   up(&uts_sem);
30878   return r;
30879 }
30880 
 Комментарий
30881 static int do_proc_dointvec(ctl_table *table, int write,
30882  struct file *filp, void *buffer, size_t *lenp, int conv)
30883 {
30884   int *i, vleft, first=1, len, left, neg, val;
30885   #define TMPBUFLEN 20
30886   char buf[TMPBUFLEN], *p;
30887 
30888   if (!table->data || !table->maxlen || !*lenp ||
30889       (filp->f_pos && !write)) {
30890     *lenp = 0;
30891     return 0;
30892   }
30893 
30894   i = (int *) table->data;
30895   vleft = table->maxlen / sizeof(int);
30896   left = *lenp;
30897 
30898   for (; left && vleft--; i++, first=0) {
30899     if (write) {
30900       while (left) {
30901         char c;
30902         if(get_user(c,(char *) buffer))
30903           return -EFAULT;
30904         if (!isspace(c))
30905           break;
30906         left--;
30907         ((char *) buffer)++;
30908       }
30909       if (!left)
30910         break;
30911       neg = 0;
30912       len = left;
30913       if (len > TMPBUFLEN-1)
30914         len = TMPBUFLEN-1;
30915       if(copy_from_user(buf, buffer, len))
30916         return -EFAULT;
30917       buf[len] = 0;
30918       p = buf;
 Комментарий
30919       if (*p == '-' && left > 1) {
30920         neg = 1;
30921         left--, p++;
30922       }
30923       if (*p < '0' || *p > '9')
30924         break;
30925       val = simple_strtoul(p, &p, 0) * conv;
30926       len = p-buf;
30927       if ((len < left) && *p && !isspace(*p))
30928         break;
30929       if (neg)
30930         val = -val;
30931       buffer += len;
30932       left -= len;
30933       *i = val;
30934     } else {
30935       p = buf;
30936       if (!first)
30937         *p++ = '\t';
30938       sprintf(p, "%d", (*i) / conv);
30939       len = strlen(buf);
30940       if (len > left)
30941         len = left;
30942       if(copy_to_user(buffer, buf, len))
30943         return -EFAULT;
30944       left -= len;
30945       buffer += len;
30946     }
30947   }
30948 
30949   if (!write && !first && left) {
30950     if(put_user('\n', (char *) buffer))
30951       return -EFAULT;
30952     left--, buffer++;
30953   }
30954   if (write) {
30955     p = (char *) buffer;
30956     while (left) {
30957       char c;
30958       if(get_user(c, p++))
30959         return -EFAULT;
30960       if (!isspace(c))
30961         break;
30962       left--;
30963     }
30964   }
30965   if (write && first)
30966     return -EINVAL;
30967   *lenp -= left;
30968   filp->f_pos += *lenp;
30969   return 0;
30970 }
30971 
30972 int proc_dointvec(ctl_table *table, int write,
30973   struct file *filp, void *buf, size_t *lenp)
30974 {
30975   return do_proc_dointvec(table,write,filp,buf,lenp,1);
30976 }
30977 
 Комментарий
30978 int proc_dointvec_minmax(ctl_table *table, int write,
30979   struct file *filp, void *buffer, size_t *lenp)
30980 {
30981   int *i, *min, *max, vleft, first=1, len, left, neg,val;
30982   #define TMPBUFLEN 20
30983   char buf[TMPBUFLEN], *p;
30984 
30985   if (!table->data || !table->maxlen || !*lenp ||
30986       (filp->f_pos && !write)) {
30987     *lenp = 0;
30988     return 0;
30989   }
30990 
30991   i = (int *) table->data;
30992   min = (int *) table->extra1;
30993   max = (int *) table->extra2;
30994   vleft = table->maxlen / sizeof(int);
30995   left = *lenp;
30996 
30997   for (; left && vleft--; i++, first=0) {
30998     if (write) {
30999       while (left) {
31000         char c;
31001         if(get_user(c, (char *) buffer))
31002           return -EFAULT;
31003         if (!isspace(c))
31004           break;
31005         left--;
31006         ((char *) buffer)++;
31007       }
31008       if (!left)
31009         break;
31010       neg = 0;
31011       len = left;
31012       if (len > TMPBUFLEN-1)
31013         len = TMPBUFLEN-1;
31014       if(copy_from_user(buf, buffer, len))
31015         return -EFAULT;
31016       buf[len] = 0;
31017       p = buf;
31018       if (*p == '-' && left > 1) {
31019         neg = 1;
31020         left--, p++;
31021       }
31022       if (*p < '0' || *p > '9')
31023         break;
31024       val = simple_strtoul(p, &p, 0);
31025       len = p-buf;
31026       if ((len < left) && *p && !isspace(*p))
31027         break;
31028       if (neg)
31029         val = -val;
31030       buffer += len;
31031       left -= len;
31032 
 Комментарий
31033       if (min && val < *min++)
31034         continue;
31035       if (max && val > *max++)
31036         continue;
31037       *i = val;
31038     } else {
31039       p = buf;
31040       if (!first)
31041         *p++ = '\t';
31042       sprintf(p, "%d", *i);
31043       len = strlen(buf);
31044       if (len > left)
31045         len = left;
31046       if(copy_to_user(buffer, buf, len))
31047         return -EFAULT;
31048       left -= len;
31049       buffer += len;
31050     }
31051   }
31052 
31053   if (!write && !first && left) {
31054     if(put_user('\n', (char *) buffer))
31055       return -EFAULT;
31056     left--, buffer++;
31057   }
31058   if (write) {
31059     p = (char *) buffer;
31060     while (left) {
31061       char c;
31062       if(get_user(c, p++))
31063         return -EFAULT;
31064       if (!isspace(c))
31065         break;
31066       left--;
31067     }
31068   }
31069   if (write && first)
31070     return -EINVAL;
31071   *lenp -= left;
31072   filp->f_pos += *lenp;
31073   return 0;
31074 }
31075 
31076 /* Like proc_dointvec, but converts seconds to jiffies */
31077 int proc_dointvec_jiffies(ctl_table *tbl, int write,
31078   struct file *filp, void *buf, size_t *lenp)
31079 {
31080     return do_proc_dointvec(tbl,write,filp,buf,lenp,HZ);
31081 }
31082 
31083 #else /* CONFIG_PROC_FS */
31084 
31085 int proc_dostring(ctl_table *table, int write,
31086   struct file *filp, void *buffer, size_t *lenp)
31087 {
31088   return -ENOSYS;
31089 }
31090 
31091 static int proc_doutsstring(ctl_table *table, int write,
31092   struct file *filp, void *buffer, size_t *lenp)
31093 {
31094   return -ENOSYS;
31095 }
31096 
31097 int proc_dointvec(ctl_table *table, int write,
31098   struct file *filp, void *buffer, size_t *lenp)
31099 {
31100   return -ENOSYS;
31101 }
31102 
31103 int proc_dointvec_minmax(ctl_table *table, int write,
31104   struct file *filp, void *buffer, size_t *lenp)
31105 {
31106   return -ENOSYS;
31107 }
31108 
31109 int proc_dointvec_jiffies(ctl_table *table, int write,
31110   struct file *filp, void *buffer, size_t *lenp)
31111 {
31112   return -ENOSYS;
31113 }
31114 
31115 #endif /* CONFIG_PROC_FS */
31116 
31117 
31118 /* General sysctl support routines */
31119 
31120 /* The generic string strategy routine: */
 Комментарий
31121 int sysctl_string(ctl_table *table, int *name, int nlen,
31122       void *oldval, size_t *oldlenp,
31123       void *newval, size_t newlen, void **context)
31124 {
31125   int l, len;
31126 
31127   if (!table->data || !table->maxlen)
31128     return -ENOTDIR;
31129 
31130   if (oldval && oldlenp) {
31131     if (get_user(len, oldlenp))
31132       return -EFAULT;
31133     if (len) {
31134       l = strlen(table->data);
31135       if (len > l) len = l;
31136       if (len >= table->maxlen)
31137         len = table->maxlen;
31138       if (copy_to_user(oldval, table->data, len))
31139         return -EFAULT;
31140       if (put_user(0, ((char *) oldval) + len))
31141         return -EFAULT;
31142       if (put_user(len, oldlenp))
31143         return -EFAULT;
31144     }
31145   }
31146   if (newval && newlen) {
31147     len = newlen;
31148     if (len > table->maxlen)
31149       len = table->maxlen;
31150     if (copy_from_user(table->data, newval, len))
31151       return -EFAULT;
31152     if (len == table->maxlen)
31153       len--;
31154     ((char *) table->data)[len] = 0;
31155   }
31156   return 0;
31157 }
31158 
31159 /* This function makes sure that all of the integers in
31160  * the vector are between the minimum and maximum values
31161  * given in the arrays table->extra1 and table->extra2,
31162  * respectively.  */
 Комментарий
31163 int sysctl_intvec(ctl_table *table, int *name, int nlen,
31164     void *oldval, size_t *oldlenp,
31165     void *newval, size_t newlen, void **context)
31166 {
31167   int i, length, *vec, *min, *max;
31168 
31169   if (newval && newlen) {
 Комментарий
31170     if (newlen % sizeof(int) != 0)
31171       return -EINVAL;
31172 
31173     if (!table->extra1 && !table->extra2)
31174       return 0;
31175 
31176     if (newlen > table->maxlen)
31177       newlen = table->maxlen;
31178     length = newlen / sizeof(int);
31179 
31180     vec = (int *) newval;
31181     min = (int *) table->extra1;
31182     max = (int *) table->extra2;
31183 
31184     for (i = 0; i < length; i++) {
31185       int value;
31186       get_user(value, vec + i);
31187       if (min && value < min[i])
31188         return -EINVAL;
31189       if (max && value > max[i])
31190         return -EINVAL;
31191     }
31192   }
31193   return 0;
31194 }
31195 
31196 int do_string (void *oldval, size_t *oldlenp,
31197                void *newval, size_t newlen,
31198                int rdwr, char *data, size_t max)
31199 {
31200   int l = strlen(data) + 1;
31201   if (newval && !rdwr)
31202     return -EPERM;
31203   if (newval && newlen >= max)
31204     return -EINVAL;
31205   if (oldval) {
31206     int old_l;
31207     if (get_user(old_l, oldlenp))
31208       return -EFAULT;
31209     if (l > old_l)
31210       return -ENOMEM;
31211     if (put_user(l, oldlenp) ||
31212         copy_to_user(oldval, data, l))
31213       return -EFAULT;
31214   }
31215   if (newval) {
31216     if (copy_from_user(data, newval, newlen))
31217       return -EFAULT;
31218     data[newlen] = 0;
31219   }
31220   return 0;
31221 }
31222 
31223 int do_int (void *oldval, size_t *oldlenp,
31224             void *newval, size_t newlen,
31225             int rdwr, int *data)
31226 {
31227   if (newval && !rdwr)
31228     return -EPERM;
31229   if (newval && newlen != sizeof(int))
31230     return -EINVAL;
31231   if (oldval) {
31232     int old_l;
31233     if (get_user(old_l, oldlenp))
31234       return -EFAULT;
31235     if (old_l < sizeof(int))
31236       return -ENOMEM;
31237     if (put_user(sizeof(int), oldlenp) ||
31238         copy_to_user(oldval, data, sizeof(int)))
31239       return -EFAULT;
31240   }
31241   if (newval)
31242     if (copy_from_user(data, newval, sizeof(int)))
31243       return -EFAULT;
31244   return 0;
31245 }
31246 
31247 int do_struct (void *oldval, size_t *oldlenp,
31248                void *newval, size_t newlen,
31249                int rdwr, void *data, size_t len)
31250 {
31251   if (newval && !rdwr)
31252     return -EPERM;
31253   if (newval && newlen != len)
31254     return -EINVAL;
31255   if (oldval) {
31256     int old_l;
31257     if (get_user(old_l, oldlenp))
31258       return -EFAULT;
31259     if (old_l < len)
31260       return -ENOMEM;
31261     if (put_user(len, oldlenp) ||
31262         copy_to_user(oldval, data, len))
31263       return -EFAULT;
31264   }
31265   if (newval)
31266     if (copy_from_user(data, newval, len))
31267       return -EFAULT;
31268   return 0;
31269 }
31270 
31271 
31272 #else /* CONFIG_SYSCTL */
31273 
31274 
31275 extern asmlinkage int sys_sysctl(
31276   struct __sysctl_args *args)
31277 {
31278   return -ENOSYS;
31279 }
31280 
31281 int sysctl_string(ctl_table *table, int *name, int nlen,
31282       void *oldval, size_t *oldlenp,
31283       void *newval, size_t newlen, void **context)
31284 {
31285   return -ENOSYS;
31286 }
31287 
31288 int sysctl_intvec(ctl_table *table, int *name, int nlen,
31289     void *oldval, size_t *oldlenp,
31290     void *newval, size_t newlen, void **context)
31291 {
31292   return -ENOSYS;
31293 }
31294 
31295 int proc_dostring(ctl_table *table, int write,
31296   struct file *filp, void *buffer, size_t *lenp)
31297 {
31298   return -ENOSYS;
31299 }
31300 
31301 int proc_dointvec(ctl_table *table, int write,
31302   struct file *filp, void *buffer, size_t *lenp)
31303 {
31304   return -ENOSYS;
31305 }
31306 
31307 int proc_dointvec_minmax(ctl_table *table, int write,
31308   struct file *filp, void *buffer, size_t *lenp)
31309 {
31310   return -ENOSYS;
31311 }
31312 
31313 int proc_dointvec_jiffies(ctl_table *table, int write,
31314   struct file *filp, void *buffer, size_t *lenp)
31315 {
31316   return -ENOSYS;
31317 }
31318 
31319 struct ctl_table_header *
31320 register_sysctl_table(ctl_table *tbl, int insert_at_head)
31321 {
31322   return 0;
31323 }
31324 
31325 void unregister_sysctl_table(
31326   struct ctl_table_header * table)
31327 {
31328 }
31329 
31330 #endif /* CONFIG_SYSCTL */

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz