* 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:
Michael Lotz 2010-02-28 07:50:28 +00:00
parent 4f3f1911cd
commit af15ee68f1
5 changed files with 318 additions and 148 deletions

View File

@ -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++;

View File

@ -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)
{ {

View File

@ -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)

View File

@ -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

View File

@ -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