/* * 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 /*! \file Icb.h */ #include "UdfStructures.h" #include #include #include "CachedBlock.h" class DirectoryIterator; class Icb; class Volume; /*! \brief Abstract interface to file entry structure members 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 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 { 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; /* The following is called by Icb::GetDirectoryIterator() */ DirectoryIterator(Icb *parent); /* The following is called by Icb::~Icb() */ 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; } // categorization 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); // for directories only 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 status_t _GetFileMap(DescriptorList &list, off_t offset, size_t size, struct file_io_vec *vecs, size_t *count); template 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 fIteratorList; uint16 fPartition; FileEntry fFileEntry; FileEntry fExtendedEntry; void * fFileCache; void * fFileMap; }; template FileEntry::FileEntry(CachedBlock *descriptorBlock) : fDescriptorBlock(descriptorBlock) { } template void FileEntry::SetTo(CachedBlock *descriptorBlock) { fDescriptorBlock = descriptorBlock; } template uint8* FileEntry::AllocationDescriptors() { Descriptor* descriptor = _Descriptor(); return descriptor ? descriptor->allocation_descriptors() : NULL; } template uint32 FileEntry::AllocationDescriptorsLength() { Descriptor* descriptor = _Descriptor(); return descriptor ? descriptor->allocation_descriptors_length() : 0; } template Descriptor* FileEntry::_Descriptor() { return fDescriptorBlock ? (Descriptor *)fDescriptorBlock->Block() : NULL; } #endif // _UDF_ICB_H