summaryrefslogtreecommitdiff
path: root/Source/Kernel/VFS/Partition.class.cpp
blob: 9da34614d21251a44ad3758ab83c0c03fc92b445 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "Partition.class.h"

using namespace CMem;	//For memcpy

Partition::Partition(BlockDevice* dev, u8int partnumber, u64int startblock, u64int blockcount)
: m_cache(dev) {
	m_device = dev;
	m_partnumber = partnumber;
	m_startblock = startblock;
	m_blockcount = blockcount;
	m_cache.init(10 + (m_device->blocks() / 1000 > 100 ? 100 : m_device->blocks() / 1000));
}

bool Partition::readBlocks(u64int startblock, u32int count, u8int *data) {
	if (startblock + count > m_startblock + m_blockcount) return false;
	return m_cache.readBlocks(startblock + m_startblock, count, data);
}

bool Partition::writeBlocks(u64int startblock, u32int count, u8int *data) {
	if (startblock + count > m_startblock + m_blockcount) return false;
	return m_cache.writeBlocks(startblock + m_startblock, count, data);
}

bool Partition::read(u64int start, u32int length, u8int *data) {
	u32int blksz = m_device->blockSize();
	u64int startBlock = start / blksz;
	u32int offset = start % blksz;
	u32int blocks = (length + offset) / blksz;
	if ((length + offset) % blksz != 0) blocks++;

	u8int* buff = new u8int [blocks * blksz];	//THIS MAY FAIL :D
	if (buff == 0) return false;

	if (!readBlocks(startBlock, blocks, buff)) return false;
	memcpy(data, buff + offset, length);

	delete [] buff;
	return true;
}

bool Partition::write(u64int start, u32int length, u8int *data) {
	u32int blksz = m_device->blockSize();
	u64int startBlock = start / blksz;
	u32int offset = start % blksz;
	u32int blocks = (length + offset) / blksz;
	if ((length + offset) % blksz != 0) blocks++;
	u64int lastBlock = startBlock + (u64int)blocks - 1;

	u8int* buff = new u8int [blocks * blksz];
	if (buff == 0) return false;

	if (offset != 0) {
		if (!readBlocks(startBlock, 1, buff)) return false;
	}
	if (lastBlock != startBlock and (length + offset) % blksz != 0) {
		if (!readBlocks(lastBlock, 1, buff + ((blocks - 1) * blksz))) return false;
	}
	memcpy(buff + offset, data, length);
	if (!writeBlocks(startBlock, blocks, buff)) return false;

	delete[] buff;
	return true;
}

//Accessors
BlockDevice* Partition::getDevice() { return m_device; }
u64int Partition::getStartBlock() { return m_startblock; }
u64int Partition::getBlockCount() { return m_blockcount; }
u8int Partition::getPartNumber() { return m_partnumber; }
u32int Partition::blockSize() { return m_device->blockSize(); }