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