1/*
2 * Copyright 2011, Haiku Inc. All rights reserved.
3 * This file may be used under the terms of the MIT License.
4 *
5 * Authors:
6 *		J��r��me Duval
7 */
8
9
10#include "DataStream.h"
11
12#include "Volume.h"
13
14
15//#define TRACE_EXFAT
16#ifdef TRACE_EXFAT
17#	define TRACE(x...) dprintf("\33[34mexfat:\33[0m " x)
18#else
19#	define TRACE(x...) ;
20#endif
21#define ERROR(x...)	dprintf("\33[34mexfat:\33[0m " x)
22
23
24DataStream::DataStream(Volume* volume, Inode* inode, off_t size)
25	:
26	kBlockSize(volume->BlockSize()),
27	kClusterSize(volume->ClusterSize()),
28	fVolume(volume),
29	fInode(inode),
30	fSize(size)
31{
32	fNumBlocks = size == 0 ? 0 : ((size - 1) / kBlockSize) + 1;
33}
34
35
36DataStream::~DataStream()
37{
38}
39
40
41status_t
42DataStream::FindBlock(off_t pos, off_t& physical, off_t *_length)
43{
44	if (pos >= fSize) {
45		TRACE("FindBlock: offset larger than size\n");
46		return B_ENTRY_NOT_FOUND;
47	}
48	cluster_t clusterIndex = pos / kClusterSize;
49	uint32 offset = pos % kClusterSize;
50
51	cluster_t cluster = fInode->StartCluster();
52	for (uint32 i = 0; i < clusterIndex; i++)
53		cluster = fInode->NextCluster(cluster);
54	fsblock_t block;
55	if (fVolume->ClusterToBlock(cluster, block) != B_OK)
56		return B_BAD_DATA;
57	physical = block * kBlockSize + offset;
58	for (uint32 i = 0; i < 64; i++) {
59		cluster_t extentEnd = fInode->NextCluster(cluster);
60		if (extentEnd == EXFAT_CLUSTER_END || extentEnd == cluster + 1)
61			break;
62		cluster = extentEnd;
63	}
64	*_length = min_c((cluster - clusterIndex + 1) * kClusterSize - offset,
65		fSize - pos);
66	TRACE("inode %" B_PRIdINO ": cluster %" B_PRIu32 ", pos %" B_PRIdOFF ", %"
67		B_PRIdOFF "\n", fInode->ID(), clusterIndex, pos, physical);
68	return B_OK;
69}
70
71