dir.c 2.7 KB

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