Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | /* * linux/fs/xiafs/dir.c * * Copyright (C) Q. Frank Xia, 1993. * * Based on Linus' minix/dir.c * Copyright (C) Linus Torvalds, 1991, 1992. * * This software may be redistributed per Linux Copyright. */ #ifdef MODULE #include <linux/module.h> #endif #include <asm/segment.h> #include <linux/sched.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/xia_fs.h> #include <linux/stat.h> #include "xiafs_mac.h" #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP(x) (((x)+3) & ~3) static int xiafs_dir_read(struct inode *, struct file *, char *, int); static int xiafs_readdir(struct inode *, struct file *, struct dirent *, int); static struct file_operations xiafs_dir_operations = { NULL, /* lseek - default */ xiafs_dir_read, /* read */ NULL, /* write - bad */ xiafs_readdir, /* readdir */ NULL, /* select - default */ NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open code */ NULL, /* no special release code */ file_fsync /* default fsync */ }; /* * directories can handle most operations... */ struct inode_operations xiafs_dir_inode_operations = { &xiafs_dir_operations, /* default directory file-ops */ xiafs_create, /* create */ xiafs_lookup, /* lookup */ xiafs_link, /* link */ xiafs_unlink, /* unlink */ xiafs_symlink, /* symlink */ xiafs_mkdir, /* mkdir */ xiafs_rmdir, /* rmdir */ xiafs_mknod, /* mknod */ xiafs_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ NULL, /* bmap */ xiafs_truncate, /* truncate */ NULL /* permission */ }; static int xiafs_dir_read(struct inode * inode, struct file * filp, char * buf, int count) { return -EISDIR; } static int xiafs_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count) { u_int offset, i,ret; struct buffer_head * bh; struct xiafs_direct * de; if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) return -EBADF; if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) ) return -EBADF; ret = 0; while (!ret && filp->f_pos < inode->i_size) { offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1); bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0); if (!bh) { filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset; continue; } for (i = 0; i < XIAFS_ZSIZE(inode->i_sb) && i < offset; ) { de = (struct xiafs_direct *) (bh->b_data + i); if (!de->d_rec_len) break; i += de->d_rec_len; } offset = i; de = (struct xiafs_direct *) (offset + bh->b_data); while (!ret && offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) { if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes || de->d_rec_len < 12 || (char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data || de->d_name_len < 1 || de->d_name_len + 8 > de->d_rec_len || de->d_name_len > _XIAFS_NAME_LEN || de->d_name[de->d_name_len] ) { printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR); brelse(bh); return 0; } offset += de->d_rec_len; filp->f_pos += de->d_rec_len; if (de->d_ino) { for (i = 0; i < de->d_name_len ; i++) put_fs_byte(de->d_name[i],i+dirent->d_name); put_fs_byte(0,i+dirent->d_name); put_fs_long(de->d_ino,&dirent->d_ino); put_fs_word(i,&dirent->d_reclen); if (!IS_RDONLY (inode)) { inode->i_atime=CURRENT_TIME; inode->i_dirt=1; } ret = ROUND_UP(NAME_OFFSET(dirent)+i+1); break; } de = (struct xiafs_direct *) (offset + bh->b_data); } brelse(bh); if (offset > XIAFS_ZSIZE(inode->i_sb)) { printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); return 0; } } if (!IS_RDONLY (inode)) { inode->i_atime=CURRENT_TIME; inode->i_dirt=1; } return ret; } |