0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/buffer_head.h>
0017 #include "qnx4.h"
0018
0019
0020
0021
0022
0023
0024
0025
0026 static int qnx4_match(int len, const char *name,
0027 struct buffer_head *bh, unsigned long *offset)
0028 {
0029 struct qnx4_inode_entry *de;
0030 int namelen, thislen;
0031
0032 if (bh == NULL) {
0033 printk(KERN_WARNING "qnx4: matching unassigned buffer !\n");
0034 return 0;
0035 }
0036 de = (struct qnx4_inode_entry *) (bh->b_data + *offset);
0037 *offset += QNX4_DIR_ENTRY_SIZE;
0038 if ((de->di_status & QNX4_FILE_LINK) != 0) {
0039 namelen = QNX4_NAME_MAX;
0040 } else {
0041 namelen = QNX4_SHORT_NAME_MAX;
0042 }
0043 thislen = strlen( de->di_fname );
0044 if ( thislen > namelen )
0045 thislen = namelen;
0046 if (len != thislen) {
0047 return 0;
0048 }
0049 if (strncmp(name, de->di_fname, len) == 0) {
0050 if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) {
0051 return 1;
0052 }
0053 }
0054 return 0;
0055 }
0056
0057 static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
0058 const char *name, struct qnx4_inode_entry **res_dir, int *ino)
0059 {
0060 unsigned long block, offset, blkofs;
0061 struct buffer_head *bh;
0062
0063 *res_dir = NULL;
0064 bh = NULL;
0065 block = offset = blkofs = 0;
0066 while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
0067 if (!bh) {
0068 block = qnx4_block_map(dir, blkofs);
0069 if (block)
0070 bh = sb_bread(dir->i_sb, block);
0071 if (!bh) {
0072 blkofs++;
0073 continue;
0074 }
0075 }
0076 *res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
0077 if (qnx4_match(len, name, bh, &offset)) {
0078 *ino = block * QNX4_INODES_PER_BLOCK +
0079 (offset / QNX4_DIR_ENTRY_SIZE) - 1;
0080 return bh;
0081 }
0082 if (offset < bh->b_size) {
0083 continue;
0084 }
0085 brelse(bh);
0086 bh = NULL;
0087 offset = 0;
0088 blkofs++;
0089 }
0090 brelse(bh);
0091 *res_dir = NULL;
0092 return NULL;
0093 }
0094
0095 struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
0096 {
0097 int ino;
0098 struct qnx4_inode_entry *de;
0099 struct qnx4_link_info *lnk;
0100 struct buffer_head *bh;
0101 const char *name = dentry->d_name.name;
0102 int len = dentry->d_name.len;
0103 struct inode *foundinode = NULL;
0104
0105 if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino)))
0106 goto out;
0107
0108 if ((de->di_status & QNX4_FILE_LINK) == QNX4_FILE_LINK) {
0109 lnk = (struct qnx4_link_info *) de;
0110 ino = (le32_to_cpu(lnk->dl_inode_blk) - 1) *
0111 QNX4_INODES_PER_BLOCK +
0112 lnk->dl_inode_ndx;
0113 }
0114 brelse(bh);
0115
0116 foundinode = qnx4_iget(dir->i_sb, ino);
0117 if (IS_ERR(foundinode))
0118 QNX4DEBUG((KERN_ERR "qnx4: lookup->iget -> error %ld\n",
0119 PTR_ERR(foundinode)));
0120 out:
0121 return d_splice_alias(foundinode, dentry);
0122 }