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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/affs/dir.c
  3.  *
  4.  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
  5.  *
  6.  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  7.  *
  8.  *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
  9.  *
  10.  *  (C) 1991  Linus Torvalds - minix filesystem
  11.  *
  12.  *  affs directory handling functions
  13.  *
  14.  */
  15. #include <asm/uaccess.h>
  16. #include <linux/errno.h>
  17. #include <linux/fs.h>
  18. #include <linux/kernel.h>
  19. #include <linux/affs_fs.h>
  20. #include <linux/stat.h>
  21. #include <linux/string.h>
  22. #include <linux/mm.h>
  23. #include <linux/amigaffs.h>
  24. static int affs_readdir(struct file *, void *, filldir_t);
  25. struct file_operations affs_dir_operations = {
  26. read: generic_read_dir,
  27. readdir: affs_readdir,
  28. fsync: file_fsync,
  29. };
  30. /*
  31.  * directories can handle most operations...
  32.  */
  33. struct inode_operations affs_dir_inode_operations = {
  34. create: affs_create,
  35. lookup: affs_lookup,
  36. link: affs_link,
  37. unlink: affs_unlink,
  38. symlink: affs_symlink,
  39. mkdir: affs_mkdir,
  40. rmdir: affs_rmdir,
  41. rename: affs_rename,
  42. setattr: affs_notify_change,
  43. };
  44. static int
  45. affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
  46. {
  47. struct inode *inode = filp->f_dentry->d_inode;
  48. struct super_block *sb = inode->i_sb;
  49. struct buffer_head *dir_bh;
  50. struct buffer_head *fh_bh;
  51. unsigned char *name;
  52. int  namelen;
  53. u32  i;
  54. int  hash_pos;
  55. int  chain_pos;
  56. u32  f_pos;
  57. u32  ino;
  58. int  stored;
  59. int  res;
  60. pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)n",inode->i_ino,(unsigned long)filp->f_pos);
  61. stored = 0;
  62. res    = -EIO;
  63. dir_bh = NULL;
  64. fh_bh  = NULL;
  65. f_pos  = filp->f_pos;
  66. if (f_pos == 0) {
  67. filp->private_data = (void *)0;
  68. if (filldir(dirent, ".", 1, f_pos, inode->i_ino, DT_DIR) < 0)
  69. return 0;
  70. filp->f_pos = f_pos = 1;
  71. stored++;
  72. }
  73. if (f_pos == 1) {
  74. if (filldir(dirent, "..", 2, f_pos, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
  75. return stored;
  76. filp->f_pos = f_pos = 2;
  77. stored++;
  78. }
  79. affs_lock_dir(inode);
  80. chain_pos = (f_pos - 2) & 0xffff;
  81. hash_pos  = (f_pos - 2) >> 16;
  82. if (chain_pos == 0xffff) {
  83. affs_warning(sb, "readdir", "More than 65535 entries in chain");
  84. chain_pos = 0;
  85. hash_pos++;
  86. filp->f_pos = ((hash_pos << 16) | chain_pos) + 2;
  87. }
  88. dir_bh = affs_bread(sb, inode->i_ino);
  89. if (!dir_bh)
  90. goto readdir_out;
  91. /* If the directory hasn't changed since the last call to readdir(),
  92.  * we can jump directly to where we left off.
  93.  */
  94. ino = (u32)(long)filp->private_data;
  95. if (ino && filp->f_version == inode->i_version) {
  96. pr_debug("AFFS: readdir() left off=%dn", ino);
  97. goto inside;
  98. }
  99. ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
  100. for (i = 0; ino && i < chain_pos; i++) {
  101. fh_bh = affs_bread(sb, ino);
  102. if (!fh_bh) {
  103. affs_error(sb, "readdir","Cannot read block %d", i);
  104. goto readdir_out;
  105. }
  106. ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
  107. affs_brelse(fh_bh);
  108. fh_bh = NULL;
  109. }
  110. if (ino)
  111. goto inside;
  112. hash_pos++;
  113. for (; hash_pos < AFFS_SB->s_hashsize; hash_pos++) {
  114. ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[hash_pos]);
  115. if (!ino)
  116. continue;
  117. f_pos = (hash_pos << 16) + 2;
  118. inside:
  119. do {
  120. fh_bh = affs_bread(sb, ino);
  121. if (!fh_bh) {
  122. affs_error(sb, "readdir","Cannot read block %d", ino);
  123. goto readdir_done;
  124. }
  125. namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
  126. name = AFFS_TAIL(sb, fh_bh)->name + 1;
  127. pr_debug("AFFS: readdir(): filldir("%.*s", ino=%u), hash=%d, f_pos=%xn",
  128.  namelen, name, ino, hash_pos, f_pos);
  129. if (filldir(dirent, name, namelen, f_pos, ino, DT_UNKNOWN) < 0)
  130. goto readdir_done;
  131. stored++;
  132. f_pos++;
  133. ino = be32_to_cpu(AFFS_TAIL(sb, fh_bh)->hash_chain);
  134. affs_brelse(fh_bh);
  135. fh_bh = NULL;
  136. } while (ino);
  137. }
  138. readdir_done:
  139. filp->f_pos = f_pos;
  140. filp->f_version = inode->i_version;
  141. filp->private_data = (void *)(long)ino;
  142. res = stored;
  143. readdir_out:
  144. affs_brelse(dir_bh);
  145. affs_brelse(fh_bh);
  146. affs_unlock_dir(inode);
  147. pr_debug("AFFS: readdir()=%dn", stored);
  148. return res;
  149. }