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/string.h> 151da177e4SLinus Torvalds #include <linux/errno.h> 161da177e4SLinus Torvalds #include <linux/fs.h> 171da177e4SLinus Torvalds #include <linux/qnx4_fs.h> 181da177e4SLinus Torvalds #include <linux/stat.h> 191da177e4SLinus Torvalds #include <linux/smp_lock.h> 201da177e4SLinus Torvalds #include <linux/buffer_head.h> 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir) 241da177e4SLinus Torvalds { 2524e23c24SJosef Sipek struct inode *inode = filp->f_path.dentry->d_inode; 261da177e4SLinus Torvalds unsigned int offset; 271da177e4SLinus Torvalds struct buffer_head *bh; 281da177e4SLinus Torvalds struct qnx4_inode_entry *de; 291da177e4SLinus Torvalds struct qnx4_link_info *le; 301da177e4SLinus Torvalds unsigned long blknum; 311da177e4SLinus Torvalds int ix, ino; 321da177e4SLinus Torvalds int size; 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds QNX4DEBUG(("qnx4_readdir:i_size = %ld\n", (long) inode->i_size)); 351da177e4SLinus Torvalds QNX4DEBUG(("filp->f_pos = %ld\n", (long) filp->f_pos)); 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds lock_kernel(); 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds while (filp->f_pos < inode->i_size) { 401da177e4SLinus Torvalds blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_BITS ); 411da177e4SLinus Torvalds bh = sb_bread(inode->i_sb, blknum); 421da177e4SLinus Torvalds if(bh==NULL) { 431da177e4SLinus Torvalds printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum); 441da177e4SLinus Torvalds break; 451da177e4SLinus Torvalds } 461da177e4SLinus Torvalds ix = (int)(filp->f_pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK; 471da177e4SLinus Torvalds while (ix < QNX4_INODES_PER_BLOCK) { 481da177e4SLinus Torvalds offset = ix * QNX4_DIR_ENTRY_SIZE; 491da177e4SLinus Torvalds de = (struct qnx4_inode_entry *) (bh->b_data + offset); 501da177e4SLinus Torvalds size = strlen(de->di_fname); 511da177e4SLinus Torvalds if (size) { 521da177e4SLinus Torvalds if ( !( de->di_status & QNX4_FILE_LINK ) && size > QNX4_SHORT_NAME_MAX ) 531da177e4SLinus Torvalds size = QNX4_SHORT_NAME_MAX; 541da177e4SLinus Torvalds else if ( size > QNX4_NAME_MAX ) 551da177e4SLinus Torvalds size = QNX4_NAME_MAX; 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds if ( ( de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK) ) != 0 ) { 581da177e4SLinus Torvalds QNX4DEBUG(("qnx4_readdir:%.*s\n", size, de->di_fname)); 591da177e4SLinus Torvalds if ( ( de->di_status & QNX4_FILE_LINK ) == 0 ) 601da177e4SLinus Torvalds ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1; 611da177e4SLinus Torvalds else { 621da177e4SLinus Torvalds le = (struct qnx4_link_info*)de; 6375043cb5SAlexey Dobriyan ino = ( le32_to_cpu(le->dl_inode_blk) - 1 ) * 641da177e4SLinus Torvalds QNX4_INODES_PER_BLOCK + 651da177e4SLinus Torvalds le->dl_inode_ndx; 661da177e4SLinus Torvalds } 671da177e4SLinus Torvalds if (filldir(dirent, de->di_fname, size, filp->f_pos, ino, DT_UNKNOWN) < 0) { 681da177e4SLinus Torvalds brelse(bh); 691da177e4SLinus Torvalds goto out; 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds } 721da177e4SLinus Torvalds } 731da177e4SLinus Torvalds ix++; 741da177e4SLinus Torvalds filp->f_pos += QNX4_DIR_ENTRY_SIZE; 751da177e4SLinus Torvalds } 761da177e4SLinus Torvalds brelse(bh); 771da177e4SLinus Torvalds } 781da177e4SLinus Torvalds out: 791da177e4SLinus Torvalds unlock_kernel(); 801da177e4SLinus Torvalds return 0; 811da177e4SLinus Torvalds } 821da177e4SLinus Torvalds 834b6f5d20SArjan van de Ven const struct file_operations qnx4_dir_operations = 841da177e4SLinus Torvalds { 851da177e4SLinus Torvalds .read = generic_read_dir, 861da177e4SLinus Torvalds .readdir = qnx4_readdir, 8779d25767SAl Viro .fsync = simple_fsync, 881da177e4SLinus Torvalds }; 891da177e4SLinus Torvalds 90c5ef1c42SArjan van de Ven const struct inode_operations qnx4_dir_inode_operations = 911da177e4SLinus Torvalds { 921da177e4SLinus Torvalds .lookup = qnx4_lookup, 931da177e4SLinus Torvalds #ifdef CONFIG_QNX4FS_RW 941da177e4SLinus Torvalds .create = qnx4_create, 951da177e4SLinus Torvalds .unlink = qnx4_unlink, 961da177e4SLinus Torvalds .rmdir = qnx4_rmdir, 971da177e4SLinus Torvalds #endif 981da177e4SLinus Torvalds }; 99