dir-item.c 2.7 KB

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