root/fs/proc/root.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. proc_register
  2. proc_unregister
  3. proc_self_followlink
  4. proc_self_readlink
  5. proc_root_init
  6. proc_match
  7. proc_lookup
  8. proc_root_lookup
  9. proc_readdir
  10. proc_root_readdir

   1 /*
   2  *  linux/fs/proc/root.c
   3  *
   4  *  Copyright (C) 1991, 1992 Linus Torvalds
   5  *
   6  *  proc root directory handling functions
   7  */
   8 
   9 #include <asm/segment.h>
  10 
  11 #include <linux/errno.h>
  12 #include <linux/sched.h>
  13 #include <linux/proc_fs.h>
  14 #include <linux/stat.h>
  15 #include <linux/config.h>
  16 
  17 /*
  18  * Offset of the first process in the /proc root directory..
  19  */
  20 #define FIRST_PROCESS_ENTRY 256
  21 
  22 static int proc_root_readdir(struct inode *, struct file *, void *, filldir_t);
  23 static int proc_root_lookup(struct inode *,const char *,int,struct inode **);
  24 
  25 static struct file_operations proc_root_operations = {
  26         NULL,                   /* lseek - default */
  27         NULL,                   /* read - bad */
  28         NULL,                   /* write - bad */
  29         proc_root_readdir,      /* readdir */
  30         NULL,                   /* select - default */
  31         NULL,                   /* ioctl - default */
  32         NULL,                   /* mmap */
  33         NULL,                   /* no special open code */
  34         NULL,                   /* no special release code */
  35         NULL                    /* no fsync */
  36 };
  37 
  38 /*
  39  * proc directories can do almost nothing..
  40  */
  41 static struct inode_operations proc_root_inode_operations = {
  42         &proc_root_operations,  /* default base directory file-ops */
  43         NULL,                   /* create */
  44         proc_root_lookup,       /* lookup */
  45         NULL,                   /* link */
  46         NULL,                   /* unlink */
  47         NULL,                   /* symlink */
  48         NULL,                   /* mkdir */
  49         NULL,                   /* rmdir */
  50         NULL,                   /* mknod */
  51         NULL,                   /* rename */
  52         NULL,                   /* readlink */
  53         NULL,                   /* follow_link */
  54         NULL,                   /* bmap */
  55         NULL,                   /* truncate */
  56         NULL                    /* permission */
  57 };
  58 
  59 /*
  60  * This is the root "inode" in the /proc tree..
  61  */
  62 struct proc_dir_entry proc_root = {
  63         PROC_ROOT_INO, 5, "/proc",
  64         S_IFDIR | S_IRUGO | S_IXUGO, 3, 0, 0,
  65         0, &proc_root_inode_operations,
  66         NULL, NULL,
  67         NULL,
  68         &proc_root, NULL
  69 };
  70 
  71 int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73         dp->next = dir->subdir;
  74         dp->parent = dir;
  75         dir->subdir = dp;
  76         if (S_ISDIR(dp->mode))
  77                 dir->nlink++;
  78         return 0;
  79 }
  80 
  81 int proc_unregister(struct proc_dir_entry * dir, int ino)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         struct proc_dir_entry **p = &dir->subdir, *dp;
  84 
  85         while ((dp = *p) != NULL) {
  86                 if (dp->low_ino == ino) {
  87                         *p = dp->next;
  88                         dp->next = NULL;
  89                         if (S_ISDIR(dp->mode))
  90                                 dir->nlink--;
  91                         return 0;
  92                 }
  93                 p = &dp->next;
  94         }
  95         return -EINVAL;
  96 }       
  97 
  98 /*
  99  * /proc/self:
 100  */
 101 static int proc_self_followlink(struct inode * dir, struct inode * inode,
     /* [previous][next][first][last][top][bottom][index][help] */
 102                         int flag, int mode, struct inode ** res_inode)
 103 {
 104         iput(dir);
 105         *res_inode = proc_get_inode(inode->i_sb, (current->pid << 16) + PROC_PID_INO, &proc_pid);
 106         iput(inode);
 107         if (!*res_inode)
 108                 return -ENOENT;
 109         return 0;
 110 }
 111 
 112 static int proc_self_readlink(struct inode * inode, char * buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114         int len;
 115         char tmp[30];
 116 
 117         iput(inode);
 118         len = 1 + sprintf(tmp, "%d", current->pid);
 119         if (buflen < len)
 120                 len = buflen;
 121         memcpy_tofs(buffer, tmp, len);
 122         return len;
 123 }
 124 
 125 static struct inode_operations proc_self_inode_operations = {
 126         NULL,                   /* no file-ops */
 127         NULL,                   /* create */
 128         NULL,                   /* lookup */
 129         NULL,                   /* link */
 130         NULL,                   /* unlink */
 131         NULL,                   /* symlink */
 132         NULL,                   /* mkdir */
 133         NULL,                   /* rmdir */
 134         NULL,                   /* mknod */
 135         NULL,                   /* rename */
 136         proc_self_readlink,     /* readlink */
 137         proc_self_followlink,   /* follow_link */
 138         NULL,                   /* bmap */
 139         NULL,                   /* truncate */
 140         NULL                    /* permission */
 141 };
 142 
 143 void proc_root_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145         static int done = 0;
 146 
 147         if (done)
 148                 return;
 149         done = 1;
 150         proc_base_init();
 151         proc_register(&proc_root, &(struct proc_dir_entry) {
 152                 PROC_LOADAVG, 7, "loadavg",
 153                 S_IFREG | S_IRUGO, 1, 0, 0,
 154         });
 155         proc_register(&proc_root, &(struct proc_dir_entry) {
 156                 PROC_UPTIME, 6, "uptime",
 157                 S_IFREG | S_IRUGO, 1, 0, 0,
 158         });
 159         proc_register(&proc_root, &(struct proc_dir_entry) {
 160                 PROC_MEMINFO, 7, "meminfo",
 161                 S_IFREG | S_IRUGO, 1, 0, 0,
 162         });
 163         proc_register(&proc_root, &(struct proc_dir_entry) {
 164                 PROC_KMSG, 4, "kmsg",
 165                 S_IFREG | S_IRUSR, 1, 0, 0,
 166         });
 167         proc_register(&proc_root, &(struct proc_dir_entry) {
 168                 PROC_VERSION, 7, "version",
 169                 S_IFREG | S_IRUGO, 1, 0, 0,
 170         });
 171 #ifdef CONFIG_PCI
 172         proc_register(&proc_root, &(struct proc_dir_entry) {
 173                 PROC_PCI, 3, "pci",
 174                 S_IFREG | S_IRUGO, 1, 0, 0,
 175         });
 176 #endif
 177         proc_register(&proc_root, &(struct proc_dir_entry) {
 178                 PROC_CPUINFO, 7, "cpuinfo",
 179                 S_IFREG | S_IRUGO, 1, 0, 0,
 180         });
 181         proc_register(&proc_root, &(struct proc_dir_entry) {
 182                 PROC_SELF, 4, "self",
 183                 S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
 184                 64, &proc_self_inode_operations,
 185         });
 186         proc_register(&proc_root, &proc_net);
 187         proc_register(&proc_root, &proc_scsi);
 188 #ifdef CONFIG_DEBUG_MALLOC
 189         proc_register(&proc_root, &(struct proc_dir_entry) {
 190                 PROC_MALLOC, 6, "malloc",
 191                 S_IFREG | S_IRUGO, 1, 0, 0,
 192         });
 193 #endif
 194         proc_register(&proc_root, &(struct proc_dir_entry) {
 195                 PROC_KCORE, 5, "kcore",
 196                 S_IFREG | S_IRUSR, 1, 0, 0,
 197         });
 198         proc_register(&proc_root, &(struct proc_dir_entry) {
 199                 PROC_MODULES, 7, "modules",
 200                 S_IFREG | S_IRUGO, 1, 0, 0,
 201         });
 202         proc_register(&proc_root, &(struct proc_dir_entry) {
 203                 PROC_STAT, 4, "stat",
 204                 S_IFREG | S_IRUGO, 1, 0, 0,
 205         });
 206         proc_register(&proc_root, &(struct proc_dir_entry) {
 207                 PROC_DEVICES, 7, "devices",
 208                 S_IFREG | S_IRUGO, 1, 0, 0,
 209         });
 210         proc_register(&proc_root, &(struct proc_dir_entry) {
 211                 PROC_INTERRUPTS, 10,"interrupts",
 212                 S_IFREG | S_IRUGO, 1, 0, 0,
 213         });
 214         proc_register(&proc_root, &(struct proc_dir_entry) {
 215                 PROC_FILESYSTEMS, 11,"filesystems",
 216                 S_IFREG | S_IRUGO, 1, 0, 0,
 217         });
 218         proc_register(&proc_root, &(struct proc_dir_entry) {
 219                 PROC_KSYMS, 5, "ksyms",
 220                 S_IFREG | S_IRUGO, 1, 0, 0,
 221         });
 222         proc_register(&proc_root, &(struct proc_dir_entry) {
 223                 PROC_DMA, 3, "dma",
 224                 S_IFREG | S_IRUGO, 1, 0, 0,
 225         });
 226         proc_register(&proc_root, &(struct proc_dir_entry) {
 227                 PROC_IOPORTS, 7, "ioports",
 228                 S_IFREG | S_IRUGO, 1, 0, 0,
 229         });
 230 #ifdef CONFIG_PROFILE
 231         proc_register(&proc_root, &(struct proc_dir_entry) {
 232                 PROC_PROFILE, 7, "profile",
 233                 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
 234         });
 235 #endif
 236 }
 237 
 238 
 239 int proc_match(int len,const char * name,struct proc_dir_entry * de)
     /* [previous][next][first][last][top][bottom][index][help] */
 240 {
 241         if (!de || !de->low_ino)
 242                 return 0;
 243         /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
 244         if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
 245                 return 1;
 246         if (de->namelen != len)
 247                 return 0;
 248         return !memcmp(name, de->name, len);
 249 }
 250 
 251 int proc_lookup(struct inode * dir,const char * name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 252         struct inode ** result)
 253 {
 254         struct proc_dir_entry * de;
 255         int ino;
 256 
 257         *result = NULL;
 258         if (!dir || !S_ISDIR(dir->i_mode)) {
 259                 iput(dir);
 260                 return -ENOTDIR;
 261         }
 262 
 263         de = (struct proc_dir_entry *) dir->u.generic_ip;
 264         if (!de)
 265                 return -EINVAL;
 266 
 267         /* Special case "." and "..": they aren't on the directory list */
 268         *result = dir;
 269         if (!len)
 270                 return 0;
 271         if (name[0] == '.') {
 272                 if (len == 1)
 273                         return 0;
 274                 if (name[1] == '.' && len == 2) {
 275                         struct inode * inode;
 276                         inode = proc_get_inode(dir->i_sb, de->parent->low_ino, de->parent);
 277                         iput(dir);
 278                         if (!inode)
 279                                 return -EINVAL;
 280                         *result = inode;
 281                         return 0;
 282                 }
 283         }
 284 
 285         *result = NULL;
 286         for (de = de->subdir; de ; de = de->next) {
 287                 if (proc_match(len, name, de))
 288                         break;
 289         }
 290         if (!de)
 291                 return -ENOENT;
 292 
 293         ino = de->low_ino | (dir->i_ino & ~(0xffff));
 294 
 295         if (!(*result = proc_get_inode(dir->i_sb, ino, de))) {
 296                 iput(dir);
 297                 return -EINVAL;
 298         }
 299         iput(dir);
 300         return 0;
 301 }
 302 
 303 static int proc_root_lookup(struct inode * dir,const char * name, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 304         struct inode ** result)
 305 {
 306         unsigned int pid, c;
 307         int i, ino;
 308 
 309         int retval = proc_lookup(dir, name, len, result);
 310         if (retval != -ENOENT)
 311                 return retval;
 312         
 313         pid = 0;
 314         while (len-- > 0) {
 315                 c = *name - '0';
 316                 name++;
 317                 if (c > 9) {
 318                         pid = 0;
 319                         break;
 320                 }
 321                 pid *= 10;
 322                 pid += c;
 323                 if (pid & 0xffff0000) {
 324                         pid = 0;
 325                         break;
 326                 }
 327         }
 328         for (i = 0 ; i < NR_TASKS ; i++)
 329                 if (task[i] && task[i]->pid == pid)
 330                         break;
 331         if (!pid || i >= NR_TASKS) {
 332                 iput(dir);
 333                 return -ENOENT;
 334         }
 335         ino = (pid << 16) + PROC_PID_INO;
 336         if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid))) {
 337                 iput(dir);
 338                 return -EINVAL;
 339         }
 340         iput(dir);
 341         return 0;
 342 }
 343 
 344 /*
 345  * This returns non-zero if at EOF, so that the /proc
 346  * root directory can use this and check if it should
 347  * continue with the <pid> entries..
 348  *
 349  * Note that the VFS-layer doesn't care about the return
 350  * value of the readdir() call, as long as it's non-negative
 351  * for success..
 352  */
 353 int proc_readdir(struct inode * inode, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 354         void * dirent, filldir_t filldir)
 355 {
 356         struct proc_dir_entry * de;
 357         unsigned int ino;
 358         int i;
 359 
 360         if (!inode || !S_ISDIR(inode->i_mode))
 361                 return -ENOTDIR;
 362         ino = inode->i_ino;
 363         de = (struct proc_dir_entry *) inode->u.generic_ip;
 364         if (!de)
 365                 return -EINVAL;
 366         i = filp->f_pos;
 367         switch (i) {
 368                 case 0:
 369                         if (filldir(dirent, ".", 1, i, ino) < 0)
 370                                 return 0;
 371                         i++;
 372                         filp->f_pos++;
 373                         /* fall through */
 374                 case 1:
 375                         if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0)
 376                                 return 0;
 377                         i++;
 378                         filp->f_pos++;
 379                         /* fall through */
 380                 default:
 381                         ino &= ~0xffff;
 382                         de = de->subdir;
 383                         i -= 2;
 384                         for (;;) {
 385                                 if (!de)
 386                                         return 1;
 387                                 if (!i)
 388                                         break;
 389                                 de = de->next;
 390                                 i--;
 391                         }
 392 
 393                         do {
 394                                 if (filldir(dirent, de->name, de->namelen, filp->f_pos, ino | de->low_ino) < 0)
 395                                         return 0;
 396                                 filp->f_pos++;
 397                                 de = de->next;
 398                         } while (de);
 399         }
 400         return 1;
 401 }
 402 
 403 #define NUMBUF 10
 404 
 405 static int proc_root_readdir(struct inode * inode, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 406         void * dirent, filldir_t filldir)
 407 {
 408         char buf[NUMBUF];
 409         unsigned int nr,pid;
 410         unsigned long i,j;
 411 
 412         nr = filp->f_pos;
 413         if (nr < FIRST_PROCESS_ENTRY) {
 414                 int error = proc_readdir(inode, filp, dirent, filldir);
 415                 if (error <= 0)
 416                         return error;
 417                 filp->f_pos = nr = FIRST_PROCESS_ENTRY;
 418         }
 419 
 420         for (nr -= FIRST_PROCESS_ENTRY; nr < NR_TASKS; nr++, filp->f_pos++) {
 421                 struct task_struct * p = task[nr];
 422 
 423                 if (!p || !(pid = p->pid))
 424                         continue;
 425 
 426                 j = NUMBUF;
 427                 i = pid;
 428                 do {
 429                         j--;
 430                         buf[j] = '0' + (i % 10);
 431                         i /= 10;
 432                 } while (i);
 433 
 434                 if (filldir(dirent, buf+j, NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0)
 435                         break;
 436         }
 437         return 0;
 438 }

/* [previous][next][first][last][top][bottom][index][help] */