dir.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * linux/drivers/staging/erofs/dir.c
  4. *
  5. * Copyright (C) 2017-2018 HUAWEI, Inc.
  6. * http://www.huawei.com/
  7. * Created by Gao Xiang <gaoxiang25@huawei.com>
  8. *
  9. * This file is subject to the terms and conditions of the GNU General Public
  10. * License. See the file COPYING in the main directory of the Linux
  11. * distribution for more details.
  12. */
  13. #include "internal.h"
  14. static const unsigned char erofs_filetype_table[EROFS_FT_MAX] = {
  15. [EROFS_FT_UNKNOWN] = DT_UNKNOWN,
  16. [EROFS_FT_REG_FILE] = DT_REG,
  17. [EROFS_FT_DIR] = DT_DIR,
  18. [EROFS_FT_CHRDEV] = DT_CHR,
  19. [EROFS_FT_BLKDEV] = DT_BLK,
  20. [EROFS_FT_FIFO] = DT_FIFO,
  21. [EROFS_FT_SOCK] = DT_SOCK,
  22. [EROFS_FT_SYMLINK] = DT_LNK,
  23. };
  24. static void debug_one_dentry(unsigned char d_type, const char *de_name,
  25. unsigned int de_namelen)
  26. {
  27. #ifdef CONFIG_EROFS_FS_DEBUG
  28. /* since the on-disk name could not have the trailing '\0' */
  29. unsigned char dbg_namebuf[EROFS_NAME_LEN + 1];
  30. memcpy(dbg_namebuf, de_name, de_namelen);
  31. dbg_namebuf[de_namelen] = '\0';
  32. debugln("found dirent %s de_len %u d_type %d", dbg_namebuf,
  33. de_namelen, d_type);
  34. #endif
  35. }
  36. static int erofs_fill_dentries(struct dir_context *ctx,
  37. void *dentry_blk, unsigned *ofs,
  38. unsigned nameoff, unsigned maxsize)
  39. {
  40. struct erofs_dirent *de = dentry_blk;
  41. const struct erofs_dirent *end = dentry_blk + nameoff;
  42. de = dentry_blk + *ofs;
  43. while (de < end) {
  44. const char *de_name;
  45. unsigned int de_namelen;
  46. unsigned char d_type;
  47. if (de->file_type < EROFS_FT_MAX)
  48. d_type = erofs_filetype_table[de->file_type];
  49. else
  50. d_type = DT_UNKNOWN;
  51. nameoff = le16_to_cpu(de->nameoff);
  52. de_name = (char *)dentry_blk + nameoff;
  53. /* the last dirent in the block? */
  54. if (de + 1 >= end)
  55. de_namelen = strnlen(de_name, maxsize - nameoff);
  56. else
  57. de_namelen = le16_to_cpu(de[1].nameoff) - nameoff;
  58. /* a corrupted entry is found */
  59. if (unlikely(nameoff + de_namelen > maxsize ||
  60. de_namelen > EROFS_NAME_LEN)) {
  61. DBG_BUGON(1);
  62. return -EIO;
  63. }
  64. debug_one_dentry(d_type, de_name, de_namelen);
  65. if (!dir_emit(ctx, de_name, de_namelen,
  66. le64_to_cpu(de->nid), d_type))
  67. /* stoped by some reason */
  68. return 1;
  69. ++de;
  70. *ofs += sizeof(struct erofs_dirent);
  71. }
  72. *ofs = maxsize;
  73. return 0;
  74. }
  75. static int erofs_readdir(struct file *f, struct dir_context *ctx)
  76. {
  77. struct inode *dir = file_inode(f);
  78. struct address_space *mapping = dir->i_mapping;
  79. const size_t dirsize = i_size_read(dir);
  80. unsigned i = ctx->pos / EROFS_BLKSIZ;
  81. unsigned ofs = ctx->pos % EROFS_BLKSIZ;
  82. int err = 0;
  83. bool initial = true;
  84. while (ctx->pos < dirsize) {
  85. struct page *dentry_page;
  86. struct erofs_dirent *de;
  87. unsigned nameoff, maxsize;
  88. dentry_page = read_mapping_page(mapping, i, NULL);
  89. if (dentry_page == ERR_PTR(-ENOMEM)) {
  90. err = -ENOMEM;
  91. break;
  92. } else if (IS_ERR(dentry_page)) {
  93. errln("fail to readdir of logical block %u of nid %llu",
  94. i, EROFS_V(dir)->nid);
  95. err = PTR_ERR(dentry_page);
  96. break;
  97. }
  98. lock_page(dentry_page);
  99. de = (struct erofs_dirent *)kmap(dentry_page);
  100. nameoff = le16_to_cpu(de->nameoff);
  101. if (unlikely(nameoff < sizeof(struct erofs_dirent) ||
  102. nameoff >= PAGE_SIZE)) {
  103. errln("%s, invalid de[0].nameoff %u",
  104. __func__, nameoff);
  105. err = -EIO;
  106. goto skip_this;
  107. }
  108. maxsize = min_t(unsigned, dirsize - ctx->pos + ofs, PAGE_SIZE);
  109. /* search dirents at the arbitrary position */
  110. if (unlikely(initial)) {
  111. initial = false;
  112. ofs = roundup(ofs, sizeof(struct erofs_dirent));
  113. if (unlikely(ofs >= nameoff))
  114. goto skip_this;
  115. }
  116. err = erofs_fill_dentries(ctx, de, &ofs, nameoff, maxsize);
  117. skip_this:
  118. kunmap(dentry_page);
  119. unlock_page(dentry_page);
  120. put_page(dentry_page);
  121. ctx->pos = blknr_to_addr(i) + ofs;
  122. if (unlikely(err))
  123. break;
  124. ++i;
  125. ofs = 0;
  126. }
  127. return err < 0 ? err : 0;
  128. }
  129. const struct file_operations erofs_dir_fops = {
  130. .llseek = generic_file_llseek,
  131. .read = generic_read_dir,
  132. .iterate = erofs_readdir,
  133. };