Blame view
fs/qnx4/namei.c
3.02 KB
1da177e4c
|
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
|
14 |
#include <linux/buffer_head.h> |
964f53696
|
15 |
#include "qnx4.h" |
1da177e4c
|
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
|
31 32 |
printk(KERN_WARNING "qnx4: matching unassigned buffer ! "); |
1da177e4c
|
33 34 35 36 37 38 39 40 41 |
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; } |
1da177e4c
|
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
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; |
1da177e4c
|
63 64 65 66 |
bh = NULL; block = offset = blkofs = 0; while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) { if (!bh) { |
8f82ecae5
|
67 68 69 |
block = qnx4_block_map(dir, blkofs); if (block) bh = sb_bread(dir->i_sb, block); |
1da177e4c
|
70 71 72 73 74 75 76 |
if (!bh) { blkofs++; continue; } } *res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset); if (qnx4_match(len, name, bh, &offset)) { |
1da177e4c
|
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
*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; } |
00cd8dd3b
|
93 |
struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
1da177e4c
|
94 95 96 97 98 99 100 101 |
{ 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
|
102 103 104 105 106 107 108 109 110 111 |
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
|
112 113 |
foundinode = qnx4_iget(dir->i_sb, ino); if (IS_ERR(foundinode)) { |
891ddb95d
|
114 115 |
QNX4DEBUG((KERN_ERR "qnx4: lookup->iget -> error %ld ", |
2b7e5bcbd
|
116 117 |
PTR_ERR(foundinode))); return ERR_CAST(foundinode); |
1da177e4c
|
118 119 |
} out: |
1da177e4c
|
120 121 122 123 |
d_add(dentry, foundinode); return NULL; } |