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/file.h> 8#include <linux/module.h> 9#include <linux/init.h> 10#include <linux/slab.h> 11#include <linux/list.h> 12#include <linux/kernel.h> 13#include <linux/ctype.h> 14#include <linux/dcache.h> 15#include <linux/statfs.h> 16#include <asm/uaccess.h> 17#include <asm/fcntl.h> 18#include "os.h" 19 20static int init_inode(struct inode *inode, struct dentry *dentry); 21 22struct hppfs_data { 23 struct list_head list; 24 char contents[PAGE_SIZE - sizeof(struct list_head)]; 25}; 26 27struct hppfs_private { 28 struct file *proc_file; 29 int host_fd; 30 loff_t len; 31 struct hppfs_data *contents; 32}; 33 34struct hppfs_inode_info { 35 struct dentry *proc_dentry; 36 struct inode vfs_inode; 37}; 38 39static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) 40{ 41 return container_of(inode, struct hppfs_inode_info, vfs_inode); 42} 43 44#define HPPFS_SUPER_MAGIC 0xb00000ee 45 46static const struct super_operations hppfs_sbops; 47 48static int is_pid(struct dentry *dentry) 49{ 50 struct super_block *sb; 51 int i; 52 53 sb = dentry->d_sb; 54 if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) 55 return(0); 56 57 for(i = 0; i < dentry->d_name.len; i++){ 58 if(!isdigit(dentry->d_name.name[i])) 59 return(0); 60 } 61 return(1); 62} 63 64static char *dentry_name(struct dentry *dentry, int extra) 65{ 66 struct dentry *parent; 67 char *root, *name; 68 const char *seg_name; 69 int len, seg_len; 70 71 len = 0; 72 parent = dentry; 73 while(parent->d_parent != parent){ 74 if(is_pid(parent)) 75 len += strlen("pid") + 1; 76 else len += parent->d_name.len + 1; 77 parent = parent->d_parent; 78 } 79 80 root = "proc"; 81 len += strlen(root); 82 name = kmalloc(len + extra + 1, GFP_KERNEL); 83 if(name == NULL) return(NULL); 84 85 name[len] = '\0'; 86 parent = dentry; 87 while(parent->d_parent != parent){ 88 if(is_pid(parent)){ 89 seg_name = "pid"; 90 seg_len = strlen("pid"); 91 } 92 else { 93 seg_name = parent->d_name.name; 94 seg_len = parent->d_name.len; 95 } 96 97 len -= seg_len + 1; 98 name[len] = '/'; 99 strncpy(&name[len + 1], seg_name, seg_len); 100 parent = parent->d_parent; 101 } 102 strncpy(name, root, strlen(root)); 103 return(name); 104} 105 106struct dentry_operations hppfs_dentry_ops = { 107}; 108 109static int file_removed(struct dentry *dentry, const char *file) 110{ 111 char *host_file; 112 int extra, fd; 113 114 extra = 0; 115 if(file != NULL) extra += strlen(file) + 1; 116 117 host_file = dentry_name(dentry, extra + strlen("/remove")); 118 if(host_file == NULL){ 119 printk("file_removed : allocation failed\n"); 120 return(-ENOMEM); 121 } 122 123 if(file != NULL){ 124 strcat(host_file, "/"); 125 strcat(host_file, file); 126 } 127 strcat(host_file, "/remove"); 128 129 fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); 130 kfree(host_file); 131 if(fd > 0){ 132 os_close_file(fd); 133 return(1); 134 } 135 return(0); 136} 137 138static void hppfs_read_inode(struct inode *ino) 139{ 140 struct inode *proc_ino; 141 142 if(HPPFS_I(ino)->proc_dentry == NULL) 143 return; 144 145 proc_ino = HPPFS_I(ino)->proc_dentry->d_inode; 146 ino->i_uid = proc_ino->i_uid; 147 ino->i_gid = proc_ino->i_gid; 148 ino->i_atime = proc_ino->i_atime; 149 ino->i_mtime = proc_ino->i_mtime; 150 ino->i_ctime = proc_ino->i_ctime; 151 ino->i_ino = proc_ino->i_ino; 152 ino->i_mode = proc_ino->i_mode; 153 ino->i_nlink = proc_ino->i_nlink; 154 ino->i_size = proc_ino->i_size; 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 mutex_lock(&parent->d_inode->i_mutex); 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 mutex_unlock(&parent->d_inode->i_mutex); 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 mutex_unlock(&parent->d_inode->i_mutex); 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 const struct inode_operations hppfs_file_iops = { 216}; 217 218static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, 219 loff_t *ppos, int is_user) 220{ 221 ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); 222 ssize_t n; 223 224 read = file->f_path.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 __user *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 err); 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 __user *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 __user *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 __user *, size_t, loff_t *); 321 int err; 322 323 write = proc_file->f_path.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_path.dentry, strlen("/rw")); 468 if(host_file == NULL) 469 goto out_free2; 470 471 proc_dentry = HPPFS_I(inode)->proc_dentry; 472 473 data->proc_file = dentry_open(dget(proc_dentry), NULL, 474 file_mode(file->f_mode)); 475 err = PTR_ERR(data->proc_file); 476 if(IS_ERR(data->proc_file)) 477 goto out_free1; 478 479 type = os_file_type(host_file); 480 if(type == OS_TYPE_FILE){ 481 fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); 482 if(fd >= 0) 483 data->host_fd = fd; 484 else printk("hppfs_open : failed to open '%s', errno = %d\n", 485 host_file, -fd); 486 487 data->contents = NULL; 488 } 489 else if(type == OS_TYPE_DIR){ 490 fd = open_host_sock(host_file, &filter); 491 if(fd > 0){ 492 data->contents = hppfs_get_data(fd, filter, 493 data->proc_file, 494 file, &data->len); 495 if(!IS_ERR(data->contents)) 496 data->host_fd = fd; 497 } 498 else printk("hppfs_open : failed to open a socket in " 499 "'%s', errno = %d\n", host_file, -fd); 500 } 501 kfree(host_file); 502 503 file->private_data = data; 504 return(0); 505 506 out_free1: 507 kfree(host_file); 508 out_free2: 509 free_contents(data->contents); 510 kfree(data); 511 out: 512 return(err); 513} 514 515static int hppfs_dir_open(struct inode *inode, struct file *file) 516{ 517 struct hppfs_private *data; 518 struct dentry *proc_dentry; 519 int err; 520 521 err = -ENOMEM; 522 data = hppfs_data(); 523 if(data == NULL) 524 goto out; 525 526 proc_dentry = HPPFS_I(inode)->proc_dentry; 527 data->proc_file = dentry_open(dget(proc_dentry), NULL, 528 file_mode(file->f_mode)); 529 err = PTR_ERR(data->proc_file); 530 if(IS_ERR(data->proc_file)) 531 goto out_free; 532 533 file->private_data = data; 534 return(0); 535 536 out_free: 537 kfree(data); 538 out: 539 return(err); 540} 541 542static loff_t hppfs_llseek(struct file *file, loff_t off, int where) 543{ 544 struct hppfs_private *data = file->private_data; 545 struct file *proc_file = data->proc_file; 546 loff_t (*llseek)(struct file *, loff_t, int); 547 loff_t ret; 548 549 llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek; 550 if(llseek != NULL){ 551 ret = (*llseek)(proc_file, off, where); 552 if(ret < 0) 553 return(ret); 554 } 555 556 return(default_llseek(file, off, where)); 557} 558 559static const struct file_operations hppfs_file_fops = { 560 .owner = NULL, 561 .llseek = hppfs_llseek, 562 .read = hppfs_read, 563 .write = hppfs_write, 564 .open = hppfs_open, 565}; 566 567struct hppfs_dirent { 568 void *vfs_dirent; 569 filldir_t filldir; 570 struct dentry *dentry; 571}; 572 573static int hppfs_filldir(void *d, const char *name, int size, 574 loff_t offset, u64 inode, unsigned int type) 575{ 576 struct hppfs_dirent *dirent = d; 577 578 if(file_removed(dirent->dentry, name)) 579 return(0); 580 581 return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, 582 inode, type)); 583} 584 585static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) 586{ 587 struct hppfs_private *data = file->private_data; 588 struct file *proc_file = data->proc_file; 589 int (*readdir)(struct file *, void *, filldir_t); 590 struct hppfs_dirent dirent = ((struct hppfs_dirent) 591 { .vfs_dirent = ent, 592 .filldir = filldir, 593 .dentry = file->f_path.dentry } ); 594 int err; 595 596 readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir; 597 598 proc_file->f_pos = file->f_pos; 599 err = (*readdir)(proc_file, &dirent, hppfs_filldir); 600 file->f_pos = proc_file->f_pos; 601 602 return(err); 603} 604 605static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) 606{ 607 return(0); 608} 609 610static const struct file_operations hppfs_dir_fops = { 611 .owner = NULL, 612 .readdir = hppfs_readdir, 613 .open = hppfs_dir_open, 614 .fsync = hppfs_fsync, 615}; 616 617static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf) 618{ 619 sf->f_blocks = 0; 620 sf->f_bfree = 0; 621 sf->f_bavail = 0; 622 sf->f_files = 0; 623 sf->f_ffree = 0; 624 sf->f_type = HPPFS_SUPER_MAGIC; 625 return(0); 626} 627 628static struct inode *hppfs_alloc_inode(struct super_block *sb) 629{ 630 struct hppfs_inode_info *hi; 631 632 hi = kmalloc(sizeof(*hi), GFP_KERNEL); 633 if(hi == NULL) 634 return(NULL); 635 636 *hi = ((struct hppfs_inode_info) { .proc_dentry = NULL }); 637 inode_init_once(&hi->vfs_inode); 638 return(&hi->vfs_inode); 639} 640 641void hppfs_delete_inode(struct inode *ino) 642{ 643 clear_inode(ino); 644} 645 646static void hppfs_destroy_inode(struct inode *inode) 647{ 648 kfree(HPPFS_I(inode)); 649} 650 651static const struct super_operations hppfs_sbops = { 652 .alloc_inode = hppfs_alloc_inode, 653 .destroy_inode = hppfs_destroy_inode, 654 .read_inode = hppfs_read_inode, 655 .delete_inode = hppfs_delete_inode, 656 .statfs = hppfs_statfs, 657}; 658 659static int hppfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) 660{ 661 struct file *proc_file; 662 struct dentry *proc_dentry; 663 int ret; 664 665 proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; 666 proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); 667 if (IS_ERR(proc_file)) 668 return PTR_ERR(proc_file); 669 670 ret = proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer, buflen); 671 672 fput(proc_file); 673 674 return ret; 675} 676 677static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) 678{ 679 struct file *proc_file; 680 struct dentry *proc_dentry; 681 void *ret; 682 683 proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; 684 proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); 685 if (IS_ERR(proc_file)) 686 return proc_file; 687 688 ret = proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd); 689 690 fput(proc_file); 691 692 return ret; 693} 694 695static const struct inode_operations hppfs_dir_iops = { 696 .lookup = hppfs_lookup, 697}; 698 699static const struct inode_operations hppfs_link_iops = { 700 .readlink = hppfs_readlink, 701 .follow_link = hppfs_follow_link, 702}; 703 704static int init_inode(struct inode *inode, struct dentry *dentry) 705{ 706 if(S_ISDIR(dentry->d_inode->i_mode)){ 707 inode->i_op = &hppfs_dir_iops; 708 inode->i_fop = &hppfs_dir_fops; 709 } 710 else if(S_ISLNK(dentry->d_inode->i_mode)){ 711 inode->i_op = &hppfs_link_iops; 712 inode->i_fop = &hppfs_file_fops; 713 } 714 else { 715 inode->i_op = &hppfs_file_iops; 716 inode->i_fop = &hppfs_file_fops; 717 } 718 719 HPPFS_I(inode)->proc_dentry = dentry; 720 721 return(0); 722} 723 724static int hppfs_fill_super(struct super_block *sb, void *d, int silent) 725{ 726 struct inode *root_inode; 727 struct file_system_type *procfs; 728 struct super_block *proc_sb; 729 int err; 730 731 err = -ENOENT; 732 procfs = get_fs_type("proc"); 733 if(procfs == NULL) 734 goto out; 735 736 if(list_empty(&procfs->fs_supers)) 737 goto out; 738 739 proc_sb = list_entry(procfs->fs_supers.next, struct super_block, 740 s_instances); 741 742 sb->s_blocksize = 1024; 743 sb->s_blocksize_bits = 10; 744 sb->s_magic = HPPFS_SUPER_MAGIC; 745 sb->s_op = &hppfs_sbops; 746 747 root_inode = iget(sb, 0); 748 if(root_inode == NULL) 749 goto out; 750 751 err = init_inode(root_inode, proc_sb->s_root); 752 if(err) 753 goto out_put; 754 755 err = -ENOMEM; 756 sb->s_root = d_alloc_root(root_inode); 757 if(sb->s_root == NULL) 758 goto out_put; 759 760 hppfs_read_inode(root_inode); 761 762 return(0); 763 764 out_put: 765 iput(root_inode); 766 out: 767 return(err); 768} 769 770static int hppfs_read_super(struct file_system_type *type, 771 int flags, const char *dev_name, 772 void *data, struct vfsmount *mnt) 773{ 774 return get_sb_nodev(type, flags, data, hppfs_fill_super, mnt); 775} 776 777static struct file_system_type hppfs_type = { 778 .owner = THIS_MODULE, 779 .name = "hppfs", 780 .get_sb = hppfs_read_super, 781 .kill_sb = kill_anon_super, 782 .fs_flags = 0, 783}; 784 785static int __init init_hppfs(void) 786{ 787 return(register_filesystem(&hppfs_type)); 788} 789 790static void __exit exit_hppfs(void) 791{ 792 unregister_filesystem(&hppfs_type); 793} 794 795module_init(init_hppfs) 796module_exit(exit_hppfs) 797MODULE_LICENSE("GPL"); 798 799/* 800 * Overrides for Emacs so that we follow Linus's tabbing style. 801 * Emacs will notice this stuff at the end of the file and automatically 802 * adjust the settings for this buffer only. This must remain at the end 803 * of the file. 804 * --------------------------------------------------------------------------- 805 * Local variables: 806 * c-file-style: "linux" 807 * End: 808 */ 809