dir.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * dir.c
  3. *
  4. * Copyright (c) 1999 Al Smith
  5. */
  6. #include <linux/buffer_head.h>
  7. #include "efs.h"
  8. static int efs_readdir(struct file *, void *, filldir_t);
  9. const struct file_operations efs_dir_operations = {
  10. .llseek = generic_file_llseek,
  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. /* work out where this entry can be found */
  29. block = filp->f_pos >> EFS_DIRBSIZE_BITS;
  30. /* each block contains at most 256 slots */
  31. slot = filp->f_pos & 0xff;
  32. /* look at all blocks */
  33. while (block < inode->i_blocks) {
  34. /* read the dir block */
  35. bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
  36. if (!bh) {
  37. printk(KERN_ERR "EFS: readdir(): failed to read dir block %d\n", block);
  38. break;
  39. }
  40. dirblock = (struct efs_dir *) bh->b_data;
  41. if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
  42. printk(KERN_ERR "EFS: readdir(): invalid directory block\n");
  43. brelse(bh);
  44. break;
  45. }
  46. while (slot < dirblock->slots) {
  47. if (dirblock->space[slot] == 0) {
  48. slot++;
  49. continue;
  50. }
  51. dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
  52. inodenum = be32_to_cpu(dirslot->inode);
  53. namelen = dirslot->namelen;
  54. nameptr = dirslot->name;
  55. #ifdef DEBUG
  56. 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);
  57. #endif
  58. if (namelen > 0) {
  59. /* found the next entry */
  60. filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
  61. /* copy filename and data in dirslot */
  62. filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN);
  63. /* sanity check */
  64. if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
  65. printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot);
  66. slot++;
  67. continue;
  68. }
  69. /* store position of next slot */
  70. if (++slot == dirblock->slots) {
  71. slot = 0;
  72. block++;
  73. }
  74. brelse(bh);
  75. filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
  76. goto out;
  77. }
  78. slot++;
  79. }
  80. brelse(bh);
  81. slot = 0;
  82. block++;
  83. }
  84. filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
  85. out:
  86. return 0;
  87. }