linux/Documentation/DocBook/procfs_example.c
<<
>>
Prefs
   1/*
   2 * procfs_example.c: an example proc interface
   3 *
   4 * Copyright (C) 2001, Erik Mouw (mouw@nl.linux.org)
   5 *
   6 * This file accompanies the procfs-guide in the Linux kernel
   7 * source. Its main use is to demonstrate the concepts and
   8 * functions described in the guide.
   9 *
  10 * This software has been developed while working on the LART
  11 * computing board (http://www.lartmaker.nl), which was sponsored
  12 * by the Delt University of Technology projects Mobile Multi-media
  13 * Communications and Ubiquitous Communications.
  14 *
  15 * This program is free software; you can redistribute
  16 * it and/or modify it under the terms of the GNU General
  17 * Public License as published by the Free Software
  18 * Foundation; either version 2 of the License, or (at your
  19 * option) any later version.
  20 *
  21 * This program is distributed in the hope that it will be
  22 * useful, but WITHOUT ANY WARRANTY; without even the implied
  23 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  24 * PURPOSE.  See the GNU General Public License for more
  25 * details.
  26 * 
  27 * You should have received a copy of the GNU General Public
  28 * License along with this program; if not, write to the
  29 * Free Software Foundation, Inc., 59 Temple Place,
  30 * Suite 330, Boston, MA  02111-1307  USA
  31 *
  32 */
  33
  34#include <linux/module.h>
  35#include <linux/kernel.h>
  36#include <linux/init.h>
  37#include <linux/proc_fs.h>
  38#include <linux/jiffies.h>
  39#include <asm/uaccess.h>
  40
  41
  42#define MODULE_VERS "1.0"
  43#define MODULE_NAME "procfs_example"
  44
  45#define FOOBAR_LEN 8
  46
  47struct fb_data_t {
  48        char name[FOOBAR_LEN + 1];
  49        char value[FOOBAR_LEN + 1];
  50};
  51
  52
  53static struct proc_dir_entry *example_dir, *foo_file,
  54        *bar_file, *jiffies_file, *symlink;
  55
  56
  57struct fb_data_t foo_data, bar_data;
  58
  59
  60static int proc_read_jiffies(char *page, char **start,
  61                             off_t off, int count,
  62                             int *eof, void *data)
  63{
  64        int len;
  65
  66        len = sprintf(page, "jiffies = %ld\n",
  67                      jiffies);
  68
  69        return len;
  70}
  71
  72
  73static int proc_read_foobar(char *page, char **start,
  74                            off_t off, int count, 
  75                            int *eof, void *data)
  76{
  77        int len;
  78        struct fb_data_t *fb_data = (struct fb_data_t *)data;
  79
  80        /* DON'T DO THAT - buffer overruns are bad */
  81        len = sprintf(page, "%s = '%s'\n", 
  82                      fb_data->name, fb_data->value);
  83
  84        return len;
  85}
  86
  87
  88static int proc_write_foobar(struct file *file,
  89                             const char *buffer,
  90                             unsigned long count, 
  91                             void *data)
  92{
  93        int len;
  94        struct fb_data_t *fb_data = (struct fb_data_t *)data;
  95
  96        if(count > FOOBAR_LEN)
  97                len = FOOBAR_LEN;
  98        else
  99                len = count;
 100
 101        if(copy_from_user(fb_data->value, buffer, len))
 102                return -EFAULT;
 103
 104        fb_data->value[len] = '\0';
 105
 106        return len;
 107}
 108
 109
 110static int __init init_procfs_example(void)
 111{
 112        int rv = 0;
 113
 114        /* create directory */
 115        example_dir = proc_mkdir(MODULE_NAME, NULL);
 116        if(example_dir == NULL) {
 117                rv = -ENOMEM;
 118                goto out;
 119        }
 120        /* create jiffies using convenience function */
 121        jiffies_file = create_proc_read_entry("jiffies", 
 122                                              0444, example_dir, 
 123                                              proc_read_jiffies,
 124                                              NULL);
 125        if(jiffies_file == NULL) {
 126                rv  = -ENOMEM;
 127                goto no_jiffies;
 128        }
 129
 130        /* create foo and bar files using same callback
 131         * functions 
 132         */
 133        foo_file = create_proc_entry("foo", 0644, example_dir);
 134        if(foo_file == NULL) {
 135                rv = -ENOMEM;
 136                goto no_foo;
 137        }
 138
 139        strcpy(foo_data.name, "foo");
 140        strcpy(foo_data.value, "foo");
 141        foo_file->data = &foo_data;
 142        foo_file->read_proc = proc_read_foobar;
 143        foo_file->write_proc = proc_write_foobar;
 144                
 145        bar_file = create_proc_entry("bar", 0644, example_dir);
 146        if(bar_file == NULL) {
 147                rv = -ENOMEM;
 148                goto no_bar;
 149        }
 150
 151        strcpy(bar_data.name, "bar");
 152        strcpy(bar_data.value, "bar");
 153        bar_file->data = &bar_data;
 154        bar_file->read_proc = proc_read_foobar;
 155        bar_file->write_proc = proc_write_foobar;
 156                
 157        /* create symlink */
 158        symlink = proc_symlink("jiffies_too", example_dir, 
 159                               "jiffies");
 160        if(symlink == NULL) {
 161                rv = -ENOMEM;
 162                goto no_symlink;
 163        }
 164
 165        /* everything OK */
 166        printk(KERN_INFO "%s %s initialised\n",
 167               MODULE_NAME, MODULE_VERS);
 168        return 0;
 169
 170no_symlink:
 171        remove_proc_entry("bar", example_dir);
 172no_bar:
 173        remove_proc_entry("foo", example_dir);
 174no_foo:
 175        remove_proc_entry("jiffies", example_dir);
 176no_jiffies:                           
 177        remove_proc_entry(MODULE_NAME, NULL);
 178out:
 179        return rv;
 180}
 181
 182
 183static void __exit cleanup_procfs_example(void)
 184{
 185        remove_proc_entry("jiffies_too", example_dir);
 186        remove_proc_entry("bar", example_dir);
 187        remove_proc_entry("foo", example_dir);
 188        remove_proc_entry("jiffies", example_dir);
 189        remove_proc_entry(MODULE_NAME, NULL);
 190
 191        printk(KERN_INFO "%s %s removed\n",
 192               MODULE_NAME, MODULE_VERS);
 193}
 194
 195
 196module_init(init_procfs_example);
 197module_exit(cleanup_procfs_example);
 198
 199MODULE_AUTHOR("Erik Mouw");
 200MODULE_DESCRIPTION("procfs examples");
 201MODULE_LICENSE("GPL");
 202