Blame view
fs/qnx4/namei.c
3.25 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* * QNX4 file system, Linux implementation. * * Version : 0.2.1 * * Using parts of the xiafs filesystem. * * History : * * 01-06-1998 by Richard Frowijn : first release. * 21-06-1998 by Frank Denis : dcache support, fixed error codes. * 04-07-1998 by Frank Denis : first step for rmdir/unlink. */ |
1da177e4c Linux-2.6.12-rc2 |
14 |
#include <linux/buffer_head.h> |
964f53696 fs/qnx4: sanitize... |
15 |
#include "qnx4.h" |
1da177e4c Linux-2.6.12-rc2 |
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/* * check if the filename is correct. For some obscure reason, qnx writes a * new file twice in the directory entry, first with all possible options at 0 * and for a second time the way it is, they want us not to access the qnx * filesystem when whe are using linux. */ static int qnx4_match(int len, const char *name, struct buffer_head *bh, unsigned long *offset) { struct qnx4_inode_entry *de; int namelen, thislen; if (bh == NULL) { |
891ddb95d qnx4fs: add missi... |
31 32 |
printk(KERN_WARNING "qnx4: matching unassigned buffer ! "); |
1da177e4c Linux-2.6.12-rc2 |
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 |
return 0; } de = (struct qnx4_inode_entry *) (bh->b_data + *offset); *offset += QNX4_DIR_ENTRY_SIZE; if ((de->di_status & QNX4_FILE_LINK) != 0) { namelen = QNX4_NAME_MAX; } else { namelen = QNX4_SHORT_NAME_MAX; } /* "" means "." ---> so paths like "/usr/lib//libc.a" work */ if (!len && (de->di_fname[0] == '.') && (de->di_fname[1] == '\0')) { return 1; } thislen = strlen( de->di_fname ); if ( thislen > namelen ) thislen = namelen; if (len != thislen) { return 0; } if (strncmp(name, de->di_fname, len) == 0) { if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) { return 1; } } return 0; } static struct buffer_head *qnx4_find_entry(int len, struct inode *dir, const char *name, struct qnx4_inode_entry **res_dir, int *ino) { unsigned long block, offset, blkofs; struct buffer_head *bh; *res_dir = NULL; if (!dir->i_sb) { |
891ddb95d qnx4fs: add missi... |
68 69 |
printk(KERN_WARNING "qnx4: no superblock on dir. "); |
1da177e4c Linux-2.6.12-rc2 |
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 |
return NULL; } bh = NULL; block = offset = blkofs = 0; while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) { if (!bh) { bh = qnx4_bread(dir, blkofs, 0); if (!bh) { blkofs++; continue; } } *res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset); if (qnx4_match(len, name, bh, &offset)) { block = qnx4_block_map( dir, blkofs ); *ino = block * QNX4_INODES_PER_BLOCK + (offset / QNX4_DIR_ENTRY_SIZE) - 1; return bh; } if (offset < bh->b_size) { continue; } brelse(bh); bh = NULL; offset = 0; blkofs++; } brelse(bh); *res_dir = NULL; return NULL; } struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { int ino; struct qnx4_inode_entry *de; struct qnx4_link_info *lnk; struct buffer_head *bh; const char *name = dentry->d_name.name; int len = dentry->d_name.len; struct inode *foundinode = NULL; |
1da177e4c Linux-2.6.12-rc2 |
111 112 113 114 115 116 117 118 119 120 |
if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino))) goto out; /* The entry is linked, let's get the real info */ if ((de->di_status & QNX4_FILE_LINK) == QNX4_FILE_LINK) { lnk = (struct qnx4_link_info *) de; ino = (le32_to_cpu(lnk->dl_inode_blk) - 1) * QNX4_INODES_PER_BLOCK + lnk->dl_inode_ndx; } brelse(bh); |
2b7e5bcbd iget: stop QNX4 f... |
121 122 |
foundinode = qnx4_iget(dir->i_sb, ino); if (IS_ERR(foundinode)) { |
891ddb95d qnx4fs: add missi... |
123 124 |
QNX4DEBUG((KERN_ERR "qnx4: lookup->iget -> error %ld ", |
2b7e5bcbd iget: stop QNX4 f... |
125 126 |
PTR_ERR(foundinode))); return ERR_CAST(foundinode); |
1da177e4c Linux-2.6.12-rc2 |
127 128 |
} out: |
1da177e4c Linux-2.6.12-rc2 |
129 130 131 132 |
d_add(dentry, foundinode); return NULL; } |