home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Utilities / vmount-0.6a-I / src / file_ops.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-21  |  20.1 KB  |  818 lines

  1. /*
  2.  * Name: file_ops.c
  3.  * Description: Functions that can be called from the NFS interface.
  4.  * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
  5.  * Date: 1996-11-14
  6.  * Copyright: GNU-GPL
  7.  * Tabsize: 4
  8.  */
  9.  
  10. #include <linux/autoconf.h>
  11. #include <linux/fs.h>
  12. #include <linux/affs_fs.h>
  13. #include <linux/ext2_fs.h>
  14. #include <linux/ext_fs.h>
  15. #include <linux/hpfs_fs.h>
  16. #include <linux/iso_fs.h>
  17. #include <linux/minix_fs.h>
  18. #include <linux/msdos_fs.h>
  19. #include <linux/ncp_fs.h>
  20. #include <linux/nfs_fs.h>
  21. #include <linux/proc_fs.h>
  22. #include <linux/smb_fs.h>
  23. #include <linux/sysv_fs.h>
  24. #include <linux/ufs_fs.h>
  25. #include <linux/umsdos_fs.h>
  26. #include <linux/xia_fs.h>
  27. #include "my_defines.h"
  28.  
  29. #define    DPRINTF(arg)    if(debug_mode & DEBUG_FOPS)    dprintf arg
  30.  
  31. extern void    init_ntfs_fs(void);
  32.  
  33. #define    MY_DEVICE                256
  34. #define    TRANSFER_BUFFER_SIZE    50000
  35.  
  36. /* ------------------------------------------------------------------------- */
  37.  
  38. extern void    bzero(void *block, int size);
  39. extern void    *malloc(int size);
  40.  
  41. extern int    my_blocksize;
  42.  
  43. /* ------------------------------------------------------------------------- */
  44.  
  45. struct super_block                my_superblock;
  46. static struct file_system_type    *fs_types = NULL;
  47.  
  48. /* ------------------------------------------------------------------------- */
  49.  
  50. int register_filesystem(struct file_system_type *fstype)
  51. {
  52.     DPRINTF(("registering filesystem %s\n", fstype->name));
  53.     fstype->next = fs_types;
  54.     fs_types = fstype;
  55.     return 0;
  56. }
  57.  
  58. /* ------------------------------------------------------------------------- */
  59.  
  60. static void    my_sync_super(void)
  61. {
  62. struct super_block    *s = &my_superblock;
  63.  
  64.     if(s->s_dirt && s->s_op->write_super != NULL){
  65.         s->s_op->write_super(s);
  66.         s->s_dirt = 0;
  67.     }
  68. }
  69.  
  70. /* ------------------------------------------------------------------------- */
  71.  
  72. void    my_sync(void)
  73. {
  74.     my_sync_super();
  75.     my_sync_inodes();
  76.     my_sync_blocks();
  77. }
  78.  
  79. /* ------------------------------------------------------------------------- */
  80.  
  81. static int    is_valid_fs(struct file_system_type *fs)
  82. {
  83. struct super_block    s;
  84.  
  85.     bzero(&s, sizeof(s));
  86.     s.s_dev = MY_DEVICE;
  87.     s.s_flags = MS_RDONLY;
  88.     return fs->read_super(&s, "", 0) != 0;
  89. }
  90.  
  91. /* ------------------------------------------------------------------------- */
  92.  
  93. char    *valid_filesystems(void)
  94. {
  95. struct file_system_type    *fs;
  96. static char                fslist[1024];    /* don't like static limits.... */
  97.  
  98.     fslist[0] = 0;
  99.     for(fs=fs_types;fs!=NULL;fs=fs->next){
  100.         if(is_valid_fs(fs)){
  101.             if(fslist[0] != 0)
  102.                 strcat(fslist, " ");
  103.             strcat(fslist, fs->name);
  104.         }
  105.     }
  106.     return fslist;
  107. }
  108.  
  109. /* ------------------------------------------------------------------------- */
  110.  
  111. static int    do_my_mount(struct file_system_type *fs, int flags, void *data, int *root_i)
  112. {
  113. struct super_block    *s = &my_superblock;
  114.  
  115.     DPRINTF(("do_my_mount(fs=%s, flags=0x%x)\n", fs->name, flags));
  116.     s->s_dev = MY_DEVICE;
  117.     s->s_flags = flags;
  118.     if (!fs->read_super(s, data, 0)){
  119.         return -1;
  120.     }
  121.     s->s_dev = MY_DEVICE;
  122.     s->s_covered = s->s_mounted;    /* used for error output! should be NULL */
  123.     s->s_type = fs;
  124.     *root_i = s->s_mounted->i_ino;
  125.     if(s->s_op->write_super != NULL){
  126.         s->s_op->write_super(s);
  127.         s->s_dirt = 0;
  128.     }
  129.     my_sync();
  130.     return 0;
  131. }
  132.  
  133. /* ------------------------------------------------------------------------- */
  134.  
  135. int    my_mount(char *fsname, int options, void *data, int *root_inode)
  136. {
  137. struct file_system_type    *fs;
  138.  
  139.     bzero(&my_superblock, sizeof(my_superblock));
  140.     for(fs=fs_types;fs!=NULL;fs=fs->next){
  141.         if(strcmp(fsname, fs->name) == 0){
  142.             break;
  143.         }
  144.     }
  145.     if(fs != NULL){
  146.         return do_my_mount(fs, options & MNT_RONLY ? MS_RDONLY : 0,
  147.                                                         data, root_inode);
  148.     }else{
  149.         printk("filesystem ->%s<- not found\n", fsname);
  150.         return -1;
  151.     }
  152. }
  153.  
  154. /* ------------------------------------------------------------------------- */
  155.  
  156. int    my_unmount(void)
  157. {
  158. struct super_block    *sb = &my_superblock;
  159.  
  160.     DPRINTF(("my_unmount()\n"));
  161.     iput(sb->s_mounted);    /* free mounted inode */
  162.     my_sync();
  163.     if(sb->s_op && sb->s_op->put_super)
  164.         sb->s_op->put_super(sb);
  165.     my_sync_inodes();
  166.     my_sync_blocks();
  167.     return 0;
  168. }
  169.  
  170. /* ------------------------------------------------------------------------- */
  171.  
  172. static int    check_access(struct inode *inode, int mode)
  173. {
  174. int        i, igid = inode->i_gid, iuid = inode->i_uid;
  175.  
  176.     if(nfs_uid == 0){        /* root may do everything */
  177.         return 1;
  178.     }
  179.     if(id_is_fixed(IDBUF_USR))
  180.         iuid = fixed_id(IDBUF_USR);
  181.     if(id_is_fixed(IDBUF_GRP))
  182.         igid = fixed_id(IDBUF_GRP);
  183.     if(nfs_uid == iuid){    /* you may always access your own files */
  184.         return 1;
  185.     }
  186.     if(iuid == nfs_uid){
  187.         return (inode->i_mode & (mode << 6)) != 0;
  188.     }
  189.     for(i=0;i<nfs_gidslen;i++){
  190.         if(igid == nfs_gids[i]){
  191.             return (inode->i_mode & (mode << 3)) != 0;
  192.         }
  193.     }
  194.     return (inode->i_mode & mode) != 0;
  195. }
  196.  
  197. /* ------------------------------------------------------------------------- */
  198.  
  199. #define    CHECK_WRITE(inode, iputs)                                    \
  200.     if(!check_access(inode, 2)){                                    \
  201.         error = -MY_NFSERR_ACCES;                                    \
  202.         DPRINTF(("write access for %ld denied\n", inode->i_ino));    \
  203.         iputs;                                                        \
  204.         goto do_return;                                                \
  205.     }
  206.  
  207. #define    CHECK_READ(inode, iputs)                                    \
  208.     if(!check_access(inode, 4)){                                    \
  209.         error = -MY_NFSERR_ACCES;                                    \
  210.         DPRINTF(("read access for %ld denied\n", inode->i_ino));    \
  211.         iputs;                                                        \
  212.         goto do_return;                                                \
  213.     }
  214.  
  215. #define    CHECK_EXEC(inode, iputs)                                    \
  216.     if(!check_access(inode, 1)){                                    \
  217.         error = -MY_NFSERR_ACCES;                                    \
  218.         DPRINTF(("search access for %ld denied\n", inode->i_ino));    \
  219.         iputs;                                                        \
  220.         goto do_return;                                                \
  221.     }
  222.  
  223. #define    CHECK_ATTR(inode, iputs)                                        \
  224.     {    int    iuid = inode->i_uid;                                        \
  225.         if(id_is_fixed(IDBUF_USR))                                        \
  226.             iuid = fixed_id(IDBUF_USR);                                    \
  227.         if(nfs_uid != 0 && iuid != nfs_uid){                            \
  228.             error = -MY_NFSERR_ACCES;                                    \
  229.             DPRINTF(("chmod access for %ld denied\n", inode->i_ino));    \
  230.             iputs;                                                        \
  231.             goto do_return;                                                \
  232.         }                                                                \
  233.     }
  234.  
  235. /* ------------------------------------------------------------------------- */
  236.  
  237. static void    set_attr(struct inode *inode, my_attr_t *attr)
  238. {
  239. int        i;
  240.  
  241.     if(attr->mode != -1 && inode->i_mode != attr->mode){
  242.         inode->i_mode = (inode->i_mode & ~07777) | (attr->mode & 07777);
  243.         inode->i_dirt = 1;
  244.     }
  245.     if(nfs_uid == 0 && attr->uid != -1 && inode->i_uid != attr->uid){
  246.         inode->i_uid = attr->uid;
  247.         inode->i_dirt = 1;
  248.     }
  249.     if(attr->gid != -1 && inode->i_gid != attr->gid){
  250.         for(i=0;i<nfs_gidslen;i++){
  251.             if(nfs_gids[i] == attr->gid){
  252.                 inode->i_gid = attr->gid;
  253.                 inode->i_dirt = 1;
  254.                 break;
  255.             }
  256.         }
  257.     }
  258.     if(attr->mtime != -1 && inode->i_mtime != attr->mtime){
  259.         inode->i_mtime = attr->mtime;
  260.         inode->i_dirt = 1;
  261.     }
  262. }
  263.  
  264. /* ------------------------------------------------------------------------- */
  265.  
  266. static void    get_attr(struct inode *inode, my_attr_t *attr)
  267. {
  268.     attr->mode = inode->i_mode;
  269.     attr->nlink = inode->i_nlink;
  270.     attr->uid = inode->i_uid;
  271.     attr->gid = inode->i_gid;
  272.     attr->size = S_ISDIR(attr->mode) && inode->i_size == 0 ?
  273.                     100000 : inode->i_size;        /* fake a directory size */
  274.     attr->blocksize = inode->i_blksize > 0 ? inode->i_blksize : PAGE_SIZE;
  275.     attr->blocks = inode->i_blocks > 0 ?
  276.             inode->i_blocks : (attr->size + my_blocksize - 1) / my_blocksize;
  277.     attr->fileid = inode->i_ino;
  278.     attr->atime = inode->i_atime;
  279.     attr->mtime = inode->i_mtime;
  280.     attr->ctime = inode->i_ctime;
  281.     attr->rdev = inode->i_rdev;
  282. }
  283.  
  284. /* ------------------------------------------------------------------------- */
  285.  
  286. #define    FIND_INODE(inode, fh, ops, iputs)                \
  287.     if((inode = iget(&my_superblock, fh)) == NULL){        \
  288.         DPRINTF(("invalid inode %d: not found in %s/%d\n",\
  289.                             fh, __FILE__, __LINE__));    \
  290.         iputs;                                            \
  291.         error = -MY_NFSERR_STALE;                        \
  292.         goto do_return;                                    \
  293.     }                                                    \
  294.     if((ops = inode->i_op) == NULL){                    \
  295.         printk("invalid inode %d: no inode operations in %s/%d\n",\
  296.                                 fh, __FILE__, __LINE__);\
  297.         iput(inode);                                    \
  298.         iputs;                                            \
  299.         error = -MY_NFSERR_STALE;                        \
  300.         goto do_return;                                    \
  301.     }
  302.  
  303. #define    VALIDATE(operation, iputs)        \
  304.     if(!(operation)){                    \
  305.         DPRINTF(("invalid operation in %s/%d\n", __FILE__, __LINE__));\
  306.         iputs;                            \
  307.         error = -EINVAL;                \
  308.         goto do_return;                    \
  309.     }
  310.  
  311. #define    RETAIN(inode)    (inode)->i_count++
  312.  
  313. /* ------------------------------------------------------------------------- */
  314.  
  315. static int    fo_new(int is_dir, int *fh, my_attr_t *fa, int dir,
  316.                                                 char *name, my_attr_t *sa)
  317. {
  318. struct inode            *inode, *new_inode = NULL;
  319. struct inode_operations    *ops;
  320. int                        error = 0;
  321.  
  322.     FIND_INODE(inode, dir, ops, ;);
  323.     VALIDATE(ops->lookup, ;);
  324.     CHECK_WRITE(inode, ;);
  325.     if(is_dir){
  326.         VALIDATE(ops->mkdir, ;);
  327.         RETAIN(inode);    /* retain for mkdir */
  328.         error = ops->mkdir(inode, name, strlen(name), sa->mode);
  329.         if(error)    goto do_return;
  330.         RETAIN(inode);    /* retain for second operation */
  331.         error = ops->lookup(inode, name, strlen(name), &new_inode);
  332.     }else{
  333.         RETAIN(inode);    /* retain for additional lookup or unlink */
  334.         if(sa->size == 0){
  335.             VALIDATE(ops->unlink, iput(inode));
  336.             ops->unlink(inode, name, strlen(name));    /* ignore errors */
  337.         }else{
  338.             if(ops->lookup(inode, name, strlen(name), &new_inode) == 0){
  339.                 *fh = new_inode->i_ino;
  340.                 get_attr(new_inode, fa);
  341.                 iput(new_inode);
  342.                 iput(inode);
  343.                 return 0;
  344.             }
  345.         }
  346.         VALIDATE(ops->create, ;);
  347.         RETAIN(inode);    /* retain for create */
  348.         error = ops->create(inode, name, strlen(name), sa->mode, &new_inode);
  349.     }
  350.     if(error)
  351.         goto do_return;
  352.     *fh = new_inode->i_ino;
  353.     new_inode->i_uid = nfs_uid;
  354.     new_inode->i_gid = nfs_gid;
  355.     new_inode->i_dirt = 1;
  356.     set_attr(new_inode, sa);
  357.     new_inode->i_mode &= ~S_IFMT;
  358.     new_inode->i_mode |= is_dir ? S_IFDIR : S_IFREG;
  359.     get_attr(new_inode, fa);
  360.     iput(new_inode);
  361. do_return:
  362.     iput(inode);
  363.     return error;
  364. }
  365.  
  366. /* ------------------------------------------------------------------------- */
  367.  
  368. int    fo_create(int *fh, my_attr_t *fa, int dir, char *name, my_attr_t *sa)
  369. {
  370.     DPRINTF(("fo_create(ino=%d, name=%s)\n", dir, name));
  371.     return fo_new(0, fh, fa, dir, name, sa);
  372. }
  373.  
  374. /* ------------------------------------------------------------------------- */
  375.  
  376. int    fo_mkdir(int *fh, my_attr_t *fa, int dir, char *name, my_attr_t *sa)
  377. {
  378.     DPRINTF(("fo_mkdir(ino=%d, name=%s)\n", dir, name));
  379.     return fo_new(1, fh, fa, dir, name, sa);
  380. }
  381.  
  382. /* ------------------------------------------------------------------------- */
  383.  
  384. int    fo_getattr(my_attr_t *fa, int fh)
  385. {
  386. struct inode            *inode;
  387. struct inode_operations    *ops;
  388. int                        error = 0;
  389.  
  390.     DPRINTF(("fo_getattr(ino=%d)\n", fh));
  391.     FIND_INODE(inode, fh, ops, ;);
  392.     get_attr(inode, fa);
  393.     iput(inode);
  394. do_return:
  395.     return error;
  396. }
  397.  
  398. /* ------------------------------------------------------------------------- */
  399.  
  400. int    fo_lookup(int *fh, my_attr_t *fa, int dir, char *name)
  401. {
  402. struct inode            *inode, *found_inode = NULL;
  403. struct inode_operations    *ops;
  404. int                        error = 0;
  405.  
  406.     DPRINTF(("fo_lookup(ino=%d, name=%s)\n", dir, name));
  407.     FIND_INODE(inode, dir, ops, ;);
  408.     CHECK_READ(inode, iput(inode));
  409.     VALIDATE(ops->lookup, iput(inode));
  410.     if((error = ops->lookup(inode, name, strlen(name), &found_inode)) != 0)
  411.         goto do_return;
  412.     get_attr(found_inode, fa);
  413.     *fh = found_inode->i_ino;
  414.     iput(found_inode);
  415. do_return:
  416.     return error;
  417. }
  418.  
  419. /* ------------------------------------------------------------------------- */
  420.  
  421. struct my_dirinfo{
  422.     my_direntry_t    **entries;
  423.     int                max_bytes;
  424.     int                *put_cookie;
  425.     int                called;
  426. };
  427.  
  428. /* ------------------------------------------------------------------------- */
  429.  
  430. static int    callback(void *arg, const char *name, int namelen,
  431.                                                     off_t offs, ino_t inum)
  432. {
  433. struct my_dirinfo    *di = arg;
  434. my_direntry_t        *p;
  435.  
  436.     di->called = 1;
  437.     if(di->put_cookie != NULL)
  438.         *(di->put_cookie) = offs;
  439.     di->max_bytes -= namelen + 1 + sizeof(my_direntry_t);
  440.     if(di->max_bytes < 0){
  441.         DPRINTF(("callback(): stopping\n"));
  442.         return -1;
  443.     }
  444.     p = malloc(sizeof(my_direntry_t));
  445.     p->fh = inum;
  446.     p->name = malloc(namelen + 1);
  447.     memcpy(p->name, name, namelen);
  448.     p->name[namelen] = 0;
  449.     p->cookie = -1;
  450.     di->put_cookie = &p->cookie;
  451.     p->next = NULL;
  452.     *(di->entries) = p;
  453.     di->entries = &p->next;
  454.     DPRINTF(("callback(): added ->%s<- offset=%d, inode=%d\n",
  455.                                             p->name, (int)offs, (int)inum));
  456.     return 0;
  457. }
  458.  
  459. /* ------------------------------------------------------------------------- */
  460.  
  461. int    fo_readdir(my_direntry_t **result, int *eof, int max_bytes,
  462.                                                         int dir, int cookie)
  463. {
  464. struct inode            *inode;
  465. struct inode_operations    *ops;
  466. struct file_operations    *fops;
  467. struct file                filp;
  468. int                        error = 0;
  469. struct my_dirinfo        dirinfo;
  470.  
  471.     *result = NULL;
  472.     dirinfo.entries = result;
  473.     dirinfo.max_bytes = max_bytes;
  474.     dirinfo.put_cookie = NULL;
  475.     dirinfo.called = 0;
  476.     DPRINTF(("fo_readdir(ino=%d, cookie=%d, max=%d)\n",dir,cookie,max_bytes));
  477.     FIND_INODE(inode, dir, ops, ;);
  478.     CHECK_EXEC(inode, ;);
  479.     CHECK_READ(inode, ;);
  480.     VALIDATE(ops->default_file_ops, ;);
  481.     fops = ops->default_file_ops;
  482.     VALIDATE(fops->readdir, ;);
  483.     bzero(&filp, sizeof(filp));
  484.     filp.f_mode = inode->i_mode;
  485.     filp.f_pos = cookie;
  486.     do{
  487.         dirinfo.called = 0;
  488.         error = fops->readdir(inode, &filp, &dirinfo, callback);
  489.         if(error < 0)
  490.             break;
  491.     }while(dirinfo.max_bytes > 0 && dirinfo.called);
  492.     if(dirinfo.put_cookie != NULL)
  493.         *(dirinfo.put_cookie) = filp.f_pos;
  494. do_return:
  495.     *eof = !dirinfo.called;
  496.     iput(inode);
  497.     return error;
  498. }
  499.  
  500. /* ------------------------------------------------------------------------- */
  501.  
  502. int    fo_setattr(my_attr_t *fa, int fh, my_attr_t *sa)
  503. {
  504. struct inode            *inode;
  505. struct inode_operations    *ops;
  506. int                        error = 0;
  507.  
  508.     DPRINTF(("fo_setattr(ino=%d)\n", fh));
  509.     FIND_INODE(inode, fh, ops, ;);
  510.     CHECK_ATTR(inode, iput(inode));
  511.     set_attr(inode, sa);
  512.     get_attr(inode, fa);
  513.     iput(inode);
  514. do_return:
  515.     return error;
  516. }
  517.  
  518. /* ------------------------------------------------------------------------- */
  519.  
  520. static int    fo_rm(int is_dir, int dir, char *name)
  521. {
  522. struct inode            *inode;
  523. struct inode_operations    *ops;
  524. int                        error = 0;
  525. int                        (*rmop)(struct inode *,const char *,int);
  526.  
  527.     DPRINTF(("fo_rm(ino=%d, name=%s)\n", dir, name));
  528.     FIND_INODE(inode, dir, ops, ;);
  529.     CHECK_WRITE(inode, iput(inode));
  530.     rmop = is_dir ? ops->rmdir : ops->unlink;
  531.     VALIDATE(rmop, iput(inode));
  532.     if((error = rmop(inode, name, strlen(name))) != 0)
  533.         goto do_return;
  534. do_return:
  535.     return error;
  536. }
  537.  
  538. /* ------------------------------------------------------------------------- */
  539.  
  540. int    fo_remove(int dir, char *name)
  541. {
  542.     return fo_rm(0, dir, name);
  543. }
  544.  
  545. /* ------------------------------------------------------------------------- */
  546.  
  547. int    fo_rmdir(int dir, char *name)
  548. {
  549.     return fo_rm(1, dir, name);
  550. }
  551.  
  552. /* ------------------------------------------------------------------------- */
  553.  
  554. int    fo_rename(int fromdir, char *fromname, int todir, char *toname)
  555. {
  556. struct inode            *from_i, *to_i;
  557. struct inode_operations    *from_o, *to_o;
  558. int                        error = 0;
  559.  
  560.     DPRINTF(("fo_rename(ino=%d, name=%s, ino=%d, name=%s)\n", fromdir,
  561.                                                 fromname, todir, toname));
  562.     FIND_INODE(from_i, fromdir, from_o, ;);
  563.     CHECK_WRITE(from_i, iput(from_i));
  564.     FIND_INODE(to_i, todir, to_o, iput(from_i));
  565.     CHECK_WRITE(to_i, iput(from_i); iput(to_i));
  566.     VALIDATE(from_o->rename, iput(from_i); iput(to_i));
  567.     error = from_o->rename(from_i, fromname, strlen(fromname),
  568.                                         to_i, toname, strlen(toname), 0);
  569. do_return:
  570.     return error;
  571. }
  572.  
  573. /* ------------------------------------------------------------------------- */
  574.  
  575. int    fo_statfs(my_statfs_t *fsstat)
  576. {
  577. struct statfs    stat;
  578.  
  579.     DPRINTF(("fo_statfs()\n"));
  580.     if(!my_superblock.s_op->statfs)
  581.         return -EINVAL;
  582.     my_superblock.s_op->statfs(&my_superblock, &stat, sizeof(stat));
  583.     fsstat->type = stat.f_type;
  584.     fsstat->bsize = stat.f_bsize;
  585.     fsstat->blocks = stat.f_blocks;
  586.     fsstat->bfree = stat.f_bfree;
  587.     fsstat->bavail = stat.f_bavail;
  588.     fsstat->files = stat.f_files;
  589.     fsstat->ffree = stat.f_ffree;
  590.     return 0;
  591. }
  592.  
  593. /* ------------------------------------------------------------------------- */
  594.  
  595. int    fo_read(my_attr_t *fa, int *len, char **data, int fh, int offs, int count)
  596. {
  597. static char                transfer_buf[TRANSFER_BUFFER_SIZE];
  598. struct inode            *inode;
  599. struct inode_operations    *ops;
  600. struct file_operations    *fops;
  601. struct file                filp;
  602. int                        error = 0;
  603.  
  604.     DPRINTF(("fo_read(ino=%d, offs=%d, len=%d)\n", fh, offs, count));
  605.     *data = transfer_buf;
  606.     FIND_INODE(inode, fh, ops, ;);
  607.     CHECK_READ(inode, ;);
  608.     if(offs + count > inode->i_size)
  609.         count = inode->i_size - offs;
  610.     if(count <= 0){    /* nothing to be done */
  611.         get_attr(inode, fa);
  612.         *len = 0;
  613.         goto do_return;
  614.     }
  615.     VALIDATE(ops->default_file_ops, ;);
  616.     fops = ops->default_file_ops;
  617.     VALIDATE(fops->read, ;);
  618.     bzero(&filp, sizeof(filp));
  619.     filp.f_mode = inode->i_mode;
  620.     filp.f_pos = offs;
  621.     if(count > sizeof(transfer_buf))
  622.         count = sizeof(transfer_buf);
  623.     error = fops->read(inode, &filp, transfer_buf, count);
  624.     *len = error;
  625.     error = error < 0 ? error : 0;
  626.     get_attr(inode, fa);
  627. do_return:
  628.     iput(inode);
  629.     DPRINTF(("fo_read() returns %d\n", error));
  630.     return error;
  631. }
  632.  
  633. /* ------------------------------------------------------------------------- */
  634.  
  635. int    fo_write(my_attr_t *fa, int fh, int offset, int count, char *data)
  636. {
  637. struct inode            *inode;
  638. struct inode_operations    *ops;
  639. struct file_operations    *fops;
  640. struct file                filp;
  641. int                        error = 0;
  642.  
  643.     DPRINTF(("fo_write(ino=%d, offs=%d, len=%d)\n", fh, offset, count));
  644.     FIND_INODE(inode, fh, ops, ;);
  645.     CHECK_WRITE(inode, ;);
  646.     if(count <= 0){    /* nothing to be done */
  647.         get_attr(inode, fa);
  648.         goto do_return;
  649.     }
  650.     VALIDATE(ops->default_file_ops, ;);
  651.     fops = ops->default_file_ops;
  652.     VALIDATE(fops->write, ;);
  653.     bzero(&filp, sizeof(filp));
  654.     filp.f_mode = inode->i_mode;
  655.     filp.f_pos = offset;
  656.     error = fops->write(inode, &filp, data, count);
  657.     error = error < 0 ? error : 0;
  658.     get_attr(inode, fa);
  659. do_return:
  660.     iput(inode);
  661.     DPRINTF(("fo_write() returns %d\n", error));
  662.     return error;
  663. }
  664.  
  665. /* ------------------------------------------------------------------------- */
  666.  
  667. int    fo_link(int from, int dir, char *name)
  668. {
  669. struct inode            *from_i, *dir_i;
  670. struct inode_operations    *from_o, *dir_o;
  671. int                        error = 0;
  672.  
  673.     DPRINTF(("fo_link(ino=%d, dir=%d, name=%s)\n", from, dir, name));
  674.     FIND_INODE(from_i, from, from_o, ;);
  675.     FIND_INODE(dir_i, dir, dir_o, iput(from_i));
  676.     CHECK_WRITE(dir_i, iput(from_i); iput(dir_i));
  677.     VALIDATE(dir_o->link, iput(from_i); iput(dir_i));
  678.     error = dir_o->link(from_i, dir_i, name, strlen(name));
  679. do_return:
  680.     return error;
  681. }
  682.  
  683. /* ------------------------------------------------------------------------- */
  684.  
  685. int    fo_readlink(char **path, int fh)
  686. {
  687. struct inode            *inode;
  688. struct inode_operations    *ops;
  689. int                        error = 0;
  690. static char                namebuf[2048];
  691.  
  692.     DPRINTF(("fo_readlink(ino=%d)\n", fh));
  693.     FIND_INODE(inode, fh, ops, ;);
  694.     VALIDATE(ops->readlink, iput(inode));
  695.     *path = namebuf;
  696.     error = ops->readlink(inode, *path, sizeof(namebuf));
  697.     if(error >= 0){
  698.         if(error < sizeof(namebuf))
  699.             namebuf[error] = 0;
  700.         else
  701.             namebuf[sizeof(namebuf)-1] = 0;
  702.     }
  703. do_return:
  704.     return error;
  705. }
  706.  
  707. /* ------------------------------------------------------------------------- */
  708.  
  709. int    fo_symlink(int fromdir, char *fromname, char *topath, my_attr_t *sa)
  710. {
  711. struct inode            *dir_i;
  712. struct inode_operations    *dir_o;
  713. int                        error = 0;
  714.  
  715.     DPRINTF(("fo_symlink(dir=%d, name=%s, path=%s)\n", fromdir,
  716.                                                     fromname, topath));
  717.     FIND_INODE(dir_i, fromdir, dir_o, ;);
  718.     CHECK_WRITE(dir_i, iput(dir_i));
  719.     VALIDATE(dir_o->symlink, iput(dir_i));
  720.     error = dir_o->symlink(dir_i, fromname, strlen(fromname), topath);
  721.     /* ignore attributes! links should have all flags set, anyway */
  722. do_return:
  723.     return error;
  724. }
  725.  
  726. /* ------------------------------------------------------------------------- */
  727.  
  728. void    fops_regular(void)
  729. {
  730. static int    i = 0;
  731.  
  732.     if(++i > 10){    /* do a sync every 10s */
  733.         i = 0;
  734.         my_sync();
  735.     }
  736. }
  737.  
  738. /* ------------------------------------------------------------------------- */
  739.  
  740. void    fops_init(void)
  741. {
  742. #ifdef CONFIG_EXT_FS
  743.     init_ext_fs();
  744. #endif
  745.  
  746. #ifdef CONFIG_EXT2_FS
  747.     init_ext2_fs();
  748. #endif
  749.  
  750. #ifdef CONFIG_XIA_FS
  751.     init_xiafs_fs();
  752. #endif
  753.  
  754. #ifdef CONFIG_MINIX_FS
  755.     init_minix_fs();
  756. #endif
  757.  
  758. #ifdef CONFIG_UMSDOS_FS
  759.     init_umsdos_fs();
  760. #endif
  761.  
  762. #ifdef CONFIG_FAT_FS
  763.     init_fat_fs();
  764. #endif
  765.  
  766. #ifdef CONFIG_MSDOS_FS
  767.     init_msdos_fs();
  768. #endif
  769.  
  770. #ifdef CONFIG_VFAT_FS
  771.     init_vfat_fs();
  772. #endif
  773.  
  774. #ifdef CONFIG_PROC_FS
  775.     init_proc_fs();
  776. #endif
  777.  
  778. #ifdef CONFIG_NFS_FS
  779.     init_nfs_fs();
  780. #endif
  781.  
  782. #ifdef CONFIG_SMB_FS
  783.     init_smb_fs();
  784. #endif
  785.  
  786. #ifdef CONFIG_NCP_FS
  787.     init_ncp_fs();
  788. #endif
  789.  
  790. #ifdef CONFIG_ISO9660_FS
  791.     init_iso9660_fs();
  792. #endif
  793.  
  794. #ifdef CONFIG_SYSV_FS
  795.     init_sysv_fs();
  796. #endif
  797.  
  798. #ifdef CONFIG_HPFS_FS
  799.     init_hpfs_fs();
  800. #endif
  801.  
  802. #ifdef CONFIG_AFFS_FS
  803.     init_affs_fs();
  804. #endif
  805.  
  806. #ifdef CONFIG_UFS_FS
  807.     init_ufs_fs();
  808. #endif
  809.  
  810. #ifdef CONFIG_NTFS_FS
  811.     init_ntfs_fs();
  812. #endif
  813.  
  814. }
  815.  
  816. /* ------------------------------------------------------------------------- */
  817.  
  818.