dir-item.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * BTRFS filesystem implementation for U-Boot
  4. *
  5. * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
  6. */
  7. #include "btrfs.h"
  8. #include "disk-io.h"
  9. static int verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total)
  10. {
  11. u16 max_len = BTRFS_NAME_LEN;
  12. u32 end;
  13. if (item->type >= BTRFS_FT_MAX) {
  14. printf("%s: invalid dir item type: %i\n", __func__, item->type);
  15. return 1;
  16. }
  17. if (item->type == BTRFS_FT_XATTR)
  18. max_len = 255; /* XATTR_NAME_MAX */
  19. end = start + sizeof(*item) + item->name_len;
  20. if (item->name_len > max_len || end > total) {
  21. printf("%s: invalid dir item name len: %u\n", __func__,
  22. item->name_len);
  23. return 1;
  24. }
  25. return 0;
  26. }
  27. static struct btrfs_dir_item *
  28. btrfs_match_dir_item_name(struct btrfs_path *path, const char *name,
  29. int name_len)
  30. {
  31. struct btrfs_dir_item *item;
  32. u32 total_len, cur = 0, this_len;
  33. const char *name_ptr;
  34. item = btrfs_path_item_ptr(path, struct btrfs_dir_item);
  35. total_len = btrfs_path_item_size(path);
  36. while (cur < total_len) {
  37. btrfs_dir_item_to_cpu(item);
  38. this_len = sizeof(*item) + item->name_len + item->data_len;
  39. name_ptr = (const char *) (item + 1);
  40. if (verify_dir_item(item, cur, total_len))
  41. return NULL;
  42. if (item->name_len == name_len && !memcmp(name_ptr, name,
  43. name_len))
  44. return item;
  45. cur += this_len;
  46. item = (struct btrfs_dir_item *) ((u8 *) item + this_len);
  47. }
  48. return NULL;
  49. }
  50. int btrfs_lookup_dir_item(const struct btrfs_root *root, u64 dir,
  51. const char *name, int name_len,
  52. struct btrfs_dir_item *item)
  53. {
  54. struct btrfs_path path;
  55. struct btrfs_key key;
  56. struct btrfs_dir_item *res = NULL;
  57. key.objectid = dir;
  58. key.type = BTRFS_DIR_ITEM_KEY;
  59. key.offset = btrfs_name_hash(name, name_len);
  60. if (btrfs_search_tree(root, &key, &path))
  61. return -1;
  62. if (btrfs_comp_keys_type(&key, btrfs_path_leaf_key(&path)))
  63. goto out;
  64. res = btrfs_match_dir_item_name(&path, name, name_len);
  65. if (res)
  66. *item = *res;
  67. out:
  68. btrfs_free_path(&path);
  69. return res ? 0 : -1;
  70. }
  71. int btrfs_readdir(const struct btrfs_root *root, u64 dir,
  72. btrfs_readdir_callback_t callback)
  73. {
  74. struct btrfs_path path;
  75. struct btrfs_key key, *found_key;
  76. struct btrfs_dir_item *item;
  77. int res = 0;
  78. key.objectid = dir;
  79. key.type = BTRFS_DIR_INDEX_KEY;
  80. key.offset = 0;
  81. if (btrfs_search_tree(root, &key, &path))
  82. return -1;
  83. do {
  84. found_key = btrfs_path_leaf_key(&path);
  85. if (btrfs_comp_keys_type(&key, found_key))
  86. break;
  87. item = btrfs_path_item_ptr(&path, struct btrfs_dir_item);
  88. btrfs_dir_item_to_cpu(item);
  89. if (verify_dir_item(item, 0, sizeof(*item) + item->name_len))
  90. continue;
  91. if (item->type == BTRFS_FT_XATTR)
  92. continue;
  93. if (callback(root, item))
  94. break;
  95. } while (!(res = btrfs_next_slot(&path)));
  96. btrfs_free_path(&path);
  97. return res < 0 ? -1 : 0;
  98. }