dir.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * dir.c
  3.  *
  4.  * Copyright (c) 1999 Al Smith
  5.  */
  6. #include <linux/efs_fs.h>
  7. static int efs_readdir(struct file *, void *, filldir_t);
  8. struct file_operations efs_dir_operations = {
  9. read: generic_read_dir,
  10. readdir: efs_readdir,
  11. };
  12. struct inode_operations efs_dir_inode_operations = {
  13. lookup: efs_lookup,
  14. };
  15. static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
  16. struct inode *inode = filp->f_dentry->d_inode;
  17. struct buffer_head *bh;
  18. struct efs_dir *dirblock;
  19. struct efs_dentry *dirslot;
  20. efs_ino_t inodenum;
  21. efs_block_t block;
  22. int slot, namelen;
  23. char *nameptr;
  24. if (inode->i_size & (EFS_DIRBSIZE-1))
  25. printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZEn");
  26. /* work out where this entry can be found */
  27. block = filp->f_pos >> EFS_DIRBSIZE_BITS;
  28. /* each block contains at most 256 slots */
  29. slot  = filp->f_pos & 0xff;
  30. /* look at all blocks */
  31. while (block < inode->i_blocks) {
  32. /* read the dir block */
  33. bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
  34. if (!bh) {
  35. printk(KERN_ERR "EFS: readdir(): failed to read dir block %dn", block);
  36. break;
  37. }
  38. dirblock = (struct efs_dir *) bh->b_data; 
  39. if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
  40. printk(KERN_ERR "EFS: readdir(): invalid directory blockn");
  41. brelse(bh);
  42. break;
  43. }
  44. while (slot < dirblock->slots) {
  45. if (dirblock->space[slot] == 0) {
  46. slot++;
  47. continue;
  48. }
  49. dirslot  = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
  50. inodenum = be32_to_cpu(dirslot->inode);
  51. namelen  = dirslot->namelen;
  52. nameptr  = dirslot->name;
  53. #ifdef DEBUG
  54. printk(KERN_DEBUG "EFS: readdir(): block %d slot %d/%d: inode %u, name "%s", namelen %un", block, slot, dirblock->slots-1, inodenum, nameptr, namelen);
  55. #endif
  56. if (namelen > 0) {
  57. /* found the next entry */
  58. filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
  59. /* copy filename and data in dirslot */
  60. filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN);
  61. /* sanity check */
  62. if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
  63. printk(KERN_WARNING "EFS: directory entry %d exceeds directory blockn", slot);
  64. slot++;
  65. continue;
  66. }
  67. /* store position of next slot */
  68. if (++slot == dirblock->slots) {
  69. slot = 0;
  70. block++;
  71. }
  72. brelse(bh);
  73. filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
  74. return 0;
  75. }
  76. slot++;
  77. }
  78. brelse(bh);
  79. slot = 0;
  80. block++;
  81. }
  82. filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
  83. return 0;
  84. }