⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 volume.c

📁 open source bios with linux platform, very good and can be reused.
💻 C
字号:
/* * libhfs - library for reading and writing Macintosh HFS volumes * * Code to acces the basic volume information of a HFS+ volume. * * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de> * Original work by 1996-1998 Robert Leslie <rob@mars.org> * other work 2000 from Brad Boyer (flar@pants.nu)   * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: volume.c,v 1.21 2000/10/25 05:43:04 hasi Exp $ */#include "openbios/config.h"#include "libhfsp.h"#include "volume.h"#include "record.h"#include "btree.h"#include "blockiter.h"#include "os.h"#include "swab.h"#include "hfstime.h"/* Fill a given buffer with the given block in volume. */int volume_readinbuf(volume * vol,void* buf, long block){	UInt16 blksize_bits;	ASSERT( block < vol->maxblocks);		blksize_bits = vol->blksize_bits;		block	+= vol->startblock;	if( os_seek(vol->os_fd, block, blksize_bits) == block) 		if( 1 == os_read(vol->os_fd, buf, 1, blksize_bits))			return 0;	return -1;}/* read multiple blocks into given memory. * * returns given pinter or NULL on failure. */void* volume_readfromfork(volume* vol, void* buf, 		hfsp_fork_raw* f, UInt32 block, 		UInt32 count, UInt8 forktype, UInt32 fileId){	blockiter iter;	char *cbuf = buf;	blockiter_init(&iter, vol, f, forktype, fileId);	if( blockiter_skip(&iter, block))		return NULL;	while( count > 0) {		--count;		if( volume_readinbuf(vol, cbuf, blockiter_curr(&iter)))			return NULL;		cbuf += vol->blksize;		if( count > 0 && blockiter_next(&iter)) 			return NULL;	}	return buf;}/* Read a raw hfsp_extent_rec from memory. *  * return pointer right after the structure. */void*volume_readextent(void *p, hfsp_extent_rec er){	int 		i;	hfsp_extent	*e;	for( i=0; i < 8; i++) {		e = &er[i];		e->start_block = bswabU32_inc(p);		e->block_count = bswabU32_inc(p);	}	return p;}/* Read a raw hfsp_fork from memory. *  * return pointer right after the structure. */void* volume_readfork(void *p, hfsp_fork_raw* f){	f->total_size   = bswabU64_inc(p);	f->clump_size   = bswabU32_inc(p);	f->total_blocks = bswabU32_inc(p);	return volume_readextent(p, f->extents);}/* Read the volume from the given buffer and swap the bytes. *  * ToDo: add more consitency checks.  */static int volume_readbuf(volume * vol, hfsp_vh* vh, void* p){	if(  (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG) 		HFSP_ERROR(-1, "This is not a HFS+ volume");	vh->version		= bswabU16_inc(p);	vh->attributes   	= bswabU32_inc(p); 	vh->last_mount_vers	= bswabU32_inc(p); 	vh->reserved		= bswabU32_inc(p);	vh->create_date		= bswabU32_inc(p);	vh->modify_date		= bswabU32_inc(p);	vh->backup_date		= bswabU32_inc(p);	vh->checked_date	= bswabU32_inc(p);	vh->file_count		= bswabU32_inc(p);	vh->folder_count	= bswabU32_inc(p);	vh->blocksize		= bswabU32_inc(p);	vh->total_blocks	= bswabU32_inc(p);	vh->free_blocks		= bswabU32_inc(p);	vh->next_alloc		= bswabU32_inc(p);	vh->rsrc_clump_sz	= bswabU32_inc(p);	vh->data_clump_sz	= bswabU32_inc(p);	vh->next_cnid		= bswabU32_inc(p);	vh->write_count		= bswabU32_inc(p);	vh->encodings_bmp	= bswabU64_inc(p);	memcpy(vh->finder_info, p, 32); 	p += 32; // So finderinfo must be swapped later, ***	p = volume_readfork(p, &vh->alloc_file );	p = volume_readfork(p, &vh->ext_file   );	p = volume_readfork(p, &vh->cat_file   );	p = volume_readfork(p, &vh->attr_file  );	p = volume_readfork(p, &vh->start_file );	return 0;  fail:	return -1;}		/* Read the volume from the given block */static int volume_read(volume * vol, hfsp_vh* vh, UInt32 block){	char buf[vol->blksize];	if( volume_readinbuf(vol, buf, block))		return -1;	return volume_readbuf(vol, vh, buf);}/* Find out wether the volume is wrapped and unwrap it eventually */static int volume_read_wrapper(volume * vol, hfsp_vh* vh){	UInt16  signature;	char	buf[vol->blksize];	void	*p = buf;	if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here		return -1;	signature = bswabU16_inc(p);	if( signature == HFS_VOLHEAD_SIG) {		/* Wrapper */		UInt32  drAlBlkSiz;			/* size (in bytes) of allocation blocks */		UInt32	sect_per_block;			/* how may block build an hfs sector */		UInt16  drAlBlSt;			/* first allocation block in volume */  		UInt16	embeds, embedl;			/* Start/lenght of embedded area in blocks */				p += 0x12;			/* skip unneded HFS vol fields */		drAlBlkSiz = bswabU32_inc(p);		/* offset 0x14 */		p += 0x4;			/* skip unneded HFS vol fields */		drAlBlSt = bswabU16_inc(p);		/* offset 0x1C */				p += 0x5E;			/* skip unneded HFS vol fields */		signature = bswabU16_inc(p);		/* offset 0x7C, drEmbedSigWord */		if( signature != HFSP_VOLHEAD_SIG)			HFSP_ERROR(-1, "This looks like a normal HFS volume");		embeds = bswabU16_inc(p);		embedl = bswabU16_inc(p);		sect_per_block =  (drAlBlkSiz / HFSP_BLOCKSZ);  		// end is absolute (not relative to HFS+ start)		vol->maxblocks = embedl * sect_per_block;		vol->startblock = drAlBlSt + embeds * sect_per_block;		/* Now we can try to read the embedded HFS+ volume header */		return volume_read(vol,vh,2);	}	else if( signature == HFSP_VOLHEAD_SIG) { /* Native HFS+ volume */		p = buf; // Restore to begin of block		return volume_readbuf(vol, vh, p);	} else		 HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found");fail:	return -1;}	/* Open the device, read and verify the volume header   (and its backup) */intvolume_open( volume* vol, int os_fd ){	hfsp_vh backup;	/* backup volume found at second to last block */	long	sect_per_block;	int	shift;	vol->blksize_bits	= HFSP_BLOCKSZ_BITS;	vol->blksize		= HFSP_BLOCKSZ;	vol->startblock		= 0;	vol->maxblocks		= 3;		/* this should be enough until we find the volume descriptor */	vol->extents		= NULL; /* Thanks to Jeremias Sauceda */		btree_reset(&vol->catalog);	vol->os_fd = os_fd;	// vol->maxblocks = os_seek(vol->os_fd, -1, HFSP_BLOCKSZ_BITS); 	// This wont work for /dev/... but we do not really need it 	if( volume_read_wrapper(vol, &vol->vol))		return -1;	if( volume_read(vol, &backup, vol->maxblocks - 2))		return -1;	/* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header	   and adjust depend values accordingly, after that a block always	   means a HFS+ allocation size */	/* Usually 4096 / 512  == 8 */	sect_per_block = vol->vol.blocksize / HFSP_BLOCKSZ;	shift = 0;	if( sect_per_block > 1) {		shift = 1;		while( sect_per_block > 2) {			sect_per_block >>=1;			shift++;		}		/* shift = 3 */	}	vol -> blksize_bits += shift;  	vol -> blksize = 1 << vol->blksize_bits;	vol -> startblock >>= shift;	vol -> maxblocks = vol->vol.total_blocks;	/* cant calculate via shift ? */		if( btree_init_cat(&vol->catalog, vol, &vol->vol.cat_file))		return -1;			return 0;} /* Write back all data eventually cached and close the device */intvolume_close(volume* vol){	btree_close(&vol->catalog);	if( vol->extents) {		btree_close(vol->extents);		FREE(vol->extents);	}	return 0;}/* internal fucntion used to create the extents btree,   is called by inline function when needed */void volume_create_extents_tree(volume* vol){	btree* result = (btree*) ALLOC(btree*, sizeof(btree));	if( !result)		HFSP_ERROR(ENOMEM, "No memory for extents btree");	if( !btree_init_extent(result, vol, &vol->vol.ext_file)) {		vol->extents = result;		return;	}  fail:	vol->extents = NULL;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -