11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * QNX4 file system, Linux implementation. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Version : 0.2.1 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Using parts of the xiafs filesystem. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * History : 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * 28-05-1998 by Richard Frowijn : first release. 111da177e4SLinus Torvalds * 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support. 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds #include <linux/smp_lock.h> 151da177e4SLinus Torvalds #include <linux/buffer_head.h> 16964f5369SAl Viro #include "qnx4.h" 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir) 191da177e4SLinus Torvalds { 2024e23c24SJosef Sipek struct inode *inode = filp->f_path.dentry->d_inode; 211da177e4SLinus Torvalds unsigned int offset; 221da177e4SLinus Torvalds struct buffer_head *bh; 231da177e4SLinus Torvalds struct qnx4_inode_entry *de; 241da177e4SLinus Torvalds struct qnx4_link_info *le; 251da177e4SLinus Torvalds unsigned long blknum; 261da177e4SLinus Torvalds int ix, ino; 271da177e4SLinus Torvalds int size; 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds QNX4DEBUG(("qnx4_readdir:i_size = %ld\n", (long) inode->i_size)); 301da177e4SLinus Torvalds QNX4DEBUG(("filp->f_pos = %ld\n", (long) filp->f_pos)); 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds lock_kernel(); 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds while (filp->f_pos < inode->i_size) { 351da177e4SLinus Torvalds blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_BITS ); 361da177e4SLinus Torvalds bh = sb_bread(inode->i_sb, blknum); 371da177e4SLinus Torvalds if(bh==NULL) { 381da177e4SLinus Torvalds printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum); 391da177e4SLinus Torvalds break; 401da177e4SLinus Torvalds } 411da177e4SLinus Torvalds ix = (int)(filp->f_pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK; 421da177e4SLinus Torvalds while (ix < QNX4_INODES_PER_BLOCK) { 431da177e4SLinus Torvalds offset = ix * QNX4_DIR_ENTRY_SIZE; 441da177e4SLinus Torvalds de = (struct qnx4_inode_entry *) (bh->b_data + offset); 451da177e4SLinus Torvalds size = strlen(de->di_fname); 461da177e4SLinus Torvalds if (size) { 471da177e4SLinus Torvalds if ( !( de->di_status & QNX4_FILE_LINK ) && size > QNX4_SHORT_NAME_MAX ) 481da177e4SLinus Torvalds size = QNX4_SHORT_NAME_MAX; 491da177e4SLinus Torvalds else if ( size > QNX4_NAME_MAX ) 501da177e4SLinus Torvalds size = QNX4_NAME_MAX; 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds if ( ( de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK) ) != 0 ) { 531da177e4SLinus Torvalds QNX4DEBUG(("qnx4_readdir:%.*s\n", size, de->di_fname)); 541da177e4SLinus Torvalds if ( ( de->di_status & QNX4_FILE_LINK ) == 0 ) 551da177e4SLinus Torvalds ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1; 561da177e4SLinus Torvalds else { 571da177e4SLinus Torvalds le = (struct qnx4_link_info*)de; 5875043cb5SAlexey Dobriyan ino = ( le32_to_cpu(le->dl_inode_blk) - 1 ) * 591da177e4SLinus Torvalds QNX4_INODES_PER_BLOCK + 601da177e4SLinus Torvalds le->dl_inode_ndx; 611da177e4SLinus Torvalds } 621da177e4SLinus Torvalds if (filldir(dirent, de->di_fname, size, filp->f_pos, ino, DT_UNKNOWN) < 0) { 631da177e4SLinus Torvalds brelse(bh); 641da177e4SLinus Torvalds goto out; 651da177e4SLinus Torvalds } 661da177e4SLinus Torvalds } 671da177e4SLinus Torvalds } 681da177e4SLinus Torvalds ix++; 691da177e4SLinus Torvalds filp->f_pos += QNX4_DIR_ENTRY_SIZE; 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds brelse(bh); 721da177e4SLinus Torvalds } 731da177e4SLinus Torvalds out: 741da177e4SLinus Torvalds unlock_kernel(); 751da177e4SLinus Torvalds return 0; 761da177e4SLinus Torvalds } 771da177e4SLinus Torvalds 784b6f5d20SArjan van de Ven const struct file_operations qnx4_dir_operations = 791da177e4SLinus Torvalds { 801da177e4SLinus Torvalds .read = generic_read_dir, 811da177e4SLinus Torvalds .readdir = qnx4_readdir, 8279d25767SAl Viro .fsync = simple_fsync, 831da177e4SLinus Torvalds }; 841da177e4SLinus Torvalds 85c5ef1c42SArjan van de Ven const struct inode_operations qnx4_dir_inode_operations = 861da177e4SLinus Torvalds { 871da177e4SLinus Torvalds .lookup = qnx4_lookup, 881da177e4SLinus Torvalds #ifdef CONFIG_QNX4FS_RW 891da177e4SLinus Torvalds .create = qnx4_create, 901da177e4SLinus Torvalds .unlink = qnx4_unlink, 911da177e4SLinus Torvalds .rmdir = qnx4_rmdir, 921da177e4SLinus Torvalds #endif 931da177e4SLinus Torvalds }; 94