UDF: support for metadata partition (feature from 2.50)
* added Icb::FindBlock() to find block in extents. * MetadataPartition uses extents descriptors found in the metadatafile to lookup blocks on a physical partition * uses struct timespec instead of time_t * added init_entities() to call C++ structures constructors. This is called at module initialization, C++ constructors are currently not called when a kernel module is loaded. * tested with a sample bluray ISO.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright 2003, Tyler Dauwalder, [email protected].
|
||||
* Copyright 2012, Jérôme Duval, [email protected].
|
||||
* Copyright 2010, Michael Lotz, [email protected].
|
||||
* Copyright 2003, Tyler Dauwalder, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -104,6 +105,7 @@ Icb::Icb(Volume *volume, long_address address)
|
||||
fData(volume),
|
||||
fInitStatus(B_NO_INIT),
|
||||
fId(to_vnode_id(address)),
|
||||
fPartition(address.partition()),
|
||||
fFileEntry(&fData),
|
||||
fExtendedEntry(&fData),
|
||||
fFileCache(NULL),
|
||||
@@ -177,17 +179,105 @@ Icb::InitCheck()
|
||||
}
|
||||
|
||||
|
||||
time_t
|
||||
Icb::AccessTime()
|
||||
void
|
||||
Icb::GetAccessTime(struct timespec ×pec) const
|
||||
{
|
||||
return make_time(_FileEntry()->access_date_and_time());
|
||||
timestamp ts;
|
||||
if ((_Tag().id() == TAGID_EXTENDED_FILE_ENTRY))
|
||||
ts = _ExtendedEntry()->access_date_and_time();
|
||||
else
|
||||
ts = _FileEntry()->access_date_and_time();
|
||||
|
||||
if (decode_time(ts, timespec) != B_OK) {
|
||||
decode_time(
|
||||
fVolume->PrimaryVolumeDescriptor()->recording_date_and_time(),
|
||||
timespec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
time_t
|
||||
Icb::ModificationTime()
|
||||
void
|
||||
Icb::GetModificationTime(struct timespec ×pec) const
|
||||
{
|
||||
return make_time(_FileEntry()->modification_date_and_time());
|
||||
timestamp ts;
|
||||
if ((_Tag().id() == TAGID_EXTENDED_FILE_ENTRY))
|
||||
ts = _ExtendedEntry()->modification_date_and_time();
|
||||
else
|
||||
ts = _FileEntry()->modification_date_and_time();
|
||||
|
||||
if (decode_time(ts, timespec) != B_OK) {
|
||||
decode_time(
|
||||
fVolume->PrimaryVolumeDescriptor()->recording_date_and_time(),
|
||||
timespec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Icb::FindBlock(uint32 logicalBlock, off_t &block)
|
||||
{
|
||||
off_t pos = logicalBlock << fVolume->BlockShift();
|
||||
if (uint64(pos) >= Length()) {
|
||||
block = -1;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
DEBUG_INIT_ETC("Icb", ("pos: %lld", pos));
|
||||
|
||||
status_t status = B_OK;
|
||||
long_address extent;
|
||||
bool isEmpty = false;
|
||||
|
||||
switch (_IcbTag().descriptor_flags()) {
|
||||
case ICB_DESCRIPTOR_TYPE_SHORT: {
|
||||
TRACE(("Icb::FindBlock: descriptor type -> short\n"));
|
||||
AllocationDescriptorList<ShortDescriptorAccessor> list(this,
|
||||
ShortDescriptorAccessor(fPartition));
|
||||
status = list.FindExtent(pos, &extent, &isEmpty);
|
||||
if (status != B_OK) {
|
||||
TRACE_ERROR(("Icb::FindBlock: error finding extent for offset %Ld. "
|
||||
"status = 0x%lx `%s'\n", pos, status, strerror(status)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ICB_DESCRIPTOR_TYPE_LONG: {
|
||||
TRACE(("Icb::FindBlock: descriptor type -> long\n"));
|
||||
AllocationDescriptorList<LongDescriptorAccessor> list(this);
|
||||
status = list.FindExtent(pos, &extent, &isEmpty);
|
||||
if (status != B_OK) {
|
||||
TRACE_ERROR(("Icb::FindBlock: error finding extent for offset %Ld. "
|
||||
"status = 0x%lx `%s'\n", pos, status, strerror(status)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ICB_DESCRIPTOR_TYPE_EXTENDED: {
|
||||
TRACE(("Icb::FindBlock: descriptor type -> extended\n"));
|
||||
// AllocationDescriptorList<ExtendedDescriptorAccessor> list(this, ExtendedDescriptorAccessor(0));
|
||||
// RETURN(_Read(list, pos, buffer, length, block));
|
||||
RETURN(B_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
case ICB_DESCRIPTOR_TYPE_EMBEDDED: {
|
||||
TRACE(("Icb::FindBlock: descriptor type: embedded\n"));
|
||||
RETURN(B_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
TRACE(("Icb::FindBlock: invalid icb descriptor flags! (flags = %d)\n",
|
||||
_IcbTag().descriptor_flags()));
|
||||
RETURN(B_BAD_VALUE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == B_OK) {
|
||||
block = extent.block();
|
||||
TRACE(("Icb::FindBlock: block %lld\n", block));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -205,13 +295,16 @@ Icb::Read(off_t pos, void *buffer, size_t *length, uint32 *block)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
DEBUG_INIT_ETC("Icb", ("pos: %lld, length: %ld", pos, *length));
|
||||
|
||||
if (fFileCache != NULL)
|
||||
return file_cache_read(fFileCache, NULL, pos, buffer, length);
|
||||
|
||||
switch (_IcbTag().descriptor_flags()) {
|
||||
case ICB_DESCRIPTOR_TYPE_SHORT: {
|
||||
TRACE(("Icb::Read: descriptor type -> short\n"));
|
||||
AllocationDescriptorList<ShortDescriptorAccessor> list(this, ShortDescriptorAccessor(0));
|
||||
AllocationDescriptorList<ShortDescriptorAccessor> list(this,
|
||||
ShortDescriptorAccessor(fPartition));
|
||||
RETURN(_Read(list, pos, buffer, length, block));
|
||||
break;
|
||||
}
|
||||
@@ -445,7 +538,7 @@ Icb::Find(const char *filename, ino_t *id)
|
||||
TRACE(("Icb::Find: filename = `%s', id = %p\n", filename, id));
|
||||
|
||||
if (!filename || !id)
|
||||
RETURN(B_BAD_VALUE);
|
||||
return B_BAD_VALUE;
|
||||
|
||||
DirectoryIterator *i;
|
||||
status_t status = GetDirectoryIterator(&i);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012, Jérôme Duval, [email protected].
|
||||
* Copyright 2008, Salvatore Benedetto, [email protected].
|
||||
* Copyright 2003, Tyler Dauwalder, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
@@ -96,14 +97,15 @@ public:
|
||||
uint64 Length() { return _FileEntry()->information_length(); }
|
||||
mode_t Mode() { return (IsDirectory() ? S_IFDIR : S_IFREG)
|
||||
| S_IRUSR | S_IRGRP | S_IROTH; }
|
||||
time_t AccessTime();
|
||||
time_t ModificationTime();
|
||||
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);
|
||||
status_t Read(off_t pos, void *buffer, size_t *length,
|
||||
uint32 *block = NULL);
|
||||
|
||||
@@ -120,15 +122,17 @@ public:
|
||||
Volume *GetVolume() const { return fVolume; }
|
||||
|
||||
private:
|
||||
AbstractFileEntry *_AbstractEntry() { return (_Tag().id()
|
||||
AbstractFileEntry *_AbstractEntry() const { return (_Tag().id()
|
||||
== TAGID_EXTENDED_FILE_ENTRY)
|
||||
? (AbstractFileEntry *)&fExtendedEntry
|
||||
: (AbstractFileEntry *)&fFileEntry; }
|
||||
|
||||
descriptor_tag &_Tag() { return ((icb_header *)fData.Block())->tag(); }
|
||||
icb_entry_tag &_IcbTag() { return ((icb_header *)fData.Block())->icb_tag(); }
|
||||
file_icb_entry *_FileEntry() { return (file_icb_entry *)fData.Block(); }
|
||||
extended_file_icb_entry &_ExtendedEntry() { return *(extended_file_icb_entry *)fData.Block(); }
|
||||
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,
|
||||
@@ -143,6 +147,7 @@ private:
|
||||
status_t fInitStatus;
|
||||
ino_t fId;
|
||||
SinglyLinkedList<DirectoryIterator> fIteratorList;
|
||||
uint16 fPartition;
|
||||
FileEntry<file_icb_entry> fFileEntry;
|
||||
FileEntry<extended_file_icb_entry> fExtendedEntry;
|
||||
void * fFileCache;
|
||||
|
||||
@@ -1,29 +1,45 @@
|
||||
/*
|
||||
* Copyright 2012, Jérôme Duval, [email protected].
|
||||
* Copyright 2003 Tyler Dauwalder, [email protected]
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "MetadataPartition.h"
|
||||
|
||||
#define B_NOT_IMPLEMENTED B_ERROR
|
||||
#include "Icb.h"
|
||||
|
||||
|
||||
/*! \brief Creates a new MetadataPartition object.
|
||||
*/
|
||||
MetadataPartition::MetadataPartition(Partition &parentPartition,
|
||||
uint32 metadataFileLocation,
|
||||
uint32 metadataMirrorFileLocation,
|
||||
uint32 metadataBitmapFileLocation,
|
||||
uint32 allocationUnitSize,
|
||||
uint16 alignmentUnitSize,
|
||||
bool metadataIsDuplicated)
|
||||
: fParentPartition(parentPartition)
|
||||
, fAllocationUnitSize(allocationUnitSize)
|
||||
, fAlignmentUnitSize(alignmentUnitSize)
|
||||
, fMetadataIsDuplicated(metadataIsDuplicated)
|
||||
, fInitStatus(B_NO_INIT)
|
||||
MetadataPartition::MetadataPartition(Volume *volume,
|
||||
uint16 parentNumber, Partition &parentPartition, uint32 metadataFileLocation,
|
||||
uint32 metadataMirrorFileLocation, uint32 metadataBitmapFileLocation,
|
||||
uint32 allocationUnitSize, uint16 alignmentUnitSize,
|
||||
bool metadataIsDuplicated)
|
||||
: fPartition(parentNumber),
|
||||
fParentPartition(parentPartition),
|
||||
fAllocationUnitSize(allocationUnitSize),
|
||||
fAlignmentUnitSize(alignmentUnitSize),
|
||||
fMetadataIsDuplicated(metadataIsDuplicated),
|
||||
fInitStatus(B_NO_INIT),
|
||||
fMetadataIcb(NULL)
|
||||
{
|
||||
long_address address;
|
||||
address.set_to(metadataFileLocation, fPartition);
|
||||
|
||||
fMetadataIcb = new(nothrow) Icb(volume, address);
|
||||
if (fMetadataIcb == NULL || fMetadataIcb->InitCheck() != B_OK)
|
||||
fInitStatus = B_NO_MEMORY;
|
||||
|
||||
fInitStatus = B_OK;
|
||||
}
|
||||
|
||||
/*! \brief Destroys the MetadataPartition object.
|
||||
*/
|
||||
MetadataPartition::~MetadataPartition()
|
||||
{
|
||||
delete fMetadataIcb;
|
||||
}
|
||||
|
||||
/*! \brief Maps the given logical block to a physical block on disc.
|
||||
@@ -31,7 +47,11 @@ MetadataPartition::~MetadataPartition()
|
||||
status_t
|
||||
MetadataPartition::MapBlock(uint32 logicalBlock, off_t &physicalBlock)
|
||||
{
|
||||
return B_NOT_IMPLEMENTED;
|
||||
off_t block = 0;
|
||||
status_t status = fMetadataIcb->FindBlock(logicalBlock, block);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
return fParentPartition.MapBlock(block, physicalBlock);
|
||||
}
|
||||
|
||||
/*! Returns the initialization status of the object.
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//
|
||||
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
||||
//---------------------------------------------------------------------
|
||||
/*
|
||||
* Copyright 2012, Jérôme Duval, [email protected].
|
||||
* Copyright 2003 Tyler Dauwalder, [email protected]
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _UDF_METADATA_PARTITION_H
|
||||
#define _UDF_METADATA_PARTITION_H
|
||||
|
||||
@@ -12,8 +11,9 @@
|
||||
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
#include "Partition.h"
|
||||
#include "UdfDebug.h"
|
||||
#include "Volume.h"
|
||||
|
||||
|
||||
/*! \brief Type 2 metadata partition
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
*/
|
||||
class MetadataPartition : public Partition {
|
||||
public:
|
||||
MetadataPartition(Partition &parentPartition, uint32 metadataFileLocation,
|
||||
uint32 metadataMirrorFileLocation, uint32 metadataBitmapFileLocation,
|
||||
uint32 allocationUnitSize, uint16 alignmentUnitSize,
|
||||
bool metadataIsDuplicated);
|
||||
MetadataPartition(Volume *volume, uint16 partition, Partition &parentPartition,
|
||||
uint32 metadataFileLocation, uint32 metadataMirrorFileLocation,
|
||||
uint32 metadataBitmapFileLocation, uint32 allocationUnitSize,
|
||||
uint16 alignmentUnitSize, bool metadataIsDuplicated);
|
||||
virtual ~MetadataPartition();
|
||||
virtual status_t MapBlock(uint32 logicalBlock, off_t &physicalBlock);
|
||||
|
||||
@@ -37,11 +37,13 @@ public:
|
||||
uint16 AlignmentUnitSize() const { return fAlignmentUnitSize; }
|
||||
uint32 MetadataIsDuplicated() const { return fMetadataIsDuplicated; }
|
||||
private:
|
||||
uint16 fPartition;
|
||||
Partition &fParentPartition;
|
||||
uint32 fAllocationUnitSize;
|
||||
uint16 fAlignmentUnitSize;
|
||||
bool fMetadataIsDuplicated;
|
||||
status_t fInitStatus;
|
||||
Icb *fMetadataIcb;
|
||||
};
|
||||
|
||||
#endif // _UDF_METADATA_PARTITION_H
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/*
|
||||
* Copyright 2012, Jérôme Duval, [email protected].
|
||||
* Copyright 2003, Tyler Dauwalder, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Recognition.h"
|
||||
|
||||
#include "UdfString.h"
|
||||
@@ -18,6 +25,7 @@ walk_volume_recognition_sequence(int device, off_t offset, uint32 blockSize,
|
||||
static status_t
|
||||
walk_anchor_volume_descriptor_sequences(int device, off_t offset, off_t length,
|
||||
uint32 blockSize, uint32 blockShift,
|
||||
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||
partition_descriptor partitionDescriptors[],
|
||||
uint8 &partitionDescriptorCount);
|
||||
@@ -25,6 +33,7 @@ walk_anchor_volume_descriptor_sequences(int device, off_t offset, off_t length,
|
||||
static status_t
|
||||
walk_volume_descriptor_sequence(extent_address descriptorSequence, int device,
|
||||
uint32 blockSize, uint32 blockShift,
|
||||
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||
partition_descriptor partitionDescriptors[],
|
||||
uint8 &partitionDescriptorCount);
|
||||
@@ -40,7 +49,8 @@ walk_integrity_sequence(int device, uint32 blockSize, uint32 blockShift,
|
||||
|
||||
status_t
|
||||
udf_recognize(int device, off_t offset, off_t length, uint32 blockSize,
|
||||
uint32 &blockShift, logical_volume_descriptor &logicalVolumeDescriptor,
|
||||
uint32 &blockShift, primary_volume_descriptor &primaryVolumeDescriptor,
|
||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||
partition_descriptor partitionDescriptors[],
|
||||
uint8 &partitionDescriptorCount)
|
||||
{
|
||||
@@ -66,7 +76,8 @@ udf_recognize(int device, off_t offset, off_t length, uint32 blockSize,
|
||||
// Now hunt down a volume descriptor sequence from one of
|
||||
// the anchor volume pointers (if there are any).
|
||||
status = walk_anchor_volume_descriptor_sequences(device, offset, length,
|
||||
blockSize, blockShift, logicalVolumeDescriptor, partitionDescriptors,
|
||||
blockSize, blockShift, primaryVolumeDescriptor,
|
||||
logicalVolumeDescriptor, partitionDescriptors,
|
||||
partitionDescriptorCount);
|
||||
if (status != B_OK) {
|
||||
TRACE_ERROR(("udf_recognize: cannot find volume descriptor. status = %ld\n",
|
||||
@@ -161,6 +172,7 @@ walk_volume_recognition_sequence(int device, off_t offset, uint32 blockSize,
|
||||
static status_t
|
||||
walk_anchor_volume_descriptor_sequences(int device, off_t offset, off_t length,
|
||||
uint32 blockSize, uint32 blockShift,
|
||||
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||
partition_descriptor partitionDescriptors[],
|
||||
uint8 &partitionDescriptorCount)
|
||||
@@ -200,13 +212,15 @@ walk_anchor_volume_descriptor_sequences(int device, off_t offset, off_t length,
|
||||
// Found an avds, so try the main sequence first, then
|
||||
// the reserve sequence if the main one fails.
|
||||
anchorErr = walk_volume_descriptor_sequence(anchor->main_vds(),
|
||||
device, blockSize, blockShift, logicalVolumeDescriptor,
|
||||
partitionDescriptors, partitionDescriptorCount);
|
||||
device, blockSize, blockShift, primaryVolumeDescriptor,
|
||||
logicalVolumeDescriptor, partitionDescriptors,
|
||||
partitionDescriptorCount);
|
||||
|
||||
if (anchorErr)
|
||||
anchorErr = walk_volume_descriptor_sequence(anchor->reserve_vds(),
|
||||
device, blockSize, blockShift, logicalVolumeDescriptor,
|
||||
partitionDescriptors, partitionDescriptorCount);
|
||||
device, blockSize, blockShift, primaryVolumeDescriptor,
|
||||
logicalVolumeDescriptor, partitionDescriptors,
|
||||
partitionDescriptorCount);
|
||||
}
|
||||
if (!anchorErr) {
|
||||
PRINT(("block %Ld: found valid vds\n", avds_locations[i]));
|
||||
@@ -225,6 +239,7 @@ static
|
||||
status_t
|
||||
walk_volume_descriptor_sequence(extent_address descriptorSequence,
|
||||
int device, uint32 blockSize, uint32 blockShift,
|
||||
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||
partition_descriptor partitionDescriptors[],
|
||||
uint8 &partitionDescriptorCount)
|
||||
@@ -271,7 +286,7 @@ walk_volume_descriptor_sequence(extent_address descriptorSequence,
|
||||
{
|
||||
primary_volume_descriptor *primary = reinterpret_cast<primary_volume_descriptor*>(tag);
|
||||
PDUMP(primary);
|
||||
(void)primary; // kill the warning
|
||||
primaryVolumeDescriptor = *primary;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//
|
||||
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
||||
//---------------------------------------------------------------------
|
||||
/*
|
||||
* Copyright 2012, Jérôme Duval, [email protected].
|
||||
* Copyright 2003, Tyler Dauwalder, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _UDF_RECOGNITION_H
|
||||
#define _UDF_RECOGNITION_H
|
||||
|
||||
@@ -14,9 +13,10 @@
|
||||
#include "UdfDebug.h"
|
||||
|
||||
status_t udf_recognize(int device, off_t offset, off_t length,
|
||||
uint32 blockSize, uint32 &blockShift,
|
||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||
partition_descriptor partitionDescriptors[],
|
||||
uint8 &partitionDescriptorCount);
|
||||
uint32 blockSize, uint32 &blockShift,
|
||||
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||
partition_descriptor partitionDescriptors[],
|
||||
uint8 &partitionDescriptorCount);
|
||||
|
||||
#endif // _UDF_RECOGNITION_H
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//
|
||||
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
||||
//----------------------------------------------------------------------
|
||||
/*
|
||||
* Copyright 2012, Jérôme Duval, [email protected].
|
||||
* Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
/*! \file UdfStructures.cpp
|
||||
|
||||
@@ -38,20 +38,6 @@ const char* kVSDID_ECMA167_2 = "NSR02";
|
||||
const char* kVSDID_ECMA167_3 = "NSR03";
|
||||
const char* kVSDID_ECMA168 = "CDW02";
|
||||
|
||||
// entity_ids
|
||||
const entity_id kMetadataPartitionMapId(0, "*UDF Metadata Partition");
|
||||
const entity_id kSparablePartitionMapId(0, "*UDF Sparable Partition");
|
||||
const entity_id kVirtualPartitionMapId(0, "*UDF Virtual Partition");
|
||||
const entity_id kImplementationId(0, "*OpenBeOS UDF", implementation_id_suffix(OS_BEOS, BEOS_GENERIC));
|
||||
const entity_id kPartitionContentsId1xx(0, "+NSR02");
|
||||
const entity_id kPartitionContentsId2xx(0, "+NSR03");
|
||||
const entity_id kLogicalVolumeInfoId150(0, "*UDF LV Info", udf_id_suffix(0x0150, OS_BEOS, BEOS_GENERIC));
|
||||
const entity_id kLogicalVolumeInfoId201(0, "*UDF LV Info", udf_id_suffix(0x0201, OS_BEOS, BEOS_GENERIC));
|
||||
const entity_id kDomainId150(0, "*OSTA UDF Compliant", domain_id_suffix(0x0150,
|
||||
DF_HARD_WRITE_PROTECT));
|
||||
const entity_id kDomainId201(0, "*OSTA UDF Compliant", domain_id_suffix(0x0201,
|
||||
DF_HARD_WRITE_PROTECT));
|
||||
|
||||
//! crc 010041 table, as generated by crc_table.cpp
|
||||
const uint16 kCrcTable[256] = {
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
@@ -92,6 +78,40 @@ const uint32 kLogicalVolumeDescriptorBaseSize = sizeof(logical_volume_descriptor
|
||||
- (UDF_MAX_PARTITION_MAPS
|
||||
* UDF_MAX_PARTITION_MAP_SIZE);
|
||||
|
||||
// entity_ids
|
||||
entity_id kMetadataPartitionMapId;
|
||||
entity_id kSparablePartitionMapId;
|
||||
entity_id kVirtualPartitionMapId;
|
||||
entity_id kImplementationId;
|
||||
entity_id kPartitionContentsId1xx;
|
||||
entity_id kPartitionContentsId2xx;
|
||||
entity_id kLogicalVolumeInfoId150;
|
||||
entity_id kLogicalVolumeInfoId201;
|
||||
entity_id kDomainId150;
|
||||
entity_id kDomainId201;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Entities initialization
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
init_entities()
|
||||
{
|
||||
kMetadataPartitionMapId = entity_id(0, "*UDF Metadata Partition");
|
||||
kSparablePartitionMapId = entity_id(0, "*UDF Sparable Partition");
|
||||
kVirtualPartitionMapId = entity_id(0, "*UDF Virtual Partition");
|
||||
kImplementationId = entity_id(0, "*OpenBeOS UDF", implementation_id_suffix(OS_BEOS, BEOS_GENERIC));
|
||||
kPartitionContentsId1xx = entity_id(0, "+NSR02");
|
||||
kPartitionContentsId2xx = entity_id(0, "+NSR03");
|
||||
kLogicalVolumeInfoId150 = entity_id(0, "*UDF LV Info", udf_id_suffix(0x0150, OS_BEOS, BEOS_GENERIC));
|
||||
kLogicalVolumeInfoId201 = entity_id(0, "*UDF LV Info", udf_id_suffix(0x0201, OS_BEOS, BEOS_GENERIC));
|
||||
kDomainId150 = entity_id(0, "*OSTA UDF Compliant", domain_id_suffix(0x0150,
|
||||
DF_HARD_WRITE_PROTECT));
|
||||
kDomainId201 = entity_id(0, "*OSTA UDF Compliant", domain_id_suffix(0x0201,
|
||||
DF_HARD_WRITE_PROTECT));
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Helper functions
|
||||
@@ -527,7 +547,7 @@ descriptor_tag::init_check(uint32 block, bool calculateCrc)
|
||||
{
|
||||
DEBUG_INIT_ETC("descriptor_tag", ("location: %ld, calculateCrc: %s",
|
||||
block, bool_to_string(calculateCrc)));
|
||||
PRINT(("location (paramater) == %ld\n", block));
|
||||
PRINT(("location (parameter) == %ld\n", block));
|
||||
PRINT(("location (in structure) == %ld\n", location()));
|
||||
if (calculateCrc) {
|
||||
PRINT(("crc (calculated) == %d\n",
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//
|
||||
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
||||
//---------------------------------------------------------------------
|
||||
/*
|
||||
* Copyright 2012, Jérôme Duval, korli@users.berlios.de.
|
||||
* Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
|
||||
* This file may be used under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _UDF_DISK_STRUCTURES_H
|
||||
#define _UDF_DISK_STRUCTURES_H
|
||||
|
||||
@@ -121,7 +120,8 @@ public:
|
||||
uint8 microsecond() const { return _microsecond; }
|
||||
|
||||
// Set functions
|
||||
void set_type_and_timezone(uint16 type_and_timezone) { _type_and_timezone = B_HOST_TO_LENDIAN_INT16(type_and_timezone); }
|
||||
void set_type_and_timezone(uint16 type_and_timezone) {
|
||||
_type_and_timezone = B_HOST_TO_LENDIAN_INT16(type_and_timezone); }
|
||||
void set_type(uint8 type) {
|
||||
type_and_timezone_accessor t;
|
||||
t.type_and_timezone = type_and_timezone();
|
||||
@@ -141,7 +141,8 @@ public:
|
||||
void set_minute(uint8 minute) { _minute = minute; }
|
||||
void set_second(uint8 second) { _second = second; }
|
||||
void set_centisecond(uint8 centisecond) { _centisecond = centisecond; }
|
||||
void set_hundred_microsecond(uint8 hundred_microsecond) { _hundred_microsecond = hundred_microsecond; }
|
||||
void set_hundred_microsecond(uint8 hundred_microsecond) {
|
||||
_hundred_microsecond = hundred_microsecond; }
|
||||
void set_microsecond(uint8 microsecond) { _microsecond = microsecond; }
|
||||
private:
|
||||
void _clear();
|
||||
@@ -293,17 +294,18 @@ private:
|
||||
array<uint8, kIdentifierSuffixLength> _identifier_suffix;
|
||||
} __attribute__((packed));
|
||||
|
||||
extern const entity_id kMetadataPartitionMapId;
|
||||
extern const entity_id kSparablePartitionMapId;
|
||||
extern const entity_id kVirtualPartitionMapId;
|
||||
extern const entity_id kImplementationId;
|
||||
extern const entity_id kPartitionContentsId1xx;
|
||||
extern const entity_id kPartitionContentsId2xx;
|
||||
extern const entity_id kUdfId;
|
||||
extern const entity_id kLogicalVolumeInfoId150;
|
||||
extern const entity_id kLogicalVolumeInfoId201;
|
||||
extern const entity_id kDomainId150;
|
||||
extern const entity_id kDomainId201;
|
||||
extern entity_id kMetadataPartitionMapId;
|
||||
extern entity_id kSparablePartitionMapId;
|
||||
extern entity_id kVirtualPartitionMapId;
|
||||
extern entity_id kImplementationId;
|
||||
extern entity_id kPartitionContentsId1xx;
|
||||
extern entity_id kPartitionContentsId2xx;
|
||||
extern entity_id kUdfId;
|
||||
extern entity_id kLogicalVolumeInfoId150;
|
||||
extern entity_id kLogicalVolumeInfoId201;
|
||||
extern entity_id kDomainId150;
|
||||
extern entity_id kDomainId201;
|
||||
extern void init_entities(void);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// ECMA-167 Part 2
|
||||
@@ -1307,6 +1309,49 @@ private:
|
||||
See also: UDF-2.50 2.2.10
|
||||
*/
|
||||
struct metadata_partition_map {
|
||||
public:
|
||||
entity_id& partition_type_id() { return _partition_type_id; }
|
||||
const entity_id& partition_type_id() const { return _partition_type_id; }
|
||||
|
||||
uint16 volume_sequence_number() const {
|
||||
return B_LENDIAN_TO_HOST_INT16(_volume_sequence_number); }
|
||||
void set_volume_sequence_number(uint16 number) {
|
||||
_volume_sequence_number = B_HOST_TO_LENDIAN_INT16(number); }
|
||||
|
||||
uint16 partition_number() const {
|
||||
return B_LENDIAN_TO_HOST_INT16(_partition_number); }
|
||||
void set_partition_number(uint16 number) {
|
||||
_partition_number = B_HOST_TO_LENDIAN_INT16(number); }
|
||||
|
||||
uint32 metadata_file_location() const {
|
||||
return B_LENDIAN_TO_HOST_INT32(_metadata_file_location); }
|
||||
void set_metadata_file_location(uint32 location) {
|
||||
_metadata_file_location = B_HOST_TO_LENDIAN_INT32(location); }
|
||||
|
||||
uint32 metadata_mirror_file_location() const {
|
||||
return B_LENDIAN_TO_HOST_INT32(_metadata_mirror_file_location); }
|
||||
void set_metadata_mirror_file_location(uint32 location) {
|
||||
_metadata_mirror_file_location = B_HOST_TO_LENDIAN_INT32(location); }
|
||||
|
||||
uint32 metadata_bitmap_file_location() const {
|
||||
return B_LENDIAN_TO_HOST_INT32(_metadata_bitmap_file_location); }
|
||||
void set_metadata_bitmap_file_location(uint32 location) {
|
||||
_metadata_bitmap_file_location = B_HOST_TO_LENDIAN_INT32(location); }
|
||||
|
||||
uint32 allocation_unit_size() const {
|
||||
return B_LENDIAN_TO_HOST_INT32(_allocation_unit_size); }
|
||||
void set_allocation_unit_size(uint32 size) {
|
||||
_allocation_unit_size = B_HOST_TO_LENDIAN_INT32(size); }
|
||||
|
||||
uint32 alignment_unit_size() const {
|
||||
return B_LENDIAN_TO_HOST_INT32(_alignment_unit_size); }
|
||||
void set_alignment_unit_size(uint32 size) {
|
||||
_alignment_unit_size = B_HOST_TO_LENDIAN_INT32(size); }
|
||||
|
||||
uint8 flags() const { return _flags; }
|
||||
void set_flags(uint8 flags) { _flags = flags; }
|
||||
|
||||
private:
|
||||
uint8 type;
|
||||
uint8 length;
|
||||
uint8 reserved1[2];
|
||||
@@ -1315,14 +1360,20 @@ struct metadata_partition_map {
|
||||
- identifier: "*UDF Metadata Partition"
|
||||
- identifier_suffix: per UDF-2.50 2.1.5
|
||||
*/
|
||||
entity_id partition_type_id;
|
||||
uint16 volume_sequence_number;
|
||||
entity_id _partition_type_id;
|
||||
uint16 _volume_sequence_number;
|
||||
|
||||
/*! corresponding type 1 or type 2 sparable partition
|
||||
map in same logical volume
|
||||
*/
|
||||
uint16 partition_number;
|
||||
uint8 reserved2[24];
|
||||
uint16 _partition_number;
|
||||
uint32 _metadata_file_location;
|
||||
uint32 _metadata_mirror_file_location;
|
||||
uint32 _metadata_bitmap_file_location;
|
||||
uint32 _allocation_unit_size;
|
||||
uint16 _alignment_unit_size;
|
||||
uint8 _flags;
|
||||
uint8 reserved2[5];
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
@@ -1470,7 +1521,7 @@ enum {
|
||||
|
||||
/*! \brief Highest currently supported UDF read revision.
|
||||
*/
|
||||
#define UDF_MAX_READ_REVISION 0x0201
|
||||
#define UDF_MAX_READ_REVISION 0x0250
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// ECMA-167 Part 4
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012, Jérôme Duval, korli@users.berlios.de.
|
||||
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@@ -79,8 +80,16 @@ get_block_shift(uint32 blockSize, uint32 &blockShift)
|
||||
}
|
||||
|
||||
|
||||
time_t
|
||||
make_time(timestamp ×tamp)
|
||||
#define EPOCH_YEAR 1970
|
||||
#define MAX_YEAR 69
|
||||
#define SECSPERMIN 60
|
||||
#define MINSPERHOUR 60
|
||||
#define HOURSPERDAY 24
|
||||
#define SECSPERDAY (SECSPERMIN * MINSPERHOUR * HOURSPERDAY)
|
||||
#define DAYSPERNYEAR 365
|
||||
|
||||
status_t
|
||||
decode_time(timestamp ×tamp, struct timespec ×pec)
|
||||
{
|
||||
DEBUG_INIT_ETC(NULL, ("timestamp: (tnt: 0x%x, type: %d, timezone: %d = 0x%x, year: %d, "
|
||||
"month: %d, day: %d, hour: %d, minute: %d, second: %d)", timestamp.type_and_timezone(),
|
||||
@@ -88,50 +97,56 @@ make_time(timestamp ×tamp)
|
||||
timestamp.timezone(),timestamp.year(),
|
||||
timestamp.month(), timestamp.day(), timestamp.hour(), timestamp.minute(), timestamp.second()));
|
||||
|
||||
if (timestamp.year() < EPOCH_YEAR || timestamp.year() >= EPOCH_YEAR + MAX_YEAR)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
time_t result = 0;
|
||||
const int monthLengths[12]
|
||||
= { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
if (timestamp.year() >= 1970) {
|
||||
const int monthLengths[12]
|
||||
= { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
int year = timestamp.year();
|
||||
int month = timestamp.month();
|
||||
int day = timestamp.day();
|
||||
int hour = timestamp.hour();
|
||||
int minute = timestamp.minute();
|
||||
int second = timestamp.second();
|
||||
|
||||
int year = timestamp.year();
|
||||
int month = timestamp.month();
|
||||
int day = timestamp.day();
|
||||
int hour = timestamp.hour();
|
||||
int minute = timestamp.minute();
|
||||
int second = timestamp.second();
|
||||
// Range check the timezone offset, then round it down
|
||||
// to the nearest hour, since no one I know treats timezones
|
||||
// with a per-minute granularity, and none of the other OSes
|
||||
// I've looked at appear to either.
|
||||
int timezone_offset = 0;
|
||||
if (timestamp.type() == 1)
|
||||
timezone_offset = timestamp.timezone();
|
||||
if (-SECSPERDAY > timezone_offset || timezone_offset > SECSPERDAY)
|
||||
timezone_offset = 0;
|
||||
timezone_offset -= timezone_offset % 60;
|
||||
|
||||
// Range check the timezone offset, then round it down
|
||||
// to the nearest hour, since no one I know treats timezones
|
||||
// with a per-minute granularity, and none of the other OSes
|
||||
// I've looked at appear to either.
|
||||
int timezone_offset = timestamp.timezone();
|
||||
if (-1440 > timezone_offset || timezone_offset > 1440)
|
||||
timezone_offset = 0;
|
||||
timezone_offset -= timezone_offset % 60;
|
||||
int previousLeapYears = (year - 1968) / 4;
|
||||
bool isLeapYear = (year - 1968) % 4 == 0;
|
||||
if (isLeapYear)
|
||||
--previousLeapYears;
|
||||
|
||||
int previousLeapYears = (year - 1968) / 4;
|
||||
bool isLeapYear = (year - 1968) % 4 == 0;
|
||||
if (isLeapYear)
|
||||
--previousLeapYears;
|
||||
|
||||
// Years to days
|
||||
result = (year - 1970) * 365 + previousLeapYears;
|
||||
// Months to days
|
||||
for (int i = 0; i < month-1; i++) {
|
||||
result += monthLengths[i];
|
||||
}
|
||||
if (month > 2 && isLeapYear)
|
||||
++result;
|
||||
// Days to hours
|
||||
result = (result + day - 1) * 24;
|
||||
// Hours to minutes
|
||||
result = (result + hour) * 60 + timezone_offset;
|
||||
// Minutes to seconds
|
||||
result = (result + minute) * 60 + second;
|
||||
// Years to days
|
||||
result = (year - EPOCH_YEAR) * DAYSPERNYEAR + previousLeapYears;
|
||||
// Months to days
|
||||
for (int i = 0; i < month-1; i++) {
|
||||
result += monthLengths[i];
|
||||
}
|
||||
if (month > 2 && isLeapYear)
|
||||
++result;
|
||||
// Days to hours
|
||||
result = (result + day - 1) * HOURSPERDAY;
|
||||
// Hours to minutes
|
||||
result = (result + hour) * MINSPERHOUR + timezone_offset;
|
||||
// Minutes to seconds
|
||||
result = (result + minute) * SECSPERMIN + second;
|
||||
|
||||
return result;
|
||||
timespec.tv_sec = result;
|
||||
timespec.tv_nsec = 1000 * (timestamp.microsecond()
|
||||
+ timestamp.hundred_microsecond() * 100
|
||||
+ timestamp.centisecond() * 10000);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ const char *bool_to_string(bool value);
|
||||
uint16 calculate_crc(uint8 *data, uint16 length);
|
||||
status_t check_size_error(ssize_t bytesReturned, ssize_t bytesExpected);
|
||||
status_t get_block_shift(uint32 blockSize, uint32 &blockShift);
|
||||
time_t make_time(timestamp ×tamp);
|
||||
status_t decode_time(timestamp ×tamp, struct timespec ×pec);
|
||||
long_address to_long_address(ino_t id, uint32 length = 0);
|
||||
ino_t to_vnode_id(long_address address);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
@@ -8,6 +9,7 @@
|
||||
|
||||
#include "Icb.h"
|
||||
#include "MemoryChunk.h"
|
||||
#include "MetadataPartition.h"
|
||||
#include "PhysicalPartition.h"
|
||||
#include "Recognition.h"
|
||||
|
||||
@@ -62,6 +64,7 @@ Volume::Mount(const char *deviceName, off_t offset, off_t length,
|
||||
return device;
|
||||
}
|
||||
|
||||
DEBUG_INIT_ETC("Volume", ("deviceName: %s", deviceName));
|
||||
status_t status = B_OK;
|
||||
|
||||
// If the device is actually a normal file, try to disable the cache
|
||||
@@ -84,8 +87,8 @@ Volume::Mount(const char *deviceName, off_t offset, off_t length,
|
||||
// Run through the volume recognition and descriptor sequences to
|
||||
// see if we have a potentially valid UDF volume on our hands
|
||||
status = udf_recognize(device, offset, length, blockSize, blockShift,
|
||||
logicalVolumeDescriptor, partitionDescriptors,
|
||||
partitionDescriptorCount);
|
||||
fPrimaryVolumeDescriptor, logicalVolumeDescriptor,
|
||||
partitionDescriptors, partitionDescriptorCount);
|
||||
|
||||
// Set up the block cache
|
||||
if (!status) {
|
||||
@@ -163,8 +166,43 @@ Volume::Mount(const char *deviceName, off_t offset, off_t length,
|
||||
TRACE(("map type: metadata\n"));
|
||||
metadata_partition_map* map =
|
||||
reinterpret_cast<metadata_partition_map*>(header);
|
||||
metadataCount++;
|
||||
(void)map; // kill the warning for now
|
||||
|
||||
|
||||
// Find the corresponding partition descriptor
|
||||
partition_descriptor *descriptor = NULL;
|
||||
for (uint8 j = 0; j < partitionDescriptorCount; j++) {
|
||||
if (map->partition_number() ==
|
||||
partitionDescriptors[j].partition_number()) {
|
||||
descriptor = &partitionDescriptors[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
Partition *parent = _GetPartition(map->partition_number());
|
||||
// Create and add the partition
|
||||
if (descriptor != NULL && parent != NULL) {
|
||||
MetadataPartition *partition
|
||||
= new(nothrow) MetadataPartition(this,
|
||||
map->partition_number(), *parent,
|
||||
map->metadata_file_location(),
|
||||
map->metadata_mirror_file_location(),
|
||||
map->metadata_bitmap_file_location(),
|
||||
map->allocation_unit_size(),
|
||||
map->alignment_unit_size(),
|
||||
map->flags() & 1);
|
||||
status = partition ? partition->InitCheck() : B_NO_MEMORY;
|
||||
if (!status) {
|
||||
TRACE(("Volume::Mount: adding MetadataPartition()"));
|
||||
status = _SetPartition(i, partition);
|
||||
if (status == B_OK)
|
||||
metadataCount++;
|
||||
} else {
|
||||
TRACE_ERROR(("Volume::Mount: metadata partition "
|
||||
"creation failed! 0x%lx\n", status));
|
||||
}
|
||||
} else {
|
||||
TRACE_ERROR(("Volume::Mount: no matching partition descriptor found!\n"));
|
||||
status = B_ERROR;
|
||||
}
|
||||
} else {
|
||||
TRACE(("map type: unrecognized (`%.23s')\n",
|
||||
typeId.identifier()));
|
||||
@@ -180,9 +218,9 @@ Volume::Mount(const char *deviceName, off_t offset, off_t length,
|
||||
// Do some checking as to what sorts of partitions we've actually found.
|
||||
if (!status) {
|
||||
status = (physicalCount == 1 && virtualCount == 0
|
||||
&& sparableCount == 0 && metadataCount == 0)
|
||||
&& sparableCount == 0)
|
||||
|| (physicalCount == 2 && virtualCount == 0
|
||||
&& sparableCount == 0 && metadataCount == 0)
|
||||
&& sparableCount == 0)
|
||||
? B_OK : B_ERROR;
|
||||
if (status) {
|
||||
TRACE(("Invalid partition layout found:\n"));
|
||||
@@ -294,6 +332,8 @@ Volume::MapBlock(long_address address, off_t *mappedBlock)
|
||||
{
|
||||
TRACE(("Volume::MapBlock: partition = %d, block = %ld, mappedBlock = %p\n",
|
||||
address.partition(), address.block(), mappedBlock));
|
||||
DEBUG_INIT_ETC("Volume", ("partition = %d, block = %ld, mappedBlock = %p",
|
||||
address.partition(), address.block(), mappedBlock));
|
||||
status_t error = mappedBlock ? B_OK : B_BAD_VALUE;
|
||||
if (!error) {
|
||||
Partition *partition = _GetPartition(address.partition());
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
@@ -50,6 +51,8 @@ public:
|
||||
uint32 BlockShift() const { return fBlockShift; }
|
||||
bool Mounted() const { return fMounted; }
|
||||
Icb* RootIcb() { return fRootIcb; }
|
||||
primary_volume_descriptor *PrimaryVolumeDescriptor()
|
||||
{ return &fPrimaryVolumeDescriptor; }
|
||||
|
||||
private:
|
||||
void _Unset();
|
||||
@@ -69,6 +72,7 @@ private:
|
||||
off_t fOffset;
|
||||
Partition *fPartitions[UDF_MAX_PARTITION_MAPS];
|
||||
Icb *fRootIcb; // Destroyed by vfs via callback to put_node()
|
||||
primary_volume_descriptor fPrimaryVolumeDescriptor;
|
||||
};
|
||||
|
||||
#endif // _UDF_VOLUME_H
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
|
||||
* Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com.
|
||||
* Copyright 2012, Jérôme Duval, korli@users.berlios.de.
|
||||
* Copyright 2010, Michael Lotz, mmlr@mlotz.ch.
|
||||
* Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com.
|
||||
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -80,13 +81,14 @@ udf_identify_partition(int fd, partition_data *partition, void **_cookie)
|
||||
partition->offset, partition->size, partition->content_size,
|
||||
partition->block_size));
|
||||
|
||||
primary_volume_descriptor primaryVolumeDescriptor;
|
||||
logical_volume_descriptor logicalVolumeDescriptor;
|
||||
partition_descriptor partitionDescriptors[kMaxPartitionDescriptors];
|
||||
uint8 descriptorCount = kMaxPartitionDescriptors;
|
||||
uint32 blockShift;
|
||||
status_t error = udf_recognize(fd, partition->offset, partition->size,
|
||||
partition->block_size, blockShift, logicalVolumeDescriptor,
|
||||
partitionDescriptors, descriptorCount);
|
||||
partition->block_size, blockShift, primaryVolumeDescriptor,
|
||||
logicalVolumeDescriptor, partitionDescriptors, descriptorCount);
|
||||
if (error != B_OK)
|
||||
return -1;
|
||||
|
||||
@@ -293,8 +295,12 @@ udf_read_stat(fs_volume *_volume, fs_vnode *node, struct stat *stat)
|
||||
// File times. For now, treat the modification time as creation
|
||||
// time as well, since true creation time is an optional extended
|
||||
// attribute, and supporting EAs is going to be a PITA. ;-)
|
||||
stat->st_atime = icb->AccessTime();
|
||||
stat->st_mtime = stat->st_ctime = stat->st_crtime = icb->ModificationTime();
|
||||
icb->GetAccessTime(stat->st_atim);
|
||||
icb->GetModificationTime(stat->st_mtim);
|
||||
icb->GetModificationTime(stat->st_ctim);
|
||||
icb->GetModificationTime(stat->st_crtim);
|
||||
//icb->GetChangeTime(stat->st_ctim);
|
||||
//icb->GetCreationTime(stat->st_crtim);
|
||||
|
||||
TRACE(("udf_read_stat: mode = 0x%x, st_ino: %Ld\n", stat->st_mode,
|
||||
stat->st_ino));
|
||||
@@ -343,6 +349,8 @@ udf_read(fs_volume *volume, fs_vnode *vnode, void *cookie, off_t pos,
|
||||
((Volume *)volume->private_volume)->ID(), pos, *length));
|
||||
|
||||
Icb *icb = (Icb *)vnode->private_node;
|
||||
DEBUG_INIT_ETC("udf_read", ("ID = %ld, pos = %lld, length = %lu",
|
||||
((Volume *)volume->private_volume)->ID(), pos, *length));
|
||||
|
||||
// if (!inode->HasUserAccessableStream()) {
|
||||
// *_length = 0;
|
||||
@@ -385,6 +393,8 @@ static status_t
|
||||
udf_open_dir(fs_volume *volume, fs_vnode *vnode, void **cookie)
|
||||
{
|
||||
TRACE(("udf_open_dir: volume = %p, vnode = %p\n", volume, vnode));
|
||||
DEBUG_INIT_ETC("udf_open_dir", ("ID = %ld",
|
||||
((Volume *)volume->private_volume)->ID()));
|
||||
|
||||
if (!volume || !vnode || !cookie)
|
||||
RETURN(B_BAD_VALUE);
|
||||
@@ -443,6 +453,8 @@ udf_read_dir(fs_volume *_volume, fs_vnode *vnode, void *cookie,
|
||||
Icb *dir = (Icb *)vnode->private_node;
|
||||
DirectoryIterator *iterator = (DirectoryIterator *)cookie;
|
||||
|
||||
DEBUG_INIT_ETC("udf_read_dir", ("ID = %ld", volume->ID()));
|
||||
|
||||
if (dir != iterator->Parent()) {
|
||||
TRACE_ERROR(("udf_read_dir: Icb does not match parent Icb of given "
|
||||
"DirectoryIterator! (iterator->Parent = %p)\n", iterator->Parent()));
|
||||
@@ -474,6 +486,8 @@ udf_rewind_dir(fs_volume *volume, fs_vnode *vnode, void *cookie)
|
||||
{
|
||||
TRACE(("udf_rewind_dir: volume = %p, vnode = %p, cookie = %p\n",
|
||||
volume, vnode, cookie));
|
||||
DEBUG_INIT_ETC("udf_rewind_dir", ("ID = %ld",
|
||||
((Volume *)volume->private_volume)->ID()));
|
||||
|
||||
if (!volume || !vnode || !cookie)
|
||||
RETURN(B_BAD_VALUE);
|
||||
@@ -604,6 +618,8 @@ udf_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
init_entities();
|
||||
return B_OK;
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user