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

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