static int qnx4_readlink(struct dentry *dentry, char *buffer, int buflen) { struct inode *inode = dentry->d_inode; struct buffer_head *bh; int i; char c; QNX4DEBUG(("qnx4: qnx4_readlink() called\n")); if (buffer == NULL || inode == NULL || !S_ISLNK(inode->i_mode)) { return -EINVAL; } if (buflen > 1023) { buflen = 1023; } bh = qnx4_bread( inode, 0, 0 ); if (bh == NULL) { QNX4DEBUG(("qnx4: NULL symlink bh\n")); return 0; } QNX4DEBUG(("qnx4: qnx4_bread sym called -> [%s]\n", bh->b_data)); i = 0; while (i < buflen && (c = bh->b_data[i])) { i++; put_user(c, buffer++); } brelse(bh); return i; }
static struct dentry *qnx4_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) { struct inode *inode = dentry->d_inode; struct buffer_head *bh; if ( !inode ) { return ERR_PTR(-ENOENT); } if ( !( bh = qnx4_bread( inode, 0, 0 ) ) ) { dput( base ); return ERR_PTR(-EIO); } UPDATE_ATIME( inode ); base = lookup_dentry( bh->b_data, base, follow ); brelse( bh ); return base; }
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) { printk("qnx4: no superblock on dir.\n"); 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; }