diff --git a/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.cpp b/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.cpp index 272be1ad8e..da326e2796 100644 --- a/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.cpp +++ b/src/add-ons/kernel/file_systems/ufs2/DirectoryIterator.cpp @@ -10,7 +10,7 @@ #include "Inode.h" -//#define TRACE_UFS2 +#define TRACE_UFS2 #ifdef TRACE_UFS2 # define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x) #else @@ -24,8 +24,7 @@ DirectoryIterator::DirectoryIterator(Inode* inode) : fInode(inode) { - fOffset = fInode->GetBlockPointer() * MINBSIZE; - TRACE("DirectoryIterator::DirectoryIterator() \n"); + fOffset = 0; } @@ -67,32 +66,30 @@ status_t DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id) { dir direct; - int fd = fInode->GetVolume()->Device(); + size_t size = sizeof(dir); + status_t status = fInode->ReadAt(fOffset, (uint8_t*)&direct, &size); + if (status == B_OK) { + int remainder = direct.namlen % 4; + if(remainder != 0) { + remainder = 4 - remainder; + remainder = direct.namlen + remainder; + } else { + remainder = direct.namlen + 4; + } + + fOffset = fOffset + 8 + remainder; + + if (direct.next_ino > 0) { + strlcpy(name, direct.name, direct.namlen + 1); + *_id = direct.next_ino; + *_nameLength = direct.namlen; + return B_OK; + } + + return B_ENTRY_NOT_FOUND; - if (read_pos(fd, fOffset, &direct, sizeof(dir)) != sizeof(dir)) { - return B_BAD_DATA; } - int remainder = direct.namlen % 4; - if(remainder != 0) { - remainder = 4 - remainder; - remainder = direct.namlen + remainder; - } else { - remainder = direct.namlen + 4; - } - - fOffset = fOffset + 8 + remainder; - - if (direct.next_ino > 0) { - TRACE("direct.next_ino %d\n",direct.next_ino); - - strlcpy(name, direct.name, remainder); - *_id = direct.next_ino; - *_nameLength = direct.namlen; - return B_OK; - } - - return B_ENTRY_NOT_FOUND; - + return B_ERROR; } diff --git a/src/add-ons/kernel/file_systems/ufs2/Inode.cpp b/src/add-ons/kernel/file_systems/ufs2/Inode.cpp index 455e753d62..9ed6198d73 100644 --- a/src/add-ons/kernel/file_systems/ufs2/Inode.cpp +++ b/src/add-ons/kernel/file_systems/ufs2/Inode.cpp @@ -5,8 +5,11 @@ */ #include "Inode.h" +#include -#ifdef TRACE_ufs2 + +#define TRACE_UFS2 +#ifdef TRACE_UFS2 #define TRACE(x...) dprintf("\33[34mufs2:\33[0m " x) #else #define TRACE(x...) ; @@ -34,7 +37,7 @@ Inode::Inode(Volume* volume, ino_t id) ufs2_super_block* superblock = (ufs2_super_block* )&fVolume->SuperBlock(); int64_t fs_block = ino_to_fsba(superblock, id); int64_t offset_in_block = ino_to_fsbo(superblock, id); - int64_t offset = fs_block * MINBSIZE + offset_in_block * 256; + int64_t offset = fs_block * MINBSIZE + offset_in_block * sizeof(fNode); if (read_pos(fd, offset, (void*)&fNode, sizeof(fNode)) != sizeof(fNode)) ERROR("Inode::Inode(): IO Error\n"); @@ -85,3 +88,130 @@ Inode::InitCheck() { return fInitStatus; } + + +status_t +Inode::ReadAt(off_t file_offset, uint8* buffer, size_t* _length) +{ + int fd = fVolume->Device(); + ufs2_super_block super_block = fVolume->SuperBlock(); + int32_t blockSize = super_block.fs_bsize; + off_t pos; + int64_t size = Size(); + off_t startBlockNumber = file_offset / blockSize; + off_t endBlockNumber = (file_offset + *_length) / blockSize; + off_t blockOffset = file_offset % blockSize; + ssize_t length = 0; + if (startBlockNumber != endBlockNumber) { + ssize_t remainingLength = blockSize - blockOffset; + for (; startBlockNumber <= endBlockNumber; startBlockNumber++) { + //code for reading multiple blocks + pos = FindBlock(startBlockNumber, blockOffset); + length += read_pos(fd, pos, buffer, remainingLength); + blockOffset = 0; + remainingLength = *_length - length; + if (remainingLength > blockSize) + remainingLength = blockSize; + } + *_length = length; + return B_OK; + } + pos = FindBlock(startBlockNumber, blockOffset); + length = read_pos(fd, pos, buffer, *_length); + *_length = length; + return B_OK; + +} + + +off_t +Inode::FindBlock(off_t blockNumber, off_t blockOffset) +{ + int fd = fVolume->Device(); + ufs2_super_block super_block = fVolume->SuperBlock(); + int32_t blockSize = super_block.fs_bsize; + int32_t fragmentSize = super_block.fs_fsize; + off_t indirectOffset; + int64_t directBlock; + off_t numberOfBlockPointers = blockSize / 8; + const off_t numberOfIndirectBlocks = numberOfBlockPointers; + const off_t numberOfDoubleIndirectBlocks = numberOfBlockPointers + * numberOfBlockPointers; + if (blockNumber < 12) { + // read from direct block + return GetBlockPointer(blockNumber) * fragmentSize + blockOffset; + + } else if (blockNumber < numberOfIndirectBlocks + 12) { + //read from indirect block + blockNumber = blockNumber - 12; + indirectOffset = GetIndirectBlockPointer() * + fragmentSize + (8 * blockNumber); + read_pos(fd, indirectOffset, + (void*)&directBlock, sizeof(directBlock)); + + return directBlock * fragmentSize + blockOffset; + + } else if (blockNumber < numberOfDoubleIndirectBlocks + + numberOfIndirectBlocks + 12) { + // Data is in double indirect block + // Subract the already read blocks + blockNumber = blockNumber - numberOfBlockPointers - 12; + // Calculate indirect block inside double indirect block + off_t indirectBlockNumber = blockNumber / numberOfBlockPointers; + indirectOffset = GetDoubleIndirectBlockPtr() * + fragmentSize + (8 * indirectBlockNumber); + + int64_t indirectPointer; + read_pos(fd, indirectOffset, + (void*)&indirectPointer, sizeof(directBlock)); + + indirectOffset = indirectPointer * fragmentSize + + (8 * (blockNumber % numberOfBlockPointers)); + + read_pos(fd, indirectOffset, + (void*)&directBlock, sizeof(directBlock)); + + return directBlock * fragmentSize + blockOffset; + + } else if (blockNumber < (numberOfIndirectBlocks + * numberOfDoubleIndirectBlocks) + + (numberOfDoubleIndirectBlocks + numberOfBlockPointers + 12)) { + // Reading from triple indirect block + blockNumber = blockNumber - numberOfDoubleIndirectBlocks + - numberOfBlockPointers - 12; + + // Get double indirect block + // Double indirect block no + off_t indirectBlockNumber = blockNumber / numberOfDoubleIndirectBlocks; + + // offset to double indirect block ptr + indirectOffset = GetTripleIndirectBlockPtr() * + fragmentSize + (8 * indirectBlockNumber); + + int64_t indirectPointer; + // Get the double indirect block ptr + read_pos(fd, indirectOffset, + (void*)&indirectPointer, sizeof(directBlock)); + + // Get the indirect block + // number of indirect block ptr + indirectBlockNumber = blockNumber / numberOfBlockPointers; + // Indirect block ptr offset + indirectOffset = indirectPointer * fragmentSize + + (8 * indirectBlockNumber); + + read_pos(fd, indirectOffset, + (void*)&indirectPointer, sizeof(directBlock)); + + // Get direct block pointer + indirectOffset = indirectPointer * fragmentSize + + (8 * (blockNumber % numberOfBlockPointers)); + + read_pos(fd, indirectOffset, + (void*)&directBlock, sizeof(directBlock)); + + return directBlock * fragmentSize + blockOffset; + } + + return B_BAD_VALUE; +} diff --git a/src/add-ons/kernel/file_systems/ufs2/Inode.h b/src/add-ons/kernel/file_systems/ufs2/Inode.h index f76cd1a0f5..eedd031814 100644 --- a/src/add-ons/kernel/file_systems/ufs2/Inode.h +++ b/src/add-ons/kernel/file_systems/ufs2/Inode.h @@ -44,18 +44,7 @@ struct ufs2_inode { int64_t extendedBklPtr1; int64_t extendedBklPtr2; /* 12 direct block pointers */ - int64_t directBlkPtr1; - int64_t directBlkPtr2; - int64_t directBlkPtr3; - int64_t directBlkPtr4; - int64_t directBlkPtr5; - int64_t directBlkPtr6; - int64_t directBlkPtr7; - int64_t directBlkPtr8; - int64_t directBlkPtr9; - int64_t directBlkPtr10; - int64_t directBlkPtr11; - int64_t directBlkPtr12; + int64_t directBlkPtr[12]; int64_t indirectBlkPtr; /* 1 Indirect block pointer */ int64_t doubleIndriectBlkPtr; // 1 Double Indirect block pointer int64_t tripleIndriectBlkPtr; // 1 Triple Indirect block pointer @@ -118,12 +107,22 @@ class Inode { Volume* GetVolume() const { return fVolume; } - int64_t GetBlockPointer() { return fNode.directBlkPtr1; } + int64_t GetBlockPointer(int ptrNumber) + { return fNode.directBlkPtr[ptrNumber]; } + + int64_t GetIndirectBlockPointer() + { return fNode.indirectBlkPtr; } + + int64_t GetDoubleIndirectBlockPtr() + { return fNode.doubleIndriectBlkPtr; } + + int64_t GetTripleIndirectBlockPtr() + { return fNode.tripleIndriectBlkPtr; } + ino_t Parent(); -// status_t FindBlock(off_t logical, off_t& physical, -// off_t* _length = NULL); -// status_t ReadAt(off_t pos, uint8* buffer, size_t* length); + off_t FindBlock(off_t block_number, off_t block_offset); + status_t ReadAt(off_t pos, uint8* buffer, size_t* length); // status_t FillGapWithZeros(off_t start, off_t end); void* FileCache() const { return fCache; } diff --git a/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp index c97855353f..fb71f73394 100644 --- a/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp @@ -3,7 +3,6 @@ * All rights reserved. Distributed under the terms of the MIT License. */ - #include "DirectoryIterator.h" #include "Inode.h" #include "system_dependencies.h" @@ -26,6 +25,7 @@ struct identify_cookie }; +#if 0 //! ufs2_io() callback hook static status_t iterative_io_get_vecs_hook(void *cookie, io_request *request, off_t offset, @@ -42,6 +42,7 @@ iterative_io_finished_hook(void *cookie, io_request *request, status_t status, { return B_NOT_SUPPORTED; } +#endif // #pragma mark - Scanning @@ -196,7 +197,6 @@ static status_t ufs2_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name, ino_t *_vnodeID) { - TRACE("UFS2_LOOKUP: %p (%s)\n", name, name); Volume* volume = (Volume*)_volume->private_volume; Inode* directory = (Inode*)_directory->private_node; @@ -207,7 +207,6 @@ ufs2_lookup(fs_volume *_volume, fs_vnode *_directory, const char *name, return status; status = get_vnode(volume->FSVolume(), *_vnodeID, NULL); - TRACE("get_vnode status: %s\n", strerror(status)); return status; } @@ -223,11 +222,9 @@ ufs2_ioctl(fs_volume *_volume, fs_vnode *_node, void *_cookie, uint32 cmd, static status_t ufs2_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat) { - TRACE("Reading stat...\n"); Inode* inode = (Inode*)_node->private_node; stat->st_dev = inode->GetVolume()->ID(); stat->st_ino = inode->ID(); - TRACE("stat->st_ino %ld\n",stat->st_ino); // TODO handle hardlinks which will have nlink > 1. Maybe linkCount in inode // structure may help? stat->st_nlink = 1; @@ -251,10 +248,27 @@ ufs2_read_stat(fs_volume *_volume, fs_vnode *_node, struct stat *stat) static status_t -ufs2_open(fs_volume * /*_volume*/, fs_vnode *_node, int openMode, +ufs2_open(fs_volume * _volume, fs_vnode *_node, int openMode, void **_cookie) { - return B_NOT_SUPPORTED; + //Volume* volume = (Volume*)_volume->private_volume; + Inode* inode = (Inode*)_node->private_node; + TRACE("in open %d \n", openMode); + if (inode->IsDirectory()) + return B_IS_A_DIRECTORY; + + file_cookie* cookie = new(std::nothrow) file_cookie; + if (cookie == NULL) + return B_NO_MEMORY; + ObjectDeleter cookieDeleter(cookie); + + cookie->last_size = inode->Size(); + cookie->last_notification = system_time(); + +// fileCacheEnabler.Detach(); + cookieDeleter.Detach(); + *_cookie = cookie; + return B_OK; } @@ -262,7 +276,14 @@ static status_t ufs2_read(fs_volume *_volume, fs_vnode *_node, void *_cookie, off_t pos, void *buffer, size_t *_length) { - return B_NOT_SUPPORTED; + Inode* inode = (Inode*)_node->private_node; + + if (!inode->IsFile()) { + *_length = 0; + return inode->IsDirectory() ? B_IS_A_DIRECTORY : B_BAD_VALUE; + } + + return inode->ReadAt(pos, (uint8*)buffer, _length); } @@ -340,14 +361,13 @@ static status_t ufs2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) { - TRACE("read dir \n"); DirectoryIterator* iterator = (DirectoryIterator*)_cookie; Volume* volume = (Volume*)_volume->private_volume; uint32 maxCount = *_num; uint32 count = 0; - while (count < maxCount and (bufferSize > sizeof(struct dirent))) { + while (count < maxCount && (bufferSize > sizeof(struct dirent))) { size_t length = bufferSize - sizeof(struct dirent) + 1; ino_t iNodeNo; @@ -371,7 +391,6 @@ ufs2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie, } *_num = count; - TRACE("count is %d\n", count); return B_OK; } diff --git a/src/add-ons/kernel/file_systems/ufs2/ufs2.h b/src/add-ons/kernel/file_systems/ufs2/ufs2.h index 00366f99b2..473b8befa6 100644 --- a/src/add-ons/kernel/file_systems/ufs2/ufs2.h +++ b/src/add-ons/kernel/file_systems/ufs2/ufs2.h @@ -359,6 +359,14 @@ struct ufs2_super_block { CTASSERT(sizeof(struct fs) == 1376); #endif + +struct file_cookie { + bigtime_t last_notification; + off_t last_size; + int open_mode; +}; + + /* * Filesystem identification */