/*
 * CiderPress
 * Copyright (C) 2007 by faddenSoft, LLC.  All Rights Reserved.
 * See the file LICENSE for distribution terms.
 */
/*
 * Base "container FS" support.
 */
#include "StdAfx.h"
#include "DiskImgPriv.h"


/*
 * Blank out the volume usage map, setting all entries to "embedded".
 */
void
DiskFSContainer::SetVolumeUsageMap(void)
{
	VolumeUsage::ChunkState cstate;
	long block;

	fVolumeUsage.Create(fpImg->GetNumBlocks());

	cstate.isUsed = true;
	cstate.isMarkedUsed = true;
	cstate.purpose = VolumeUsage::kChunkPurposeEmbedded;

	for (block = fpImg->GetNumBlocks()-1; block >= 0; block--)
		fVolumeUsage.SetChunkState(block, &cstate);
}


/*
 * Create a "placeholder" sub-volume.  Useful for some of the tools when
 * dealing with unformatted (or unknown-formatted) partitions.
 */
DIError
DiskFSContainer::CreatePlaceholder(long startBlock, long numBlocks,
	const char* partName, const char* partType,
	DiskImg** ppNewImg, DiskFS** ppNewFS)
{
	DIError dierr = kDIErrNone;
	DiskFS* pNewFS = nil;
	DiskImg* pNewImg = nil;

	WMSG3(" %s/CrPl creating placeholder for %ld +%ld\n", GetDebugName(),
		startBlock, numBlocks);

	if (startBlock > fpImg->GetNumBlocks()) {
		WMSG3(" %s/CrPl start block out of range (%ld vs %ld)\n",
			GetDebugName(), startBlock, fpImg->GetNumBlocks());
		return kDIErrBadPartition;
	}

	pNewImg = new DiskImg;
	if (pNewImg == nil) {
		dierr = kDIErrMalloc;
		goto bail;
	}

	if (partName != nil) {
		if (partType != nil)
			pNewImg->AddNote(DiskImg::kNoteInfo,
				"Partition name='%s' type='%s'.", partName, partType);
		else
			pNewImg->AddNote(DiskImg::kNoteInfo,
				"Partition name='%s'.", partName);
	}

	dierr = pNewImg->OpenImage(fpImg, startBlock, numBlocks);
	if (dierr != kDIErrNone) {
		WMSG4(" %s/CrPl: OpenImage(%ld,%ld) failed (err=%d)\n",
			GetDebugName(), startBlock, numBlocks, dierr);
		goto bail;
	}

	/*
	 * If this slot isn't formatted at all, the call will return with
	 * "unknown FS".  If it's formatted enough to pass the initial test,
	 * but fails during "Initialize", we'll have a non-unknown value
	 * for the FS format.  We need to stomp that.
	 */
	dierr = pNewImg->AnalyzeImage();
	if (dierr != kDIErrNone) {
		WMSG2(" %s/CrPl: analysis failed (err=%d)\n", GetDebugName(), dierr);
		goto bail;
	}
	if (pNewImg->GetFSFormat() != DiskImg::kFormatUnknown) {
		dierr = pNewImg->OverrideFormat(pNewImg->GetPhysicalFormat(),
					DiskImg::kFormatUnknown, pNewImg->GetSectorOrder());
		if (dierr != kDIErrNone) {
			WMSG1(" %s/CrPl: unable to override to unknown\n",
				GetDebugName());
			goto bail;
		}
	}

	/* open a DiskFS for the sub-image, allowing "unknown" */
	pNewFS = pNewImg->OpenAppropriateDiskFS(true);
	if (pNewFS == nil) {
		WMSG1(" %s/CrPl: OpenAppropriateDiskFS failed\n", GetDebugName());
		dierr = kDIErrUnsupportedFSFmt;
		goto bail;
	}

	/* sets the DiskImg ptr (and very little else) */
	dierr = pNewFS->Initialize(pNewImg, kInitFull);
	if (dierr != kDIErrNone) {
		WMSG2(" %s/CrPl: init failed (err=%d)\n", GetDebugName(), dierr);
		goto bail;
	}

bail:
	if (dierr != kDIErrNone) {
		delete pNewFS;
		delete pNewImg;
	} else {
		*ppNewImg = pNewImg;
		*ppNewFS = pNewFS;
	}
	return dierr;
}
