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