ReactOS 0.4.16-dev-1946-g52006dd
btrfs.c
Go to the documentation of this file.
1/*
2 * PROJECT: FreeLoader
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: BTRFS support for FreeLoader
5 * COPYRIGHT: Copyright 2018 Victor Perevertkin (victor@perevertkin.ru)
6 */
7
8/* Some code was taken from u-boot, https://github.com/u-boot/u-boot/tree/master/fs/btrfs */
9
10#include <freeldr.h>
11#include "fs/stat.h"
12
13#include <debug.h>
15
16#define TAG_BTRFS_INFO 'IftB'
17#define TAG_BTRFS_CHUNK_MAP 'CftB'
18#define TAG_BTRFS_NODE 'NftB'
19#define TAG_BTRFS_FILE 'FftB'
20#define TAG_BTRFS_LINK 'LftB'
21
22#define INVALID_INODE _UI64_MAX
23#define INVALID_ADDRESS _UI64_MAX
24#define READ_ERROR _UI64_MAX
25
26typedef struct _BTRFS_INFO
27{
34
36
37/* compare function used for bin_search */
38typedef int (*cmp_func)(const void *ptr1, const void *ptr2);
39
40/* simple but useful bin search, used for chunk search and btree search */
41static int bin_search(void *ptr, int item_size, void *cmp_item, cmp_func func,
42 int min, int max, int *slot)
43{
44 int low = min;
45 int high = max;
46 int mid;
47 int ret;
48 unsigned long offset;
49 UCHAR *item;
50
51 while (low < high)
52 {
53 mid = (low + high) / 2;
54 offset = mid * item_size;
55
56 item = (UCHAR *) ptr + offset;
57 ret = func((void *) item, cmp_item);
58
59 if (ret < 0)
60 {
61 low = mid + 1;
62 }
63 else if (ret > 0)
64 {
65 high = mid;
66 }
67 else
68 {
69 *slot = mid;
70 return 0;
71 }
72 }
73 *slot = low;
74 return 1;
75}
76
78 struct btrfs_chunk_map_item *m2)
79{
80 if (m1->logical > m2->logical)
81 return 1;
82 if (m1->logical < m2->logical)
83 return -1;
84 return 0;
85}
86
87/* insert a new chunk mapping item */
88static void insert_chunk_item(struct btrfs_chunk_map *chunk_map, struct btrfs_chunk_map_item *item)
89{
90 int ret;
91 int slot;
92 int i;
93
94 if (chunk_map->map == NULL)
95 {
96 /* first item */
98 chunk_map->map = FrLdrTempAlloc(chunk_map->map_length * sizeof(chunk_map->map[0]), TAG_BTRFS_CHUNK_MAP);
99 chunk_map->map[0] = *item;
100 chunk_map->cur_length = 1;
101 return;
102 }
103 ret = bin_search(chunk_map->map, sizeof(*item), item,
105 chunk_map->cur_length, &slot);
106 if (ret == 0)/* already in map */
107 return;
108
109 if (chunk_map->cur_length == BTRFS_MAX_CHUNK_ENTRIES)
110 {
111 /* should be impossible */
112 TRACE("too many chunk items\n");
113 return;
114 }
115
116 for (i = chunk_map->cur_length; i > slot; i--)
117 chunk_map->map[i] = chunk_map->map[i - 1];
118
119 chunk_map->map[slot] = *item;
120 chunk_map->cur_length++;
121}
122
123static inline void insert_map(struct btrfs_chunk_map *chunk_map,
124 const struct btrfs_disk_key *key,
125 struct btrfs_chunk *chunk)
126{
127 struct btrfs_stripe *stripe = &chunk->stripe;
128 struct btrfs_stripe *stripe_end = stripe + chunk->num_stripes;
130
131 item.logical = key->offset;
132 item.length = chunk->length;
133 for (; stripe < stripe_end; stripe++)
134 {
135 TRACE("stripe: %p\n", stripe);
136 item.devid = stripe->devid;
137 item.physical = stripe->offset;
138 TRACE("inserting chunk log: %llx len: %llx devid: %llx phys: %llx\n",
139 item.logical, item.length, item.devid, item.physical);
140 insert_chunk_item(chunk_map, &item);
141 }
142
143#if 0
144 struct btrfs_chunk_map_item *itm;
145 int i;
146
147 TRACE("insert finished. Printing chunk map:\n------------------------------\n");
148
149 for (i = 0; i < chunk_map->cur_length; i++)
150 {
151 itm = &chunk_map->map[i];
152 TRACE("%llx..%llx -> %llx..%llx, devid: %llu\n",
153 itm->logical,
154 itm->logical + itm->length,
155 itm->physical,
156 itm->physical + itm->length,
157 itm->devid);
158 }
159#endif
160}
161
162static inline unsigned long btrfs_chunk_item_size(int num_stripes)
163{
164 return sizeof(struct btrfs_chunk) +
166}
167
168static inline void init_path(const struct btrfs_super_block *sb, struct btrfs_path *path)
169{
170 RtlZeroMemory(path, sizeof(*path));
171 path->tree_buf = FrLdrTempAlloc(sb->nodesize, TAG_BTRFS_NODE);
172}
173
174static inline void free_path(struct btrfs_path *path)
175{
176 if (path->tree_buf) FrLdrTempFree(path->tree_buf, TAG_BTRFS_NODE);
177}
178
179static inline struct btrfs_item *path_current_item(struct btrfs_path *path)
180{
181 return &path->tree_buf->leaf.items[path->slots[0]];
182}
183
184static inline UCHAR *path_current_data(struct btrfs_path *path)
185{
186 return (UCHAR *) path->tree_buf->leaf.items + path_current_item(path)->offset;
187}
188
189static inline const struct btrfs_disk_key *path_current_disk_key(struct btrfs_path *path)
190{
191 return &path_current_item(path)->key;
192}
193
194
195static int btrfs_comp_keys(const struct btrfs_disk_key *k1,
196 const struct btrfs_disk_key *k2)
197{
198 if (k1->objectid > k2->objectid)
199 return 1;
200 if (k1->objectid < k2->objectid)
201 return -1;
202 if (k1->type > k2->type)
203 return 1;
204 if (k1->type < k2->type)
205 return -1;
206 if (k1->offset > k2->offset)
207 return 1;
208 if (k1->offset < k2->offset)
209 return -1;
210 return 0;
211}
212
213/* compare keys but ignore offset, is useful to enumerate all same kind keys */
214static int btrfs_comp_keys_type(const struct btrfs_disk_key *k1,
215 const struct btrfs_disk_key *k2)
216{
217 if (k1->objectid > k2->objectid)
218 return 1;
219 if (k1->objectid < k2->objectid)
220 return -1;
221 if (k1->type > k2->type)
222 return 1;
223 if (k1->type < k2->type)
224 return -1;
225 return 0;
226}
227
228/*
229 * from sys_chunk_array or chunk_tree, we can convert a logical address to
230 * a physical address we can not support multi device case yet
231 */
232static u64 logical_physical(struct btrfs_chunk_map *chunk_map, u64 logical)
233{
235 int slot, ret;
236
237 item.logical = logical;
238 ret = bin_search(chunk_map->map, sizeof(chunk_map->map[0]), &item,
240 chunk_map->cur_length, &slot);
241 if (ret == 0)
242 slot++;
243 else if (slot == 0)
244 return INVALID_ADDRESS;
245 if (logical >= chunk_map->map[slot - 1].logical + chunk_map->map[slot - 1].length)
246 return INVALID_ADDRESS;
247
248 TRACE("Address translation: 0x%llx -> 0x%llx\n", logical,
249 chunk_map->map[slot - 1].physical + logical - chunk_map->map[slot - 1].logical);
250
251 return chunk_map->map[slot - 1].physical + logical - chunk_map->map[slot - 1].logical;
252}
253
254static BOOLEAN disk_read(ULONG DeviceId, u64 physical, void *dest, u32 count)
255{
257 ULONG Count;
259
260 if (!dest)
261 return FALSE;
262
263 Position.QuadPart = physical;
264 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
265 if (Status != ESUCCESS)
266 {
267 ERR("ArcSeek returned status %lu\n", Status);
268 return FALSE;
269 }
270
271 Status = ArcRead(DeviceId, dest, count, &Count);
272 if (Status != ESUCCESS || Count != count)
273 {
274 ERR("ArcRead returned status %lu\n", Status);
275 return FALSE;
276 }
277
278 return TRUE;
279}
280
281static BOOLEAN
283 struct btrfs_disk_key *key, struct btrfs_path *path)
284{
285 union tree_buf *tree_buf = path->tree_buf;
286 int slot, ret, lvl;
287 u64 physical, logical = loffset;
288
289 TRACE("BtrFsSearchTree called: offset: 0x%llx, level: %u (%llu %u %llu)\n",
290 loffset, level, key->objectid, key->type, key->offset);
291
292 if (!tree_buf)
293 {
294 ERR("Path struct is not allocated\n");
295 return FALSE;
296 }
297
298 for (lvl = level; lvl >= 0; lvl--)
299 {
300 physical = logical_physical(&BtrFsInfo->ChunkMap, logical);
301
302 if (!disk_read(BtrFsInfo->DeviceId, physical, &tree_buf->header,
303 BtrFsInfo->SuperBlock.nodesize))
304 {
305 ERR("Error when reading tree node, loffset: 0x%llx, poffset: 0x%llx, level: %u\n",
306 logical, physical, lvl);
307 return FALSE;
308 }
309
310 if (tree_buf->header.level != lvl)
311 {
312 ERR("Error when searching in tree: expected lvl=%u but got %u\n",
313 lvl, tree_buf->header.level);
314 return FALSE;
315 }
316
317 TRACE("BtrFsSearchTree loop, level %u, loffset: 0x%llx\n", lvl, logical);
318
319 if (lvl)
320 {
321 ret = bin_search(tree_buf->node.ptrs,
322 sizeof(struct btrfs_key_ptr),
324 path->slots[lvl],
325 tree_buf->header.nritems, &slot);
326 TRACE("Inner node, min=%lu max=%lu\n", path->slots[0], tree_buf->header.nritems);
327 if (ret && slot > path->slots[lvl])
328 --slot;
329 }
330 else
331 {
332 ret = bin_search(tree_buf->leaf.items,
333 sizeof(struct btrfs_item),
335 path->slots[0],
336 tree_buf->header.nritems, &slot);
337 TRACE("Leaf node, min=%lu max=%lu\n", path->slots[0], tree_buf->header.nritems);
338 if (slot == tree_buf->header.nritems)
339 --slot;
340 }
341
342 path->itemsnr[lvl] = tree_buf->header.nritems;
343 path->offsets[lvl] = logical;
344 path->slots[lvl] = slot;
345
346 logical = tree_buf->node.ptrs[slot].blockptr;
347 }
348
349 TRACE("Found slot no=%lu\n", slot);
350
351 TRACE("BtrFsSearchTree found item (%llu %u %llu) offset: %lu, size: %lu, returning %lu\n",
354
355 return !ret;
356}
357
358static inline BOOLEAN
360 struct btrfs_disk_key *key, struct btrfs_path *path)
361{
362 return _BtrFsSearchTree(BtrFsInfo, root->bytenr, root->level, key, path);
363}
364
365static inline BOOLEAN
367 u64 objectid, u8 type, struct btrfs_path *path)
368{
369 struct btrfs_disk_key key;
370
371 key.objectid = objectid;
372 key.type = type;
373 key.offset = 0;
374
375 if (!_BtrFsSearchTree(BtrFsInfo, root->bytenr, root->level, &key, path))
376 return FALSE;
377
379 return TRUE;
380 else
381 return FALSE;
382}
383
384/* return 0 if slot found */
385static int next_slot(PBTRFS_INFO BtrFsInfo,
386 struct btrfs_disk_key *key, struct btrfs_path *path)
387{
388 int slot, level = 1;
389
390 if (!path->itemsnr[0])
391 return 1;
392 slot = path->slots[0] + 1;
393 if (slot >= path->itemsnr[0])
394 {
395 /* jumping to next leaf */
396 while (level < BTRFS_MAX_LEVEL)
397 {
398 if (!path->itemsnr[level]) /* no more nodes */
399 return 1;
400 slot = path->slots[level] + 1;
401 if (slot >= path->itemsnr[level])
402 {
403 level++;
404 continue;
405 }
406 path->slots[level] = slot;
407 path->slots[level - 1] = 0; /* reset low level slots info */
408 path->itemsnr[level - 1] = 0;
409 path->offsets[level - 1] = 0;
410 _BtrFsSearchTree(BtrFsInfo, path->offsets[level], level, key, path);
411 break;
412 }
413 if (level == BTRFS_MAX_LEVEL)
414 return 1;
415 goto out;
416 }
417 path->slots[0] = slot;
418
419out:
421 return 0;
422 else
423 return 1;
424}
425
426static int prev_slot(struct btrfs_disk_key *key,
427 struct btrfs_path *path)
428{
429 if (!path->slots[0])
430 return 1;
431 --path->slots[0];
433 return 0;
434 else
435 return 1;
436}
437
438/*
439 * read chunk_array in super block
440 */
442{
443 const struct btrfs_super_block *sb = &BtrFsInfo->SuperBlock;
444 struct btrfs_disk_key *key;
445 struct btrfs_chunk *chunk;
446 u16 cur;
447
448 /* read chunk array in superblock */
449 TRACE("reading chunk array\n-----------------------------\n");
450 cur = 0;
451 while (cur < sb->sys_chunk_array_size)
452 {
453 key = (struct btrfs_disk_key *) (sb->sys_chunk_array + cur);
454 TRACE("chunk key objectid: %llx, offset: %llx, type: %u\n",
455 key->objectid, key->offset, key->type);
456 cur += sizeof(*key);
457 chunk = (struct btrfs_chunk *) (sb->sys_chunk_array + cur);
458 TRACE("chunk length: %llx\n", chunk->length);
459 TRACE("chunk owner: %llu\n", chunk->owner);
460 TRACE("chunk stripe_len: %llx\n", chunk->stripe_len);
461 TRACE("chunk type: %llu\n", chunk->type);
462 TRACE("chunk io_align: %u\n", chunk->io_align);
463 TRACE("chunk io_width: %u\n", chunk->io_width);
464 TRACE("chunk sector_size: %u\n", chunk->sector_size);
465 TRACE("chunk num_stripes: %u\n", chunk->num_stripes);
466 TRACE("chunk sub_stripes: %u\n", chunk->sub_stripes);
467
468 cur += btrfs_chunk_item_size(chunk->num_stripes);
469 TRACE("read_sys_chunk_array() cur=%d\n", cur);
470 insert_map(&BtrFsInfo->ChunkMap, key, chunk);
471 }
472}
473
474/*
475 * read chunk items from chunk_tree and insert them to chunk map
476 * */
477static void btrfs_read_chunk_tree(PBTRFS_INFO BtrFsInfo)
478{
479 const struct btrfs_super_block *sb = &BtrFsInfo->SuperBlock;
480 struct btrfs_disk_key ignore_key;
481 struct btrfs_disk_key search_key;
482 struct btrfs_chunk *chunk;
483 struct btrfs_path path;
484
486 {
487 if (sb->num_devices > 1)
488 TRACE("warning: only support single device btrfs\n");
489
491 ignore_key.type = BTRFS_DEV_ITEM_KEY;
492
493 /* read chunk from chunk_tree */
495 search_key.type = BTRFS_CHUNK_ITEM_KEY;
496 search_key.offset = 0;
497 init_path(sb, &path);
498 _BtrFsSearchTree(BtrFsInfo, sb->chunk_root, sb->chunk_root_level, &search_key, &path);
499 do
500 {
501 /* skip information about underlying block
502 * devices.
503 */
505 continue;
507 break;
508
509 chunk = (struct btrfs_chunk *) (path_current_data(&path));
511 } while (!next_slot(BtrFsInfo, &search_key, &path));
512 free_path(&path);
513 }
514}
515
519
521{
522 u16 max_len = BTRFS_NAME_MAX;
523 u32 end;
524
525 if (item->type >= BTRFS_FT_MAX)
526 {
527 ERR("Invalid dir item type: %i\n", item->type);
528 return TRUE;
529 }
530
531 if (item->type == BTRFS_FT_XATTR)
532 max_len = 255; /* XATTR_NAME_MAX */
533
534 end = start + sizeof(*item) + item->name_len;
535 if (item->name_len > max_len || end > total)
536 {
537 ERR("Invalid dir item name len: %u\n", item->name_len);
538 return TRUE;
539 }
540
541 return FALSE;
542}
543
544
545static struct btrfs_dir_item *
547{
549 u32 cur = 0, this_len;
550 const char *name_ptr;
551
552 while (cur < path_current_item(path)->size)
553 {
554 this_len = sizeof(*item) + item->name_len + item->data_len;
555 name_ptr = (const char *) item + sizeof(*item);
556
557 if (verify_dir_item(item, cur, this_len))
558 return NULL;
559 if (item->name_len == name_len && !memcmp(name_ptr, name, name_len))
560 return item;
561
562 cur += this_len;
563 item = (struct btrfs_dir_item *) ((u8 *) item + this_len);
564 }
565
566 return NULL;
567}
568
569static BOOLEAN
571 const struct btrfs_root_item *root, u64 dir,
572 const char *name, int name_len,
573 struct btrfs_dir_item *item)
574{
575 struct btrfs_path path;
576 struct btrfs_disk_key key;
577 struct btrfs_dir_item *res = NULL;
578
579 key.objectid = dir;
580 key.type = BTRFS_DIR_ITEM_KEY;
581 key.offset = btrfs_crc32c(name, name_len);
582 init_path(&BtrFsInfo->SuperBlock, &path);
583
584 if (!BtrFsSearchTree(BtrFsInfo, root, &key, &path))
585 {
586 free_path(&path);
587 return FALSE;
588 }
589
591 if (res)
592 *item = *res;
593 free_path(&path);
594
595 return res != NULL;
596}
597
598static BOOLEAN
600 const struct btrfs_root_item *root, u64 dir_haystack,
601 const char *name, int name_len,
602 struct btrfs_dir_item *ret_item)
603{
604 struct btrfs_path path;
605 struct btrfs_disk_key key;
606 struct btrfs_dir_item *item;
607 char *name_buf;
609
610 key.objectid = dir_haystack;
612 key.offset = 0;
613 init_path(&BtrFsInfo->SuperBlock, &path);
614
615 BtrFsSearchTree(BtrFsInfo, root, &key, &path);
616
618 goto cleanup;
619
620 do
621 {
623 // TRACE("slot: %ld, KEY (%llu %u %llu) %.*s\n",
624 // path.slots[0], path.item.key.objectid, path.item.key.type,
625 // path.item.key.offset, item->name_len, (char *)item + sizeof(*item));
626
627 if (verify_dir_item(item, 0, sizeof(*item) + item->name_len))
628 continue;
629 if (item->type == BTRFS_FT_XATTR)
630 continue;
631
632 name_buf = (char *) item + sizeof(*item);
633 TRACE("Compare names %.*s and %.*s\n", name_len, name, item->name_len, name_buf);
634
635 if (name_len == item->name_len && _strnicmp(name, name_buf, name_len) == 0)
636 {
637 *ret_item = *item;
638 result = TRUE;
639 goto cleanup;
640 }
641
642 } while (!next_slot(BtrFsInfo, &key, &path));
643
644cleanup:
645 free_path(&path);
646 return result;
647}
648
652
655 u64 offset, u64 size, char *out)
656{
657 u32 dlen;
658 const char *cbuf;
659 const int data_off = offsetof(
660 struct btrfs_file_extent_item, disk_bytenr);
661
662 cbuf = (const char *) extent + data_off;
663 dlen = extent->ram_bytes;
664
665 TRACE("read_extent_inline offset=%llu size=%llu gener=%llu\n", offset, size, extent->generation);
666
667 if (offset > dlen)
668 {
669 ERR("Tried to read offset (%llu) beyond extent length (%lu)\n", offset, dlen);
670 return READ_ERROR;
671 }
672
673 if (size > dlen - offset)
674 size = dlen - offset;
675
676 if (extent->compression == BTRFS_COMPRESS_NONE)
677 {
678 TRACE("read_extent_inline %lu, \n", data_off);
679 memcpy(out, cbuf + offset, size);
680 return size;
681 }
682
683 ERR("No compression supported right now\n");
684 return READ_ERROR;
685}
686
688 struct btrfs_path *path,
690 u64 offset, u64 size, char *out)
691{
692 u64 physical, dlen;
693 char *temp_out;
694 dlen = extent->num_bytes;
695
696 if (offset > dlen)
697 {
698 ERR("Tried to read offset (%llu) beyond extent length (%lu)\n", offset, dlen);
699 return READ_ERROR;
700 }
701
702 if (size > dlen - offset)
703 size = dlen - offset;
704
705 /* Handle sparse extent */
706 if (extent->disk_bytenr == 0 && extent->disk_num_bytes == 0)
707 {
709 return size;
710 }
711
712 physical = logical_physical(&BtrFsInfo->ChunkMap, extent->disk_bytenr);
713 if (physical == INVALID_ADDRESS)
714 {
715 ERR("Unable to convert logical address to physical: %llu\n", extent->disk_bytenr);
716 return READ_ERROR;
717 }
718
719 if (extent->compression == BTRFS_COMPRESS_NONE)
720 {
721 physical += extent->offset + offset;
722
723 /* If somebody tried to do unaligned access */
724 if (physical & (SECTOR_SIZE - 1))
725 {
726 u32 shift;
727
729
730 if (!disk_read(BtrFsInfo->DeviceId,
731 ALIGN_DOWN_BY(physical, SECTOR_SIZE),
732 temp_out, SECTOR_SIZE))
733 {
734 FrLdrTempFree(temp_out, TAG_BTRFS_FILE);
735 return READ_ERROR;
736 }
737
738 shift = (u32)(physical & (SECTOR_SIZE - 1));
739
740 if (size <= SECTOR_SIZE - shift)
741 {
742 memcpy(out, temp_out + shift, size);
743 FrLdrTempFree(temp_out, TAG_BTRFS_FILE);
744 return size;
745 }
746
747 memcpy(out, temp_out + shift, SECTOR_SIZE - shift);
748 FrLdrTempFree(temp_out, TAG_BTRFS_FILE);
749
750 if (!disk_read(BtrFsInfo->DeviceId,
751 physical + SECTOR_SIZE - shift,
754 {
755 return READ_ERROR;
756 }
757 } else
758 {
759 if (!disk_read(BtrFsInfo->DeviceId, physical, out, size))
760 return READ_ERROR;
761 }
762
763 return size;
764 }
765
766 ERR("No compression supported right now\n");
767 return READ_ERROR;
768}
769
771 const struct btrfs_root_item *root,
772 u64 inr, u64 offset, u64 size, char *buf)
773{
774 struct btrfs_path path;
775 struct btrfs_disk_key key;
777 int res = 0;
778 u64 rd, seek_pointer = READ_ERROR, offset_in_extent;
779 BOOLEAN find_res;
780
781 TRACE("btrfs_file_read inr=%llu offset=%llu size=%llu\n", inr, offset, size);
782
783 key.objectid = inr;
785 key.offset = offset;
786 init_path(&BtrFsInfo->SuperBlock, &path);
787
788 find_res = BtrFsSearchTree(BtrFsInfo, root, &key, &path);
789
790 /* if we found greater key, switch to the previous one */
791 if (!find_res && btrfs_comp_keys(&key, path_current_disk_key(&path)) < 0)
792 {
793 if (prev_slot(&key, &path))
794 goto out;
795
797 {
798 goto out;
799 }
800
801 seek_pointer = offset;
802
803 do
804 {
805 TRACE("Current extent: (%llu %u %llu) \n",
806 path_current_disk_key(&path)->objectid,
809
811
812 offset_in_extent = seek_pointer;
813 /* check if we need clean extent offset when switching to the next extent */
814 if ((seek_pointer) >= path_current_disk_key(&path)->offset)
815 offset_in_extent -= path_current_disk_key(&path)->offset;
816
817 if (extent->type == BTRFS_FILE_EXTENT_INLINE)
818 {
819 rd = btrfs_read_extent_inline(&path, extent, offset_in_extent, size, buf);
820 }
821 else
822 {
823 rd = btrfs_read_extent_reg(BtrFsInfo, &path, extent, offset_in_extent, size, buf);
824 }
825
826 if (rd == READ_ERROR)
827 {
828 ERR("Error while reading extent\n");
829 seek_pointer = READ_ERROR;
830 goto out;
831 }
832
833 buf += rd;
834 seek_pointer += rd;
835 size -= rd;
836 TRACE("file_read size=%llu rd=%llu seek_pointer=%llu\n", size, rd, seek_pointer);
837
838 if (!size)
839 break;
840 } while (!(res = next_slot(BtrFsInfo, &key, &path)));
841
842 if (res)
843 {
844 seek_pointer = READ_ERROR;
845 goto out;
846 }
847
848 seek_pointer -= offset;
849out:
850 free_path(&path);
851 return seek_pointer;
852}
853
857
858
860 const struct btrfs_root_item *root, u64 inr,
861 struct btrfs_inode_ref *refp, char *name)
862{
863 struct btrfs_path path;
864 struct btrfs_inode_ref *ref;
866 init_path(&BtrFsInfo->SuperBlock, &path);
867
868 if (BtrFsSearchTreeType(BtrFsInfo, root, inr, BTRFS_INODE_REF_KEY, &path))
869 {
871
872 if (refp)
873 *refp = *ref;
874 ret = path_current_disk_key(&path)->offset;
875 }
876
877 free_path(&path);
878 return ret;
879}
880
881static int btrfs_lookup_inode(PBTRFS_INFO BtrFsInfo,
882 const struct btrfs_root_item *root,
883 struct btrfs_disk_key *location,
884 struct btrfs_inode_item *item,
885 struct btrfs_root_item *new_root)
886{
887 const struct btrfs_root_item tmp_root = *root;
888 struct btrfs_path path;
889 int res = -1;
890
891// if (location->type == BTRFS_ROOT_ITEM_KEY) {
892// if (btrfs_find_root(location->objectid, &tmp_root, NULL))
893// return -1;
894//
895// location->objectid = tmp_root.root_dirid;
896// location->type = BTRFS_INODE_ITEM_KEY;
897// location->offset = 0;
898// }
899 init_path(&BtrFsInfo->SuperBlock, &path);
900 TRACE("Searching inode (%llu %u %llu)\n", location->objectid, location->type, location->offset);
901
902 if (BtrFsSearchTree(BtrFsInfo, &tmp_root, location, &path))
903 {
904 if (item)
905 *item = *((struct btrfs_inode_item *) path_current_data(&path));
906
907 if (new_root)
908 *new_root = tmp_root;
909
910 res = 0;
911 }
912
913 free_path(&path);
914 return res;
915}
916
918 const struct btrfs_root_item *root,
919 u64 inr, char **target)
920{
921 struct btrfs_path path;
923 char *data_ptr;
924 BOOLEAN res = FALSE;
925
926 init_path(&BtrFsInfo->SuperBlock, &path);
927
928 if (!BtrFsSearchTreeType(BtrFsInfo, root, inr, BTRFS_EXTENT_DATA_KEY, &path))
929 goto out;
930
932 if (extent->type != BTRFS_FILE_EXTENT_INLINE)
933 {
934 ERR("Extent for symlink %llu not of INLINE type\n", inr);
935 goto out;
936 }
937
938 if (extent->compression != BTRFS_COMPRESS_NONE)
939 {
940 ERR("Symlink %llu extent data compressed!\n", inr);
941 goto out;
942 }
943 else if (extent->encryption != 0)
944 {
945 ERR("Symlink %llu extent data encrypted!\n", inr);
946 goto out;
947 }
948 else if (extent->ram_bytes >= BtrFsInfo->SuperBlock.sectorsize)
949 {
950 ERR("Symlink %llu extent data too long (%llu)!\n", inr, extent->ram_bytes);
951 goto out;
952 }
953
954 data_ptr = (char *) extent + offsetof(
956
957 *target = FrLdrTempAlloc(extent->ram_bytes + 1, TAG_BTRFS_LINK);
958 if (!*target)
959 {
960 ERR("Cannot allocate %llu bytes\n", extent->ram_bytes + 1);
961 goto out;
962 }
963
964 memcpy(*target, data_ptr, extent->ram_bytes);
965 (*target)[extent->ram_bytes] = '\0';
966
967 res = TRUE;
968
969out:
970 free_path(&path);
971 return res;
972}
973
974/* inr must be a directory (for regular files with multiple hard links this
975 function returns only one of the parents of the file) */
977 const struct btrfs_root_item *root, u64 inr,
978 struct btrfs_inode_item *inode_item)
979{
980 struct btrfs_disk_key key;
981 u64 res;
982
983 if (inr == BTRFS_FIRST_FREE_OBJECTID)
984 {
985// if (root->objectid != btrfs_info.fs_root.objectid) {
986// u64 parent;
987// struct btrfs_root_ref ref;
988//
989// parent = btrfs_lookup_root_ref(root->objectid, &ref,
990// NULL);
991// if (parent == -1ULL)
992// return -1ULL;
993//
994// if (btrfs_find_root(parent, root, NULL))
995// return -1ULL;
996//
997// inr = ref.dirid;
998// }
999
1000 if (inode_item)
1001 {
1002 key.objectid = inr;
1004 key.offset = 0;
1005
1006 if (btrfs_lookup_inode(BtrFsInfo, root, &key, inode_item, NULL))
1007 return INVALID_INODE;
1008 }
1009
1010 return inr;
1011 }
1012
1013 res = btrfs_lookup_inode_ref(BtrFsInfo, root, inr, NULL, NULL);
1014 if (res == INVALID_INODE)
1015 return INVALID_INODE;
1016
1017 if (inode_item)
1018 {
1019 key.objectid = res;
1021 key.offset = 0;
1022
1023 if (btrfs_lookup_inode(BtrFsInfo, root, &key, inode_item, NULL))
1024 return INVALID_INODE;
1025 }
1026
1027 return res;
1028}
1029
1030static inline int next_length(const char *path)
1031{
1032 int res = 0;
1033 while (*path != '\0' && *path != '/' && *path != '\\' && res <= BTRFS_NAME_MAX)
1034 ++res, ++path;
1035 return res;
1036}
1037
1038static inline const char *skip_current_directories(const char *cur)
1039{
1040 while (1)
1041 {
1042 if (cur[0] == '/' || cur[0] == '\\')
1043 ++cur;
1044 else if (cur[0] == '.' && (cur[1] == '/' || cur[1] == '\\'))
1045 cur += 2;
1046 else
1047 break;
1048 }
1049
1050 return cur;
1051}
1052
1054 const struct btrfs_root_item *root, u64 inr, const char *path,
1055 u8 *type_p, struct btrfs_inode_item *inode_item_p, int symlink_limit,
1056 _Out_opt_ PCHAR filename_buffer, _Inout_ PULONG filename_length)
1057{
1058 struct btrfs_dir_item item;
1059 struct btrfs_inode_item inode_item;
1061 int len, have_inode = 0;
1062 const char *cur = path;
1063 const char *last_elem;
1064 int last_elem_len;
1065
1066 if (*cur == '/' || *cur == '\\')
1067 {
1068 ++cur;
1069 inr = root->root_dirid;
1070 }
1071
1072 do
1073 {
1075
1076 len = next_length(cur);
1077 if (len > BTRFS_NAME_MAX)
1078 {
1079 ERR("%s: Name too long at \"%.*s\"\n", BTRFS_NAME_MAX, cur);
1080 return INVALID_INODE;
1081 }
1082
1083 /* Save the pointer/length of the current path element */
1084 last_elem = cur;
1085 last_elem_len = len;
1086
1087 if (len == 1 && cur[0] == '.')
1088 break;
1089
1090 if (len == 2 && cur[0] == '.' && cur[1] == '.')
1091 {
1092 cur += 2;
1093 inr = get_parent_inode(BtrFsInfo, root, inr, &inode_item);
1094 if (inr == INVALID_INODE)
1095 return INVALID_INODE;
1096
1098 continue;
1099 }
1100
1101 if (!*cur)
1102 break;
1103
1104 if (!BtrFsLookupDirItem(BtrFsInfo, root, inr, cur, len, &item))
1105 {
1106 TRACE("Try to find case-insensitive, path=%s inr=%llu s=%.*s\n", path, inr, len, cur);
1107 if (!BtrFsLookupDirItemI(BtrFsInfo, root, inr, cur, len, &item))
1108 return INVALID_INODE;
1109 }
1110
1111 type = item.type;
1112 have_inode = 1;
1113 if (btrfs_lookup_inode(BtrFsInfo, root, &item.location, &inode_item, NULL))
1114 return INVALID_INODE;
1115
1116 if (type == BTRFS_FT_SYMLINK && symlink_limit >= 0)
1117 {
1118 char *link_target = NULL;
1119
1120 if (!symlink_limit)
1121 {
1122 TRACE("%s: Too much symlinks!\n");
1123 return INVALID_INODE;
1124 }
1125
1126 /* btrfs_readlink allocates link_target by itself */
1127 if (!btrfs_readlink(BtrFsInfo, root, item.location.objectid, &link_target))
1128 return INVALID_INODE;
1129
1130 inr = btrfs_lookup_path(BtrFsInfo, root, inr, link_target,
1131 &type, &inode_item, symlink_limit - 1,
1132 NULL, NULL);
1133
1134 FrLdrTempFree(link_target, TAG_BTRFS_LINK);
1135
1136 if (inr == INVALID_INODE)
1137 return INVALID_INODE;
1138 } else if (type != BTRFS_FT_DIR && cur[len])
1139 {
1140 TRACE("%s: \"%.*s\" not a directory\n", (int) (cur - path + len), path);
1141 return INVALID_INODE;
1142 } else
1143 {
1144 inr = item.location.objectid;
1145 }
1146
1147 cur += len;
1148 } while (*cur);
1149
1150 if (type_p)
1151 *type_p = type;
1152
1153 if (inode_item_p)
1154 {
1155 if (!have_inode)
1156 {
1157 struct btrfs_disk_key key;
1158 key.objectid = inr;
1160 key.offset = 0;
1161
1162 if (btrfs_lookup_inode(BtrFsInfo, root, &key, &inode_item, NULL))
1163 return INVALID_INODE;
1164 }
1165
1166 *inode_item_p = inode_item;
1167 }
1168
1169 if (filename_buffer)
1170 {
1171 /* Copy the file name, perhaps truncated */
1172 *filename_length = min(*filename_length, last_elem_len);
1173 RtlCopyMemory(filename_buffer, last_elem, *filename_length);
1174 }
1175
1176 return inr;
1177}
1178
1179
1181{
1182 pbtrfs_file_info phandle = FsGetDeviceSpecific(FileId);
1183 TRACE("BtrFsClose %lu\n", FileId);
1184
1185 FrLdrTempFree(phandle, TAG_BTRFS_FILE);
1186 return ESUCCESS;
1187}
1188
1190{
1191 pbtrfs_file_info phandle = FsGetDeviceSpecific(FileId);
1192
1194 Information->EndingAddress.QuadPart = phandle->inode.size;
1195 Information->CurrentAddress.QuadPart = phandle->position;
1196
1197 /* Set the ARC file attributes */
1198 Information->Attributes = phandle->Attributes;
1199
1200 /* Copy the file name, perhaps truncated, and NUL-terminated */
1201 Information->FileNameLength = min(phandle->FileNameLength, sizeof(Information->FileName) - 1);
1202 RtlCopyMemory(Information->FileName, phandle->FileName, Information->FileNameLength);
1203 Information->FileName[Information->FileNameLength] = ANSI_NULL;
1204
1205 TRACE("BtrFsGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n",
1206 FileId, Information->EndingAddress.QuadPart, Information->CurrentAddress.QuadPart);
1207
1208 return ESUCCESS;
1209}
1210
1212{
1213 PBTRFS_INFO BtrFsInfo;
1214 ULONG DeviceId;
1216 u64 inr;
1217 u8 type;
1218
1219 btrfs_file_info temp_file_info;
1220 pbtrfs_file_info phandle;
1221
1222 TRACE("BtrFsOpen %s\n", Path);
1223
1224 /* Check parameters */
1225 if (OpenMode != OpenReadOnly)
1226 return EACCES;
1227
1228 /* Get underlying device */
1229 DeviceId = FsGetDeviceId(*FileId);
1230 BtrFsInfo = BtrFsVolumes[DeviceId];
1231
1232 temp_file_info.FileNameLength = 0;
1233 temp_file_info.FileName[0] = ANSI_NULL;
1234 FileNameLength = sizeof(temp_file_info.FileName) - 1;
1235
1236 inr = btrfs_lookup_path(BtrFsInfo, &BtrFsInfo->FsRoot,
1237 BtrFsInfo->FsRoot.root_dirid,
1238 Path, &type, &temp_file_info.inode, 40,
1239 temp_file_info.FileName, &FileNameLength);
1240 if (inr == INVALID_INODE)
1241 {
1242 TRACE("Cannot lookup file %s\n", Path);
1243 return ENOENT;
1244 }
1245 if (type != BTRFS_FT_REG_FILE)
1246 {
1247 TRACE("Not a regular file: %s\n", Path);
1248 return EISDIR;
1249 }
1250
1251 temp_file_info.FileNameLength = FileNameLength;
1252
1253 /* Map the attributes to ARC file attributes. NOTE: We don't look
1254 * at the "user.DOSATTRIB" (EA_DOSATTRIB) WinBtrfs-compatible XATTR. */
1255 temp_file_info.Attributes = 0;
1256 if (!(temp_file_info.inode.mode & (_S_IWUSR | _S_IWGRP | _S_IWOTH)))
1257 temp_file_info.Attributes |= ReadOnlyFile;
1258 if (_S_ISDIR(temp_file_info.inode.mode))
1259 temp_file_info.Attributes |= DirectoryFile;
1260
1261 /* Set hidden attribute for all entries starting with '.' */
1262 if ((temp_file_info.FileNameLength >= 2 && temp_file_info.FileName[0] == '.') &&
1263 ((temp_file_info.FileNameLength == 2 && temp_file_info.FileName[1] != '.') ||
1264 temp_file_info.FileNameLength >= 3))
1265 {
1266 temp_file_info.Attributes |= HiddenFile;
1267 }
1268
1269 TRACE("found inode inr=%llu size=%llu\n", inr, temp_file_info.inode.size);
1270
1271 temp_file_info.inr = inr;
1272 temp_file_info.position = 0;
1273
1274 phandle = FrLdrTempAlloc(sizeof(btrfs_file_info), TAG_BTRFS_FILE);
1275 if (!phandle)
1276 return ENOMEM;
1277
1278 RtlCopyMemory(phandle, &temp_file_info, sizeof(btrfs_file_info));
1279 phandle->Volume = BtrFsInfo;
1280
1281 FsSetDeviceSpecific(*FileId, phandle);
1282 return ESUCCESS;
1283}
1284
1286{
1287 pbtrfs_file_info phandle = FsGetDeviceSpecific(FileId);
1288 u64 rd;
1289
1290 TRACE("BtrFsRead %lu, size=%lu \n", FileId, Size);
1291
1292 if (!Size)
1293 Size = phandle->inode.size;
1294
1295 if (Size > phandle->inode.size)
1296 Size = phandle->inode.size;
1297
1298 rd = btrfs_file_read(phandle->Volume, &phandle->Volume->FsRoot,
1299 phandle->inr, phandle->position, Size, Buffer);
1300 if (rd == READ_ERROR)
1301 {
1302 TRACE("An error occured while reading file %lu\n", FileId);
1303 return ENOENT;
1304 }
1305
1306 phandle->position += rd;
1307 *BytesRead = rd;
1308 return ESUCCESS;
1309}
1310
1312{
1313 pbtrfs_file_info phandle = FsGetDeviceSpecific(FileId);
1314 LARGE_INTEGER NewPosition = *Position;
1315
1316 switch (SeekMode)
1317 {
1318 case SeekAbsolute:
1319 break;
1320 case SeekRelative:
1321 NewPosition.QuadPart += phandle->position;
1322 break;
1323 default:
1324 ASSERT(FALSE);
1325 return EINVAL;
1326 }
1327
1328 if (NewPosition.QuadPart >= phandle->inode.size)
1329 return EINVAL;
1330
1331 phandle->position = NewPosition.QuadPart;
1332 return ESUCCESS;
1333}
1334
1335
1343 _In_ ULONG DeviceId)
1344{
1345 PBTRFS_INFO Volume = BtrFsVolumes[DeviceId];
1346 ASSERT(Volume);
1347
1348 /* NOTE: BytesPerSector is given by Volume->SuperBlock.sectorsize */
1349 return Volume->SuperBlock.total_bytes;
1350}
1351
1352
1354{
1355 BtrFsClose,
1357 BtrFsOpen,
1358 BtrFsRead,
1359 BtrFsSeek,
1360 L"btrfs",
1361};
1362
1363const DEVVTBL *BtrFsMount(ULONG DeviceId)
1364{
1365 PBTRFS_INFO BtrFsInfo;
1366 struct btrfs_path path;
1367 struct btrfs_root_item fs_root_item;
1368
1369 TRACE("Enter BtrFsMount(%lu)\n", DeviceId);
1370
1371 BtrFsInfo = FrLdrTempAlloc(sizeof(BTRFS_INFO), TAG_BTRFS_INFO);
1372 if (!BtrFsInfo)
1373 return NULL;
1374 RtlZeroMemory(BtrFsInfo, sizeof(BTRFS_INFO));
1375
1376 /* Read the SuperBlock */
1377 if (!disk_read(DeviceId, BTRFS_SUPER_INFO_OFFSET,
1378 &BtrFsInfo->SuperBlock, sizeof(BtrFsInfo->SuperBlock)))
1379 {
1380 FrLdrTempFree(BtrFsInfo, TAG_BTRFS_INFO);
1381 return NULL;
1382 }
1383
1384 /* Check if SuperBlock is valid. If yes, return BTRFS function table */
1385 if (BtrFsInfo->SuperBlock.magic != BTRFS_MAGIC_N)
1386 {
1387 FrLdrTempFree(BtrFsInfo, TAG_BTRFS_INFO);
1388 return NULL;
1389 }
1390
1391 BtrFsInfo->DeviceId = DeviceId;
1392 TRACE("BtrFsMount(%lu) superblock magic ok\n", DeviceId);
1393
1395
1396 btrfs_read_sys_chunk_array(BtrFsInfo);
1397 btrfs_read_chunk_tree(BtrFsInfo);
1398
1399 /* setup roots */
1400 fs_root_item.bytenr = BtrFsInfo->SuperBlock.root;
1401 fs_root_item.level = BtrFsInfo->SuperBlock.root_level;
1402
1403 init_path(&BtrFsInfo->SuperBlock, &path);
1404 if (!BtrFsSearchTreeType(BtrFsInfo, &fs_root_item, BTRFS_FS_TREE_OBJECTID, BTRFS_ROOT_ITEM_KEY, &path))
1405 {
1406 free_path(&path);
1407 FrLdrTempFree(BtrFsInfo, TAG_BTRFS_INFO);
1408 return NULL;
1409 }
1410
1411 BtrFsInfo->FsRoot = *(struct btrfs_root_item *) path_current_data(&path);
1412
1413 free_path(&path);
1414
1415 /* Remember BTRFS volume information */
1416 BtrFsVolumes[DeviceId] = BtrFsInfo;
1417
1418 TRACE("BtrFsMount(%lu) success\n", DeviceId);
1419 return &BtrFsFuncTable;
1420}
#define ALIGN_DOWN_BY(size, align)
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
#define ENOENT
Definition: acclib.h:79
#define EINVAL
Definition: acclib.h:90
#define ENOMEM
Definition: acclib.h:84
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define EACCES
Definition: acclib.h:85
unsigned int dir
Definition: maze.c:112
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
#define BTRFS_SUPER_FLAG_METADUMP
Definition: btrfs.h:46
#define BTRFS_FT_DIR
Definition: btrfs.h:76
#define btrfs_crc32c(name, len)
Definition: btrfs.h:23
#define BTRFS_FIRST_CHUNK_TREE_OBJECTID
Definition: btrfs.h:63
#define BTRFS_DEV_ITEMS_OBJECTID
Definition: btrfs.h:72
ULONG32 u32
Definition: btrfs.h:14
#define BTRFS_FT_SYMLINK
Definition: btrfs.h:77
#define BTRFS_FIRST_FREE_OBJECTID
Definition: btrfs.h:61
#define BTRFS_DIR_INDEX_KEY
Definition: btrfs.h:54
#define BTRFS_FT_MAX
Definition: btrfs.h:79
#define BTRFS_INODE_REF_KEY
Definition: btrfs.h:56
#define BTRFS_DEV_ITEM_KEY
Definition: btrfs.h:48
#define BTRFS_DIR_ITEM_KEY
Definition: btrfs.h:53
ULONG64 u64
Definition: btrfs.h:15
#define BTRFS_COMPRESS_NONE
Definition: btrfs.h:81
#define BTRFS_FT_XATTR
Definition: btrfs.h:78
#define BTRFS_MAX_CHUNK_ENTRIES
Definition: btrfs.h:70
#define BTRFS_FS_TREE_OBJECTID
Definition: btrfs.h:59
#define BTRFS_ROOT_ITEM_KEY
Definition: btrfs.h:51
#define BTRFS_SUPER_INFO_OFFSET
Definition: btrfs.h:25
#define BTRFS_MAX_LEVEL
Definition: btrfs.h:69
UCHAR u8
Definition: btrfs.h:12
#define BTRFS_INODE_ITEM_KEY
Definition: btrfs.h:55
#define BTRFS_NAME_MAX
Definition: btrfs.h:40
#define BTRFS_MAGIC_N
Definition: btrfs.h:44
#define BTRFS_FT_REG_FILE
Definition: btrfs.h:75
#define BTRFS_CHUNK_ITEM_KEY
Definition: btrfs.h:49
#define BTRFS_EXTENT_DATA_KEY
Definition: btrfs.h:52
#define BTRFS_FILE_EXTENT_INLINE
Definition: btrfs.h:65
USHORT u16
Definition: btrfs.h:13
static void btrfs_init_crc32c(void)
Definition: crc32c.h:39
#define _S_IWOTH
Definition: stat.h:99
#define _S_IWUSR
Definition: stat.h:89
#define _S_IWGRP
Definition: stat.h:94
#define _S_ISDIR(m)
Definition: stat.h:46
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:455
PVOID FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:709
VOID FsSetDeviceSpecific(ULONG FileId, PVOID Specific)
Definition: fs.c:702
ULONG FsGetDeviceId(ULONG FileId)
Definition: fs.c:716
#define MAX_FDS
Definition: fs.h:34
#define SECTOR_SIZE
Definition: fs.h:22
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:448
VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: heap.c:553
PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: heap.c:545
static u64 btrfs_file_read(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 inr, u64 offset, u64 size, char *buf)
Definition: btrfs.c:770
static u64 btrfs_lookup_path(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 inr, const char *path, u8 *type_p, struct btrfs_inode_item *inode_item_p, int symlink_limit, _Out_opt_ PCHAR filename_buffer, _Inout_ PULONG filename_length)
Definition: btrfs.c:1053
ARC_STATUS BtrFsClose(ULONG FileId)
Definition: btrfs.c:1180
static u64 get_parent_inode(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 inr, struct btrfs_inode_item *inode_item)
Definition: btrfs.c:976
static u64 btrfs_lookup_inode_ref(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 inr, struct btrfs_inode_ref *refp, char *name)
Definition: btrfs.c:859
ARC_STATUS BtrFsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: btrfs.c:1211
ULONGLONG BtrFsGetVolumeSize(_In_ ULONG DeviceId)
Returns the size of the BTRFS volume laid on the storage media device opened via DeviceId.
Definition: btrfs.c:1342
#define TAG_BTRFS_LINK
Definition: btrfs.c:20
ARC_STATUS BtrFsSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: btrfs.c:1311
struct _BTRFS_INFO BTRFS_INFO
static const struct btrfs_disk_key * path_current_disk_key(struct btrfs_path *path)
Definition: btrfs.c:189
const DEVVTBL * BtrFsMount(ULONG DeviceId)
Definition: btrfs.c:1363
static struct btrfs_item * path_current_item(struct btrfs_path *path)
Definition: btrfs.c:179
static u64 logical_physical(struct btrfs_chunk_map *chunk_map, u64 logical)
Definition: btrfs.c:232
static u64 btrfs_read_extent_reg(PBTRFS_INFO BtrFsInfo, struct btrfs_path *path, struct btrfs_file_extent_item *extent, u64 offset, u64 size, char *out)
Definition: btrfs.c:687
ARC_STATUS BtrFsRead(ULONG FileId, VOID *Buffer, ULONG Size, ULONG *BytesRead)
Definition: btrfs.c:1285
static void free_path(struct btrfs_path *path)
Definition: btrfs.c:174
#define TAG_BTRFS_CHUNK_MAP
Definition: btrfs.c:17
static BOOLEAN BtrFsSearchTree(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, struct btrfs_disk_key *key, struct btrfs_path *path)
Definition: btrfs.c:359
static BOOLEAN _BtrFsSearchTree(PBTRFS_INFO BtrFsInfo, u64 loffset, u8 level, struct btrfs_disk_key *key, struct btrfs_path *path)
Definition: btrfs.c:282
static BOOLEAN BtrFsLookupDirItemI(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 dir_haystack, const char *name, int name_len, struct btrfs_dir_item *ret_item)
Definition: btrfs.c:599
static int next_slot(PBTRFS_INFO BtrFsInfo, struct btrfs_disk_key *key, struct btrfs_path *path)
Definition: btrfs.c:385
static void insert_map(struct btrfs_chunk_map *chunk_map, const struct btrfs_disk_key *key, struct btrfs_chunk *chunk)
Definition: btrfs.c:123
static int btrfs_lookup_inode(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, struct btrfs_disk_key *location, struct btrfs_inode_item *item, struct btrfs_root_item *new_root)
Definition: btrfs.c:881
static int next_length(const char *path)
Definition: btrfs.c:1030
static BOOLEAN BtrFsLookupDirItem(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 dir, const char *name, int name_len, struct btrfs_dir_item *item)
Definition: btrfs.c:570
ARC_STATUS BtrFsGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: btrfs.c:1189
static int btrfs_comp_keys(const struct btrfs_disk_key *k1, const struct btrfs_disk_key *k2)
Definition: btrfs.c:195
static BOOLEAN btrfs_readlink(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 inr, char **target)
Definition: btrfs.c:917
static int btrfs_comp_chunk_map(struct btrfs_chunk_map_item *m1, struct btrfs_chunk_map_item *m2)
Definition: btrfs.c:77
#define TAG_BTRFS_NODE
Definition: btrfs.c:18
static void init_path(const struct btrfs_super_block *sb, struct btrfs_path *path)
Definition: btrfs.c:168
static void btrfs_read_chunk_tree(PBTRFS_INFO BtrFsInfo)
Definition: btrfs.c:477
static int bin_search(void *ptr, int item_size, void *cmp_item, cmp_func func, int min, int max, int *slot)
Definition: btrfs.c:41
static void insert_chunk_item(struct btrfs_chunk_map *chunk_map, struct btrfs_chunk_map_item *item)
Definition: btrfs.c:88
PBTRFS_INFO BtrFsVolumes[MAX_FDS]
Definition: btrfs.c:35
static void btrfs_read_sys_chunk_array(PBTRFS_INFO BtrFsInfo)
Definition: btrfs.c:441
#define TAG_BTRFS_INFO
Definition: btrfs.c:16
static u64 btrfs_read_extent_inline(struct btrfs_path *path, struct btrfs_file_extent_item *extent, u64 offset, u64 size, char *out)
Definition: btrfs.c:653
static BOOLEAN disk_read(ULONG DeviceId, u64 physical, void *dest, u32 count)
Definition: btrfs.c:254
static UCHAR * path_current_data(struct btrfs_path *path)
Definition: btrfs.c:184
#define INVALID_ADDRESS
Definition: btrfs.c:23
#define TAG_BTRFS_FILE
Definition: btrfs.c:19
static int btrfs_comp_keys_type(const struct btrfs_disk_key *k1, const struct btrfs_disk_key *k2)
Definition: btrfs.c:214
#define READ_ERROR
Definition: btrfs.c:24
static struct btrfs_dir_item * BtrFsMatchDirItemName(struct btrfs_path *path, const char *name, int name_len)
Definition: btrfs.c:546
#define INVALID_INODE
Definition: btrfs.c:22
static int prev_slot(struct btrfs_disk_key *key, struct btrfs_path *path)
Definition: btrfs.c:426
static const char * skip_current_directories(const char *cur)
Definition: btrfs.c:1038
static BOOLEAN BtrFsSearchTreeType(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 objectid, u8 type, struct btrfs_path *path)
Definition: btrfs.c:366
const DEVVTBL BtrFsFuncTable
Definition: btrfs.c:1353
static unsigned long btrfs_chunk_item_size(int num_stripes)
Definition: btrfs.c:162
static BOOLEAN verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total)
Definition: btrfs.c:520
int(* cmp_func)(const void *ptr1, const void *ptr2)
Definition: btrfs.c:38
struct _root root
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
static void cleanup(void)
Definition: main.c:1335
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
superblock * sb
Definition: btrfs.c:4261
#define EISDIR
Definition: errno.h:27
@ DirectoryFile
Definition: fatprocs.h:1047
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
Definition: fltkernel.h:1129
FxCollectionEntry * cur
size_t total
Status
Definition: gdiplustypes.h:25
GLuint start
Definition: gl.h:1545
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLenum func
Definition: glext.h:6028
GLuint res
Definition: glext.h:9613
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
UNICODE_STRING Volume
Definition: fltkernel.h:1172
#define ASSERT(a)
Definition: mode.c:44
static PVOID ptr
Definition: dispmode.c:27
static char * dest
Definition: rtl.c:135
#define shift
Definition: input.c:1755
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
#define ANSI_NULL
int rd
Definition: scanf.h:134
#define offsetof(TYPE, MEMBER)
@ ESUCCESS
Definition: arc.h:32
ULONG ARC_STATUS
Definition: arc.h:4
@ SeekRelative
Definition: arc.h:60
@ SeekAbsolute
Definition: arc.h:59
enum _OPENMODE OPENMODE
@ ReadOnlyFile
Definition: arc.h:78
@ HiddenFile
Definition: arc.h:79
enum _SEEKMODE SEEKMODE
@ OpenReadOnly
Definition: arc.h:65
#define u32
Definition: types.h:9
#define TRACE(s)
Definition: solgame.cpp:4
struct btrfs_super_block SuperBlock
Definition: btrfs.c:29
struct btrfs_root_item FsRoot
Definition: btrfs.c:31
struct btrfs_root_item ExtentRoot
Definition: btrfs.c:32
ULONG DeviceId
Definition: btrfs.c:28
struct btrfs_chunk_map ChunkMap
Definition: btrfs.c:30
Definition: vfat.h:185
struct btrfs_chunk_map_item * map
Definition: btrfs.h:408
u32 map_length
Definition: btrfs.h:409
u32 cur_length
Definition: btrfs.h:410
__u16 num_stripes
Definition: btrfs.h:207
__u16 name_len
Definition: btrfs.h:260
__u8 type
Definition: btrfs.h:91
__u64 offset
Definition: btrfs.h:92
__u64 objectid
Definition: btrfs.h:90
UCHAR Attributes
Definition: btrfs.h:421
PBTRFS_INFO Volume
Definition: btrfs.h:419
struct btrfs_inode_item inode
Definition: btrfs.h:418
ULONG FileNameLength
Definition: btrfs.h:420
u64 position
Definition: btrfs.h:417
CHAR FileName[RTL_FIELD_SIZE(FILEINFORMATION, FileName)]
Definition: btrfs.h:422
__u64 bytenr
Definition: btrfs.h:268
__u8 level
Definition: btrfs.h:276
uint64_t offset
Definition: btrfs_drv.h:228
uacpi_u8 type
Definition: interpreter.c:38
Definition: copy.c:22
ULONG_PTR offset
Definition: name.c:39
Definition: send.c:48
Definition: write.c:113
uint8_t chunk_root_level
Definition: btrfs.h:249
uint64_t flags
Definition: btrfs.h:227
uint8_t sys_chunk_array[SYS_CHUNK_ARRAY_SIZE]
Definition: btrfs.h:257
uint64_t num_devices
Definition: btrfs.h:237
Definition: fs.h:25
Definition: tools.h:99
static COORD Position
Definition: mouse.c:34
#define max(a, b)
Definition: svc.c:63
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
char * PCHAR
Definition: typedefs.h:51
LONGLONG QuadPart
Definition: typedefs.h:114
struct btrfs_leaf leaf
Definition: btrfs.h:387
struct btrfs_header header
Definition: btrfs.h:385
struct btrfs_node node
Definition: btrfs.h:386
struct _slot slot
Definition: vfat.h:196
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
unsigned char UCHAR
Definition: xmlstorage.h:181
char CHAR
Definition: xmlstorage.h:175