15af32e75SAxel Dörfler /* Stream - inode stream access functions 25af32e75SAxel Dörfler ** 35af32e75SAxel Dörfler ** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 45af32e75SAxel Dörfler ** Distributed under the terms of the OpenBeOS License. 55af32e75SAxel Dörfler */ 65af32e75SAxel Dörfler 75af32e75SAxel Dörfler 85af32e75SAxel Dörfler #include "Stream.h" 95af32e75SAxel Dörfler #include "Directory.h" 105af32e75SAxel Dörfler #include "File.h" 115af32e75SAxel Dörfler #include "Link.h" 125af32e75SAxel Dörfler 135af32e75SAxel Dörfler #include <util/kernel_cpp.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; 215af32e75SAxel Dörfler 225af32e75SAxel Dörfler 235af32e75SAxel Dörfler class CachedBlock { 245af32e75SAxel Dörfler public: 255af32e75SAxel Dörfler CachedBlock(Volume &volume); 265af32e75SAxel Dörfler CachedBlock(Volume &volume, block_run run); 275af32e75SAxel Dörfler ~CachedBlock(); 285af32e75SAxel Dörfler 295af32e75SAxel Dörfler uint8 *SetTo(block_run run); 305af32e75SAxel Dörfler uint8 *SetTo(off_t offset); 315af32e75SAxel Dörfler 325af32e75SAxel Dörfler void Unset(); 335af32e75SAxel Dörfler 345af32e75SAxel Dörfler uint8 *Block() const { return fBlock; } 355af32e75SAxel Dörfler off_t BlockNumber() const { return fBlockNumber; } 365af32e75SAxel Dörfler uint32 BlockSize() const { return fVolume.BlockSize(); } 375af32e75SAxel Dörfler uint32 BlockShift() const { return fVolume.BlockShift(); } 385af32e75SAxel Dörfler 395af32e75SAxel Dörfler private: 405af32e75SAxel Dörfler Volume &fVolume; 415af32e75SAxel Dörfler off_t fBlockNumber; 425af32e75SAxel Dörfler uint8 *fBlock; 435af32e75SAxel Dörfler }; 445af32e75SAxel Dörfler 455af32e75SAxel Dörfler 465af32e75SAxel Dörfler CachedBlock::CachedBlock(Volume &volume) 475af32e75SAxel Dörfler : 485af32e75SAxel Dörfler fVolume(volume), 495af32e75SAxel Dörfler fBlockNumber(-1LL), 505af32e75SAxel Dörfler fBlock(NULL) 515af32e75SAxel Dörfler { 525af32e75SAxel Dörfler } 535af32e75SAxel Dörfler 545af32e75SAxel Dörfler 555af32e75SAxel Dörfler CachedBlock::CachedBlock(Volume &volume, block_run run) 565af32e75SAxel Dörfler : 575af32e75SAxel Dörfler fVolume(volume), 585af32e75SAxel Dörfler fBlockNumber(-1LL), 595af32e75SAxel Dörfler fBlock(NULL) 605af32e75SAxel Dörfler { 615af32e75SAxel Dörfler SetTo(run); 625af32e75SAxel Dörfler } 635af32e75SAxel Dörfler 645af32e75SAxel Dörfler 655af32e75SAxel Dörfler CachedBlock::~CachedBlock() 665af32e75SAxel Dörfler { 675af32e75SAxel Dörfler free(fBlock); 685af32e75SAxel Dörfler } 695af32e75SAxel Dörfler 705af32e75SAxel Dörfler 715af32e75SAxel Dörfler inline void 725af32e75SAxel Dörfler CachedBlock::Unset() 735af32e75SAxel Dörfler { 745af32e75SAxel Dörfler fBlockNumber = -1; 755af32e75SAxel Dörfler } 765af32e75SAxel Dörfler 775af32e75SAxel Dörfler 785af32e75SAxel Dörfler inline uint8 * 795af32e75SAxel Dörfler CachedBlock::SetTo(off_t block) 805af32e75SAxel Dörfler { 815af32e75SAxel Dörfler if (block == fBlockNumber) 825af32e75SAxel Dörfler return fBlock; 835af32e75SAxel Dörfler if (fBlock == NULL) { 845af32e75SAxel Dörfler fBlock = (uint8 *)malloc(BlockSize()); 855af32e75SAxel Dörfler if (fBlock == NULL) 865af32e75SAxel Dörfler return NULL; 875af32e75SAxel Dörfler } 885af32e75SAxel Dörfler 895af32e75SAxel Dörfler fBlockNumber = block; 905af32e75SAxel Dörfler if (read_pos(fVolume.Device(), block << BlockShift(), fBlock, BlockSize()) < (ssize_t)BlockSize()) 915af32e75SAxel Dörfler return NULL; 925af32e75SAxel Dörfler 935af32e75SAxel Dörfler return fBlock; 945af32e75SAxel Dörfler } 955af32e75SAxel Dörfler 965af32e75SAxel Dörfler 975af32e75SAxel Dörfler inline uint8 * 985af32e75SAxel Dörfler CachedBlock::SetTo(block_run run) 995af32e75SAxel Dörfler { 1005af32e75SAxel Dörfler return SetTo(fVolume.ToBlock(run)); 1015af32e75SAxel Dörfler } 1025af32e75SAxel Dörfler 1035af32e75SAxel Dörfler 1045af32e75SAxel Dörfler // #pragma mark - 1055af32e75SAxel Dörfler 1065af32e75SAxel Dörfler 1075af32e75SAxel Dörfler Stream::Stream(Volume &volume, block_run run) 1085af32e75SAxel Dörfler : 1090dc4d1e5SIngo Weinhold fVolume(volume) 1105af32e75SAxel Dörfler { 1110dc4d1e5SIngo Weinhold if (read_pos(volume.Device(), volume.ToOffset(run), this, sizeof(bfs_inode)) != sizeof(bfs_inode)) 1120dc4d1e5SIngo Weinhold return; 1135af32e75SAxel Dörfler } 1145af32e75SAxel Dörfler 1155af32e75SAxel Dörfler 1165af32e75SAxel Dörfler Stream::Stream(Volume &volume, off_t id) 1175af32e75SAxel Dörfler : 1180dc4d1e5SIngo Weinhold fVolume(volume) 1195af32e75SAxel Dörfler { 1200dc4d1e5SIngo Weinhold if (read_pos(volume.Device(), volume.ToOffset(id), this, sizeof(bfs_inode)) != sizeof(bfs_inode)) 1210dc4d1e5SIngo Weinhold return; 1225af32e75SAxel Dörfler } 1235af32e75SAxel Dörfler 1245af32e75SAxel Dörfler 1255af32e75SAxel Dörfler Stream::~Stream() 1265af32e75SAxel Dörfler { 1275af32e75SAxel Dörfler } 1285af32e75SAxel Dörfler 1295af32e75SAxel Dörfler 1305af32e75SAxel Dörfler status_t 1315af32e75SAxel Dörfler Stream::InitCheck() 1325af32e75SAxel Dörfler { 1330dc4d1e5SIngo Weinhold return bfs_inode::InitCheck(&fVolume); 1345af32e75SAxel Dörfler } 1355af32e75SAxel Dörfler 1365af32e75SAxel Dörfler 1375af32e75SAxel Dörfler status_t 1385af32e75SAxel Dörfler Stream::GetNextSmallData(const small_data **_smallData) const 1395af32e75SAxel Dörfler { 140*9618c0dcSIngo Weinhold // TODO: Stream derives from bfs_inode and we read only sizeof(bfs_inode) 141*9618c0dcSIngo Weinhold // bytes from disk, i.e. the small data region is not in memory. 142*9618c0dcSIngo Weinhold panic("Stream::GetNextSmallData(): small data region is not loaded!"); 143*9618c0dcSIngo Weinhold 1445af32e75SAxel Dörfler const small_data *smallData = *_smallData; 1455af32e75SAxel Dörfler 1465af32e75SAxel Dörfler // begin from the start? 1475af32e75SAxel Dörfler if (smallData == NULL) 1480dc4d1e5SIngo Weinhold smallData = small_data_start; 1495af32e75SAxel Dörfler else 1505af32e75SAxel Dörfler smallData = smallData->Next(); 1515af32e75SAxel Dörfler 1525af32e75SAxel Dörfler // is already last item? 1530dc4d1e5SIngo Weinhold if (smallData->IsLast(this)) 1545af32e75SAxel Dörfler return B_ENTRY_NOT_FOUND; 1555af32e75SAxel Dörfler 1565af32e75SAxel Dörfler *_smallData = smallData; 1575af32e75SAxel Dörfler 1585af32e75SAxel Dörfler return B_OK; 1595af32e75SAxel Dörfler } 1605af32e75SAxel Dörfler 1615af32e75SAxel Dörfler 1625af32e75SAxel Dörfler status_t 1635af32e75SAxel Dörfler Stream::GetName(char *name, size_t size) const 1645af32e75SAxel Dörfler { 1655af32e75SAxel Dörfler const small_data *smallData = NULL; 1665af32e75SAxel Dörfler while (GetNextSmallData(&smallData) == B_OK) { 1675af32e75SAxel Dörfler if (*smallData->Name() == FILE_NAME_NAME 1685af32e75SAxel Dörfler && smallData->NameSize() == FILE_NAME_NAME_LENGTH) { 1695af32e75SAxel Dörfler strlcpy(name, (const char *)smallData->Data(), size); 1705af32e75SAxel Dörfler return B_OK; 1715af32e75SAxel Dörfler } 1725af32e75SAxel Dörfler } 1735af32e75SAxel Dörfler return B_ERROR; 1745af32e75SAxel Dörfler } 1755af32e75SAxel Dörfler 1765af32e75SAxel Dörfler 1775af32e75SAxel Dörfler status_t 1785af32e75SAxel Dörfler Stream::ReadLink(char *buffer, size_t bufferSize) 1795af32e75SAxel Dörfler { 1805af32e75SAxel Dörfler // link in the stream 1815af32e75SAxel Dörfler 1820dc4d1e5SIngo Weinhold if (Flags() & INODE_LONG_SYMLINK) 1835af32e75SAxel Dörfler return ReadAt(0, (uint8 *)buffer, &bufferSize); 1845af32e75SAxel Dörfler 1855af32e75SAxel Dörfler // link in the inode 1865af32e75SAxel Dörfler 1870dc4d1e5SIngo Weinhold strlcpy(buffer, short_symlink, bufferSize); 1885af32e75SAxel Dörfler return B_OK; 1895af32e75SAxel Dörfler } 1905af32e75SAxel Dörfler 1915af32e75SAxel Dörfler 1925af32e75SAxel Dörfler status_t 1935af32e75SAxel Dörfler Stream::FindBlockRun(off_t pos, block_run &run, off_t &offset) 1945af32e75SAxel Dörfler { 1955af32e75SAxel Dörfler // find matching block run 1965af32e75SAxel Dörfler 1970dc4d1e5SIngo Weinhold if (data.MaxDirectRange() > 0 && pos >= data.MaxDirectRange()) { 1980dc4d1e5SIngo Weinhold if (data.MaxDoubleIndirectRange() > 0 && pos >= data.MaxIndirectRange()) { 1995af32e75SAxel Dörfler // access to double indirect blocks 2005af32e75SAxel Dörfler 2015af32e75SAxel Dörfler CachedBlock cached(fVolume); 2025af32e75SAxel Dörfler 2030dc4d1e5SIngo Weinhold off_t start = pos - data.MaxIndirectRange(); 2040dc4d1e5SIngo Weinhold int32 indirectSize = (1L << (INDIRECT_BLOCKS_SHIFT + cached.BlockShift())) 2055af32e75SAxel Dörfler * (fVolume.BlockSize() / sizeof(block_run)); 2065af32e75SAxel Dörfler int32 directSize = NUM_ARRAY_BLOCKS << cached.BlockShift(); 2075af32e75SAxel Dörfler int32 index = start / indirectSize; 2085af32e75SAxel Dörfler int32 runsPerBlock = cached.BlockSize() / sizeof(block_run); 2095af32e75SAxel Dörfler 2105af32e75SAxel Dörfler block_run *indirect = (block_run *)cached.SetTo( 2110dc4d1e5SIngo Weinhold fVolume.ToBlock(data.double_indirect) + index / runsPerBlock); 2125af32e75SAxel Dörfler if (indirect == NULL) 2135af32e75SAxel Dörfler return B_ERROR; 2145af32e75SAxel Dörfler 2155af32e75SAxel Dörfler //printf("\tstart = %Ld, indirectSize = %ld, directSize = %ld, index = %ld\n",start,indirectSize,directSize,index); 2165af32e75SAxel Dörfler //printf("\tlook for indirect block at %ld,%d\n",indirect[index].allocation_group,indirect[index].start); 2175af32e75SAxel Dörfler 2185af32e75SAxel Dörfler int32 current = (start % indirectSize) / directSize; 2195af32e75SAxel Dörfler 2205af32e75SAxel Dörfler indirect = (block_run *)cached.SetTo( 2215af32e75SAxel Dörfler fVolume.ToBlock(indirect[index % runsPerBlock]) + current / runsPerBlock); 2225af32e75SAxel Dörfler if (indirect == NULL) 2235af32e75SAxel Dörfler return B_ERROR; 2245af32e75SAxel Dörfler 2255af32e75SAxel Dörfler run = indirect[current % runsPerBlock]; 2260dc4d1e5SIngo Weinhold offset = data.MaxIndirectRange() + (index * indirectSize) + (current * directSize); 2275af32e75SAxel Dörfler //printf("\tfCurrent = %ld, fRunFileOffset = %Ld, fRunBlockEnd = %Ld, fRun = %ld,%d\n",fCurrent,fRunFileOffset,fRunBlockEnd,fRun.allocation_group,fRun.start); 2285af32e75SAxel Dörfler } else { 2295af32e75SAxel Dörfler // access to indirect blocks 2305af32e75SAxel Dörfler 2315af32e75SAxel Dörfler int32 runsPerBlock = fVolume.BlockSize() / sizeof(block_run); 2320dc4d1e5SIngo Weinhold off_t runBlockEnd = data.MaxDirectRange(); 2335af32e75SAxel Dörfler 2345af32e75SAxel Dörfler CachedBlock cached(fVolume); 2350dc4d1e5SIngo Weinhold off_t block = fVolume.ToBlock(data.indirect); 2365af32e75SAxel Dörfler 2370dc4d1e5SIngo Weinhold for (int32 i = 0;i < data.indirect.Length();i++) { 2385af32e75SAxel Dörfler block_run *indirect = (block_run *)cached.SetTo(block + i); 2395af32e75SAxel Dörfler if (indirect == NULL) 2405af32e75SAxel Dörfler return B_IO_ERROR; 2415af32e75SAxel Dörfler 2425af32e75SAxel Dörfler int32 current = -1; 2435af32e75SAxel Dörfler while (++current < runsPerBlock) { 2445af32e75SAxel Dörfler if (indirect[current].IsZero()) 2455af32e75SAxel Dörfler break; 2465af32e75SAxel Dörfler 2475af32e75SAxel Dörfler runBlockEnd += indirect[current].Length() << cached.BlockShift(); 2485af32e75SAxel Dörfler if (runBlockEnd > pos) { 2495af32e75SAxel Dörfler run = indirect[current]; 2505af32e75SAxel Dörfler offset = runBlockEnd - (run.Length() << cached.BlockShift()); 2515af32e75SAxel Dörfler //printf("reading from indirect block: %ld,%d\n",fRun.allocation_group,fRun.start); 2525af32e75SAxel Dörfler //printf("### indirect-run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset); 2535af32e75SAxel Dörfler return fVolume.ValidateBlockRun(run); 2545af32e75SAxel Dörfler } 2555af32e75SAxel Dörfler } 2565af32e75SAxel Dörfler } 2575af32e75SAxel Dörfler return B_ERROR; 2585af32e75SAxel Dörfler } 2595af32e75SAxel Dörfler } else { 2605af32e75SAxel Dörfler // access from direct blocks 2615af32e75SAxel Dörfler 2625af32e75SAxel Dörfler off_t runBlockEnd = 0LL; 2635af32e75SAxel Dörfler int32 current = -1; 2645af32e75SAxel Dörfler 2655af32e75SAxel Dörfler while (++current < NUM_DIRECT_BLOCKS) { 2660dc4d1e5SIngo Weinhold if (data.direct[current].IsZero()) 2675af32e75SAxel Dörfler break; 2685af32e75SAxel Dörfler 2690dc4d1e5SIngo Weinhold runBlockEnd += data.direct[current].Length() << fVolume.BlockShift(); 2705af32e75SAxel Dörfler if (runBlockEnd > pos) { 2710dc4d1e5SIngo Weinhold run = data.direct[current]; 2725af32e75SAxel Dörfler offset = runBlockEnd - (run.Length() << fVolume.BlockShift()); 2735af32e75SAxel Dörfler //printf("### run[%ld] = (%ld,%d,%d), offset = %Ld\n",fCurrent,fRun.allocation_group,fRun.start,fRun.length,fRunFileOffset); 2745af32e75SAxel Dörfler return fVolume.ValidateBlockRun(run); 2755af32e75SAxel Dörfler } 2765af32e75SAxel Dörfler } 2775af32e75SAxel Dörfler //PRINT(("FindBlockRun() failed in direct range: size = %Ld, pos = %Ld\n",data.size,pos)); 2785af32e75SAxel Dörfler return B_ENTRY_NOT_FOUND; 2795af32e75SAxel Dörfler } 2805af32e75SAxel Dörfler return fVolume.ValidateBlockRun(run); 2815af32e75SAxel Dörfler } 2825af32e75SAxel Dörfler 2835af32e75SAxel Dörfler 2845af32e75SAxel Dörfler status_t 2855af32e75SAxel Dörfler Stream::ReadAt(off_t pos, uint8 *buffer, size_t *_length) 2865af32e75SAxel Dörfler { 2875af32e75SAxel Dörfler // set/check boundaries for pos/length 2885af32e75SAxel Dörfler 2895af32e75SAxel Dörfler if (pos < 0) 2905af32e75SAxel Dörfler return B_BAD_VALUE; 2910dc4d1e5SIngo Weinhold if (pos >= data.Size()) { 2925af32e75SAxel Dörfler *_length = 0; 2935af32e75SAxel Dörfler return B_NO_ERROR; 2945af32e75SAxel Dörfler } 2955af32e75SAxel Dörfler 2965af32e75SAxel Dörfler size_t length = *_length; 2975af32e75SAxel Dörfler 2980dc4d1e5SIngo Weinhold if (pos + length > data.Size()) 2990dc4d1e5SIngo Weinhold length = data.Size() - pos; 3005af32e75SAxel Dörfler 3015af32e75SAxel Dörfler block_run run; 3025af32e75SAxel Dörfler off_t offset; 3035af32e75SAxel Dörfler if (FindBlockRun(pos, run, offset) < B_OK) { 3045af32e75SAxel Dörfler *_length = 0; 3055af32e75SAxel Dörfler return B_BAD_VALUE; 3065af32e75SAxel Dörfler } 3075af32e75SAxel Dörfler 3085af32e75SAxel Dörfler uint32 bytesRead = 0; 3095af32e75SAxel Dörfler uint32 blockSize = fVolume.BlockSize(); 3105af32e75SAxel Dörfler uint32 blockShift = fVolume.BlockShift(); 3115af32e75SAxel Dörfler uint8 *block; 3125af32e75SAxel Dörfler 3135af32e75SAxel Dörfler // the first block_run we read could not be aligned to the block_size boundary 3145af32e75SAxel Dörfler // (read partial block at the beginning) 3155af32e75SAxel Dörfler 3165af32e75SAxel Dörfler // pos % block_size == (pos - offset) % block_size, offset % block_size == 0 3175af32e75SAxel Dörfler if (pos % blockSize != 0) { 3185af32e75SAxel Dörfler run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift)); 3195af32e75SAxel Dörfler run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift)); 3205af32e75SAxel Dörfler 3215af32e75SAxel Dörfler CachedBlock cached(fVolume, run); 3225af32e75SAxel Dörfler if ((block = cached.Block()) == NULL) { 3235af32e75SAxel Dörfler *_length = 0; 3245af32e75SAxel Dörfler return B_BAD_VALUE; 3255af32e75SAxel Dörfler } 3265af32e75SAxel Dörfler 3275af32e75SAxel Dörfler bytesRead = blockSize - (pos % blockSize); 3285af32e75SAxel Dörfler if (length < bytesRead) 3295af32e75SAxel Dörfler bytesRead = length; 3305af32e75SAxel Dörfler 3315af32e75SAxel Dörfler memcpy(buffer, block + (pos % blockSize), bytesRead); 3325af32e75SAxel Dörfler pos += bytesRead; 3335af32e75SAxel Dörfler 3345af32e75SAxel Dörfler length -= bytesRead; 3355af32e75SAxel Dörfler if (length == 0) { 3365af32e75SAxel Dörfler *_length = bytesRead; 3375af32e75SAxel Dörfler return B_OK; 3385af32e75SAxel Dörfler } 3395af32e75SAxel Dörfler 3405af32e75SAxel Dörfler if (FindBlockRun(pos, run, offset) < B_OK) { 3415af32e75SAxel Dörfler *_length = bytesRead; 3425af32e75SAxel Dörfler return B_BAD_VALUE; 3435af32e75SAxel Dörfler } 3445af32e75SAxel Dörfler } 3455af32e75SAxel Dörfler 3465af32e75SAxel Dörfler // the first block_run is already filled in at this point 3475af32e75SAxel Dörfler // read the following complete blocks using cached_read(), 3485af32e75SAxel Dörfler // the last partial block is read using the generic Cache class 3495af32e75SAxel Dörfler 3505af32e75SAxel Dörfler bool partial = false; 3515af32e75SAxel Dörfler 3525af32e75SAxel Dörfler while (length > 0) { 3535af32e75SAxel Dörfler // offset is the offset to the current pos in the block_run 3545af32e75SAxel Dörfler run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + ((pos - offset) >> blockShift)); 3555af32e75SAxel Dörfler run.length = HOST_ENDIAN_TO_BFS_INT16(run.Length() - ((pos - offset) >> blockShift)); 3565af32e75SAxel Dörfler 3575af32e75SAxel Dörfler if (uint32(run.Length() << blockShift) > length) { 3585af32e75SAxel Dörfler if (length < blockSize) { 3595af32e75SAxel Dörfler CachedBlock cached(fVolume, run); 3605af32e75SAxel Dörfler if ((block = cached.Block()) == NULL) { 3615af32e75SAxel Dörfler *_length = bytesRead; 3625af32e75SAxel Dörfler return B_BAD_VALUE; 3635af32e75SAxel Dörfler } 3645af32e75SAxel Dörfler memcpy(buffer + bytesRead, block, length); 3655af32e75SAxel Dörfler bytesRead += length; 3665af32e75SAxel Dörfler break; 3675af32e75SAxel Dörfler } 3685af32e75SAxel Dörfler run.length = HOST_ENDIAN_TO_BFS_INT16(length >> blockShift); 3695af32e75SAxel Dörfler partial = true; 3705af32e75SAxel Dörfler } 3715af32e75SAxel Dörfler 3725af32e75SAxel Dörfler if (read_pos(fVolume.Device(), fVolume.ToOffset(run), buffer + bytesRead, run.Length() << fVolume.BlockShift()) < B_OK) { 3735af32e75SAxel Dörfler *_length = bytesRead; 3745af32e75SAxel Dörfler return B_BAD_VALUE; 3755af32e75SAxel Dörfler } 3765af32e75SAxel Dörfler 3775af32e75SAxel Dörfler int32 bytes = run.Length() << blockShift; 3785af32e75SAxel Dörfler length -= bytes; 3795af32e75SAxel Dörfler bytesRead += bytes; 3805af32e75SAxel Dörfler if (length == 0) 3815af32e75SAxel Dörfler break; 3825af32e75SAxel Dörfler 3835af32e75SAxel Dörfler pos += bytes; 3845af32e75SAxel Dörfler 3855af32e75SAxel Dörfler if (partial) { 3865af32e75SAxel Dörfler // if the last block was read only partially, point block_run 3875af32e75SAxel Dörfler // to the remaining part 3885af32e75SAxel Dörfler run.start = HOST_ENDIAN_TO_BFS_INT16(run.Start() + run.Length()); 3895af32e75SAxel Dörfler run.length = 1; 3905af32e75SAxel Dörfler offset = pos; 3915af32e75SAxel Dörfler } else if (FindBlockRun(pos, run, offset) < B_OK) { 3925af32e75SAxel Dörfler *_length = bytesRead; 3935af32e75SAxel Dörfler return B_BAD_VALUE; 3945af32e75SAxel Dörfler } 3955af32e75SAxel Dörfler } 3965af32e75SAxel Dörfler 3975af32e75SAxel Dörfler *_length = bytesRead; 3985af32e75SAxel Dörfler return B_NO_ERROR; 3995af32e75SAxel Dörfler } 4005af32e75SAxel Dörfler 4015af32e75SAxel Dörfler 4025af32e75SAxel Dörfler Node * 4030dc4d1e5SIngo Weinhold Stream::NodeFactory(Volume &volume, off_t id) 4045af32e75SAxel Dörfler { 4055af32e75SAxel Dörfler Stream stream(volume, id); 4065af32e75SAxel Dörfler if (stream.InitCheck() != B_OK) 4075af32e75SAxel Dörfler return NULL; 4085af32e75SAxel Dörfler 4095af32e75SAxel Dörfler if (stream.IsContainer()) 4100dc4d1e5SIngo Weinhold return new(nothrow) Directory(stream); 4115af32e75SAxel Dörfler 4125af32e75SAxel Dörfler if (stream.IsSymlink()) 41382029bdaSMarcus Overhagen return new(nothrow) Link(stream); 4145af32e75SAxel Dörfler 41582029bdaSMarcus Overhagen return new(nothrow) File(stream); 4165af32e75SAxel Dörfler } 4175af32e75SAxel Dörfler 4185af32e75SAxel Dörfler 4195af32e75SAxel Dörfler // #pragma mark - 4205af32e75SAxel Dörfler 4215af32e75SAxel Dörfler 4225af32e75SAxel Dörfler status_t 4235af32e75SAxel Dörfler bfs_inode::InitCheck(Volume *volume) 4245af32e75SAxel Dörfler { 4255af32e75SAxel Dörfler if (Flags() & INODE_NOT_READY) { 4265af32e75SAxel Dörfler // the other fields may not yet contain valid values 4275af32e75SAxel Dörfler return B_BUSY; 4285af32e75SAxel Dörfler } 4295af32e75SAxel Dörfler 4305af32e75SAxel Dörfler if (Magic1() != INODE_MAGIC1 4315af32e75SAxel Dörfler || !(Flags() & INODE_IN_USE) 4325af32e75SAxel Dörfler || inode_num.Length() != 1 4335af32e75SAxel Dörfler // matches inode size? 4345af32e75SAxel Dörfler || (uint32)InodeSize() != volume->InodeSize() 4355af32e75SAxel Dörfler // parent resides on disk? 4365af32e75SAxel Dörfler || parent.AllocationGroup() > int32(volume->AllocationGroups()) 4375af32e75SAxel Dörfler || parent.AllocationGroup() < 0 4385af32e75SAxel Dörfler || parent.Start() > (1L << volume->AllocationGroupShift()) 4395af32e75SAxel Dörfler || parent.Length() != 1 4405af32e75SAxel Dörfler // attributes, too? 4415af32e75SAxel Dörfler || attributes.AllocationGroup() > int32(volume->AllocationGroups()) 4425af32e75SAxel Dörfler || attributes.AllocationGroup() < 0 4435af32e75SAxel Dörfler || attributes.Start() > (1L << volume->AllocationGroupShift())) 4445af32e75SAxel Dörfler return B_BAD_DATA; 4455af32e75SAxel Dörfler 4465af32e75SAxel Dörfler // ToDo: Add some tests to check the integrity of the other stuff here, 4475af32e75SAxel Dörfler // especially for the data_stream! 4485af32e75SAxel Dörfler 4495af32e75SAxel Dörfler return B_OK; 4505af32e75SAxel Dörfler } 4515af32e75SAxel Dörfler 452