⛏️ index : haiku.git

/*
 * Copyright 2008, Haiku, Inc.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		FranΓ§ois Revol <revol@free.fr>
 */


#include "CachedBlock.h"

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <util/kernel_cpp.h>


using namespace FATFS;


CachedBlock::CachedBlock(Volume &volume)
	:
	fVolume(volume),
	fBlockNumber(-1LL),
	fBlock(NULL)
{
}


CachedBlock::CachedBlock(Volume &volume, off_t block)
	:
	fVolume(volume),
	fBlockNumber(-1LL),
	fBlock(NULL)
{
	SetTo(block);
}


CachedBlock::~CachedBlock()
{
	free(fBlock);
}


uint8 *
CachedBlock::SetTo(off_t block)
{
	status_t error = SetTo(block, READ);
	return error == B_OK ? fBlock : NULL;
}


status_t
CachedBlock::SetTo(off_t blockNumber, uint32 flags)
{
	if (fBlock == NULL) {
		fBlock = (uint8*)malloc(BlockSize());
		if (fBlock == NULL)
			return B_NO_MEMORY;
	}

	if (blockNumber != fBlockNumber)
		flags |= FORCE;

	fBlockNumber = blockNumber;

	status_t error = B_OK;

	if ((flags & READ) != 0) {
		if ((flags & FORCE) != 0) {
			ssize_t bytesRead = read_pos(fVolume.Device(),
				fBlockNumber << BlockShift(), fBlock, BlockSize());
			if (bytesRead < 0)
				error = bytesRead;
			else if (bytesRead < (ssize_t)BlockSize())
				error = B_ERROR;
		}
	} else if ((flags & CLEAR) != 0)
		memset(fBlock, 0, BlockSize());

	if (error != B_OK)
		fBlockNumber = -1;

	return error;
}


status_t
CachedBlock::Flush()
{
	if (fBlockNumber < 0)
		return B_BAD_VALUE;

	ssize_t written = write_pos(fVolume.Device(), fBlockNumber << BlockShift(),
		fBlock, BlockSize());
	if (written < 0)
		return errno;
	if (written != (ssize_t)BlockSize())
		return B_ERROR;

	return B_OK;
}