Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13-rc2 815 lines 17 kB view raw
1/* 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 3 * Licensed under the GPL 4 */ 5 6#include <linux/fs.h> 7#include <linux/module.h> 8#include <linux/init.h> 9#include <linux/slab.h> 10#include <linux/list.h> 11#include <linux/kernel.h> 12#include <linux/ctype.h> 13#include <linux/dcache.h> 14#include <linux/statfs.h> 15#include <asm/uaccess.h> 16#include <asm/fcntl.h> 17#include "os.h" 18 19static int init_inode(struct inode *inode, struct dentry *dentry); 20 21struct hppfs_data { 22 struct list_head list; 23 char contents[PAGE_SIZE - sizeof(struct list_head)]; 24}; 25 26struct hppfs_private { 27 struct file *proc_file; 28 int host_fd; 29 loff_t len; 30 struct hppfs_data *contents; 31}; 32 33struct hppfs_inode_info { 34 struct dentry *proc_dentry; 35 struct inode vfs_inode; 36}; 37 38static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) 39{ 40 return(list_entry(inode, struct hppfs_inode_info, vfs_inode)); 41} 42 43#define HPPFS_SUPER_MAGIC 0xb00000ee 44 45static struct super_operations hppfs_sbops; 46 47static int is_pid(struct dentry *dentry) 48{ 49 struct super_block *sb; 50 int i; 51 52 sb = dentry->d_sb; 53 if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) 54 return(0); 55 56 for(i = 0; i < dentry->d_name.len; i++){ 57 if(!isdigit(dentry->d_name.name[i])) 58 return(0); 59 } 60 return(1); 61} 62 63static char *dentry_name(struct dentry *dentry, int extra) 64{ 65 struct dentry *parent; 66 char *root, *name; 67 const char *seg_name; 68 int len, seg_len; 69 70 len = 0; 71 parent = dentry; 72 while(parent->d_parent != parent){ 73 if(is_pid(parent)) 74 len += strlen("pid") + 1; 75 else len += parent->d_name.len + 1; 76 parent = parent->d_parent; 77 } 78 79 root = "proc"; 80 len += strlen(root); 81 name = kmalloc(len + extra + 1, GFP_KERNEL); 82 if(name == NULL) return(NULL); 83 84 name[len] = '\0'; 85 parent = dentry; 86 while(parent->d_parent != parent){ 87 if(is_pid(parent)){ 88 seg_name = "pid"; 89 seg_len = strlen("pid"); 90 } 91 else { 92 seg_name = parent->d_name.name; 93 seg_len = parent->d_name.len; 94 } 95 96 len -= seg_len + 1; 97 name[len] = '/'; 98 strncpy(&name[len + 1], seg_name, seg_len); 99 parent = parent->d_parent; 100 } 101 strncpy(name, root, strlen(root)); 102 return(name); 103} 104 105struct dentry_operations hppfs_dentry_ops = { 106}; 107 108static int file_removed(struct dentry *dentry, const char *file) 109{ 110 char *host_file; 111 int extra, fd; 112 113 extra = 0; 114 if(file != NULL) extra += strlen(file) + 1; 115 116 host_file = dentry_name(dentry, extra + strlen("/remove")); 117 if(host_file == NULL){ 118 printk("file_removed : allocation failed\n"); 119 return(-ENOMEM); 120 } 121 122 if(file != NULL){ 123 strcat(host_file, "/"); 124 strcat(host_file, file); 125 } 126 strcat(host_file, "/remove"); 127 128 fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); 129 kfree(host_file); 130 if(fd > 0){ 131 os_close_file(fd); 132 return(1); 133 } 134 return(0); 135} 136 137static void hppfs_read_inode(struct inode *ino) 138{ 139 struct inode *proc_ino; 140 141 if(HPPFS_I(ino)->proc_dentry == NULL) 142 return; 143 144 proc_ino = HPPFS_I(ino)->proc_dentry->d_inode; 145 ino->i_uid = proc_ino->i_uid; 146 ino->i_gid = proc_ino->i_gid; 147 ino->i_atime = proc_ino->i_atime; 148 ino->i_mtime = proc_ino->i_mtime; 149 ino->i_ctime = proc_ino->i_ctime; 150 ino->i_ino = proc_ino->i_ino; 151 ino->i_mode = proc_ino->i_mode; 152 ino->i_nlink = proc_ino->i_nlink; 153 ino->i_size = proc_ino->i_size; 154 ino->i_blksize = proc_ino->i_blksize; 155 ino->i_blocks = proc_ino->i_blocks; 156} 157 158static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, 159 struct nameidata *nd) 160{ 161 struct dentry *proc_dentry, *new, *parent; 162 struct inode *inode; 163 int err, deleted; 164 165 deleted = file_removed(dentry, NULL); 166 if(deleted < 0) 167 return(ERR_PTR(deleted)); 168 else if(deleted) 169 return(ERR_PTR(-ENOENT)); 170 171 err = -ENOMEM; 172 parent = HPPFS_I(ino)->proc_dentry; 173 down(&parent->d_inode->i_sem); 174 proc_dentry = d_lookup(parent, &dentry->d_name); 175 if(proc_dentry == NULL){ 176 proc_dentry = d_alloc(parent, &dentry->d_name); 177 if(proc_dentry == NULL){ 178 up(&parent->d_inode->i_sem); 179 goto out; 180 } 181 new = (*parent->d_inode->i_op->lookup)(parent->d_inode, 182 proc_dentry, NULL); 183 if(new){ 184 dput(proc_dentry); 185 proc_dentry = new; 186 } 187 } 188 up(&parent->d_inode->i_sem); 189 190 if(IS_ERR(proc_dentry)) 191 return(proc_dentry); 192 193 inode = iget(ino->i_sb, 0); 194 if(inode == NULL) 195 goto out_dput; 196 197 err = init_inode(inode, proc_dentry); 198 if(err) 199 goto out_put; 200 201 hppfs_read_inode(inode); 202 203 d_add(dentry, inode); 204 dentry->d_op = &hppfs_dentry_ops; 205 return(NULL); 206 207 out_put: 208 iput(inode); 209 out_dput: 210 dput(proc_dentry); 211 out: 212 return(ERR_PTR(err)); 213} 214 215static struct inode_operations hppfs_file_iops = { 216}; 217 218static ssize_t read_proc(struct file *file, char *buf, ssize_t count, 219 loff_t *ppos, int is_user) 220{ 221 ssize_t (*read)(struct file *, char *, size_t, loff_t *); 222 ssize_t n; 223 224 read = file->f_dentry->d_inode->i_fop->read; 225 226 if(!is_user) 227 set_fs(KERNEL_DS); 228 229 n = (*read)(file, buf, count, &file->f_pos); 230 231 if(!is_user) 232 set_fs(USER_DS); 233 234 if(ppos) *ppos = file->f_pos; 235 return(n); 236} 237 238static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count) 239{ 240 ssize_t n; 241 int cur, err; 242 char *new_buf; 243 244 n = -ENOMEM; 245 new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 246 if(new_buf == NULL){ 247 printk("hppfs_read_file : kmalloc failed\n"); 248 goto out; 249 } 250 n = 0; 251 while(count > 0){ 252 cur = min_t(ssize_t, count, PAGE_SIZE); 253 err = os_read_file(fd, new_buf, cur); 254 if(err < 0){ 255 printk("hppfs_read : read failed, errno = %d\n", 256 count); 257 n = err; 258 goto out_free; 259 } 260 else if(err == 0) 261 break; 262 263 if(copy_to_user(buf, new_buf, err)){ 264 n = -EFAULT; 265 goto out_free; 266 } 267 n += err; 268 count -= err; 269 } 270 out_free: 271 kfree(new_buf); 272 out: 273 return(n); 274} 275 276static ssize_t hppfs_read(struct file *file, char *buf, size_t count, 277 loff_t *ppos) 278{ 279 struct hppfs_private *hppfs = file->private_data; 280 struct hppfs_data *data; 281 loff_t off; 282 int err; 283 284 if(hppfs->contents != NULL){ 285 if(*ppos >= hppfs->len) return(0); 286 287 data = hppfs->contents; 288 off = *ppos; 289 while(off >= sizeof(data->contents)){ 290 data = list_entry(data->list.next, struct hppfs_data, 291 list); 292 off -= sizeof(data->contents); 293 } 294 295 if(off + count > hppfs->len) 296 count = hppfs->len - off; 297 copy_to_user(buf, &data->contents[off], count); 298 *ppos += count; 299 } 300 else if(hppfs->host_fd != -1){ 301 err = os_seek_file(hppfs->host_fd, *ppos); 302 if(err){ 303 printk("hppfs_read : seek failed, errno = %d\n", err); 304 return(err); 305 } 306 count = hppfs_read_file(hppfs->host_fd, buf, count); 307 if(count > 0) 308 *ppos += count; 309 } 310 else count = read_proc(hppfs->proc_file, buf, count, ppos, 1); 311 312 return(count); 313} 314 315static ssize_t hppfs_write(struct file *file, const char *buf, size_t len, 316 loff_t *ppos) 317{ 318 struct hppfs_private *data = file->private_data; 319 struct file *proc_file = data->proc_file; 320 ssize_t (*write)(struct file *, const char *, size_t, loff_t *); 321 int err; 322 323 write = proc_file->f_dentry->d_inode->i_fop->write; 324 325 proc_file->f_pos = file->f_pos; 326 err = (*write)(proc_file, buf, len, &proc_file->f_pos); 327 file->f_pos = proc_file->f_pos; 328 329 return(err); 330} 331 332static int open_host_sock(char *host_file, int *filter_out) 333{ 334 char *end; 335 int fd; 336 337 end = &host_file[strlen(host_file)]; 338 strcpy(end, "/rw"); 339 *filter_out = 1; 340 fd = os_connect_socket(host_file); 341 if(fd > 0) 342 return(fd); 343 344 strcpy(end, "/r"); 345 *filter_out = 0; 346 fd = os_connect_socket(host_file); 347 return(fd); 348} 349 350static void free_contents(struct hppfs_data *head) 351{ 352 struct hppfs_data *data; 353 struct list_head *ele, *next; 354 355 if(head == NULL) return; 356 357 list_for_each_safe(ele, next, &head->list){ 358 data = list_entry(ele, struct hppfs_data, list); 359 kfree(data); 360 } 361 kfree(head); 362} 363 364static struct hppfs_data *hppfs_get_data(int fd, int filter, 365 struct file *proc_file, 366 struct file *hppfs_file, 367 loff_t *size_out) 368{ 369 struct hppfs_data *data, *new, *head; 370 int n, err; 371 372 err = -ENOMEM; 373 data = kmalloc(sizeof(*data), GFP_KERNEL); 374 if(data == NULL){ 375 printk("hppfs_get_data : head allocation failed\n"); 376 goto failed; 377 } 378 379 INIT_LIST_HEAD(&data->list); 380 381 head = data; 382 *size_out = 0; 383 384 if(filter){ 385 while((n = read_proc(proc_file, data->contents, 386 sizeof(data->contents), NULL, 0)) > 0) 387 os_write_file(fd, data->contents, n); 388 err = os_shutdown_socket(fd, 0, 1); 389 if(err){ 390 printk("hppfs_get_data : failed to shut down " 391 "socket\n"); 392 goto failed_free; 393 } 394 } 395 while(1){ 396 n = os_read_file(fd, data->contents, sizeof(data->contents)); 397 if(n < 0){ 398 err = n; 399 printk("hppfs_get_data : read failed, errno = %d\n", 400 err); 401 goto failed_free; 402 } 403 else if(n == 0) 404 break; 405 406 *size_out += n; 407 408 if(n < sizeof(data->contents)) 409 break; 410 411 new = kmalloc(sizeof(*data), GFP_KERNEL); 412 if(new == 0){ 413 printk("hppfs_get_data : data allocation failed\n"); 414 err = -ENOMEM; 415 goto failed_free; 416 } 417 418 INIT_LIST_HEAD(&new->list); 419 list_add(&new->list, &data->list); 420 data = new; 421 } 422 return(head); 423 424 failed_free: 425 free_contents(head); 426 failed: 427 return(ERR_PTR(err)); 428} 429 430static struct hppfs_private *hppfs_data(void) 431{ 432 struct hppfs_private *data; 433 434 data = kmalloc(sizeof(*data), GFP_KERNEL); 435 if(data == NULL) 436 return(data); 437 438 *data = ((struct hppfs_private ) { .host_fd = -1, 439 .len = -1, 440 .contents = NULL } ); 441 return(data); 442} 443 444static int file_mode(int fmode) 445{ 446 if(fmode == (FMODE_READ | FMODE_WRITE)) 447 return(O_RDWR); 448 if(fmode == FMODE_READ) 449 return(O_RDONLY); 450 if(fmode == FMODE_WRITE) 451 return(O_WRONLY); 452 return(0); 453} 454 455static int hppfs_open(struct inode *inode, struct file *file) 456{ 457 struct hppfs_private *data; 458 struct dentry *proc_dentry; 459 char *host_file; 460 int err, fd, type, filter; 461 462 err = -ENOMEM; 463 data = hppfs_data(); 464 if(data == NULL) 465 goto out; 466 467 host_file = dentry_name(file->f_dentry, strlen("/rw")); 468 if(host_file == NULL) 469 goto out_free2; 470 471 proc_dentry = HPPFS_I(inode)->proc_dentry; 472 473 /* XXX This isn't closed anywhere */ 474 data->proc_file = dentry_open(dget(proc_dentry), NULL, 475 file_mode(file->f_mode)); 476 err = PTR_ERR(data->proc_file); 477 if(IS_ERR(data->proc_file)) 478 goto out_free1; 479 480 type = os_file_type(host_file); 481 if(type == OS_TYPE_FILE){ 482 fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); 483 if(fd >= 0) 484 data->host_fd = fd; 485 else printk("hppfs_open : failed to open '%s', errno = %d\n", 486 host_file, -fd); 487 488 data->contents = NULL; 489 } 490 else if(type == OS_TYPE_DIR){ 491 fd = open_host_sock(host_file, &filter); 492 if(fd > 0){ 493 data->contents = hppfs_get_data(fd, filter, 494 &data->proc_file, 495 file, &data->len); 496 if(!IS_ERR(data->contents)) 497 data->host_fd = fd; 498 } 499 else printk("hppfs_open : failed to open a socket in " 500 "'%s', errno = %d\n", host_file, -fd); 501 } 502 kfree(host_file); 503 504 file->private_data = data; 505 return(0); 506 507 out_free1: 508 kfree(host_file); 509 out_free2: 510 free_contents(data->contents); 511 kfree(data); 512 out: 513 return(err); 514} 515 516static int hppfs_dir_open(struct inode *inode, struct file *file) 517{ 518 struct hppfs_private *data; 519 struct dentry *proc_dentry; 520 int err; 521 522 err = -ENOMEM; 523 data = hppfs_data(); 524 if(data == NULL) 525 goto out; 526 527 proc_dentry = HPPFS_I(inode)->proc_dentry; 528 data->proc_file = dentry_open(dget(proc_dentry), NULL, 529 file_mode(file->f_mode)); 530 err = PTR_ERR(data->proc_file); 531 if(IS_ERR(data->proc_file)) 532 goto out_free; 533 534 file->private_data = data; 535 return(0); 536 537 out_free: 538 kfree(data); 539 out: 540 return(err); 541} 542 543static loff_t hppfs_llseek(struct file *file, loff_t off, int where) 544{ 545 struct hppfs_private *data = file->private_data; 546 struct file *proc_file = &data->proc_file; 547 loff_t (*llseek)(struct file *, loff_t, int); 548 loff_t ret; 549 550 llseek = proc_file->f_dentry->d_inode->i_fop->llseek; 551 if(llseek != NULL){ 552 ret = (*llseek)(proc_file, off, where); 553 if(ret < 0) 554 return(ret); 555 } 556 557 return(default_llseek(file, off, where)); 558} 559 560static struct file_operations hppfs_file_fops = { 561 .owner = NULL, 562 .llseek = hppfs_llseek, 563 .read = hppfs_read, 564 .write = hppfs_write, 565 .open = hppfs_open, 566}; 567 568struct hppfs_dirent { 569 void *vfs_dirent; 570 filldir_t filldir; 571 struct dentry *dentry; 572}; 573 574static int hppfs_filldir(void *d, const char *name, int size, 575 loff_t offset, ino_t inode, unsigned int type) 576{ 577 struct hppfs_dirent *dirent = d; 578 579 if(file_removed(dirent->dentry, name)) 580 return(0); 581 582 return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, 583 inode, type)); 584} 585 586static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) 587{ 588 struct hppfs_private *data = file->private_data; 589 struct file *proc_file = &data->proc_file; 590 int (*readdir)(struct file *, void *, filldir_t); 591 struct hppfs_dirent dirent = ((struct hppfs_dirent) 592 { .vfs_dirent = ent, 593 .filldir = filldir, 594 .dentry = file->f_dentry } ); 595 int err; 596 597 readdir = proc_file->f_dentry->d_inode->i_fop->readdir; 598 599 proc_file->f_pos = file->f_pos; 600 err = (*readdir)(proc_file, &dirent, hppfs_filldir); 601 file->f_pos = proc_file->f_pos; 602 603 return(err); 604} 605 606static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) 607{ 608 return(0); 609} 610 611static struct file_operations hppfs_dir_fops = { 612 .owner = NULL, 613 .readdir = hppfs_readdir, 614 .open = hppfs_dir_open, 615 .fsync = hppfs_fsync, 616}; 617 618static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf) 619{ 620 sf->f_blocks = 0; 621 sf->f_bfree = 0; 622 sf->f_bavail = 0; 623 sf->f_files = 0; 624 sf->f_ffree = 0; 625 sf->f_type = HPPFS_SUPER_MAGIC; 626 return(0); 627} 628 629static struct inode *hppfs_alloc_inode(struct super_block *sb) 630{ 631 struct hppfs_inode_info *hi; 632 633 hi = kmalloc(sizeof(*hi), GFP_KERNEL); 634 if(hi == NULL) 635 return(NULL); 636 637 *hi = ((struct hppfs_inode_info) { .proc_dentry = NULL }); 638 inode_init_once(&hi->vfs_inode); 639 return(&hi->vfs_inode); 640} 641 642void hppfs_delete_inode(struct inode *ino) 643{ 644 clear_inode(ino); 645} 646 647static void hppfs_destroy_inode(struct inode *inode) 648{ 649 kfree(HPPFS_I(inode)); 650} 651 652static struct super_operations hppfs_sbops = { 653 .alloc_inode = hppfs_alloc_inode, 654 .destroy_inode = hppfs_destroy_inode, 655 .read_inode = hppfs_read_inode, 656 .delete_inode = hppfs_delete_inode, 657 .statfs = hppfs_statfs, 658}; 659 660static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen) 661{ 662 struct file *proc_file; 663 struct dentry *proc_dentry; 664 int (*readlink)(struct dentry *, char *, int); 665 int err, n; 666 667 proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; 668 proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); 669 err = PTR_ERR(proc_dentry); 670 if(IS_ERR(proc_dentry)) 671 return(err); 672 673 readlink = proc_dentry->d_inode->i_op->readlink; 674 n = (*readlink)(proc_dentry, buffer, buflen); 675 676 fput(proc_file); 677 678 return(n); 679} 680 681static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) 682{ 683 struct file *proc_file; 684 struct dentry *proc_dentry; 685 int (*follow_link)(struct dentry *, struct nameidata *); 686 int err, n; 687 688 proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; 689 proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); 690 err = PTR_ERR(proc_dentry); 691 if(IS_ERR(proc_dentry)) 692 return(err); 693 694 follow_link = proc_dentry->d_inode->i_op->follow_link; 695 n = (*follow_link)(proc_dentry, nd); 696 697 fput(proc_file); 698 699 return(n); 700} 701 702static struct inode_operations hppfs_dir_iops = { 703 .lookup = hppfs_lookup, 704}; 705 706static struct inode_operations hppfs_link_iops = { 707 .readlink = hppfs_readlink, 708 .follow_link = hppfs_follow_link, 709}; 710 711static int init_inode(struct inode *inode, struct dentry *dentry) 712{ 713 if(S_ISDIR(dentry->d_inode->i_mode)){ 714 inode->i_op = &hppfs_dir_iops; 715 inode->i_fop = &hppfs_dir_fops; 716 } 717 else if(S_ISLNK(dentry->d_inode->i_mode)){ 718 inode->i_op = &hppfs_link_iops; 719 inode->i_fop = &hppfs_file_fops; 720 } 721 else { 722 inode->i_op = &hppfs_file_iops; 723 inode->i_fop = &hppfs_file_fops; 724 } 725 726 HPPFS_I(inode)->proc_dentry = dentry; 727 728 return(0); 729} 730 731static int hppfs_fill_super(struct super_block *sb, void *d, int silent) 732{ 733 struct inode *root_inode; 734 struct file_system_type *procfs; 735 struct super_block *proc_sb; 736 int err; 737 738 err = -ENOENT; 739 procfs = get_fs_type("proc"); 740 if(procfs == NULL) 741 goto out; 742 743 if(list_empty(&procfs->fs_supers)) 744 goto out; 745 746 proc_sb = list_entry(procfs->fs_supers.next, struct super_block, 747 s_instances); 748 749 sb->s_blocksize = 1024; 750 sb->s_blocksize_bits = 10; 751 sb->s_magic = HPPFS_SUPER_MAGIC; 752 sb->s_op = &hppfs_sbops; 753 754 root_inode = iget(sb, 0); 755 if(root_inode == NULL) 756 goto out; 757 758 err = init_inode(root_inode, proc_sb->s_root); 759 if(err) 760 goto out_put; 761 762 err = -ENOMEM; 763 sb->s_root = d_alloc_root(root_inode); 764 if(sb->s_root == NULL) 765 goto out_put; 766 767 hppfs_read_inode(root_inode); 768 769 return(0); 770 771 out_put: 772 iput(root_inode); 773 out: 774 return(err); 775} 776 777static struct super_block *hppfs_read_super(struct file_system_type *type, 778 int flags, const char *dev_name, 779 void *data) 780{ 781 return(get_sb_nodev(type, flags, data, hppfs_fill_super)); 782} 783 784static struct file_system_type hppfs_type = { 785 .owner = THIS_MODULE, 786 .name = "hppfs", 787 .get_sb = hppfs_read_super, 788 .kill_sb = kill_anon_super, 789 .fs_flags = 0, 790}; 791 792static int __init init_hppfs(void) 793{ 794 return(register_filesystem(&hppfs_type)); 795} 796 797static void __exit exit_hppfs(void) 798{ 799 unregister_filesystem(&hppfs_type); 800} 801 802module_init(init_hppfs) 803module_exit(exit_hppfs) 804MODULE_LICENSE("GPL"); 805 806/* 807 * Overrides for Emacs so that we follow Linus's tabbing style. 808 * Emacs will notice this stuff at the end of the file and automatically 809 * adjust the settings for this buffer only. This must remain at the end 810 * of the file. 811 * --------------------------------------------------------------------------- 812 * Local variables: 813 * c-file-style: "linux" 814 * End: 815 */