btrfs.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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 <config.h>
  9. #include <malloc.h>
  10. #include <uuid.h>
  11. #include <linux/time.h>
  12. struct btrfs_info btrfs_info;
  13. static int readdir_callback(const struct btrfs_root *root,
  14. struct btrfs_dir_item *item)
  15. {
  16. static const char typestr[BTRFS_FT_MAX][4] = {
  17. [BTRFS_FT_UNKNOWN] = " ? ",
  18. [BTRFS_FT_REG_FILE] = " ",
  19. [BTRFS_FT_DIR] = "DIR",
  20. [BTRFS_FT_CHRDEV] = "CHR",
  21. [BTRFS_FT_BLKDEV] = "BLK",
  22. [BTRFS_FT_FIFO] = "FIF",
  23. [BTRFS_FT_SOCK] = "SCK",
  24. [BTRFS_FT_SYMLINK] = "SYM",
  25. [BTRFS_FT_XATTR] = " ? ",
  26. };
  27. struct btrfs_inode_item inode;
  28. const char *name = (const char *) (item + 1);
  29. char filetime[32], *target = NULL;
  30. time_t mtime;
  31. if (btrfs_lookup_inode(root, &item->location, &inode, NULL)) {
  32. printf("%s: Cannot find inode item for directory entry %.*s!\n",
  33. __func__, item->name_len, name);
  34. return 0;
  35. }
  36. mtime = inode.mtime.sec;
  37. ctime_r(&mtime, filetime);
  38. if (item->type == BTRFS_FT_SYMLINK) {
  39. target = malloc(min(inode.size + 1,
  40. (u64) btrfs_info.sb.sectorsize));
  41. if (target && btrfs_readlink(root, item->location.objectid,
  42. target)) {
  43. free(target);
  44. target = NULL;
  45. }
  46. if (!target)
  47. printf("%s: Cannot read symlink target!\n", __func__);
  48. }
  49. printf("<%s> ", typestr[item->type]);
  50. if (item->type == BTRFS_FT_CHRDEV || item->type == BTRFS_FT_BLKDEV)
  51. printf("%4u,%5u ", (unsigned int) (inode.rdev >> 20),
  52. (unsigned int) (inode.rdev & 0xfffff));
  53. else
  54. printf("%10llu ", inode.size);
  55. printf("%24.24s %.*s", filetime, item->name_len, name);
  56. if (item->type == BTRFS_FT_SYMLINK) {
  57. printf(" -> %s", target ? target : "?");
  58. if (target)
  59. free(target);
  60. }
  61. printf("\n");
  62. return 0;
  63. }
  64. int btrfs_probe(struct blk_desc *fs_dev_desc,
  65. struct disk_partition *fs_partition)
  66. {
  67. btrfs_blk_desc = fs_dev_desc;
  68. btrfs_part_info = fs_partition;
  69. memset(&btrfs_info, 0, sizeof(btrfs_info));
  70. btrfs_hash_init();
  71. if (btrfs_read_superblock())
  72. return -1;
  73. if (btrfs_chunk_map_init()) {
  74. printf("%s: failed to init chunk map\n", __func__);
  75. return -1;
  76. }
  77. btrfs_info.tree_root.objectid = 0;
  78. btrfs_info.tree_root.bytenr = btrfs_info.sb.root;
  79. btrfs_info.chunk_root.objectid = 0;
  80. btrfs_info.chunk_root.bytenr = btrfs_info.sb.chunk_root;
  81. if (btrfs_read_chunk_tree()) {
  82. printf("%s: failed to read chunk tree\n", __func__);
  83. return -1;
  84. }
  85. if (btrfs_find_root(btrfs_get_default_subvol_objectid(),
  86. &btrfs_info.fs_root, NULL)) {
  87. printf("%s: failed to find default subvolume\n", __func__);
  88. return -1;
  89. }
  90. return 0;
  91. }
  92. int btrfs_ls(const char *path)
  93. {
  94. struct btrfs_root root = btrfs_info.fs_root;
  95. u64 inr;
  96. u8 type;
  97. inr = btrfs_lookup_path(&root, root.root_dirid, path, &type, NULL, 40);
  98. if (inr == -1ULL) {
  99. printf("Cannot lookup path %s\n", path);
  100. return -1;
  101. }
  102. if (type != BTRFS_FT_DIR) {
  103. printf("Not a directory: %s\n", path);
  104. return -1;
  105. }
  106. if (btrfs_readdir(&root, inr, readdir_callback)) {
  107. printf("An error occured while listing directory %s\n", path);
  108. return -1;
  109. }
  110. return 0;
  111. }
  112. int btrfs_exists(const char *file)
  113. {
  114. struct btrfs_root root = btrfs_info.fs_root;
  115. u64 inr;
  116. u8 type;
  117. inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, NULL, 40);
  118. return (inr != -1ULL && type == BTRFS_FT_REG_FILE);
  119. }
  120. int btrfs_size(const char *file, loff_t *size)
  121. {
  122. struct btrfs_root root = btrfs_info.fs_root;
  123. struct btrfs_inode_item inode;
  124. u64 inr;
  125. u8 type;
  126. inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
  127. 40);
  128. if (inr == -1ULL) {
  129. printf("Cannot lookup file %s\n", file);
  130. return -1;
  131. }
  132. if (type != BTRFS_FT_REG_FILE) {
  133. printf("Not a regular file: %s\n", file);
  134. return -1;
  135. }
  136. *size = inode.size;
  137. return 0;
  138. }
  139. int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
  140. loff_t *actread)
  141. {
  142. struct btrfs_root root = btrfs_info.fs_root;
  143. struct btrfs_inode_item inode;
  144. u64 inr, rd;
  145. u8 type;
  146. inr = btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode,
  147. 40);
  148. if (inr == -1ULL) {
  149. printf("Cannot lookup file %s\n", file);
  150. return -1;
  151. }
  152. if (type != BTRFS_FT_REG_FILE) {
  153. printf("Not a regular file: %s\n", file);
  154. return -1;
  155. }
  156. if (!len)
  157. len = inode.size;
  158. if (len > inode.size - offset)
  159. len = inode.size - offset;
  160. rd = btrfs_file_read(&root, inr, offset, len, buf);
  161. if (rd == -1ULL) {
  162. printf("An error occured while reading file %s\n", file);
  163. return -1;
  164. }
  165. *actread = rd;
  166. return 0;
  167. }
  168. void btrfs_close(void)
  169. {
  170. btrfs_chunk_map_exit();
  171. }
  172. int btrfs_uuid(char *uuid_str)
  173. {
  174. #ifdef CONFIG_LIB_UUID
  175. uuid_bin_to_str(btrfs_info.sb.fsid, uuid_str, UUID_STR_FORMAT_STD);
  176. return 0;
  177. #endif
  178. return -ENOSYS;
  179. }