xref: /haiku/src/system/boot/loader/file_systems/fat/CachedBlock.cpp (revision 085cf27b40c06dc45f633f33c41258f32bec3a23)
12cf4975bSFrançois Revol /*
22cf4975bSFrançois Revol  * Copyright 2008, Haiku, Inc.
32cf4975bSFrançois Revol  * Distributed under the terms of the MIT License.
42cf4975bSFrançois Revol  *
52cf4975bSFrançois Revol  * Authors:
62cf4975bSFrançois Revol  *		François Revol <revol@free.fr>
72cf4975bSFrançois Revol  */
82cf4975bSFrançois Revol 
92cf4975bSFrançois Revol 
102cf4975bSFrançois Revol #include "CachedBlock.h"
112cf4975bSFrançois Revol 
12*085cf27bSIngo Weinhold #include <errno.h>
132cf4975bSFrançois Revol #include <stdlib.h>
142cf4975bSFrançois Revol #include <string.h>
15861fb97cSFrançois Revol #include <unistd.h>
162cf4975bSFrançois Revol 
17*085cf27bSIngo Weinhold #include <util/kernel_cpp.h>
18*085cf27bSIngo Weinhold 
192cf4975bSFrançois Revol 
202cf4975bSFrançois Revol using namespace FATFS;
212cf4975bSFrançois Revol 
222cf4975bSFrançois Revol 
CachedBlock(Volume & volume)232cf4975bSFrançois Revol CachedBlock::CachedBlock(Volume &volume)
242cf4975bSFrançois Revol 	:
252cf4975bSFrançois Revol 	fVolume(volume),
262cf4975bSFrançois Revol 	fBlockNumber(-1LL),
272cf4975bSFrançois Revol 	fBlock(NULL)
282cf4975bSFrançois Revol {
292cf4975bSFrançois Revol }
302cf4975bSFrançois Revol 
312cf4975bSFrançois Revol 
CachedBlock(Volume & volume,off_t block)322cf4975bSFrançois Revol CachedBlock::CachedBlock(Volume &volume, off_t block)
332cf4975bSFrançois Revol 	:
342cf4975bSFrançois Revol 	fVolume(volume),
352cf4975bSFrançois Revol 	fBlockNumber(-1LL),
362cf4975bSFrançois Revol 	fBlock(NULL)
372cf4975bSFrançois Revol {
382cf4975bSFrançois Revol 	SetTo(block);
392cf4975bSFrançois Revol }
402cf4975bSFrançois Revol 
412cf4975bSFrançois Revol 
~CachedBlock()422cf4975bSFrançois Revol CachedBlock::~CachedBlock()
432cf4975bSFrançois Revol {
442cf4975bSFrançois Revol 	free(fBlock);
452cf4975bSFrançois Revol }
462cf4975bSFrançois Revol 
472cf4975bSFrançois Revol 
48*085cf27bSIngo Weinhold uint8 *
SetTo(off_t block)49*085cf27bSIngo Weinhold CachedBlock::SetTo(off_t block)
50*085cf27bSIngo Weinhold {
51*085cf27bSIngo Weinhold 	status_t error = SetTo(block, READ);
52*085cf27bSIngo Weinhold 	return error == B_OK ? fBlock : NULL;
53*085cf27bSIngo Weinhold }
54*085cf27bSIngo Weinhold 
55*085cf27bSIngo Weinhold 
56*085cf27bSIngo Weinhold status_t
SetTo(off_t blockNumber,uint32 flags)57*085cf27bSIngo Weinhold CachedBlock::SetTo(off_t blockNumber, uint32 flags)
58*085cf27bSIngo Weinhold {
59*085cf27bSIngo Weinhold 	if (fBlock == NULL) {
60*085cf27bSIngo Weinhold 		fBlock = (uint8*)malloc(BlockSize());
61*085cf27bSIngo Weinhold 		if (fBlock == NULL)
62*085cf27bSIngo Weinhold 			return B_NO_MEMORY;
63*085cf27bSIngo Weinhold 	}
64*085cf27bSIngo Weinhold 
65*085cf27bSIngo Weinhold 	if (blockNumber != fBlockNumber)
66*085cf27bSIngo Weinhold 		flags |= FORCE;
67*085cf27bSIngo Weinhold 
68*085cf27bSIngo Weinhold 	fBlockNumber = blockNumber;
69*085cf27bSIngo Weinhold 
70*085cf27bSIngo Weinhold 	status_t error = B_OK;
71*085cf27bSIngo Weinhold 
72*085cf27bSIngo Weinhold 	if ((flags & READ) != 0) {
73*085cf27bSIngo Weinhold 		if ((flags & FORCE) != 0) {
74*085cf27bSIngo Weinhold 			ssize_t bytesRead = read_pos(fVolume.Device(),
75*085cf27bSIngo Weinhold 				fBlockNumber << BlockShift(), fBlock, BlockSize());
76*085cf27bSIngo Weinhold 			if (bytesRead < 0)
77*085cf27bSIngo Weinhold 				error = bytesRead;
78*085cf27bSIngo Weinhold 			else if (bytesRead < (ssize_t)BlockSize())
79*085cf27bSIngo Weinhold 				error = B_ERROR;
80*085cf27bSIngo Weinhold 		}
81*085cf27bSIngo Weinhold 	} else if ((flags & CLEAR) != 0)
82*085cf27bSIngo Weinhold 		memset(fBlock, 0, BlockSize());
83*085cf27bSIngo Weinhold 
84*085cf27bSIngo Weinhold 	if (error != B_OK)
85*085cf27bSIngo Weinhold 		fBlockNumber = -1;
86*085cf27bSIngo Weinhold 
87*085cf27bSIngo Weinhold 	return error;
88*085cf27bSIngo Weinhold }
89*085cf27bSIngo Weinhold 
90*085cf27bSIngo Weinhold 
91*085cf27bSIngo Weinhold status_t
Flush()92*085cf27bSIngo Weinhold CachedBlock::Flush()
93*085cf27bSIngo Weinhold {
94*085cf27bSIngo Weinhold 	if (fBlockNumber < 0)
95*085cf27bSIngo Weinhold 		return B_BAD_VALUE;
96*085cf27bSIngo Weinhold 
97*085cf27bSIngo Weinhold 	ssize_t written = write_pos(fVolume.Device(), fBlockNumber << BlockShift(),
98*085cf27bSIngo Weinhold 		fBlock, BlockSize());
99*085cf27bSIngo Weinhold 	if (written < 0)
100*085cf27bSIngo Weinhold 		return errno;
101*085cf27bSIngo Weinhold 	if (written != (ssize_t)BlockSize())
102*085cf27bSIngo Weinhold 		return B_ERROR;
103*085cf27bSIngo Weinhold 
104*085cf27bSIngo Weinhold 	return B_OK;
105*085cf27bSIngo Weinhold }
106