* Copyright 2012, JΓ©rΓ΄me Duval, korli@users.berlios.de.
* Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com.
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
* Distributed under the terms of the MIT License.
*/
#ifndef _UDF_ICB_H
#define _UDF_ICB_H
#include "UdfStructures.h"
#include <util/kernel_cpp.h>
#include <util/SinglyLinkedList.h>
#include "CachedBlock.h"
class DirectoryIterator;
class Icb;
class Volume;
that are not commonly accessible through file_icb_entry().
This is necessary, since we can't use virtual functions in
the disk structure structs themselves, since we generally
don't create disk structure objects by calling new, but
rather just cast a chunk of memory read off disk to be
a pointer to the struct of interest (which works fine
for regular functions, but fails miserably for virtuals
due to the vtable not being setup properly).
*/
class AbstractFileEntry {
public:
virtual uint8* AllocationDescriptors() = 0;
virtual uint32 AllocationDescriptorsLength() = 0;
};
template <class Descriptor>
class FileEntry : public AbstractFileEntry {
public:
FileEntry(CachedBlock *descriptorBlock = NULL);
void SetTo(CachedBlock *descriptorBlock);
virtual uint8* AllocationDescriptors();
virtual uint32 AllocationDescriptorsLength();
private:
Descriptor *_Descriptor();
CachedBlock *fDescriptorBlock;
};
class DirectoryIterator : public SinglyLinkedListLinkImpl<DirectoryIterator> {
public:
status_t GetNextEntry(char *name, uint32 *length,
ino_t *id);
Icb *Parent() { return fParent; }
const Icb *Parent() const { return fParent; }
void Rewind();
private:
friend class Icb;
DirectoryIterator(Icb *parent);
void _Invalidate() { fParent = NULL; }
bool fAtBeginning;
Icb *fParent;
off_t fPosition;
};
class Icb {
public:
Icb(Volume *volume, long_address address);
~Icb();
status_t InitCheck();
ino_t Id() { return fId; }
uint8 Type() { return _IcbTag().file_type(); }
bool IsFile() { return Type() == ICB_TYPE_REGULAR_FILE; }
bool IsDirectory() { return (Type() == ICB_TYPE_DIRECTORY
|| Type() == ICB_TYPE_STREAM_DIRECTORY); }
uint32 Uid() { return _FileEntry()->uid(); }
uint32 Gid() { return 0; }
uint16 FileLinkCount() { return _FileEntry()->file_link_count(); }
uint64 Length() { return _FileEntry()->information_length(); }
mode_t Mode() { return (IsDirectory() ? S_IFDIR : S_IFREG)
| S_IRUSR | S_IRGRP | S_IROTH; }
void GetAccessTime(struct timespec ×pec) const;
void GetModificationTime(struct timespec ×pec) const;
uint8 *AllocationDescriptors()
{ return _AbstractEntry()->AllocationDescriptors(); }
uint32 AllocationDescriptorsSize()
{ return _AbstractEntry()->AllocationDescriptorsLength(); }
status_t FindBlock(uint32 logicalBlock, off_t &block,
bool &recorded);
status_t Read(off_t pos, void *buffer, size_t *length,
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);
status_t GetDirectoryIterator(DirectoryIterator **iterator);
status_t Find(const char *filename, ino_t *id);
Volume *GetVolume() const { return fVolume; }
private:
AbstractFileEntry *_AbstractEntry() const { return (_Tag().id()
== TAGID_EXTENDED_FILE_ENTRY)
? (AbstractFileEntry *)&fExtendedEntry
: (AbstractFileEntry *)&fFileEntry; }
descriptor_tag &_Tag() const { return ((icb_header *)fData.Block())->tag(); }
icb_entry_tag &_IcbTag() const { return ((icb_header *)fData.Block())->icb_tag(); }
file_icb_entry *_FileEntry() const
{ return (file_icb_entry *)fData.Block(); }
extended_file_icb_entry *_ExtendedEntry() const
{ return (extended_file_icb_entry *)fData.Block(); }
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,
void *buffer, size_t *length, uint32 *block);
Volume *fVolume;
CachedBlock fData;
status_t fInitStatus;
ino_t fId;
SinglyLinkedList<DirectoryIterator> fIteratorList;
uint16 fPartition;
FileEntry<file_icb_entry> fFileEntry;
FileEntry<extended_file_icb_entry> fExtendedEntry;
void * fFileCache;
void * fFileMap;
};
template <class Descriptor>
FileEntry<Descriptor>::FileEntry(CachedBlock *descriptorBlock)
: fDescriptorBlock(descriptorBlock)
{
}
template <class Descriptor>
void
FileEntry<Descriptor>::SetTo(CachedBlock *descriptorBlock)
{
fDescriptorBlock = descriptorBlock;
}
template <class Descriptor>
uint8*
FileEntry<Descriptor>::AllocationDescriptors()
{
Descriptor* descriptor = _Descriptor();
return descriptor ? descriptor->allocation_descriptors() : NULL;
}
template <class Descriptor>
uint32
FileEntry<Descriptor>::AllocationDescriptorsLength()
{
Descriptor* descriptor = _Descriptor();
return descriptor ? descriptor->allocation_descriptors_length() : 0;
}
template <class Descriptor>
Descriptor*
FileEntry<Descriptor>::_Descriptor()
{
return fDescriptorBlock
? (Descriptor *)fDescriptorBlock->Block() : NULL;
}
#endif