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