* Implement udf_io and udf_get_file_map.
* Add file map and cache and do reads through the file_cache for file ICBs. * Move the private _Read() backend from the header to the implementation file. * Read() is now only used for directory iteration. * Turned off the verbose debug output. * Minor cleanup. This fixes the abuse of the block_cache, should allow executables on UDF and won't panic on protected content. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35652 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4f3f1911cd
commit
af15ee68f1
@ -39,7 +39,7 @@ public:
|
|||||||
Accessor accessor = Accessor());
|
Accessor accessor = Accessor());
|
||||||
|
|
||||||
status_t FindExtent(off_t start, long_address *extent,
|
status_t FindExtent(off_t start, long_address *extent,
|
||||||
bool *isEmpty);
|
bool *isEmpty);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ AllocationDescriptorList<Accessor>::_MoveToNextDescriptor()
|
|||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
// Increment our indices and get the next descriptor
|
// Increment our indices and get the next descriptor
|
||||||
// from this extent.
|
// from this extent.
|
||||||
fBlockIndex += fAccessor.GetLength(*descriptor);
|
fBlockIndex += fAccessor.GetLength(*descriptor);
|
||||||
fDescriptorIndex++;
|
fDescriptorIndex++;
|
||||||
fDescriptorNumber++;
|
fDescriptorNumber++;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// This software is part of the Haiku distribution and is covered
|
// This software is part of the Haiku distribution and is covered
|
||||||
// by the MIT license.
|
// by the MIT license.
|
||||||
//
|
//
|
||||||
// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
|
// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
|
||||||
@ -12,10 +12,12 @@
|
|||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
#include <file_cache.h>
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DirectoryIterator::GetNextEntry(char *name, uint32 *length, ino_t *id)
|
DirectoryIterator::GetNextEntry(char *name, uint32 *length, ino_t *id)
|
||||||
{
|
{
|
||||||
if (!id || !name || !length)
|
if (!id || !name || !length)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
@ -103,7 +105,9 @@ Icb::Icb(Volume *volume, long_address address)
|
|||||||
fInitStatus(B_NO_INIT),
|
fInitStatus(B_NO_INIT),
|
||||||
fId(to_vnode_id(address)),
|
fId(to_vnode_id(address)),
|
||||||
fFileEntry(&fData),
|
fFileEntry(&fData),
|
||||||
fExtendedEntry(&fData)
|
fExtendedEntry(&fData),
|
||||||
|
fFileCache(NULL),
|
||||||
|
fFileMap(NULL)
|
||||||
{
|
{
|
||||||
TRACE(("Icb::Icb: volume = %p, address(block = %ld, partition = %d, "
|
TRACE(("Icb::Icb: volume = %p, address(block = %ld, partition = %d, "
|
||||||
"length = %ld)\n", volume, address.block(), address.partition(),
|
"length = %ld)\n", volume, address.block(), address.partition(),
|
||||||
@ -130,11 +134,25 @@ Icb::Icb(Volume *volume, long_address address)
|
|||||||
status = header->tag().init_check(address.block());
|
status = header->tag().init_check(address.block());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsFile()) {
|
||||||
|
fFileCache = file_cache_create(fVolume->ID(), fId, Length());
|
||||||
|
fFileMap = file_map_create(fVolume->ID(), fId, Length());
|
||||||
|
}
|
||||||
|
|
||||||
fInitStatus = status;
|
fInitStatus = status;
|
||||||
TRACE(("Icb::Icb: status = 0x%lx, `%s'\n", status, strerror(status)));
|
TRACE(("Icb::Icb: status = 0x%lx, `%s'\n", status, strerror(status)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Icb::~Icb()
|
||||||
|
{
|
||||||
|
if (fFileCache != NULL) {
|
||||||
|
file_cache_delete(fFileCache);
|
||||||
|
file_map_delete(fFileMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Icb::GetDirectoryIterator(DirectoryIterator **iterator)
|
Icb::GetDirectoryIterator(DirectoryIterator **iterator)
|
||||||
{
|
{
|
||||||
@ -187,6 +205,9 @@ Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fFileCache != NULL)
|
||||||
|
return file_cache_read(fFileCache, NULL, pos, buffer, length);
|
||||||
|
|
||||||
switch (_IcbTag().descriptor_flags()) {
|
switch (_IcbTag().descriptor_flags()) {
|
||||||
case ICB_DESCRIPTOR_TYPE_SHORT: {
|
case ICB_DESCRIPTOR_TYPE_SHORT: {
|
||||||
TRACE(("Icb::Read: descriptor type -> short\n"));
|
TRACE(("Icb::Read: descriptor type -> short\n"));
|
||||||
@ -194,7 +215,7 @@ Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block)
|
|||||||
RETURN(_Read(list, pos, buffer, length, block));
|
RETURN(_Read(list, pos, buffer, length, block));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ICB_DESCRIPTOR_TYPE_LONG: {
|
case ICB_DESCRIPTOR_TYPE_LONG: {
|
||||||
TRACE(("Icb::Read: descriptor type -> long\n"));
|
TRACE(("Icb::Read: descriptor type -> long\n"));
|
||||||
AllocationDescriptorList<LongDescriptorAccessor> list(this);
|
AllocationDescriptorList<LongDescriptorAccessor> list(this);
|
||||||
@ -220,11 +241,204 @@ Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block)
|
|||||||
TRACE(("Icb::Read: invalid icb descriptor flags! (flags = %d)\n",
|
TRACE(("Icb::Read: invalid icb descriptor flags! (flags = %d)\n",
|
||||||
_IcbTag().descriptor_flags()));
|
_IcbTag().descriptor_flags()));
|
||||||
RETURN(B_BAD_VALUE);
|
RETURN(B_BAD_VALUE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Does the dirty work of reading using the given DescriptorList object
|
||||||
|
to access the allocation descriptors properly.
|
||||||
|
*/
|
||||||
|
template <class DescriptorList>
|
||||||
|
status_t
|
||||||
|
Icb::_Read(DescriptorList &list, off_t pos, void *_buffer, size_t *length, uint32 *block)
|
||||||
|
{
|
||||||
|
TRACE(("Icb::_Read(): list = %p, pos = %Ld, buffer = %p, length = %ld\n",
|
||||||
|
&list, pos, _buffer, (length ? *length : 0)));
|
||||||
|
|
||||||
|
uint64 bytesLeftInFile = uint64(pos) > Length() ? 0 : Length() - pos;
|
||||||
|
size_t bytesLeft = (*length >= bytesLeftInFile) ? bytesLeftInFile : *length;
|
||||||
|
size_t bytesRead = 0;
|
||||||
|
|
||||||
|
Volume *volume = GetVolume();
|
||||||
|
status_t status = B_OK;
|
||||||
|
uint8 *buffer = (uint8 *)_buffer;
|
||||||
|
bool isFirstBlock = true;
|
||||||
|
|
||||||
|
while (bytesLeft > 0) {
|
||||||
|
|
||||||
|
TRACE(("Icb::_Read(): pos: %Ld, bytesLeft: %ld\n", pos, bytesLeft));
|
||||||
|
long_address extent;
|
||||||
|
bool isEmpty = false;
|
||||||
|
status = list.FindExtent(pos, &extent, &isEmpty);
|
||||||
|
if (status != B_OK) {
|
||||||
|
TRACE_ERROR(("Icb::_Read: error finding extent for offset %Ld. "
|
||||||
|
"status = 0x%lx `%s'\n", pos, status, strerror(status)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE(("Icb::_Read(): found extent for offset %Ld: (block: %ld, "
|
||||||
|
"partition: %d, length: %ld, type: %d)\n", pos, extent.block(),
|
||||||
|
extent.partition(), extent.length(), extent.type()));
|
||||||
|
|
||||||
|
switch (extent.type()) {
|
||||||
|
case EXTENT_TYPE_RECORDED:
|
||||||
|
isEmpty = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXTENT_TYPE_ALLOCATED:
|
||||||
|
case EXTENT_TYPE_UNALLOCATED:
|
||||||
|
isEmpty = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
TRACE_ERROR(("Icb::_Read(): Invalid extent type found: %d\n",
|
||||||
|
extent.type()));
|
||||||
|
status = B_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != B_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Note the unmapped first block of the total read in
|
||||||
|
// the block output parameter if provided
|
||||||
|
if (isFirstBlock) {
|
||||||
|
isFirstBlock = false;
|
||||||
|
if (block)
|
||||||
|
*block = extent.block();
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t blockOffset
|
||||||
|
= pos - off_t((pos >> volume->BlockShift()) << volume->BlockShift());
|
||||||
|
|
||||||
|
size_t readLength = volume->BlockSize() - blockOffset;
|
||||||
|
if (bytesLeft < readLength)
|
||||||
|
readLength = bytesLeft;
|
||||||
|
if (extent.length() < readLength)
|
||||||
|
readLength = extent.length();
|
||||||
|
|
||||||
|
TRACE(("Icb::_Read: reading block. offset = %Ld, length: %ld\n",
|
||||||
|
blockOffset, readLength));
|
||||||
|
|
||||||
|
if (isEmpty) {
|
||||||
|
TRACE(("Icb::_Read: reading %ld empty bytes as zeros\n",
|
||||||
|
readLength));
|
||||||
|
memset(buffer, 0, readLength);
|
||||||
|
} else {
|
||||||
|
off_t diskBlock;
|
||||||
|
status = volume->MapBlock(extent, &diskBlock);
|
||||||
|
if (status != B_OK) {
|
||||||
|
TRACE_ERROR(("Icb::_Read: could not map extent\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE(("Icb::_Read: %ld bytes from disk block %Ld using "
|
||||||
|
"block_cache_get_etc()\n", readLength, diskBlock));
|
||||||
|
uint8 *data = (uint8*)block_cache_get_etc(volume->BlockCache(),
|
||||||
|
diskBlock, 0, readLength);
|
||||||
|
if (data == NULL)
|
||||||
|
break;
|
||||||
|
memcpy(buffer, data + blockOffset, readLength);
|
||||||
|
block_cache_put(volume->BlockCache(), diskBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesLeft -= readLength;
|
||||||
|
bytesRead += readLength;
|
||||||
|
pos += readLength;
|
||||||
|
buffer += readLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
*length = bytesRead;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Icb::GetFileMap(off_t offset, size_t size, file_io_vec *vecs, size_t *count)
|
||||||
|
{
|
||||||
|
switch (_IcbTag().descriptor_flags()) {
|
||||||
|
case ICB_DESCRIPTOR_TYPE_SHORT:
|
||||||
|
{
|
||||||
|
AllocationDescriptorList<ShortDescriptorAccessor> list(this,
|
||||||
|
ShortDescriptorAccessor(0));
|
||||||
|
return _GetFileMap(list, offset, size, vecs, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
case ICB_DESCRIPTOR_TYPE_LONG:
|
||||||
|
{
|
||||||
|
AllocationDescriptorList<LongDescriptorAccessor> list(this);
|
||||||
|
return _GetFileMap(list, offset, size, vecs, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
case ICB_DESCRIPTOR_TYPE_EXTENDED:
|
||||||
|
case ICB_DESCRIPTOR_TYPE_EMBEDDED:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// TODO: implement?
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class DescriptorList>
|
||||||
|
status_t
|
||||||
|
Icb::_GetFileMap(DescriptorList &list, off_t offset, size_t size,
|
||||||
|
struct file_io_vec *vecs, size_t *count)
|
||||||
|
{
|
||||||
|
size_t index = 0;
|
||||||
|
size_t max = *count;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
long_address extent;
|
||||||
|
bool isEmpty = false;
|
||||||
|
status_t status = list.FindExtent(offset, &extent, &isEmpty);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
switch (extent.type()) {
|
||||||
|
case EXTENT_TYPE_RECORDED:
|
||||||
|
isEmpty = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXTENT_TYPE_ALLOCATED:
|
||||||
|
case EXTENT_TYPE_UNALLOCATED:
|
||||||
|
isEmpty = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmpty)
|
||||||
|
vecs[index].offset = -1;
|
||||||
|
else {
|
||||||
|
off_t diskBlock;
|
||||||
|
fVolume->MapBlock(extent, &diskBlock);
|
||||||
|
vecs[index].offset = diskBlock << fVolume->BlockShift();
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t length = extent.length();
|
||||||
|
vecs[index].length = length;
|
||||||
|
|
||||||
|
offset += length;
|
||||||
|
size -= length;
|
||||||
|
index++;
|
||||||
|
|
||||||
|
if (index >= max || size <= vecs[index - 1].length
|
||||||
|
|| offset >= (off_t)Length()) {
|
||||||
|
*count = index;
|
||||||
|
return index >= max ? B_BUFFER_OVERFLOW : B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// can never get here
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Icb::Find(const char *filename, ino_t *id)
|
Icb::Find(const char *filename, ino_t *id)
|
||||||
{
|
{
|
||||||
|
@ -79,6 +79,8 @@ friend class Icb;
|
|||||||
class Icb {
|
class Icb {
|
||||||
public:
|
public:
|
||||||
Icb(Volume *volume, long_address address);
|
Icb(Volume *volume, long_address address);
|
||||||
|
~Icb();
|
||||||
|
|
||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
ino_t Id() { return fId; }
|
ino_t Id() { return fId; }
|
||||||
|
|
||||||
@ -105,6 +107,12 @@ public:
|
|||||||
status_t Read(off_t pos, void *buffer, size_t *length,
|
status_t Read(off_t pos, void *buffer, size_t *length,
|
||||||
uint32 *block = NULL);
|
uint32 *block = NULL);
|
||||||
|
|
||||||
|
void * FileCache() { return fFileCache; }
|
||||||
|
void * FileMap() { return fFileMap; }
|
||||||
|
|
||||||
|
status_t GetFileMap(off_t offset, size_t size,
|
||||||
|
struct file_io_vec *vecs, size_t *count);
|
||||||
|
|
||||||
// for directories only
|
// for directories only
|
||||||
status_t GetDirectoryIterator(DirectoryIterator **iterator);
|
status_t GetDirectoryIterator(DirectoryIterator **iterator);
|
||||||
status_t Find(const char *filename, ino_t *id);
|
status_t Find(const char *filename, ino_t *id);
|
||||||
@ -114,7 +122,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
AbstractFileEntry *_AbstractEntry() { return (_Tag().id()
|
AbstractFileEntry *_AbstractEntry() { return (_Tag().id()
|
||||||
== TAGID_EXTENDED_FILE_ENTRY)
|
== TAGID_EXTENDED_FILE_ENTRY)
|
||||||
? (AbstractFileEntry *)&fExtendedEntry
|
? (AbstractFileEntry *)&fExtendedEntry
|
||||||
: (AbstractFileEntry *)&fFileEntry; }
|
: (AbstractFileEntry *)&fFileEntry; }
|
||||||
|
|
||||||
descriptor_tag &_Tag() { return ((icb_header *)fData.Block())->tag(); }
|
descriptor_tag &_Tag() { return ((icb_header *)fData.Block())->tag(); }
|
||||||
@ -122,130 +130,26 @@ private:
|
|||||||
file_icb_entry *_FileEntry() { return (file_icb_entry *)fData.Block(); }
|
file_icb_entry *_FileEntry() { return (file_icb_entry *)fData.Block(); }
|
||||||
extended_file_icb_entry &_ExtendedEntry() { return *(extended_file_icb_entry *)fData.Block(); }
|
extended_file_icb_entry &_ExtendedEntry() { return *(extended_file_icb_entry *)fData.Block(); }
|
||||||
|
|
||||||
template <class DescriptorList>
|
template<class DescriptorList>
|
||||||
|
status_t _GetFileMap(DescriptorList &list, off_t offset,
|
||||||
|
size_t size, struct file_io_vec *vecs,
|
||||||
|
size_t *count);
|
||||||
|
template<class DescriptorList>
|
||||||
status_t _Read(DescriptorList &list, off_t pos,
|
status_t _Read(DescriptorList &list, off_t pos,
|
||||||
void *buffer, size_t *length, uint32 *block);
|
void *buffer, size_t *length, uint32 *block);
|
||||||
|
|
||||||
private:
|
|
||||||
Volume *fVolume;
|
Volume *fVolume;
|
||||||
CachedBlock fData;
|
CachedBlock fData;
|
||||||
status_t fInitStatus;
|
status_t fInitStatus;
|
||||||
ino_t fId;
|
ino_t fId;
|
||||||
SinglyLinkedList<DirectoryIterator> fIteratorList;
|
SinglyLinkedList<DirectoryIterator> fIteratorList;
|
||||||
FileEntry<file_icb_entry> fFileEntry;
|
FileEntry<file_icb_entry> fFileEntry;
|
||||||
FileEntry<extended_file_icb_entry> fExtendedEntry;
|
FileEntry<extended_file_icb_entry> fExtendedEntry;
|
||||||
|
void * fFileCache;
|
||||||
|
void * fFileMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Does the dirty work of reading using the given DescriptorList object
|
|
||||||
to access the allocation descriptors properly.
|
|
||||||
*/
|
|
||||||
template <class DescriptorList>
|
|
||||||
status_t
|
|
||||||
Icb::_Read(DescriptorList &list, off_t pos, void *_buffer, size_t *length, uint32 *block)
|
|
||||||
{
|
|
||||||
TRACE(("Icb::_Read(): list = %p, pos = %Ld, buffer = %p, length = %ld\n",
|
|
||||||
&list, pos, _buffer, (length ? *length : 0)));
|
|
||||||
|
|
||||||
uint64 bytesLeftInFile = uint64(pos) > Length() ? 0 : Length() - pos;
|
|
||||||
size_t bytesLeft = (*length >= bytesLeftInFile) ? bytesLeftInFile : *length;
|
|
||||||
size_t bytesRead = 0;
|
|
||||||
|
|
||||||
Volume *volume = GetVolume();
|
|
||||||
status_t status = B_OK;
|
|
||||||
uint8 *buffer = (uint8 *)_buffer;
|
|
||||||
bool isFirstBlock = true;
|
|
||||||
|
|
||||||
while (bytesLeft > 0) {
|
|
||||||
|
|
||||||
TRACE(("Icb::_Read(): pos: %Ld, bytesLeft: %ld\n", pos, bytesLeft));
|
|
||||||
long_address extent;
|
|
||||||
bool isEmpty = false;
|
|
||||||
status = list.FindExtent(pos, &extent, &isEmpty);
|
|
||||||
if (status != B_OK) {
|
|
||||||
TRACE_ERROR(("Icb::_Read: error finding extent for offset %Ld. "
|
|
||||||
"status = 0x%lx `%s'\n", pos, status, strerror(status)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE(("Icb::_Read(): found extent for offset %Ld: (block: %ld, "
|
|
||||||
"partition: %d, length: %ld, type: %d)\n", pos, extent.block(),
|
|
||||||
extent.partition(), extent.length(), extent.type()));
|
|
||||||
|
|
||||||
switch (extent.type()) {
|
|
||||||
case EXTENT_TYPE_RECORDED:
|
|
||||||
isEmpty = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EXTENT_TYPE_ALLOCATED:
|
|
||||||
case EXTENT_TYPE_UNALLOCATED:
|
|
||||||
isEmpty = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
TRACE_ERROR(("Icb::_Read(): Invalid extent type found: %d\n",
|
|
||||||
extent.type()));
|
|
||||||
status = B_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != B_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Note the unmapped first block of the total read in
|
|
||||||
// the block output parameter if provided
|
|
||||||
if (isFirstBlock) {
|
|
||||||
isFirstBlock = false;
|
|
||||||
if (block)
|
|
||||||
*block = extent.block();
|
|
||||||
}
|
|
||||||
|
|
||||||
off_t blockOffset
|
|
||||||
= pos - off_t((pos >> volume->BlockShift()) << volume->BlockShift());
|
|
||||||
|
|
||||||
size_t readLength = volume->BlockSize() - blockOffset;
|
|
||||||
if (bytesLeft < readLength)
|
|
||||||
readLength = bytesLeft;
|
|
||||||
if (extent.length() < readLength)
|
|
||||||
readLength = extent.length();
|
|
||||||
|
|
||||||
TRACE(("Icb::_Read: reading block. offset = %Ld, length: %ld\n",
|
|
||||||
blockOffset, readLength));
|
|
||||||
|
|
||||||
if (isEmpty) {
|
|
||||||
TRACE(("Icb::_Read: reading %ld empty bytes as zeros\n",
|
|
||||||
readLength));
|
|
||||||
memset(buffer, 0, readLength);
|
|
||||||
} else {
|
|
||||||
off_t diskBlock;
|
|
||||||
status = volume->MapBlock(extent, &diskBlock);
|
|
||||||
if (status != B_OK) {
|
|
||||||
TRACE_ERROR(("Icb::_Read: could not map extent\n"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE(("Icb::_Read: %ld bytes from disk block %Ld using "
|
|
||||||
"block_cache_get_etc()\n", readLength, diskBlock));
|
|
||||||
uint8 *data = (uint8*)block_cache_get_etc(volume->BlockCache(),
|
|
||||||
diskBlock, 0, readLength);
|
|
||||||
if (data == NULL)
|
|
||||||
break;
|
|
||||||
memcpy(buffer, data + blockOffset, readLength);
|
|
||||||
block_cache_put(volume->BlockCache(), diskBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesLeft -= readLength;
|
|
||||||
bytesRead += readLength;
|
|
||||||
pos += readLength;
|
|
||||||
buffer += readLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
*length = bytesRead;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class Descriptor>
|
template <class Descriptor>
|
||||||
FileEntry<Descriptor>::FileEntry(CachedBlock *descriptorBlock)
|
FileEntry<Descriptor>::FileEntry(CachedBlock *descriptorBlock)
|
||||||
: fDescriptorBlock(descriptorBlock)
|
: fDescriptorBlock(descriptorBlock)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// This software is part of the OpenBeOS distribution and is covered
|
// This software is part of the OpenBeOS distribution and is covered
|
||||||
// by the OpenBeOS license.
|
// by the OpenBeOS license.
|
||||||
//
|
//
|
||||||
// This version copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
|
// This version copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
|
||||||
@ -31,15 +31,15 @@
|
|||||||
# include <stdarg.h>
|
# include <stdarg.h>
|
||||||
extern "C" int vsprintf(char *s, const char *format, va_list arg);
|
extern "C" int vsprintf(char *s, const char *format, va_list arg);
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# define __out dbg_printf
|
# define __out dbg_printf
|
||||||
void dbg_printf(const char *format,...);
|
void dbg_printf(const char *format,...);
|
||||||
void initialize_debugger(const char *filename);
|
void initialize_debugger(const char *filename);
|
||||||
#else
|
#else
|
||||||
# if !_KERNEL_MODE
|
# if !_KERNEL_MODE
|
||||||
//# include <stdio.h>
|
//# include <stdio.h>
|
||||||
# define __out printf
|
# define __out printf
|
||||||
# else
|
# else
|
||||||
//# include <null.h>
|
//# include <null.h>
|
||||||
# define __out dprintf
|
# define __out dprintf
|
||||||
# endif
|
# endif
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
@ -64,10 +64,10 @@ class DebugHelper
|
|||||||
public:
|
public:
|
||||||
DebugHelper(const char *className = NULL, uint8 tabCount = 1);
|
DebugHelper(const char *className = NULL, uint8 tabCount = 1);
|
||||||
~DebugHelper();
|
~DebugHelper();
|
||||||
|
|
||||||
uint8 TabCount() const { return fTabCount; }
|
uint8 TabCount() const { return fTabCount; }
|
||||||
const char* ClassName() const { return fClassName; }
|
const char* ClassName() const { return fClassName; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8 fTabCount;
|
uint8 fTabCount;
|
||||||
char *fClassName;
|
char *fClassName;
|
||||||
@ -98,14 +98,14 @@ private:
|
|||||||
#else
|
#else
|
||||||
#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
|
#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEBUG_INIT_SILENT(className) \
|
#define DEBUG_INIT_SILENT(className) \
|
||||||
DebugHelper _debugHelper(className, 2);
|
DebugHelper _debugHelper(className, 2);
|
||||||
|
|
||||||
#define DEBUG_INIT(className) \
|
#define DEBUG_INIT(className) \
|
||||||
DEBUG_INIT_SILENT(className); \
|
DEBUG_INIT_SILENT(className); \
|
||||||
PRINT(("\n"));
|
PRINT(("\n"));
|
||||||
|
|
||||||
#define DEBUG_INIT_ETC(className, arguments) \
|
#define DEBUG_INIT_ETC(className, arguments) \
|
||||||
DEBUG_INIT_SILENT(className) \
|
DEBUG_INIT_SILENT(className) \
|
||||||
{ \
|
{ \
|
||||||
@ -119,10 +119,10 @@ private:
|
|||||||
__out arguments; \
|
__out arguments; \
|
||||||
__out("):\n"); \
|
__out("):\n"); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DUMP_INIT(className) \
|
#define DUMP_INIT(className) \
|
||||||
DEBUG_INIT_SILENT(className);
|
DEBUG_INIT_SILENT(className);
|
||||||
|
|
||||||
#define PRINT(x) { \
|
#define PRINT(x) { \
|
||||||
{ \
|
{ \
|
||||||
PRINT_INDENT(); \
|
PRINT_INDENT(); \
|
||||||
@ -164,21 +164,21 @@ private:
|
|||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PRINT_DIVIDER() \
|
#define PRINT_DIVIDER() \
|
||||||
PRINT_INDENT(); \
|
PRINT_INDENT(); \
|
||||||
SIMPLE_PRINT(("------------------------------------------------------------\n"));
|
SIMPLE_PRINT(("------------------------------------------------------------\n"));
|
||||||
|
|
||||||
#define DUMP(object) \
|
#define DUMP(object) \
|
||||||
{ \
|
{ \
|
||||||
(object).dump(); \
|
(object).dump(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PDUMP(objectPointer) \
|
#define PDUMP(objectPointer) \
|
||||||
{ \
|
{ \
|
||||||
(objectPointer)->dump(); \
|
(objectPointer)->dump(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define REPORT_ERROR(error) { \
|
#define REPORT_ERROR(error) { \
|
||||||
LPRINT(("returning error 0x%lx, `%s'\n", error, strerror(error))); \
|
LPRINT(("returning error 0x%lx, `%s'\n", error, strerror(error))); \
|
||||||
}
|
}
|
||||||
@ -205,9 +205,9 @@ private:
|
|||||||
#define FATAL(x) { \
|
#define FATAL(x) { \
|
||||||
PRINT(("fatal error: ")); SIMPLE_PRINT(x); \
|
PRINT(("fatal error: ")); SIMPLE_PRINT(x); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DBG(x) x ;
|
#define DBG(x) x ;
|
||||||
|
|
||||||
#else // ifdef DEBUG
|
#else // ifdef DEBUG
|
||||||
#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
|
#define INITIALIZE_DEBUGGING_OUTPUT_FILE(filename) ;
|
||||||
#define DEBUG_INIT_SILENT(className) ;
|
#define DEBUG_INIT_SILENT(className) ;
|
||||||
@ -228,7 +228,7 @@ private:
|
|||||||
#define DBG(x) ;
|
#define DBG(x) ;
|
||||||
#endif // ifdef DEBUG else
|
#endif // ifdef DEBUG else
|
||||||
|
|
||||||
#define TRACE(x) dprintf x
|
#define TRACE(x) /*dprintf x*/
|
||||||
#define TRACE_ERROR(x) dprintf x
|
#define TRACE_ERROR(x) dprintf x
|
||||||
|
|
||||||
// These macros turn on or off extensive and generally unnecessary
|
// These macros turn on or off extensive and generally unnecessary
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <util/kernel_cpp.h>
|
#include <util/kernel_cpp.h>
|
||||||
|
|
||||||
|
#include <io_requests.h>
|
||||||
|
|
||||||
#include "Icb.h"
|
#include "Icb.h"
|
||||||
#include "Recognition.h"
|
#include "Recognition.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
@ -37,6 +39,28 @@ extern fs_volume_ops gUDFVolumeOps;
|
|||||||
extern fs_vnode_ops gUDFVnodeOps;
|
extern fs_vnode_ops gUDFVnodeOps;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - io callbacks
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
iterative_io_get_vecs_hook(void *cookie, io_request *request, off_t offset,
|
||||||
|
size_t size, struct file_io_vec *vecs, size_t *count)
|
||||||
|
{
|
||||||
|
Icb *icb = (Icb *)cookie;
|
||||||
|
return file_map_translate(icb->FileMap(), offset, size, vecs, count,
|
||||||
|
icb->GetVolume()->BlockSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
iterative_io_finished_hook(void *cookie, io_request *request, status_t status,
|
||||||
|
bool partialTransfer, size_t bytesTransferred)
|
||||||
|
{
|
||||||
|
// nothing to do
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - fs_volume_ops fuctions
|
// #pragma mark - fs_volume_ops fuctions
|
||||||
|
|
||||||
|
|
||||||
@ -266,7 +290,7 @@ udf_close(fs_volume* _volume, fs_vnode* _node, void* _cookie)
|
|||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
udf_free_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie)
|
udf_free_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie)
|
||||||
{
|
{
|
||||||
TRACE(("udf_free_cookie: _volume = %p, _node = %p\n", _volume, _node));
|
TRACE(("udf_free_cookie: _volume = %p, _node = %p\n", _volume, _node));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@ -274,7 +298,7 @@ udf_free_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie)
|
|||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
udf_access(fs_volume* _volume, fs_vnode* _node, int accessMode)
|
udf_access(fs_volume* _volume, fs_vnode* _node, int accessMode)
|
||||||
{
|
{
|
||||||
TRACE(("udf_access: _volume = %p, _node = %p\n", _volume, _node));
|
TRACE(("udf_access: _volume = %p, _node = %p\n", _volume, _node));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@ -298,6 +322,34 @@ udf_read(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
udf_io(fs_volume *volume, fs_vnode *vnode, void *cookie, io_request *request)
|
||||||
|
{
|
||||||
|
if (io_request_is_write(request)) {
|
||||||
|
notify_io_request(request, B_READ_ONLY_DEVICE);
|
||||||
|
return B_READ_ONLY_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Icb *icb = (Icb *)vnode->private_node;
|
||||||
|
if (icb->FileCache() == NULL) {
|
||||||
|
notify_io_request(request, B_BAD_VALUE);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_iterative_fd_io(((Volume *)volume->private_volume)->Device(),
|
||||||
|
request, iterative_io_get_vecs_hook, iterative_io_finished_hook, icb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
udf_get_file_map(fs_volume *_volume, fs_vnode *vnode, off_t offset, size_t size,
|
||||||
|
struct file_io_vec *vecs, size_t *count)
|
||||||
|
{
|
||||||
|
Icb *icb = (Icb *)vnode->private_node;
|
||||||
|
return icb->GetFileMap(offset, size, vecs, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
udf_open_dir(fs_volume *volume, fs_vnode *vnode, void **cookie)
|
udf_open_dir(fs_volume *volume, fs_vnode *vnode, void **cookie)
|
||||||
{
|
{
|
||||||
@ -568,11 +620,11 @@ fs_vnode_ops gUDFVnodeOps = {
|
|||||||
NULL, // write_pages
|
NULL, // write_pages
|
||||||
|
|
||||||
/* asynchronous I/O */
|
/* asynchronous I/O */
|
||||||
NULL, // io()
|
&udf_io,
|
||||||
NULL, // cancel_io()
|
NULL, // cancel_io()
|
||||||
|
|
||||||
/* cache file access */
|
/* cache file access */
|
||||||
NULL, // &udf_get_file_map,
|
&udf_get_file_map,
|
||||||
|
|
||||||
/* common operations */
|
/* common operations */
|
||||||
NULL, // ioctl
|
NULL, // ioctl
|
||||||
|
Loading…
Reference in New Issue
Block a user