URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [ufs/] [ufs_dir.c] - Rev 1765
Compare with Previous | Blame | View Log
/* * linux/fs/ufs/ufs_dir.c * * Copyright (C) 1996 * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu) * Laboratory for Computer Science Research Computing Facility * Rutgers, The State University of New Jersey * * $Id: ufs_dir.c,v 1.1 2005-12-20 10:26:35 jcastillo Exp $ * */ #include <linux/fs.h> /* XXX */ extern int ufs_lookup (struct inode *, const char *, int, struct inode **); extern int ufs_bmap (struct inode *, int); extern void ufs_print_inode (struct inode *); /* * This is blatantly stolen from ext2fs */ static int ufs_readdir (struct inode * inode, struct file * filp, void * dirent, filldir_t filldir) { int error = 0; unsigned long offset, lblk, blk; int i, stored; struct buffer_head * bh; struct ufs_direct * de; struct super_block * sb; if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; sb = inode->i_sb; if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) { printk("ufs_readdir: ino %lu f_pos %lu\n", inode->i_ino, (unsigned long) filp->f_pos); ufs_print_inode(inode); } stored = 0; bh = NULL; offset = filp->f_pos & (sb->s_blocksize - 1); while (!error && !stored && filp->f_pos < inode->i_size) { lblk = (filp->f_pos) >> sb->s_blocksize_bits; blk = ufs_bmap(inode, lblk); /* XXX - ufs_bmap() call needs error checking */ blk = ufs_bmap(inode, lblk); bh = bread (sb->s_dev, blk, sb->s_blocksize); if (!bh) { /* XXX - error - skip to the next block */ printk("ufs_readdir: dir inode %lu has a hole at offset %lu\n", inode->i_ino, (unsigned long int)filp->f_pos); filp->f_pos += sb->s_blocksize - offset; continue; } revalidate: /* If the dir block has changed since the last call to * readdir(2), then we might be pointing to an invalid * dirent right now. Scan from the start of the block * to make sure. */ if (filp->f_version != inode->i_version) { for (i = 0; i < sb->s_blocksize && i < offset; ) { de = (struct ufs_direct *) (bh->b_data + i); /* It's too expensive to do a full * dirent test each time round this * loop, but we do have to test at * least that it is non-zero. A * failure will be detected in the * dirent test below. */ if (de->d_reclen < 1) break; i += de->d_reclen; } offset = i; filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | offset; filp->f_version = inode->i_version; } while (!error && filp->f_pos < inode->i_size && offset < sb->s_blocksize) { de = (struct ufs_direct *) (bh->b_data + offset); /* XXX - put in a real ufs_check_dir_entry() */ if ((de->d_reclen == 0) || (de->d_namlen == 0)) { filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + sb->s_blocksize; brelse(bh); return stored; } #if 0 if (!ext2_check_dir_entry ("ext2_readdir", inode, de, bh, offset)) { /* On error, skip the f_pos to the next block. */ filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + sb->s_blocksize; brelse (bh); return stored; } #endif /* XXX */ offset += de->d_reclen; if (de->d_ino) { /* We might block in the next section * if the data destination is * currently swapped out. So, use a * version stamp to detect whether or * not the directory has been modified * during the copy operation. */ unsigned long version; dcache_add(inode, de->d_name, de->d_namlen, de->d_ino); version = inode->i_version; if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) { printk("ufs_readdir: filldir(%s,%u)\n", de->d_name, de->d_ino); } error = filldir(dirent, de->d_name, de->d_namlen, filp->f_pos, de->d_ino); if (error) break; if (version != inode->i_version) goto revalidate; stored ++; } filp->f_pos += de->d_reclen; } offset = 0; brelse (bh); } #if 0 /* XXX */ if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; } #endif /* XXX */ return 0; } static struct file_operations ufs_dir_operations = { NULL, /* lseek */ NULL, /* read */ NULL, /* write */ ufs_readdir, /* readdir */ NULL, /* select */ NULL, /* ioctl */ NULL, /* mmap */ NULL, /* open */ NULL, /* release */ file_fsync, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ NULL, /* revalidate */ }; struct inode_operations ufs_dir_inode_operations = { &ufs_dir_operations, /* default directory file operations */ NULL, /* create */ ufs_lookup, /* lookup */ NULL, /* link */ NULL, /* unlink */ NULL, /* symlink */ NULL, /* mkdir */ NULL, /* rmdir */ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */ }; /* * Local Variables: *** * c-indent-level: 8 *** * c-continued-statement-offset: 8 *** * c-brace-offset: -8 *** * c-argdecl-indent: 0 *** * c-label-offset: -8 *** * End: *** */