4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* $Id$ */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * fsw_hfs.c - HFS file system driver code, see
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * http://developer.apple.com/technotes/tn/tn1150.html
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Current limitations:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - Doesn't support permissions
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - Complete Unicode case-insensitiveness disabled (large tables)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - No links
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - Only supports pure HFS+ (i.e. no HFS, or HFS+ embedded to HFS)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2010 Oracle Corporation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * available from http://www.virtualbox.org. This file is free software;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * General Public License (GPL) as published by the Free Software
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * The contents of this file may alternatively be used under the terms
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * of the Common Development and Distribution License Version 1.0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * VirtualBox OSE distribution, in which case the provisions of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * CDDL are applicable instead of those of the GPL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * You may elect to license modified versions of this file under the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * terms and conditions of either the GPL or the CDDL or both.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "fsw_hfs.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef HOST_POSIX
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define DPRINT(x) printf(x)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define DPRINT2(x,y) printf(x,y)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define BP(msg) do { printf("ERROR: %s", msg); asm("int3"); } while (0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CONCAT(x,y) x##y
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define DPRINT(x) Print(CONCAT(L,x))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define DPRINT2(x,y) Print(CONCAT(L,x), y)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define BP(msg) DPRINT(msg)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// functions
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#if 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncvoid dump_str(fsw_u16* p, fsw_u32 len, int swap)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i=0; i<len; i++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fprintf(stderr, "%c", swap ? be16_to_cpu(p[i]) : p[i]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fprintf(stderr, "\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_volume_mount(struct fsw_hfs_volume *vol);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void fsw_hfs_volume_free(struct fsw_hfs_volume *vol);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_volume_stat(struct fsw_hfs_volume *vol, struct fsw_volume_stat *sb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_dnode_fill(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void fsw_hfs_dnode_free(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_dnode_stat(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_dnode_stat *sb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_get_extent(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_extent *extent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_dir_lookup(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_string *lookup_name, struct fsw_hfs_dnode **child_dno);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_dir_read(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_shandle *shand, struct fsw_hfs_dnode **child_dno);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#if 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_read_dirrec(struct fsw_shandle *shand, struct hfs_dirrec_buffer *dirrec_buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_readlink(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_string *link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Dispatch Table
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstruct fsw_fstype_table FSW_FSTYPE_TABLE_NAME(hfs) = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync { FSW_STRING_TYPE_ISO88591, 4, 4, "hfs" },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof(struct fsw_hfs_volume),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof(struct fsw_hfs_dnode),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_volume_mount,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_volume_free,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_volume_stat,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_dnode_fill,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_dnode_free,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_dnode_stat,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_get_extent,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_dir_lookup,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_dir_read,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_readlink,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_s32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_read_block (struct fsw_hfs_dnode * dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 log_bno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 off,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_s32 len,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u8 * buf)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_status_t status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_extent extent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 phys_bno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u8* buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync extent.log_start = log_bno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_hfs_get_extent(dno->g.vol, dno, &extent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync phys_bno = extent.phys_start;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_block_get(dno->g.vol, phys_bno, 0, (void **)&buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memcpy(buf, buffer + off, len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_block_release(dno->g.vol, phys_bno, buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Read data from HFS file. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_s32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_read_file (struct fsw_hfs_dnode * dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u64 pos,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_s32 len,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u8 * buf)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_status_t status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 log_bno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 block_size_bits = dno->g.vol->block_size_shift;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 block_size = (1 << block_size_bits);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 block_size_mask = block_size - 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_s32 read = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (len > 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 off = (fsw_u32)(pos & block_size_mask);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_s32 next_len = len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync log_bno = (fsw_u32)RShiftU64(pos, block_size_bits);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ( next_len >= 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && (fsw_u32)next_len > block_size)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync next_len = block_size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_hfs_read_block(dno, log_bno, off, next_len, buf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync buf += next_len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pos += next_len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync len -= next_len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync read += next_len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return read;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_s32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_compute_shift(fsw_u32 size)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_s32 i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i=0; i<32; i++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((size >> i) == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return i - 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BP("BUG\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Mount an HFS+ volume. Reads the superblock and constructs the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * root directory dnode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_volume_mount(struct fsw_hfs_volume *vol)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_status_t status, rv;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync void *buffer = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusVolumeHeader *voldesc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 blockno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_string s;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rv = FSW_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->primary_voldesc = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_set_blocksize(vol, HFS_BLOCKSIZE, HFS_BLOCKSIZE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync blockno = HFS_SUPERBLOCK_BLOCKNO;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CHECK(s) \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status) { \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rv = status; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break; \
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->emb_block_off = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->hfs_kind = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 signature;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTHeaderRec tree_header;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_s32 r;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 block_size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_block_get(vol, blockno, 0, &buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHECK(status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync voldesc = (HFSPlusVolumeHeader *)buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync signature = be16_to_cpu(voldesc->signature);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((signature == kHFSPlusSigWord) || (signature == kHFSXSigWord))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (vol->hfs_kind == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DPRINT("found HFS+\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->hfs_kind = FSW_HFS_PLUS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if (signature == kHFSSigWord)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSMasterDirectoryBlock* mdb = (HFSMasterDirectoryBlock*)buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (be16_to_cpu(mdb->drEmbedSigWord) == kHFSPlusSigWord)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DPRINT("found HFS+ inside HFS, untested\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->hfs_kind = FSW_HFS_PLUS_EMB;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->emb_block_off = be32_to_cpu(mdb->drEmbedExtent.startBlock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync blockno += vol->emb_block_off;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* retry */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DPRINT("found plain HFS, unsupported\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->hfs_kind = FSW_HFS_PLAIN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rv = FSW_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rv = FSW_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_memdup((void **)&vol->primary_voldesc, voldesc,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof(*voldesc));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHECK(status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync block_size = be32_to_cpu(voldesc->blockSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->block_size_shift = fsw_hfs_compute_shift(block_size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_block_release(vol, blockno, buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync buffer = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync voldesc = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_set_blocksize(vol, block_size, block_size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* get volume name */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync s.type = FSW_STRING_TYPE_ISO88591;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync s.size = s.len = kHFSMaxVolumeNameChars;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync s.data = "HFS+ volume";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_strdup_coerce(&vol->g.label, vol->g.host_string_type, &s);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHECK(status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Setup catalog dnode */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_dnode_create_root(vol, kHFSCatalogFileID, &vol->catalog_tree.file);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHECK(status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memcpy (vol->catalog_tree.file->extents,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->primary_voldesc->catalogFile.extents,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof vol->catalog_tree.file->extents);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->catalog_tree.file->g.size =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync be64_to_cpu(vol->primary_voldesc->catalogFile.logicalSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Setup extents overflow file */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_dnode_create_root(vol, kHFSExtentsFileID, &vol->extents_tree.file);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memcpy (vol->extents_tree.file->extents,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->primary_voldesc->extentsFile.extents,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof vol->extents_tree.file->extents);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->extents_tree.file->g.size =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync be64_to_cpu(vol->primary_voldesc->extentsFile.logicalSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Setup the root dnode */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_dnode_create_root(vol, kHFSRootFolderID, &vol->g.root);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHECK(status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Read catalog file, we know that first record is in the first node, right after
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the node descriptor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync r = fsw_hfs_read_file(vol->catalog_tree.file,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (BTNodeDescriptor),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (BTHeaderRec), (fsw_u8 *) &tree_header);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (r <= 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_VOLUME_CORRUPTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->case_sensitive =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (signature == kHFSXSigWord) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (tree_header.keyCompareType == kHFSBinaryCompare);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->catalog_tree.root_node = be32_to_cpu (tree_header.rootNode);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->catalog_tree.node_size = be16_to_cpu (tree_header.nodeSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Read extents overflow file */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync r = fsw_hfs_read_file(vol->extents_tree.file,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (BTNodeDescriptor),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (BTHeaderRec), (fsw_u8 *) &tree_header);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (r <= 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_VOLUME_CORRUPTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->extents_tree.root_node = be32_to_cpu (tree_header.rootNode);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->extents_tree.node_size = be16_to_cpu (tree_header.nodeSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rv = FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#undef CHECK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (buffer != NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_block_release(vol, blockno, buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return rv;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Free the volume data structure. Called by the core after an unmount or after
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * an unsuccessful mount to release the memory used by the file system type specific
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * part of the volume structure.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void fsw_hfs_volume_free(struct fsw_hfs_volume *vol)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (vol->primary_voldesc)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_free(vol->primary_voldesc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->primary_voldesc = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Get in-depth information on a volume.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_volume_stat(struct fsw_hfs_volume *vol, struct fsw_volume_stat *sb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sb->total_bytes = be32_to_cpu(vol->primary_voldesc->totalBlocks) << vol->block_size_shift;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sb->free_bytes = be32_to_cpu(vol->primary_voldesc->freeBlocks) << vol->block_size_shift;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Get full information on a dnode from disk. This function is called by the core
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * whenever it needs to access fields in the dnode structure that may not
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * be filled immediately upon creation of the dnode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_dnode_fill(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Free the dnode data structure. Called by the core when deallocating a dnode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * structure to release the memory used by the file system type specific part
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * of the dnode structure.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void fsw_hfs_dnode_free(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_u32 mac_to_posix(fsw_u32 mac_time)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Mac time is 1904 year based */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return mac_time ? mac_time - 2082844800 : 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Get in-depth information on a dnode. The core makes sure that fsw_hfs_dnode_fill
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * has been called on the dnode before this function is called. Note that some
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * data is not directly stored into the structure, but passed to a host-specific
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * callback that converts it to the host-specific format.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_dnode_stat(struct fsw_hfs_volume *vol,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_hfs_dnode *dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_dnode_stat *sb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sb->used_bytes = dno->used_bytes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sb->store_time_posix(sb, FSW_DNODE_STAT_CTIME, mac_to_posix(dno->ctime));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sb->store_time_posix(sb, FSW_DNODE_STAT_MTIME, mac_to_posix(dno->mtime));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sb->store_time_posix(sb, FSW_DNODE_STAT_ATIME, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sb->store_attr_posix(sb, 0700);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_find_block(HFSPlusExtentRecord * exts,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 * lbno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 * pbno)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 cur_lbno = *lbno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; i < 8; i++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 start = be32_to_cpu ((*exts)[i].startBlock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 count = be32_to_cpu ((*exts)[i].blockCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cur_lbno < count)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *pbno = start + cur_lbno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cur_lbno -= count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *lbno = cur_lbno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Find record offset, numbering starts from the end */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_u32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_btree_recoffset (struct fsw_hfs_btree * btree,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTNodeDescriptor * node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 index)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u8 *cnode = (fsw_u8 *) node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 *recptr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync recptr = (fsw_u16 *) (cnode+btree->node_size - index * 2 - 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return be16_to_cpu(*recptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Pointer to the key inside node */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic BTreeKey *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_btree_rec (struct fsw_hfs_btree * btree,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTNodeDescriptor * node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 index)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u8 *cnode = (fsw_u8 *) node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync offset = fsw_hfs_btree_recoffset (btree, node, index);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (BTreeKey *) (cnode + offset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_btree_search (struct fsw_hfs_btree * btree,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTreeKey * key,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int (*compare_keys) (BTreeKey* key1, BTreeKey* key2),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTNodeDescriptor ** result,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 * key_offset)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTNodeDescriptor* node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 currnode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 rec;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_status_t status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u8* buffer = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync currnode = btree->root_node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_alloc(btree->node_size, &buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync node = (BTNodeDescriptor*)buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int cmp = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int match;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync readnode:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync match = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Read a node. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fsw_hfs_read_file (btree->file,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (fsw_u64)currnode * btree->node_size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync btree->node_size, buffer) <= 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_VOLUME_CORRUPTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (be16_to_cpu(*(fsw_u16*)(buffer + btree->node_size - 2)) != sizeof(BTNodeDescriptor))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BP("corrupted node\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync count = be16_to_cpu (node->numRecords);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#if 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (rec = 0; rec < count; rec++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTreeKey *currkey;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync currkey = fsw_hfs_btree_rec (btree, node, rec);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cmp = compare_keys (currkey, key);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //fprintf(stderr, "rec=%d cmp=%d kind=%d \n", rec, cmp, node->kind);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Leaf node. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (node->kind == kBTLeafNode)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cmp == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Found! */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *result = node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *key_offset = rec;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if (node->kind == kBTIndexNode)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 *pointer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cmp > 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pointer = (fsw_u32 *) ((char *) currkey
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync + be16_to_cpu (currkey->length16)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync + 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync currnode = be32_to_cpu (*pointer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync match = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (node->kind == kBTLeafNode && cmp < 0 && node->fLink)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync currnode = be32_to_cpu(node->fLink);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto readnode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else if (!match)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Perform binary search */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 lower = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 upper = count - 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_s32 cmp = -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTreeKey *currkey = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (count == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (lower <= upper)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 index = (lower + upper) / 2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync currkey = fsw_hfs_btree_rec (btree, node, index);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cmp = compare_keys (currkey, key);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cmp < 0) upper = index - 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cmp > 0) lower = index + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cmp == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Found! */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *result = node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *key_offset = rec;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (cmp < 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync currkey = fsw_hfs_btree_rec (btree, node, upper);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (node->kind == kBTIndexNode && currkey)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 *pointer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pointer = (fsw_u32 *) ((char *) currkey
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync + be16_to_cpu (currkey->length16)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync + 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync currnode = be32_to_cpu (*pointer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync done:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (buffer != NULL && status != FSW_SUCCESS)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_free(buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 id;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 type;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_string * name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u64 size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u64 used;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 ctime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 mtime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusExtentRecord extents;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} file_info_t;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 cur_pos; /* current position */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 parent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_hfs_volume * vol;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_shandle * shandle; /* this one track iterator's state */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info_t file_info;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} visitor_parameter_t;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_btree_visit_node(BTreeKey *record, void* param)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync visitor_parameter_t* vp = (visitor_parameter_t*)param;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u8* base = (fsw_u8*)record->rawData + be16_to_cpu(record->length16) + 2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 rec_type = be16_to_cpu(*(fsw_u16*)base);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct HFSPlusCatalogKey* cat_key = (HFSPlusCatalogKey*)record;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 name_len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 *name_ptr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_string * file_name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (be32_to_cpu(cat_key->parentID) != vp->parent)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* not smth we care about */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (vp->shandle->pos != vp->cur_pos++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (rec_type)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case kHFSPlusFolderRecord:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusCatalogFolder* folder_info = (HFSPlusCatalogFolder*)base;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.id = be32_to_cpu(folder_info->folderID);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.type = FSW_DNODE_TYPE_DIR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.size = be32_to_cpu(folder_info->valence);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.used = be32_to_cpu(folder_info->valence);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.ctime = be32_to_cpu(folder_info->createDate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.mtime = be32_to_cpu(folder_info->contentModDate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case kHFSPlusFileRecord:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusCatalogFile* file_info = (HFSPlusCatalogFile*)base;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.id = be32_to_cpu(file_info->fileID);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.type = FSW_DNODE_TYPE_FILE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.size = be64_to_cpu(file_info->dataFork.logicalSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.used = LShiftU64(be32_to_cpu(file_info->dataFork.totalBlocks),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->vol->block_size_shift);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.ctime = be32_to_cpu(file_info->createDate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.mtime = be32_to_cpu(file_info->contentModDate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memcpy(&vp->file_info.extents, &file_info->dataFork.extents,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof vp->file_info.extents);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case kHFSPlusFolderThreadRecord:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case kHFSPlusFileThreadRecord:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->shandle->pos++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BP("unknown file type\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->file_info.type = FSW_DNODE_TYPE_UNKNOWN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name_len = be16_to_cpu(cat_key->nodeName.length);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_name = vp->file_info.name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_name->len = name_len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memdup(&file_name->data, &cat_key->nodeName.unicode[0], 2*name_len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_name->size = 2*name_len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_name->type = FSW_STRING_TYPE_UTF16;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name_ptr = (fsw_u16*)file_name->data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i=0; i<name_len; i++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync name_ptr[i] = be16_to_cpu(name_ptr[i]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vp->shandle->pos++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_btree_iterate_node (struct fsw_hfs_btree * btree,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTNodeDescriptor * first_node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 first_rec,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int (*callback) (BTreeKey *record, void* param),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync void * param)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_status_t status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* We modify node, so make a copy */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTNodeDescriptor* node = first_node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u8* buffer = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_alloc(btree->node_size, &buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 count = be16_to_cpu(node->numRecords);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 next_node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Iterate over all records in this node. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = first_rec; i < count; i++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int rv = callback(fsw_hfs_btree_rec (btree, node, i), param);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (rv)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case 1:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case -1:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* if callback returned 0 - continue */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync next_node = be32_to_cpu(node->fLink);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!next_node)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fsw_hfs_read_file (btree->file,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync next_node * btree->node_size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync btree->node_size, buffer) <= 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_VOLUME_CORRUPTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync node = (BTNodeDescriptor*)buffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync first_rec = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync done:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (buffer)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_free(buffer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#if 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncvoid deb(fsw_u16* p, int len, int swap)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i=0; i<len; i++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync printf("%c", swap ? be16_to_cpu(p[i]) : p[i]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync printf("\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_cmp_extkey(BTreeKey* key1, BTreeKey* key2)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusExtentKey* ekey1 = (HFSPlusExtentKey*)key1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusExtentKey* ekey2 = (HFSPlusExtentKey*)key2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* First key is read from the FS data, second is in-memory in CPU endianess */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync result = be32_to_cpu(ekey1->fileID) - ekey2->fileID;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (result)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync result = ekey1->forkType - ekey2->forkType;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (result)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync result = be32_to_cpu(ekey1->startBlock) - ekey2->startBlock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_cmp_catkey (BTreeKey *key1, BTreeKey *key2)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusCatalogKey *ckey1 = (HFSPlusCatalogKey*)key1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusCatalogKey *ckey2 = (HFSPlusCatalogKey*)key2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int apos, bpos, lc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 ac, bc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 parentId1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int key1Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 *p1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 *p2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync parentId1 = be32_to_cpu(ckey1->parentID);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (parentId1 > ckey2->parentID)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (parentId1 < ckey2->parentID)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p1 = &ckey1->nodeName.unicode[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p2 = &ckey2->nodeName.unicode[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync key1Len = be16_to_cpu (ckey1->nodeName.length);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync apos = bpos = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while(1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* get next valid character from ckey1 */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (lc = 0; lc == 0 && apos < key1Len; apos++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ac = be16_to_cpu(p1[apos]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lc = ac;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync };
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ac = (fsw_u16)lc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* get next valid character from ckey2 */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (lc = 0; lc == 0 && bpos < ckey2->nodeName.length; bpos++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bc = p2[bpos];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lc = bc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync };
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bc = (fsw_u16)lc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ac != bc || (ac == 0 && bc == 0))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ac - bc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncfsw_hfs_cmpi_catkey (BTreeKey *key1, BTreeKey *key2)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusCatalogKey *ckey1 = (HFSPlusCatalogKey*)key1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusCatalogKey *ckey2 = (HFSPlusCatalogKey*)key2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int apos, bpos, lc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 ac, bc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 parentId1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int key1Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 *p1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 *p2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync parentId1 = be32_to_cpu(ckey1->parentID);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (parentId1 > ckey2->parentID)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (parentId1 < ckey2->parentID)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync key1Len = be16_to_cpu (ckey1->nodeName.length);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (key1Len == 0 && ckey2->nodeName.length == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p1 = &ckey1->nodeName.unicode[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p2 = &ckey2->nodeName.unicode[0];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync apos = bpos = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while(1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* get next valid character from ckey1 */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (lc = 0; lc == 0 && apos < key1Len; apos++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ac = be16_to_cpu(p1[apos]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lc = ac ? fsw_to_lower(ac) : 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync };
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ac = (fsw_u16)lc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* get next valid character from ckey2 */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (lc = 0; lc == 0 && bpos < ckey2->nodeName.length; bpos++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bc = p2[bpos];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lc = bc ? fsw_to_lower(bc) : 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync };
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bc = (fsw_u16)lc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ac != bc || (ac == 0 && bc == 0))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ac - bc;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Retrieve file data mapping information. This function is called by the core when
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * fsw_shandle_read needs to know where on the disk the required piece of the file's
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * data can be found. The core makes sure that fsw_hfs_dnode_fill has been called
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * on the dnode before. Our task here is to get the physical disk block number for
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the requested logical block number.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_get_extent(struct fsw_hfs_volume * vol,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_hfs_dnode * dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_extent * extent)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_status_t status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 lbno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusExtentRecord *exts;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTNodeDescriptor *node = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync extent->type = FSW_EXTENT_TYPE_PHYSBLOCK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync extent->log_count = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lbno = extent->log_start;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* we only care about data forks atm, do we? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync exts = &dno->extents;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct HFSPlusExtentKey* key;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct HFSPlusExtentKey overflowkey;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 ptr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 phys_bno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fsw_hfs_find_block(exts, &lbno, &phys_bno))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync extent->phys_start = phys_bno + vol->emb_block_off;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Find appropriate overflow record */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync overflowkey.fileID = dno->g.dnode_id;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync overflowkey.startBlock = extent->log_start - lbno;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (node != NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_free(node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync node = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_hfs_btree_search (&vol->extents_tree,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (BTreeKey*)&overflowkey,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_cmp_extkey,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &node, &ptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync key = (struct HFSPlusExtentKey *)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_btree_rec (&vol->extents_tree, node, ptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync exts = (HFSPlusExtentRecord*) (key + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (node != NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_free(node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const fsw_u16* g_blacklist[] =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //L"AppleIntelCPUPowerManagement.kext",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//#define HFS_FILE_INJECTION
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef HFS_FILE_INJECTION
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic struct
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const fsw_u16* path;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const fsw_u16* name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} g_injectList[] =
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync L"/System/Library/Extensions",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync L"ApplePS2Controller.kext"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynccreate_hfs_dnode(struct fsw_hfs_dnode * dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info_t * file_info,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_hfs_dnode ** child_dno_out)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_status_t status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_hfs_dnode * baby;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_dnode_create(dno, file_info->id, file_info->type,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info->name, &baby);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync baby->g.size = file_info->size;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync baby->used_bytes = file_info->used;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync baby->ctime = file_info->ctime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync baby->mtime = file_info->mtime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Fill-in extents info */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (file_info->type == FSW_DNODE_TYPE_FILE)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memcpy(baby->extents, &file_info->extents, sizeof file_info->extents);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *child_dno_out = baby;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Lookup a directory's child dnode by name. This function is called on a directory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * to retrieve the directory entry with the given name. A dnode is constructed for
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * this entry and returned. The core makes sure that fsw_hfs_dnode_fill has been called
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * and the dnode is actually a directory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_dir_lookup(struct fsw_hfs_volume * vol,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_hfs_dnode * dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_string * lookup_name,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_hfs_dnode ** child_dno_out)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_status_t status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct HFSPlusCatalogKey catkey;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 ptr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u16 rec_type;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTNodeDescriptor * node = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_string rec_name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int free_data = 0, i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusCatalogKey* file_key;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info_t file_info;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u8* base;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memzero(&file_info, sizeof file_info);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.name = &rec_name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync catkey.parentID = dno->g.dnode_id;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync catkey.nodeName.length = (fsw_u16)lookup_name->len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* no need to allocate anything */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lookup_name->type == FSW_STRING_TYPE_UTF16)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memcpy(catkey.nodeName.unicode, lookup_name->data, lookup_name->size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rec_name = *lookup_name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_strdup_coerce(&rec_name, FSW_STRING_TYPE_UTF16, lookup_name);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* nothing allocated so far */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync free_data = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memcpy(catkey.nodeName.unicode, rec_name.data, rec_name.size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Dirty hack: blacklisting of certain files on FS driver level */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (i = 0; g_blacklist[i]; i++)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fsw_memeq(g_blacklist[i], catkey.nodeName.unicode, catkey.nodeName.length*2))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DPRINT2("Blacklisted %s\n", g_blacklist[i]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef HFS_FILE_INJECTION
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (fsw_hfs_inject(vol,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync catkey.nodeName.unicode,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync catkey.nodeName.length,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &file_info))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = FSW_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto create;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync catkey.keyLength = (fsw_u16)(5 + rec_name.size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_hfs_btree_search (&vol->catalog_tree,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (BTreeKey*)&catkey,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->case_sensitive ?
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_cmp_catkey : fsw_hfs_cmpi_catkey,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &node, &ptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_key = (HFSPlusCatalogKey *)fsw_hfs_btree_rec (&vol->catalog_tree, node, ptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* for plain HFS "-(keySize & 1)" would be needed */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync base = (fsw_u8*)file_key + be16_to_cpu(file_key->keyLength) + 2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rec_type = be16_to_cpu(*(fsw_u16*)base);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /** @todo: read additional info */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (rec_type)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case kHFSPlusFolderRecord:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusCatalogFolder* info = (HFSPlusCatalogFolder*)base;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.id = be32_to_cpu(info->folderID);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.type = FSW_DNODE_TYPE_DIR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* @todo: return number of elements, maybe use smth else */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.size = be32_to_cpu(info->valence);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.used = be32_to_cpu(info->valence);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.ctime = be32_to_cpu(info->createDate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.mtime = be32_to_cpu(info->contentModDate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case kHFSPlusFileRecord:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HFSPlusCatalogFile* info = (HFSPlusCatalogFile*)base;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.id = be32_to_cpu(info->fileID);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.type = FSW_DNODE_TYPE_FILE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.size = be64_to_cpu(info->dataFork.logicalSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.used = LShiftU64(be32_to_cpu(info->dataFork.totalBlocks), vol->block_size_shift);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.ctime = be32_to_cpu(info->createDate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.mtime = be32_to_cpu(info->contentModDate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memcpy(&file_info.extents, &info->dataFork.extents,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof file_info.extents);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BP("unknown file type\n");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync file_info.type = FSW_DNODE_TYPE_UNKNOWN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#ifdef HFS_FILE_INJECTION
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynccreate:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = create_hfs_dnode(dno, &file_info, child_dno_out);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncdone:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (node != NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_free(node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (free_data)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_strfree(&rec_name);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Get the next directory entry when reading a directory. This function is called during
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * directory iteration to retrieve the next directory entry. A dnode is constructed for
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the entry and returned. The core makes sure that fsw_hfs_dnode_fill has been called
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * and the dnode is actually a directory. The shandle provided by the caller is used to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * record the position in the directory between calls.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_dir_read(struct fsw_hfs_volume *vol,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_hfs_dnode *dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_shandle *shand,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_hfs_dnode **child_dno_out)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_status_t status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct HFSPlusCatalogKey catkey;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_u32 ptr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BTNodeDescriptor * node = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync visitor_parameter_t param;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_string rec_name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync catkey.parentID = dno->g.dnode_id;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync catkey.nodeName.length = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_memzero(&param, sizeof(param));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rec_name.type = FSW_STRING_TYPE_EMPTY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync param.file_info.name = &rec_name;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_hfs_btree_search (&vol->catalog_tree,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (BTreeKey*)&catkey,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync vol->case_sensitive ?
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_cmp_catkey : fsw_hfs_cmpi_catkey,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &node, &ptr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Iterator updates shand state */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync param.vol = vol;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync param.shandle = shand;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync param.parent = dno->g.dnode_id;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync param.cur_pos = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = fsw_hfs_btree_iterate_node (&vol->catalog_tree,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ptr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_hfs_btree_visit_node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &param);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync status = create_hfs_dnode(dno, &param.file_info, child_dno_out);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (status)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto done;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync done:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync fsw_strfree(&rec_name);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Get the target path of a symbolic link. This function is called when a symbolic
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * link needs to be resolved. The core makes sure that the fsw_hfs_dnode_fill has been
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * called on the dnode and that it really is a symlink.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic fsw_status_t fsw_hfs_readlink(struct fsw_hfs_volume *vol, struct fsw_hfs_dnode *dno,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct fsw_string *link_target)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FSW_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// EOF