/* Some code was taken from u-boot, https://github.com/u-boot/u-boot/tree/master/fs/btrfs */
#include <freeldr.h>
-#include <debug.h>
+#include <debug.h>
DBG_DEFAULT_CHANNEL(FILESYSTEM);
#define TAG_BTRFS_INFO 'IftB'
#define TAG_BTRFS_FILE 'FftB'
#define TAG_BTRFS_LINK 'LftB'
-#define INVALID_INODE ((ULONGLONG)-1)
+#define INVALID_INODE _UI64_MAX
+#define INVALID_ADDRESS _UI64_MAX
+#define READ_ERROR _UI64_MAX
struct BTRFS_INFO {
ULONG DeviceId;
if (ret == 0)
slot++;
else if (slot == 0)
- return -1;
+ return INVALID_ADDRESS;
if (logical >= chunk_map->map[slot - 1].logical + chunk_map->map[slot - 1].length)
- return -1;
+ return INVALID_ADDRESS;
TRACE("Address translation: 0x%llx -> 0x%llx\n", logical,
chunk_map->map[slot - 1].physical + logical - chunk_map->map[slot - 1].logical);
}
path->slots[0] = slot;
- out:
+out:
if (path_current_disk_key(path)->objectid && !btrfs_comp_keys_type(key, path_current_disk_key(path)))
return 0;
else
name_buf = (char *) item + sizeof(*item);
TRACE("Compare names %.*s and %.*s\n", name_len, name, item->name_len, name_buf);
- if (_strnicmp(name, name_buf, name_len) == 0)
+ if (name_len == item->name_len && _strnicmp(name, name_buf, name_len) == 0)
{
*ret_item = *item;
result = TRUE;
} while (!next_slot(&key, &path));
- cleanup:
+cleanup:
free_path(&path);
return result;
}
if (offset > dlen)
{
ERR("Tried to read offset (%llu) beyond extent length (%lu)\n", offset, dlen);
- return INVALID_INODE;
+ return READ_ERROR;
}
if (size > dlen - offset)
}
ERR("No compression supported right now\n");
- return INVALID_INODE;
+ return READ_ERROR;
}
static u64 btrfs_read_extent_reg(struct btrfs_path *path, struct btrfs_file_extent_item *extent,
if (offset > dlen)
{
ERR("Tried to read offset (%llu) beyond extent length (%lu)\n", offset, dlen);
- return -1ULL;
+ return READ_ERROR;
}
if (size > dlen - offset)
size = dlen - offset;
+ /* Handle sparse extent */
+ if (extent->disk_bytenr == 0 && extent->disk_num_bytes == 0)
+ {
+ RtlZeroMemory(out, size);
+ return size;
+ }
+
physical = logical_physical(extent->disk_bytenr);
- if (physical == -1ULL)
+ if (physical == INVALID_ADDRESS)
{
ERR("Unable to convert logical address to physical: %llu\n", extent->disk_bytenr);
- return -1ULL;
+ return READ_ERROR;
}
if (extent->compression == BTRFS_COMPRESS_NONE)
if (!disk_read(physical, temp_out, size + offset))
{
FrLdrTempFree(temp_out, TAG_BTRFS_FILE);
- return -1ULL;
+ return READ_ERROR;
}
memcpy(out, temp_out + offset, size);
} else
{
if (!disk_read(physical, out, size))
- return -1ULL;
+ return READ_ERROR;
}
return size;
}
ERR("No compression supported right now\n");
- return -1ULL;
+ return READ_ERROR;
}
static u64 btrfs_file_read(const struct btrfs_root_item *root, u64 inr, u64 offset, u64 size, char *buf)
struct btrfs_disk_key key;
struct btrfs_file_extent_item *extent;
int res = 0;
- u64 rd, seek_pointer = (u64) -1ULL, offset_in_extent;
+ u64 rd, seek_pointer = READ_ERROR, offset_in_extent;
BOOLEAN find_res;
TRACE("btrfs_file_read inr=%llu offset=%llu size=%llu\n", inr, offset, size);
rd = btrfs_read_extent_reg(&path, extent, offset_in_extent, size, buf);
}
- if (rd == -1ULL)
+ if (rd == READ_ERROR)
{
ERR("Error while reading extent\n");
- seek_pointer = (u64) -1ULL;
+ seek_pointer = READ_ERROR;
goto out;
}
if (res)
{
- seek_pointer = (u64) -1ULL;
+ seek_pointer = READ_ERROR;
goto out;
}
seek_pointer -= offset;
- out:
+out:
free_path(&path);
return seek_pointer;
}
{
struct btrfs_path path;
struct btrfs_inode_ref *ref;
- u64 ret = -1ULL;
+ u64 ret = INVALID_INODE;
init_path(&path);
if (BtrFsSearchTreeType(root, inr, BTRFS_INODE_REF_KEY, &path))
res = TRUE;
- out:
+out:
free_path(&path);
return res;
}
if (len > BTRFS_NAME_MAX)
{
ERR("%s: Name too long at \"%.*s\"\n", BTRFS_NAME_MAX, cur);
- return -1ULL;
+ return INVALID_INODE;
}
if (len == 1 && cur[0] == '.')
TRACE("BtrFsClose %lu\n", FileId);
FrLdrTempFree(phandle, TAG_BTRFS_FILE);
-
return ESUCCESS;
}
{
pbtrfs_file_info phandle = FsGetDeviceSpecific(FileId);
- TRACE("BtrFsGetFileInformation %lu\n", FileId);
-
- RtlZeroMemory(Information, sizeof(FILEINFORMATION));
+ RtlZeroMemory(Information, sizeof(*Information));
Information->EndingAddress.QuadPart = phandle->inode.size;
Information->CurrentAddress.QuadPart = phandle->position;
- TRACE("BtrFsGetFileInformation() FileSize = %llu\n",
- Information->EndingAddress.QuadPart);
- TRACE("BtrFsGetFileInformation() FilePointer = %llu\n",
- Information->CurrentAddress.QuadPart);
+ TRACE("BtrFsGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n",
+ FileId, Information->EndingAddress.QuadPart, Information->CurrentAddress.QuadPart);
return ESUCCESS;
}
inr = btrfs_lookup_path(&BtrFsInfo->FsRoot, BtrFsInfo->FsRoot.root_dirid, Path, &type, &temp_file_info.inode, 40);
- if (inr == -1ULL)
+ if (inr == INVALID_INODE)
{
TRACE("Cannot lookup file %s\n", Path);
return ENOENT;
Size = phandle->inode.size;
rd = btrfs_file_read(&BtrFsInfo->FsRoot, phandle->inr, phandle->position, Size, Buffer);
- if (rd == -1ULL)
+ if (rd == READ_ERROR)
{
TRACE("An error occured while reading file %lu\n", FileId);
return ENOENT;
}
+ phandle->position += rd;
*BytesRead = rd;
return ESUCCESS;
}
ARC_STATUS BtrFsSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
{
pbtrfs_file_info phandle = FsGetDeviceSpecific(FileId);
+ LARGE_INTEGER NewPosition = *Position;
- TRACE("BtrFsSeek %lu NewFilePointer = %llu\n", FileId, Position->QuadPart);
+ switch (SeekMode)
+ {
+ case SeekAbsolute:
+ break;
+ case SeekRelative:
+ NewPosition.QuadPart += phandle->position;
+ break;
+ default:
+ ASSERT(FALSE);
+ return EINVAL;
+ }
- if (SeekMode != SeekAbsolute)
- return EINVAL;
- if (Position->QuadPart >= phandle->inode.size)
+ if (NewPosition.QuadPart >= phandle->inode.size)
return EINVAL;
- phandle->position = Position->QuadPart;
+ phandle->position = NewPosition.QuadPart;
return ESUCCESS;
}
struct btrfs_path path;
struct btrfs_root_item fs_root_item;
- TRACE("Enter BtrFsMount(), sizeof %d %d\n", sizeof(struct BTRFS_INFO), sizeof(struct btrfs_super_block));
+ TRACE("Enter BtrFsMount(%lu)\n", DeviceId);
BtrFsInfo = FrLdrTempAlloc(sizeof(struct BTRFS_INFO), TAG_BTRFS_INFO);
if (!BtrFsInfo)
return NULL;
}
- /* Check if SuperBlock is valid. If yes, return Ext2 function table */
- if (BtrFsInfo->SuperBlock.magic == BTRFS_MAGIC_N)
+ /* Check if SuperBlock is valid. If yes, return BTRFS function table */
+ if (BtrFsInfo->SuperBlock.magic != BTRFS_MAGIC_N)
{
- BtrFsInfo->DeviceId = DeviceId;
- TRACE("BtrFsMount() superblock magic ok\n");
-
- btrfs_init_crc32c();
-
- btrfs_read_sys_chunk_array();
- btrfs_read_chunk_tree();
+ FrLdrTempFree(BtrFsInfo, TAG_BTRFS_INFO);
+ return NULL;
+ }
- /* setup roots */
- fs_root_item.bytenr = BtrFsInfo->SuperBlock.root;
- fs_root_item.level = BtrFsInfo->SuperBlock.root_level;
+ BtrFsInfo->DeviceId = DeviceId;
+ TRACE("BtrFsMount(%lu) superblock magic ok\n", DeviceId);
- init_path(&path);
- if (!BtrFsSearchTreeType(&fs_root_item, BTRFS_FS_TREE_OBJECTID, BTRFS_ROOT_ITEM_KEY, &path))
- {
- FrLdrTempFree(BtrFsInfo, TAG_BTRFS_INFO);
- free_path(&path);
- return NULL;
- }
+ btrfs_init_crc32c();
- BtrFsInfo->FsRoot = *(struct btrfs_root_item *) path_current_data(&path);
-
- free_path(&path);
+ btrfs_read_sys_chunk_array();
+ btrfs_read_chunk_tree();
- TRACE("BtrFsMount success\n");
+ /* setup roots */
+ fs_root_item.bytenr = BtrFsInfo->SuperBlock.root;
+ fs_root_item.level = BtrFsInfo->SuperBlock.root_level;
- return &BtrFsFuncTable;
- }
- else
+ init_path(&path);
+ if (!BtrFsSearchTreeType(&fs_root_item, BTRFS_FS_TREE_OBJECTID, BTRFS_ROOT_ITEM_KEY, &path))
{
+ FrLdrTempFree(BtrFsInfo, TAG_BTRFS_INFO);
+ free_path(&path);
return NULL;
}
+
+ BtrFsInfo->FsRoot = *(struct btrfs_root_item *) path_current_data(&path);
+
+ free_path(&path);
+
+ TRACE("BtrFsMount(%lu) success\n", DeviceId);
+ return &BtrFsFuncTable;
}