ReactOS  0.4.15-dev-341-g17c5fb8
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>
13 DBG_DEFAULT_CHANNEL(FILESYSTEM);
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 
25 typedef struct _BTRFS_INFO
26 {
32 } BTRFS_INFO;
33 
35 
36 /* compare function used for bin_search */
37 typedef int (*cmp_func)(const void *ptr1, const void *ptr2);
38 
39 /* simple but useful bin search, used for chunk search and btree search */
40 static 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 */
87 static 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 
122 static 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;
128  struct btrfs_chunk_map_item item;
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 
161 static inline unsigned long btrfs_chunk_item_size(int num_stripes)
162 {
163  return sizeof(struct btrfs_chunk) +
165 }
166 
167 static inline void init_path(const struct btrfs_super_block *sb, struct btrfs_path *path)
168 {
169  memset(path, 0, sizeof(*path));
170  path->tree_buf = FrLdrTempAlloc(sb->nodesize, TAG_BTRFS_NODE);
171 }
172 
173 static inline void free_path(struct btrfs_path *path)
174 {
175  if (path->tree_buf) FrLdrTempFree(path->tree_buf, TAG_BTRFS_NODE);
176 }
177 
178 static inline struct btrfs_item *path_current_item(struct btrfs_path *path)
179 {
180  return &path->tree_buf->leaf.items[path->slots[0]];
181 }
182 
183 static 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 
188 static 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 
194 static 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 */
213 static 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  */
231 static u64 logical_physical(struct btrfs_chunk_map *chunk_map, u64 logical)
232 {
233  struct btrfs_chunk_map_item item;
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 
253 static 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 
280 static 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 
357 static 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 
364 static 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 */
384 static 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 
418 out:
420  return 0;
421  else
422  return 1;
423 }
424 
425 static 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  * */
476 static 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 
489  ignore_key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
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  */
503  if (!btrfs_comp_keys_type(&ignore_key, path_current_disk_key(&path)))
504  continue;
505  if (btrfs_comp_keys_type(&search_key, path_current_disk_key(&path)))
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 
544 static 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 
568 static 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 
597 static 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;
607  BOOLEAN result = FALSE;
608 
609  key.objectid = dir_haystack;
610  key.type = BTRFS_DIR_INDEX_KEY;
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  {
621  item = (struct btrfs_dir_item *) path_current_data(&path);
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 
643 cleanup:
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,
751  out + SECTOR_SIZE - shift,
752  size - 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 
769 static u64 btrfs_file_read(PBTRFS_INFO BtrFsInfo,
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;
783  key.type = BTRFS_EXTENT_DATA_KEY;
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;
848 out:
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  {
869  ref = (struct btrfs_inode_ref *) path_current_data(&path);
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 
880 static 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 
968 out:
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;
1002  key.type = BTRFS_INODE_ITEM_KEY;
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;
1019  key.type = BTRFS_INODE_ITEM_KEY;
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 
1029 static 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 
1037 static 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;
1058  u8 type = BTRFS_FT_DIR;
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  {
1072  cur = skip_current_directories(cur);
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 
1091  type = BTRFS_FT_DIR;
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;
1148  key.type = BTRFS_INODE_ITEM_KEY;
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 
1297 const 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 BTRFS_FS_TREE_OBJECTID
Definition: btrfs.h:59
uint8_t sys_chunk_array[SYS_CHUNK_ARRAY_SIZE]
Definition: btrfs.h:250
int rd
Definition: scanf.h:134
ARC_STATUS BtrFsSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: btrfs.c:1263
GLenum func
Definition: glext.h:6028
#define BTRFS_FT_DIR
Definition: btrfs.h:75
#define READ_ERROR
Definition: btrfs.c:23
GLint level
Definition: gl.h:1546
#define max(a, b)
Definition: svc.c:63
#define BTRFS_MAX_LEVEL
Definition: btrfs.h:69
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define shift
Definition: input.c:1756
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define u32
Definition: types.h:9
static const char * skip_current_directories(const char *cur)
Definition: btrfs.c:1037
#define BTRFS_NAME_MAX
Definition: btrfs.h:40
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
u32 map_length
Definition: btrfs.h:408
struct _slot slot
Definition: vfat.h:196
Definition: arc.h:32
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define BTRFS_DEV_ITEMS_OBJECTID
Definition: btrfs.h:72
superblock * sb
Definition: btrfs.c:4220
#define TAG_BTRFS_FILE
Definition: btrfs.c:18
GLsizei const GLchar ** path
Definition: glext.h:7234
Definition: arc.h:39
GLuint GLuint GLsizei count
Definition: gl.h:1545
static COORD Position
Definition: mouse.c:34
char CHAR
Definition: xmlstorage.h:175
struct _root root
static BOOLEAN _BtrFsSearchTree(PBTRFS_INFO BtrFsInfo, u64 loffset, u8 level, struct btrfs_disk_key *key, struct btrfs_path *path)
Definition: btrfs.c:281
GLintptr offset
Definition: glext.h:5920
Definition: fs.h:24
struct _BTRFS_INFO BTRFS_INFO
static unsigned long btrfs_chunk_item_size(int num_stripes)
Definition: btrfs.c:161
Status
Definition: btrfs.c:4232
#define BTRFS_MAX_CHUNK_ENTRIES
Definition: btrfs.h:70
Definition: write.c:111
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
ULONG ARC_STATUS
Definition: arc.h:4
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_read_extent_inline(struct btrfs_path *path, struct btrfs_file_extent_item *extent, u64 offset, u64 size, char *out)
Definition: btrfs.c:652
GLuint GLuint end
Definition: gl.h:1545
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 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 next_length(const char *path)
Definition: btrfs.c:1029
VOID * FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:416
static int btrfs_comp_keys_type(const struct btrfs_disk_key *k1, const struct btrfs_disk_key *k2)
Definition: btrfs.c:213
Definition: send.c:48
Definition: arc.h:48
ULONG32 u32
Definition: btrfs.h:14
static void init_path(const struct btrfs_super_block *sb, struct btrfs_path *path)
Definition: btrfs.c:167
const DEVVTBL BtrFsFuncTable
Definition: btrfs.c:1287
#define BTRFS_SUPER_FLAG_METADUMP
Definition: btrfs.h:46
static BOOLEAN btrfs_readlink(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 inr, char **target)
Definition: btrfs.c:916
#define BTRFS_ROOT_ITEM_KEY
Definition: btrfs.h:51
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 BTRFS_FT_REG_FILE
Definition: btrfs.h:74
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
#define TAG_BTRFS_CHUNK_MAP
Definition: btrfs.c:16
#define TAG_BTRFS_LINK
Definition: btrfs.c:19
uint64_t offset
Definition: btrfs_drv.h:239
uint64_t num_devices
Definition: btrfs.h:230
const DEVVTBL * BtrFsMount(ULONG DeviceId)
Definition: btrfs.c:1297
struct btrfs_chunk_map ChunkMap
Definition: btrfs.c:29
GLenum GLint ref
Definition: glext.h:6028
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
ARC_STATUS BtrFsGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: btrfs.c:1171
__u64 objectid
Definition: btrfs.h:89
static PVOID ptr
Definition: dispmode.c:27
static int btrfs_comp_chunk_map(struct btrfs_chunk_map_item *m1, struct btrfs_chunk_map_item *m2)
Definition: btrfs.c:76
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
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define offsetof(TYPE, MEMBER)
enum _SEEKMODE SEEKMODE
Definition: bufpool.h:45
__u64 bytenr
Definition: btrfs.h:267
#define TAG_BTRFS_INFO
Definition: btrfs.c:15
unsigned int dir
Definition: maze.c:112
ULONG DeviceId
Definition: btrfs.c:27
static const struct btrfs_disk_key * path_current_disk_key(struct btrfs_path *path)
Definition: btrfs.c:188
u32 cur_length
Definition: btrfs.h:409
__u16 num_stripes
Definition: btrfs.h:206
uint64_t flags
Definition: btrfs.h:220
int(* cmp_func)(const void *ptr1, const void *ptr2)
Definition: btrfs.c:37
#define TRACE(s)
Definition: solgame.cpp:4
struct btrfs_header header
Definition: btrfs.h:384
GLsizeiptr size
Definition: glext.h:5919
static void btrfs_read_chunk_tree(PBTRFS_INFO BtrFsInfo)
Definition: btrfs.c:476
#define INVALID_ADDRESS
Definition: btrfs.c:22
PBTRFS_INFO BtrFsVolumes[MAX_FDS]
Definition: btrfs.c:34
__u8 level
Definition: btrfs.h:275
__u64 offset
Definition: btrfs.h:91
#define BTRFS_FIRST_FREE_OBJECTID
Definition: btrfs.h:61
static FILE * out
Definition: regtests2xml.c:44
VOID FsSetDeviceSpecific(ULONG FileId, VOID *Specific)
Definition: fs.c:409
static void btrfs_init_crc32c(void)
Definition: crc32c.h:39
struct btrfs_node node
Definition: btrfs.h:385
UCHAR u8
Definition: btrfs.h:12
u64 position
Definition: btrfs.h:416
ARC_STATUS BtrFsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: btrfs.c:1185
#define MAX_FDS
Definition: fs.h:34
struct btrfs_leaf leaf
Definition: btrfs.h:386
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
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:236
unsigned char UCHAR
Definition: xmlstorage.h:181
int ret
ULONG64 u64
Definition: btrfs.h:15
Definition: arc.h:34
static const WCHAR L[]
Definition: oid.c:1250
static struct btrfs_dir_item * BtrFsMatchDirItemName(struct btrfs_path *path, const char *name, int name_len)
Definition: btrfs.c:545
HKEY key
Definition: reg.c:42
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:243
#define TAG_BTRFS_NODE
Definition: btrfs.c:17
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
PBTRFS_INFO Volume
Definition: btrfs.h:418
#define BTRFS_DIR_ITEM_KEY
Definition: btrfs.h:53
struct btrfs_root_item ExtentRoot
Definition: btrfs.c:31
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define btrfs_crc32c(name, len)
Definition: btrfs.h:23
Definition: vfat.h:184
uint8_t chunk_root_level
Definition: btrfs.h:242
Status
Definition: gdiplustypes.h:24
#define ALIGN_DOWN_BY(size, align)
struct btrfs_inode_item inode
Definition: btrfs.h:417
#define ERR(fmt,...)
Definition: debug.h:110
#define BTRFS_SUPER_INFO_OFFSET
Definition: btrfs.h:25
static void btrfs_read_sys_chunk_array(PBTRFS_INFO BtrFsInfo)
Definition: btrfs.c:440
ARC_STATUS BtrFsRead(ULONG FileId, VOID *Buffer, ULONG Size, ULONG *BytesRead)
Definition: btrfs.c:1237
struct btrfs_chunk_map_item * map
Definition: btrfs.h:407
ARC_STATUS BtrFsClose(ULONG FileId)
Definition: btrfs.c:1162
PRTL_UNICODE_STRING_BUFFER Path
#define BTRFS_DEV_ITEM_KEY
Definition: btrfs.h:48
static ATOM item
Definition: dde.c:856
static BOOLEAN verify_dir_item(struct btrfs_dir_item *item, u32 start, u32 total)
Definition: btrfs.c:519
GLuint start
Definition: gl.h:1545
static BOOLEAN BtrFsSearchTreeType(PBTRFS_INFO BtrFsInfo, const struct btrfs_root_item *root, u64 objectid, u8 type, struct btrfs_path *path)
Definition: btrfs.c:365
DBG_DEFAULT_CHANNEL(FILESYSTEM)
RtlZeroMemory(r->fcbs_ptrs, sizeof(LIST_ENTRY *) *256)
static UCHAR * path_current_data(struct btrfs_path *path)
Definition: btrfs.c:183
static void insert_chunk_item(struct btrfs_chunk_map *chunk_map, struct btrfs_chunk_map_item *item)
Definition: btrfs.c:87
#define BTRFS_EXTENT_DATA_KEY
Definition: btrfs.h:52
#define min(a, b)
Definition: monoChain.cc:55
Definition: arc.h:46
#define BTRFS_COMPRESS_NONE
Definition: btrfs.h:80
#define BTRFS_DIR_INDEX_KEY
Definition: btrfs.h:54
Definition: arc.h:41
static struct btrfs_item * path_current_item(struct btrfs_path *path)
Definition: btrfs.c:178
static int next_slot(PBTRFS_INFO BtrFsInfo, struct btrfs_disk_key *key, struct btrfs_path *path)
Definition: btrfs.c:384
static int btrfs_comp_keys(const struct btrfs_disk_key *k1, const struct btrfs_disk_key *k2)
Definition: btrfs.c:194
#define BTRFS_FIRST_CHUNK_TREE_OBJECTID
Definition: btrfs.h:63
#define INVALID_INODE
Definition: btrfs.c:21
Definition: name.c:38
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
__u16 name_len
Definition: btrfs.h:259
GLuint res
Definition: glext.h:9613
unsigned long offset
#define BTRFS_MAGIC_N
Definition: btrfs.h:44
__u8 type
Definition: btrfs.h:90
#define BTRFS_CHUNK_ITEM_KEY
Definition: btrfs.h:49
ULONG FsGetDeviceId(ULONG FileId)
Definition: fs.c:423
unsigned int ULONG
Definition: retypes.h:1
GLenum target
Definition: glext.h:7315
char * cleanup(char *str)
Definition: wpickclick.c:99
#define BTRFS_FT_XATTR
Definition: btrfs.h:77
static char * dest
Definition: rtl.c:135
#define SECTOR_SIZE
Definition: fs.h:22
static u64 logical_physical(struct btrfs_chunk_map *chunk_map, u64 logical)
Definition: btrfs.c:231
#define BTRFS_FILE_EXTENT_INLINE
Definition: btrfs.h:65
static void free_path(struct btrfs_path *path)
Definition: btrfs.c:173
static BOOLEAN disk_read(ULONG DeviceId, u64 physical, void *dest, u32 count)
Definition: btrfs.c:253
enum _OPENMODE OPENMODE
USHORT u16
Definition: btrfs.h:13
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
static int prev_slot(struct btrfs_disk_key *key, struct btrfs_path *path)
Definition: btrfs.c:425
struct btrfs_super_block SuperBlock
Definition: btrfs.c:28
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
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
struct btrfs_root_item FsRoot
Definition: btrfs.c:30
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesRead
Definition: fltkernel.h:1255
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
#define BTRFS_INODE_REF_KEY
Definition: btrfs.h:56
#define BTRFS_INODE_ITEM_KEY
Definition: btrfs.h:55
Iosb Information
Definition: create.c:4377
LONGLONG QuadPart
Definition: typedefs.h:113
#define BTRFS_FT_MAX
Definition: btrfs.h:78
Definition: path.c:41
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
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define BTRFS_FT_SYMLINK
Definition: btrfs.h:76
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186