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:
Jérôme Duval
2012-10-09 22:50:17 +02:00
parent c58a87027a
commit c530d46cca
13 changed files with 436 additions and 155 deletions
+102 -9
View File
@@ -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 &timespec) 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 &timespec) 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);
+12 -7
View File
@@ -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 &timespec) const;
void GetModificationTime(struct timespec &timespec) 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
+54 -39
View File
@@ -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 &timestamp)
#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 &timestamp, struct timespec &timespec)
{
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 &timestamp)
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;
}
+1 -1
View File
@@ -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 &timestamp);
status_t decode_time(timestamp &timestamp, struct timespec &timespec);
long_address to_long_address(ino_t id, uint32 length = 0);
ino_t to_vnode_id(long_address address);
+46 -6
View File
@@ -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: