1/*
2 * Copyright 2008, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Fran��ois Revol <revol@free.fr>
7 */
8
9
10#include "CachedBlock.h"
11
12#include <errno.h>
13#include <stdlib.h>
14#include <string.h>
15#include <unistd.h>
16
17#include <util/kernel_cpp.h>
18
19
20using namespace FATFS;
21
22
23CachedBlock::CachedBlock(Volume &volume)
24	:
25	fVolume(volume),
26	fBlockNumber(-1LL),
27	fBlock(NULL)
28{
29}
30
31
32CachedBlock::CachedBlock(Volume &volume, off_t block)
33	:
34	fVolume(volume),
35	fBlockNumber(-1LL),
36	fBlock(NULL)
37{
38	SetTo(block);
39}
40
41
42CachedBlock::~CachedBlock()
43{
44	free(fBlock);
45}
46
47
48uint8 *
49CachedBlock::SetTo(off_t block)
50{
51	status_t error = SetTo(block, READ);
52	return error == B_OK ? fBlock : NULL;
53}
54
55
56status_t
57CachedBlock::SetTo(off_t blockNumber, uint32 flags)
58{
59	if (fBlock == NULL) {
60		fBlock = (uint8*)malloc(BlockSize());
61		if (fBlock == NULL)
62			return B_NO_MEMORY;
63	}
64
65	if (blockNumber != fBlockNumber)
66		flags |= FORCE;
67
68	fBlockNumber = blockNumber;
69
70	status_t error = B_OK;
71
72	if ((flags & READ) != 0) {
73		if ((flags & FORCE) != 0) {
74			ssize_t bytesRead = read_pos(fVolume.Device(),
75				fBlockNumber << BlockShift(), fBlock, BlockSize());
76			if (bytesRead < 0)
77				error = bytesRead;
78			else if (bytesRead < (ssize_t)BlockSize())
79				error = B_ERROR;
80		}
81	} else if ((flags & CLEAR) != 0)
82		memset(fBlock, 0, BlockSize());
83
84	if (error != B_OK)
85		fBlockNumber = -1;
86
87	return error;
88}
89
90
91status_t
92CachedBlock::Flush()
93{
94	if (fBlockNumber < 0)
95		return B_BAD_VALUE;
96
97	ssize_t written = write_pos(fVolume.Device(), fBlockNumber << BlockShift(),
98		fBlock, BlockSize());
99	if (written < 0)
100		return errno;
101	if (written != (ssize_t)BlockSize())
102		return B_ERROR;
103
104	return B_OK;
105}
106