xref: /haiku/src/system/boot/loader/file_systems/fat/CachedBlock.cpp (revision fce4895d1884da5ae6fb299d23c735c598e690b1)
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 
20 using namespace FATFS;
21 
22 
23 CachedBlock::CachedBlock(Volume &volume)
24 	:
25 	fVolume(volume),
26 	fBlockNumber(-1LL),
27 	fBlock(NULL)
28 {
29 }
30 
31 
32 CachedBlock::CachedBlock(Volume &volume, off_t block)
33 	:
34 	fVolume(volume),
35 	fBlockNumber(-1LL),
36 	fBlock(NULL)
37 {
38 	SetTo(block);
39 }
40 
41 
42 CachedBlock::~CachedBlock()
43 {
44 	free(fBlock);
45 }
46 
47 
48 uint8 *
49 CachedBlock::SetTo(off_t block)
50 {
51 	status_t error = SetTo(block, READ);
52 	return error == B_OK ? fBlock : NULL;
53 }
54 
55 
56 status_t
57 CachedBlock::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 
91 status_t
92 CachedBlock::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