xref: /haiku/src/system/boot/loader/file_systems/bfs/Stream.cpp (revision 425ac1b60a56f4df7a0e88bd784545c0ec4fa01f)
1361f5cdfSAxel Dörfler /*
24b723e3fSAxel Dörfler  * Copyright 2003-2013, Axel Dörfler, axeld@pinc-software.de.
3361f5cdfSAxel Dörfler  * This file may be used under the terms of the MIT License.
45af32e75SAxel Dörfler  */
55af32e75SAxel Dörfler 
65af32e75SAxel Dörfler 
7361f5cdfSAxel Dörfler //!	Inode stream access functions
8361f5cdfSAxel Dörfler 
9361f5cdfSAxel Dörfler 
105af32e75SAxel Dörfler #include "Stream.h"
115af32e75SAxel Dörfler #include "Directory.h"
125af32e75SAxel Dörfler #include "File.h"
135af32e75SAxel Dörfler #include "Link.h"
145af32e75SAxel Dörfler 
155af32e75SAxel Dörfler #include <stdlib.h>
165af32e75SAxel Dörfler #include <unistd.h>
175af32e75SAxel Dörfler #include <string.h>
185af32e75SAxel Dörfler 
195af32e75SAxel Dörfler 
205af32e75SAxel Dörfler using namespace BFS;
2195d4ed67SJonathan Schleifer using std::nothrow;
225af32e75SAxel Dörfler 
235af32e75SAxel Dörfler 
245af32e75SAxel Dörfler class CachedBlock {
255af32e75SAxel Dörfler public:
265af32e75SAxel Dörfler 								CachedBlock(Volume& volume);
275af32e75SAxel Dörfler 								CachedBlock(Volume& volume, block_run run);
285af32e75SAxel Dörfler 								~CachedBlock();
295af32e75SAxel Dörfler 
305af32e75SAxel Dörfler 			uint8*				SetTo(block_run run);
315af32e75SAxel Dörfler 			uint8*				SetTo(off_t offset);
325af32e75SAxel Dörfler 
335af32e75SAxel Dörfler 			void				Unset();
345af32e75SAxel Dörfler 
Block() const355af32e75SAxel Dörfler 			uint8*				Block() const { return fBlock; }
BlockNumber() const365af32e75SAxel Dörfler 			off_t				BlockNumber() const { return fBlockNumber; }
BlockSize() const375af32e75SAxel Dörfler 			uint32				BlockSize() const { return fVolume.BlockSize(); }
BlockShift() const38e190cae1SAxel Dörfler 			uint32				BlockShift() const
39e190cae1SAxel Dörfler 									{ return fVolume.BlockShift(); }
405af32e75SAxel Dörfler 
415af32e75SAxel Dörfler private:
425af32e75SAxel Dörfler 			Volume&				fVolume;
435af32e75SAxel Dörfler 			off_t				fBlockNumber;
445af32e75SAxel Dörfler 			uint8*				fBlock;
455af32e75SAxel Dörfler };
465af32e75SAxel Dörfler 
475af32e75SAxel Dörfler 
CachedBlock(Volume & volume)485af32e75SAxel Dörfler CachedBlock::CachedBlock(Volume& volume)
495af32e75SAxel Dörfler 	:
505af32e75SAxel Dörfler 	fVolume(volume),
515af32e75SAxel Dörfler 	fBlockNumber(-1LL),
525af32e75SAxel Dörfler 	fBlock(NULL)
535af32e75SAxel Dörfler {
545af32e75SAxel Dörfler }
555af32e75SAxel Dörfler 
565af32e75SAxel Dörfler 
CachedBlock(Volume & volume,block_run run)575af32e75SAxel Dörfler CachedBlock::CachedBlock(Volume &volume, block_run run)
585af32e75SAxel Dörfler 	:
595af32e75SAxel Dörfler 	fVolume(volume),
605af32e75SAxel Dörfler 	fBlockNumber(-1LL),
615af32e75SAxel Dörfler 	fBlock(NULL)
625af32e75SAxel Dörfler {
635af32e75SAxel Dörfler 	SetTo(run);
645af32e75SAxel Dörfler }
655af32e75SAxel Dörfler 
665af32e75SAxel Dörfler 
~CachedBlock()675af32e75SAxel Dörfler CachedBlock::~CachedBlock()
685af32e75SAxel Dörfler {
695af32e75SAxel Dörfler 	free(fBlock);
705af32e75SAxel Dörfler }
715af32e75SAxel Dörfler 
725af32e75SAxel Dörfler 
735af32e75SAxel Dörfler inline void
Unset()745af32e75SAxel Dörfler CachedBlock::Unset()
755af32e75SAxel Dörfler {
765af32e75SAxel Dörfler 	fBlockNumber = -1;
775af32e75SAxel Dörfler }
785af32e75SAxel Dörfler 
795af32e75SAxel Dörfler 
805af32e75SAxel Dörfler inline uint8*
SetTo(off_t block)815af32e75SAxel Dörfler CachedBlock::SetTo(off_t block)
825af32e75SAxel Dörfler {
835af32e75SAxel Dörfler 	if (block == fBlockNumber)
845af32e75SAxel Dörfler 		return fBlock;
855af32e75SAxel Dörfler 	if (fBlock == NULL) {
865af32e75SAxel Dörfler 		fBlock = (uint8*)malloc(BlockSize());
875af32e75SAxel Dörfler 		if (fBlock == NULL)
885af32e75SAxel Dörfler 			return NULL;
895af32e75SAxel Dörfler 	}
905af32e75SAxel Dörfler 
915af32e75SAxel Dörfler 	fBlockNumber = block;
92e190cae1SAxel Dörfler 	if (read_pos(fVolume.Device(), block << BlockShift(), fBlock, BlockSize())
93e190cae1SAxel Dörfler 			< (ssize_t)BlockSize())
945af32e75SAxel Dörfler 		return NULL;
955af32e75SAxel Dörfler 
965af32e75SAxel Dörfler 	return fBlock;
975af32e75SAxel Dörfler }
985af32e75SAxel Dörfler 
995af32e75SAxel Dörfler 
1005af32e75SAxel Dörfler inline uint8*
SetTo(block_run run)1015af32e75SAxel Dörfler CachedBlock::SetTo(block_run run)
1025af32e75SAxel Dörfler {
1035af32e75SAxel Dörfler 	return SetTo(fVolume.ToBlock(run));
1045af32e75SAxel Dörfler }
1055af32e75SAxel Dörfler 
1065af32e75SAxel Dörfler 
1075af32e75SAxel Dörfler //	#pragma mark -
1085af32e75SAxel Dörfler 
1095af32e75SAxel Dörfler 
Stream(Volume & volume,block_run run)1105af32e75SAxel Dörfler Stream::Stream(Volume& volume, block_run run)
1115af32e75SAxel Dörfler 	:
1120dc4d1e5SIngo Weinhold 	fVolume(volume)
1135af32e75SAxel Dörfler {
114e190cae1SAxel Dörfler 	if (read_pos(volume.Device(), volume.ToOffset(run), this, sizeof(bfs_inode))
115e190cae1SAxel Dörfler 			!= sizeof(bfs_inode))
1160dc4d1e5SIngo Weinhold 		return;
1175af32e75SAxel Dörfler }
1185af32e75SAxel Dörfler 
1195af32e75SAxel Dörfler 
Stream(Volume & volume,off_t id)1205af32e75SAxel Dörfler Stream::Stream(Volume& volume, off_t id)
1215af32e75SAxel Dörfler 	:
1220dc4d1e5SIngo Weinhold 	fVolume(volume)
1235af32e75SAxel Dörfler {
124e190cae1SAxel Dörfler 	if (read_pos(volume.Device(), volume.ToOffset(id), this, sizeof(bfs_inode))
125e190cae1SAxel Dörfler 			!= sizeof(bfs_inode))
1260dc4d1e5SIngo Weinhold 		return;
1275af32e75SAxel Dörfler }
1285af32e75SAxel Dörfler 
1295af32e75SAxel Dörfler 
~Stream()1305af32e75SAxel Dörfler Stream::~Stream()
1315af32e75SAxel Dörfler {
1325af32e75SAxel Dörfler }
1335af32e75SAxel Dörfler 
1345af32e75SAxel Dörfler 
1355af32e75SAxel Dörfler status_t
InitCheck()1365af32e75SAxel Dörfler Stream::InitCheck()
1375af32e75SAxel Dörfler {
1380dc4d1e5SIngo Weinhold 	return bfs_inode::InitCheck(&fVolume);
1395af32e75SAxel Dörfler }
1405af32e75SAxel Dörfler 
1415af32e75SAxel Dörfler 
1425af32e75SAxel Dörfler status_t
GetNextSmallData(const small_data ** _smallData) const1435af32e75SAxel Dörfler Stream::GetNextSmallData(const small_data** _smallData) const
1445af32e75SAxel Dörfler {
1459618c0dcSIngo Weinhold 	// TODO: Stream derives from bfs_inode and we read only sizeof(bfs_inode)
1469618c0dcSIngo Weinhold 	// bytes from disk, i.e. the small data region is not in memory.
1479618c0dcSIngo Weinhold 	panic("Stream::GetNextSmallData(): small data region is not loaded!");
1489618c0dcSIngo Weinhold 
1495af32e75SAxel Dörfler 	const small_data* smallData = *_smallData;
1505af32e75SAxel Dörfler 
1515af32e75SAxel Dörfler 	// begin from the start?
1525af32e75SAxel Dörfler 	if (smallData == NULL)
1530dc4d1e5SIngo Weinhold 		smallData = small_data_start;
1545af32e75SAxel Dörfler 	else
1555af32e75SAxel Dörfler 		smallData = smallData->Next();
1565af32e75SAxel Dörfler 
1575af32e75SAxel Dörfler 	// is already last item?
1580dc4d1e5SIngo Weinhold 	if (smallData->IsLast(this))
1595af32e75SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
1605af32e75SAxel Dörfler 
1615af32e75SAxel Dörfler 	*_smallData = smallData;
1625af32e75SAxel Dörfler 
1635af32e75SAxel Dörfler 	return B_OK;
1645af32e75SAxel Dörfler }
1655af32e75SAxel Dörfler 
1665af32e75SAxel Dörfler 
1675af32e75SAxel Dörfler status_t
GetName(char * name,size_t size) const1685af32e75SAxel Dörfler Stream::GetName(char* name, size_t size) const
1695af32e75SAxel Dörfler {
1705af32e75SAxel Dörfler 	const small_data* smallData = NULL;
1715af32e75SAxel Dörfler 	while (GetNextSmallData(&smallData) == B_OK) {
1725af32e75SAxel Dörfler 		if (*smallData->Name() == FILE_NAME_NAME
1735af32e75SAxel Dörfler 			&& smallData->NameSize() == FILE_NAME_NAME_LENGTH) {
1745af32e75SAxel Dörfler 			strlcpy(name, (const char*)smallData->Data(), size);
1755af32e75SAxel Dörfler 			return B_OK;
1765af32e75SAxel Dörfler 		}
1775af32e75SAxel Dörfler 	}
1785af32e75SAxel Dörfler 	return B_ERROR;
1795af32e75SAxel Dörfler }
1805af32e75SAxel Dörfler 
1815af32e75SAxel Dörfler 
1825af32e75SAxel Dörfler status_t
ReadLink(char * buffer,size_t bufferSize)1835af32e75SAxel Dörfler Stream::ReadLink(char* buffer, size_t bufferSize)
1845af32e75SAxel Dörfler {
1855af32e75SAxel Dörfler 	// link in the stream
1865af32e75SAxel Dörfler 
1870dc4d1e5SIngo Weinhold 	if (Flags() & INODE_LONG_SYMLINK)
1885af32e75SAxel Dörfler 		return ReadAt(0, (uint8*)buffer, &bufferSize);
1895af32e75SAxel Dörfler 
1905af32e75SAxel Dörfler 	// link in the inode
1915af32e75SAxel Dörfler 
1920dc4d1e5SIngo Weinhold 	strlcpy(buffer, short_symlink, bufferSize);
1935af32e75SAxel Dörfler 	return B_OK;
1945af32e75SAxel Dörfler }
1955af32e75SAxel Dörfler 
1965af32e75SAxel Dörfler 
1975af32e75SAxel Dörfler status_t
FindBlockRun(off_t pos,block_run & run,off_t & offset)1985af32e75SAxel Dörfler Stream::FindBlockRun(off_t pos, block_run& run, off_t& offset)
1995af32e75SAxel Dörfler {
2005af32e75SAxel Dörfler 	// find matching block run
2015af32e75SAxel Dörfler 
2020dc4d1e5SIngo Weinhold 	if (data.MaxDirectRange() > 0 && pos >= data.MaxDirectRange()) {
203e190cae1SAxel Dörfler 		if (data.MaxDoubleIndirectRange() > 0
204e190cae1SAxel Dörfler 			&& pos >= data.MaxIndirectRange()) {
2055af32e75SAxel Dörfler 			// access to double indirect blocks
2065af32e75SAxel Dörfler 
2075af32e75SAxel Dörfler 			CachedBlock cached(fVolume);
2085af32e75SAxel Dörfler 
209361f5cdfSAxel Dörfler 			int32 runsPerBlock;
210361f5cdfSAxel Dörfler 			int32 directSize;
211361f5cdfSAxel Dörfler 			int32 indirectSize;
212361f5cdfSAxel Dörfler 			get_double_indirect_sizes(data.double_indirect.Length(),
213361f5cdfSAxel Dörfler 				cached.BlockSize(), runsPerBlock, directSize, indirectSize);
214361f5cdfSAxel Dörfler 
2150dc4d1e5SIngo Weinhold 			off_t start = pos - data.MaxIndirectRange();
2165af32e75SAxel Dörfler 			int32 index = start / indirectSize;
2175af32e75SAxel Dörfler 
2185af32e75SAxel Dörfler 			block_run* indirect = (block_run*)cached.SetTo(
2190dc4d1e5SIngo Weinhold 				fVolume.ToBlock(data.double_indirect) + index / runsPerBlock);
2205af32e75SAxel Dörfler 			if (indirect == NULL)
2215af32e75SAxel Dörfler 				return B_ERROR;
2225af32e75SAxel Dörfler 
223*425ac1b6SAlexander von Gluck IV 			//printf("\tstart = %lld, indirectSize = %ld, directSize = %ld, index = %ld\n",start,indirectSize,directSize,index);
2245af32e75SAxel Dörfler 			//printf("\tlook for indirect block at %ld,%d\n",indirect[index].allocation_group,indirect[index].start);
2255af32e75SAxel Dörfler 
2265af32e75SAxel Dörfler 			int32 current = (start % indirectSize) / directSize;
2275af32e75SAxel Dörfler 
228e190cae1SAxel Dörfler 			indirect = (block_run*)cached.SetTo(fVolume.ToBlock(indirect[
229e190cae1SAxel Dörfler 					index % runsPerBlock]) + current / runsPerBlock);
2305af32e75SAxel Dörfler 			if (indirect == NULL)
2315af32e75SAxel Dörfler 				return B_ERROR;
2325af32e75SAxel Dörfler 
2335af32e75SAxel Dörfler 			run = indirect[current % runsPerBlock];
234e190cae1SAxel Dörfler 			offset = data.MaxIndirectRange() + (index * indirectSize)
235e190cae1SAxel Dörfler 				+ (current * directSize);
236*425ac1b6SAlexander von Gluck IV 			//printf("\tfCurrent = %ld, fRunFileOffset = %lld, fRunBlockEnd = %lld, fRun = %ld,%d\n",fCurrent,fRunFileOffset,fRunBlockEnd,fRun.allocation_group,fRun.start);
2375af32e75SAxel Dörfler 		} else {
2385af32e75SAxel Dörfler 			// access to indirect blocks
2395af32e75SAxel Dörfler 
2405af32e75SAxel Dörfler 			int32 runsPerBlock = fVolume.BlockSize() / sizeof(block_run);
2410dc4d1e5SIngo Weinhold 			off_t runBlockEnd = data.MaxDirectRange();
2425af32e75SAxel Dörfler 
2435af32e75SAxel Dörfler 			CachedBlock cached(fVolume);
2440dc4d1e5SIngo Weinhold 			off_t block = fVolume.ToBlock(data.indirect);
2455af32e75SAxel Dörfler 
2460dc4d1e5SIngo Weinhold 			for (int32 i = 0; i < data.indirect.Length(); i++) {
2475af32e75SAxel Dörfler 				block_run* indirect = (block_run *)cached.SetTo(block + i);
2485af32e75SAxel Dörfler 				if (indirect == NULL)
2495af32e75SAxel Dörfler 					return B_IO_ERROR;
2505af32e75SAxel Dörfler 
2515af32e75SAxel Dörfler 				int32 current = -1;
2525af32e75SAxel Dörfler 				while (++current < runsPerBlock) {
2535af32e75SAxel Dörfler 					if (indirect[current].IsZero())
2545af32e75SAxel Dörfler 						break;
2555af32e75SAxel Dörfler 
256e190cae1SAxel Dörfler 					runBlockEnd
257e6a0c797SAlex Smith 						+= (uint32)indirect[current].Length() << cached.BlockShift();
2585af32e75SAxel Dörfler 					if (runBlockEnd > pos) {
2595af32e75SAxel Dörfler 						run = indirect[current];
260599b9881SAxel Dörfler 						offset = runBlockEnd
261e6a0c797SAlex Smith 							- ((uint32)run.Length() << cached.BlockShift());
2625af32e75SAxel Dörfler 						//printf("reading from indirect block: %ld,%d\n",fRun.allocation_group,fRun.start);
263*425ac1b6SAlexander von Gluck IV 						//printf("### indirect-run[%ld] = (%ld,%d,%d), offset = %lld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset);
2645af32e75SAxel Dörfler 						return fVolume.ValidateBlockRun(run);
2655af32e75SAxel Dörfler 					}
2665af32e75SAxel Dörfler 				}
2675af32e75SAxel Dörfler 			}
2685af32e75SAxel Dörfler 			return B_ERROR;
2695af32e75SAxel Dörfler 		}
2705af32e75SAxel Dörfler 	} else {
2715af32e75SAxel Dörfler 		// access from direct blocks
2725af32e75SAxel Dörfler 
2735af32e75SAxel Dörfler 		off_t runBlockEnd = 0LL;
2745af32e75SAxel Dörfler 		int32 current = -1;
2755af32e75SAxel Dörfler 
2765af32e75SAxel Dörfler 		while (++current < NUM_DIRECT_BLOCKS) {
2770dc4d1e5SIngo Weinhold 			if (data.direct[current].IsZero())
2785af32e75SAxel Dörfler 				break;
2795af32e75SAxel Dörfler 
280e6a0c797SAlex Smith 			runBlockEnd += (uint32)data.direct[current].Length() << fVolume.BlockShift();
2815af32e75SAxel Dörfler 			if (runBlockEnd > pos) {
2820dc4d1e5SIngo Weinhold 				run = data.direct[current];
283e6a0c797SAlex Smith 				offset = runBlockEnd - ((uint32)run.Length() << fVolume.BlockShift());
284*425ac1b6SAlexander von Gluck IV 				//printf("### run[%ld] = (%ld,%d,%d), offset = %lld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset);
2855af32e75SAxel Dörfler 				return fVolume.ValidateBlockRun(run);
2865af32e75SAxel Dörfler 			}
2875af32e75SAxel Dörfler 		}
288*425ac1b6SAlexander von Gluck IV 		//PRINT(("FindBlockRun() failed in direct range: size = %lld, pos = %lld\n",data.size,pos));
2895af32e75SAxel Dörfler 		return B_ENTRY_NOT_FOUND;
2905af32e75SAxel Dörfler 	}
2915af32e75SAxel Dörfler 	return fVolume.ValidateBlockRun(run);
2925af32e75SAxel Dörfler }
2935af32e75SAxel Dörfler 
2945af32e75SAxel Dörfler 
2955af32e75SAxel Dörfler status_t
ReadAt(off_t pos,uint8 * buffer,size_t * _length)2965af32e75SAxel Dörfler Stream::ReadAt(off_t pos, uint8* buffer, size_t* _length)
2975af32e75SAxel Dörfler {
2985af32e75SAxel Dörfler 	// set/check boundaries for pos/length
2995af32e75SAxel Dörfler 
3005af32e75SAxel Dörfler 	if (pos < 0)
3015af32e75SAxel Dörfler 		return B_BAD_VALUE;
3020dc4d1e5SIngo Weinhold 	if (pos >= data.Size()) {
3035af32e75SAxel Dörfler 		*_length = 0;
3045af32e75SAxel Dörfler 		return B_NO_ERROR;
3055af32e75SAxel Dörfler 	}
3065af32e75SAxel Dörfler 
3075af32e75SAxel Dörfler 	size_t length = *_length;
3085af32e75SAxel Dörfler 
309211483cbSFredrik Holmqvist 	if (pos + (off_t)length > data.Size())
3100dc4d1e5SIngo Weinhold 		length = data.Size() - pos;
3115af32e75SAxel Dörfler 
3125af32e75SAxel Dörfler 	block_run run;
3135af32e75SAxel Dörfler 	off_t offset;
3145af32e75SAxel Dörfler 	if (FindBlockRun(pos, run, offset) < B_OK) {
3155af32e75SAxel Dörfler 		*_length = 0;
3165af32e75SAxel Dörfler 		return B_BAD_VALUE;
3175af32e75SAxel Dörfler 	}
3185af32e75SAxel Dörfler 
3195af32e75SAxel Dörfler 	uint32 bytesRead = 0;
3205af32e75SAxel Dörfler 	uint32 blockSize = fVolume.BlockSize();
3215af32e75SAxel Dörfler 	uint32 blockShift = fVolume.BlockShift();
3225af32e75SAxel Dörfler 	uint8* block;
3235af32e75SAxel Dörfler 
3245af32e75SAxel Dörfler 	// the first block_run we read could not be aligned to the block_size boundary
3255af32e75SAxel Dörfler 	// (read partial block at the beginning)
3265af32e75SAxel Dörfler 
3275af32e75SAxel Dörfler 	// pos % block_size == (pos - offset) % block_size, offset % block_size == 0
3285af32e75SAxel Dörfler 	if (pos % blockSize != 0) {
329e190cae1SAxel Dörfler 		run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start()
330e190cae1SAxel Dörfler 			+ ((pos - offset) >> blockShift));
331e190cae1SAxel Dörfler 		run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length()
332e190cae1SAxel Dörfler 			- ((pos - offset) >> blockShift));
3335af32e75SAxel Dörfler 
3345af32e75SAxel Dörfler 		CachedBlock cached(fVolume, run);
3355af32e75SAxel Dörfler 		if ((block = cached.Block()) == NULL) {
3365af32e75SAxel Dörfler 			*_length = 0;
3375af32e75SAxel Dörfler 			return B_BAD_VALUE;
3385af32e75SAxel Dörfler 		}
3395af32e75SAxel Dörfler 
3405af32e75SAxel Dörfler 		bytesRead = blockSize - (pos % blockSize);
3415af32e75SAxel Dörfler 		if (length < bytesRead)
3425af32e75SAxel Dörfler 			bytesRead = length;
3435af32e75SAxel Dörfler 
3445af32e75SAxel Dörfler 		memcpy(buffer, block + (pos % blockSize), bytesRead);
3455af32e75SAxel Dörfler 		pos += bytesRead;
3465af32e75SAxel Dörfler 
3475af32e75SAxel Dörfler 		length -= bytesRead;
3485af32e75SAxel Dörfler 		if (length == 0) {
3495af32e75SAxel Dörfler 			*_length = bytesRead;
3505af32e75SAxel Dörfler 			return B_OK;
3515af32e75SAxel Dörfler 		}
3525af32e75SAxel Dörfler 
3535af32e75SAxel Dörfler 		if (FindBlockRun(pos, run, offset) < B_OK) {
3545af32e75SAxel Dörfler 			*_length = bytesRead;
3555af32e75SAxel Dörfler 			return B_BAD_VALUE;
3565af32e75SAxel Dörfler 		}
3575af32e75SAxel Dörfler 	}
3585af32e75SAxel Dörfler 
3595af32e75SAxel Dörfler 	// the first block_run is already filled in at this point
3605af32e75SAxel Dörfler 	// read the following complete blocks using cached_read(),
3615af32e75SAxel Dörfler 	// the last partial block is read using the generic Cache class
3625af32e75SAxel Dörfler 
3635af32e75SAxel Dörfler 	bool partial = false;
3645af32e75SAxel Dörfler 
3655af32e75SAxel Dörfler 	while (length > 0) {
3665af32e75SAxel Dörfler 		// offset is the offset to the current pos in the block_run
367e190cae1SAxel Dörfler 		run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start()
368e190cae1SAxel Dörfler 			+ ((pos - offset) >> blockShift));
369e190cae1SAxel Dörfler 		run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length()
370e190cae1SAxel Dörfler 			- ((pos - offset) >> blockShift));
3715af32e75SAxel Dörfler 
3725af32e75SAxel Dörfler 		if (uint32(run.Length() << blockShift) > length) {
3735af32e75SAxel Dörfler 			if (length < blockSize) {
3745af32e75SAxel Dörfler 				CachedBlock cached(fVolume, run);
3755af32e75SAxel Dörfler 				if ((block = cached.Block()) == NULL) {
3765af32e75SAxel Dörfler 					*_length = bytesRead;
3775af32e75SAxel Dörfler 					return B_BAD_VALUE;
3785af32e75SAxel Dörfler 				}
3795af32e75SAxel Dörfler 				memcpy(buffer + bytesRead, block, length);
3805af32e75SAxel Dörfler 				bytesRead += length;
3815af32e75SAxel Dörfler 				break;
3825af32e75SAxel Dörfler 			}
3835af32e75SAxel Dörfler 			run.length = HOST_ENDIAN_TO_BFS_INT16(length >> blockShift);
3845af32e75SAxel Dörfler 			partial = true;
3855af32e75SAxel Dörfler 		}
3865af32e75SAxel Dörfler 
387e190cae1SAxel Dörfler 		if (read_pos(fVolume.Device(), fVolume.ToOffset(run), buffer + bytesRead,
388e190cae1SAxel Dörfler 				run.Length() << fVolume.BlockShift()) < B_OK) {
3895af32e75SAxel Dörfler 			*_length = bytesRead;
3905af32e75SAxel Dörfler 			return B_BAD_VALUE;
3915af32e75SAxel Dörfler 		}
3925af32e75SAxel Dörfler 
3935af32e75SAxel Dörfler 		int32 bytes = run.Length() << blockShift;
3945af32e75SAxel Dörfler 		length -= bytes;
3955af32e75SAxel Dörfler 		bytesRead += bytes;
3965af32e75SAxel Dörfler 		if (length == 0)
3975af32e75SAxel Dörfler 			break;
3985af32e75SAxel Dörfler 
3995af32e75SAxel Dörfler 		pos += bytes;
4005af32e75SAxel Dörfler 
4015af32e75SAxel Dörfler 		if (partial) {
4025af32e75SAxel Dörfler 			// if the last block was read only partially, point block_run
4035af32e75SAxel Dörfler 			// to the remaining part
4045af32e75SAxel Dörfler 			run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + run.Length());
4055af32e75SAxel Dörfler 			run.length = 1;
4065af32e75SAxel Dörfler 			offset = pos;
4075af32e75SAxel Dörfler 		} else if (FindBlockRun(pos, run, offset) < B_OK) {
4085af32e75SAxel Dörfler 			*_length = bytesRead;
4095af32e75SAxel Dörfler 			return B_BAD_VALUE;
4105af32e75SAxel Dörfler 		}
4115af32e75SAxel Dörfler 	}
4125af32e75SAxel Dörfler 
4135af32e75SAxel Dörfler 	*_length = bytesRead;
4145af32e75SAxel Dörfler 	return B_NO_ERROR;
4155af32e75SAxel Dörfler }
4165af32e75SAxel Dörfler 
4175af32e75SAxel Dörfler 
4185af32e75SAxel Dörfler Node*
NodeFactory(Volume & volume,off_t id)4190dc4d1e5SIngo Weinhold Stream::NodeFactory(Volume& volume, off_t id)
4205af32e75SAxel Dörfler {
4215af32e75SAxel Dörfler 	Stream stream(volume, id);
4225af32e75SAxel Dörfler 	if (stream.InitCheck() != B_OK)
4235af32e75SAxel Dörfler 		return NULL;
4245af32e75SAxel Dörfler 
4255af32e75SAxel Dörfler 	if (stream.IsContainer())
4260dc4d1e5SIngo Weinhold 		return new(nothrow) Directory(stream);
4275af32e75SAxel Dörfler 
4285af32e75SAxel Dörfler 	if (stream.IsSymlink())
42982029bdaSMarcus Overhagen 		return new(nothrow) Link(stream);
4305af32e75SAxel Dörfler 
43182029bdaSMarcus Overhagen 	return new(nothrow) File(stream);
4325af32e75SAxel Dörfler }
4335af32e75SAxel Dörfler 
4345af32e75SAxel Dörfler 
4355af32e75SAxel Dörfler //	#pragma mark -
4365af32e75SAxel Dörfler 
4375af32e75SAxel Dörfler 
4385af32e75SAxel Dörfler status_t
InitCheck(Volume * volume) const439e190cae1SAxel Dörfler bfs_inode::InitCheck(Volume* volume) const
4405af32e75SAxel Dörfler {
441e190cae1SAxel Dörfler 	if ((Flags() & INODE_NOT_READY) != 0) {
4425af32e75SAxel Dörfler 		// the other fields may not yet contain valid values
4435af32e75SAxel Dörfler 		return B_BUSY;
4445af32e75SAxel Dörfler 	}
4455af32e75SAxel Dörfler 
4465af32e75SAxel Dörfler 	if (Magic1() != INODE_MAGIC1
4475af32e75SAxel Dörfler 		|| !(Flags() & INODE_IN_USE)
4485af32e75SAxel Dörfler 		|| inode_num.Length() != 1
4495af32e75SAxel Dörfler 		// matches inode size?
4505af32e75SAxel Dörfler 		|| (uint32)InodeSize() != volume->InodeSize()
4515af32e75SAxel Dörfler 		// parent resides on disk?
4525af32e75SAxel Dörfler 		|| parent.AllocationGroup() > int32(volume->AllocationGroups())
4535af32e75SAxel Dörfler 		|| parent.AllocationGroup() < 0
4545af32e75SAxel Dörfler 		|| parent.Start() > (1L << volume->AllocationGroupShift())
4555af32e75SAxel Dörfler 		|| parent.Length() != 1
4565af32e75SAxel Dörfler 		// attributes, too?
4575af32e75SAxel Dörfler 		|| attributes.AllocationGroup() > int32(volume->AllocationGroups())
4585af32e75SAxel Dörfler 		|| attributes.AllocationGroup() < 0
4595af32e75SAxel Dörfler 		|| attributes.Start() > (1L << volume->AllocationGroupShift()))
4605af32e75SAxel Dörfler 		return B_BAD_DATA;
4615af32e75SAxel Dörfler 
462e190cae1SAxel Dörfler 	// TODO: Add some tests to check the integrity of the other stuff here,
4635af32e75SAxel Dörfler 	// especially for the data_stream!
4645af32e75SAxel Dörfler 
4655af32e75SAxel Dörfler 	return B_OK;
4665af32e75SAxel Dörfler }
467