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 2010, Michael Lotz, [email protected].
|
||||||
|
* Copyright 2003, Tyler Dauwalder, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -104,6 +105,7 @@ Icb::Icb(Volume *volume, long_address address)
|
|||||||
fData(volume),
|
fData(volume),
|
||||||
fInitStatus(B_NO_INIT),
|
fInitStatus(B_NO_INIT),
|
||||||
fId(to_vnode_id(address)),
|
fId(to_vnode_id(address)),
|
||||||
|
fPartition(address.partition()),
|
||||||
fFileEntry(&fData),
|
fFileEntry(&fData),
|
||||||
fExtendedEntry(&fData),
|
fExtendedEntry(&fData),
|
||||||
fFileCache(NULL),
|
fFileCache(NULL),
|
||||||
@@ -177,17 +179,105 @@ Icb::InitCheck()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
time_t
|
void
|
||||||
Icb::AccessTime()
|
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
|
void
|
||||||
Icb::ModificationTime()
|
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;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_INIT_ETC("Icb", ("pos: %lld, length: %ld", pos, *length));
|
||||||
|
|
||||||
if (fFileCache != NULL)
|
if (fFileCache != NULL)
|
||||||
return file_cache_read(fFileCache, NULL, pos, buffer, length);
|
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"));
|
||||||
AllocationDescriptorList<ShortDescriptorAccessor> list(this, ShortDescriptorAccessor(0));
|
AllocationDescriptorList<ShortDescriptorAccessor> list(this,
|
||||||
|
ShortDescriptorAccessor(fPartition));
|
||||||
RETURN(_Read(list, pos, buffer, length, block));
|
RETURN(_Read(list, pos, buffer, length, block));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -445,7 +538,7 @@ Icb::Find(const char *filename, ino_t *id)
|
|||||||
TRACE(("Icb::Find: filename = `%s', id = %p\n", filename, id));
|
TRACE(("Icb::Find: filename = `%s', id = %p\n", filename, id));
|
||||||
|
|
||||||
if (!filename || !id)
|
if (!filename || !id)
|
||||||
RETURN(B_BAD_VALUE);
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
DirectoryIterator *i;
|
DirectoryIterator *i;
|
||||||
status_t status = GetDirectoryIterator(&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 2008, Salvatore Benedetto, [email protected].
|
||||||
* Copyright 2003, Tyler Dauwalder, [email protected].
|
* Copyright 2003, Tyler Dauwalder, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@@ -96,14 +97,15 @@ public:
|
|||||||
uint64 Length() { return _FileEntry()->information_length(); }
|
uint64 Length() { return _FileEntry()->information_length(); }
|
||||||
mode_t Mode() { return (IsDirectory() ? S_IFDIR : S_IFREG)
|
mode_t Mode() { return (IsDirectory() ? S_IFDIR : S_IFREG)
|
||||||
| S_IRUSR | S_IRGRP | S_IROTH; }
|
| S_IRUSR | S_IRGRP | S_IROTH; }
|
||||||
time_t AccessTime();
|
void GetAccessTime(struct timespec ×pec) const;
|
||||||
time_t ModificationTime();
|
void GetModificationTime(struct timespec ×pec) const;
|
||||||
|
|
||||||
uint8 *AllocationDescriptors()
|
uint8 *AllocationDescriptors()
|
||||||
{ return _AbstractEntry()->AllocationDescriptors(); }
|
{ return _AbstractEntry()->AllocationDescriptors(); }
|
||||||
uint32 AllocationDescriptorsSize()
|
uint32 AllocationDescriptorsSize()
|
||||||
{ return _AbstractEntry()->AllocationDescriptorsLength(); }
|
{ return _AbstractEntry()->AllocationDescriptorsLength(); }
|
||||||
|
|
||||||
|
status_t FindBlock(uint32 logicalBlock, off_t &block);
|
||||||
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);
|
||||||
|
|
||||||
@@ -120,15 +122,17 @@ public:
|
|||||||
Volume *GetVolume() const { return fVolume; }
|
Volume *GetVolume() const { return fVolume; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AbstractFileEntry *_AbstractEntry() { return (_Tag().id()
|
AbstractFileEntry *_AbstractEntry() const { 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() const { return ((icb_header *)fData.Block())->tag(); }
|
||||||
icb_entry_tag &_IcbTag() { return ((icb_header *)fData.Block())->icb_tag(); }
|
icb_entry_tag &_IcbTag() const { return ((icb_header *)fData.Block())->icb_tag(); }
|
||||||
file_icb_entry *_FileEntry() { return (file_icb_entry *)fData.Block(); }
|
file_icb_entry *_FileEntry() const
|
||||||
extended_file_icb_entry &_ExtendedEntry() { return *(extended_file_icb_entry *)fData.Block(); }
|
{ return (file_icb_entry *)fData.Block(); }
|
||||||
|
extended_file_icb_entry *_ExtendedEntry() const
|
||||||
|
{ return (extended_file_icb_entry *)fData.Block(); }
|
||||||
|
|
||||||
template<class DescriptorList>
|
template<class DescriptorList>
|
||||||
status_t _GetFileMap(DescriptorList &list, off_t offset,
|
status_t _GetFileMap(DescriptorList &list, off_t offset,
|
||||||
@@ -143,6 +147,7 @@ private:
|
|||||||
status_t fInitStatus;
|
status_t fInitStatus;
|
||||||
ino_t fId;
|
ino_t fId;
|
||||||
SinglyLinkedList<DirectoryIterator> fIteratorList;
|
SinglyLinkedList<DirectoryIterator> fIteratorList;
|
||||||
|
uint16 fPartition;
|
||||||
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 * 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"
|
#include "MetadataPartition.h"
|
||||||
|
|
||||||
#define B_NOT_IMPLEMENTED B_ERROR
|
#include "Icb.h"
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Creates a new MetadataPartition object.
|
/*! \brief Creates a new MetadataPartition object.
|
||||||
*/
|
*/
|
||||||
MetadataPartition::MetadataPartition(Partition &parentPartition,
|
MetadataPartition::MetadataPartition(Volume *volume,
|
||||||
uint32 metadataFileLocation,
|
uint16 parentNumber, Partition &parentPartition, uint32 metadataFileLocation,
|
||||||
uint32 metadataMirrorFileLocation,
|
uint32 metadataMirrorFileLocation, uint32 metadataBitmapFileLocation,
|
||||||
uint32 metadataBitmapFileLocation,
|
uint32 allocationUnitSize, uint16 alignmentUnitSize,
|
||||||
uint32 allocationUnitSize,
|
bool metadataIsDuplicated)
|
||||||
uint16 alignmentUnitSize,
|
: fPartition(parentNumber),
|
||||||
bool metadataIsDuplicated)
|
fParentPartition(parentPartition),
|
||||||
: fParentPartition(parentPartition)
|
fAllocationUnitSize(allocationUnitSize),
|
||||||
, fAllocationUnitSize(allocationUnitSize)
|
fAlignmentUnitSize(alignmentUnitSize),
|
||||||
, fAlignmentUnitSize(alignmentUnitSize)
|
fMetadataIsDuplicated(metadataIsDuplicated),
|
||||||
, fMetadataIsDuplicated(metadataIsDuplicated)
|
fInitStatus(B_NO_INIT),
|
||||||
, 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.
|
/*! \brief Destroys the MetadataPartition object.
|
||||||
*/
|
*/
|
||||||
MetadataPartition::~MetadataPartition()
|
MetadataPartition::~MetadataPartition()
|
||||||
{
|
{
|
||||||
|
delete fMetadataIcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Maps the given logical block to a physical block on disc.
|
/*! \brief Maps the given logical block to a physical block on disc.
|
||||||
@@ -31,7 +47,11 @@ MetadataPartition::~MetadataPartition()
|
|||||||
status_t
|
status_t
|
||||||
MetadataPartition::MapBlock(uint32 logicalBlock, off_t &physicalBlock)
|
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.
|
/*! Returns the initialization status of the object.
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
//----------------------------------------------------------------------
|
/*
|
||||||
// This software is part of the OpenBeOS distribution and is covered
|
* Copyright 2012, Jérôme Duval, [email protected].
|
||||||
// by the OpenBeOS license.
|
* Copyright 2003 Tyler Dauwalder, [email protected]
|
||||||
//
|
* This file may be used under the terms of the MIT License.
|
||||||
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
*/
|
||||||
//---------------------------------------------------------------------
|
|
||||||
#ifndef _UDF_METADATA_PARTITION_H
|
#ifndef _UDF_METADATA_PARTITION_H
|
||||||
#define _UDF_METADATA_PARTITION_H
|
#define _UDF_METADATA_PARTITION_H
|
||||||
|
|
||||||
@@ -12,8 +11,9 @@
|
|||||||
|
|
||||||
#include <util/kernel_cpp.h>
|
#include <util/kernel_cpp.h>
|
||||||
|
|
||||||
#include "Partition.h"
|
|
||||||
#include "UdfDebug.h"
|
#include "UdfDebug.h"
|
||||||
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Type 2 metadata partition
|
/*! \brief Type 2 metadata partition
|
||||||
|
|
||||||
@@ -24,10 +24,10 @@
|
|||||||
*/
|
*/
|
||||||
class MetadataPartition : public Partition {
|
class MetadataPartition : public Partition {
|
||||||
public:
|
public:
|
||||||
MetadataPartition(Partition &parentPartition, uint32 metadataFileLocation,
|
MetadataPartition(Volume *volume, uint16 partition, Partition &parentPartition,
|
||||||
uint32 metadataMirrorFileLocation, uint32 metadataBitmapFileLocation,
|
uint32 metadataFileLocation, uint32 metadataMirrorFileLocation,
|
||||||
uint32 allocationUnitSize, uint16 alignmentUnitSize,
|
uint32 metadataBitmapFileLocation, uint32 allocationUnitSize,
|
||||||
bool metadataIsDuplicated);
|
uint16 alignmentUnitSize, bool metadataIsDuplicated);
|
||||||
virtual ~MetadataPartition();
|
virtual ~MetadataPartition();
|
||||||
virtual status_t MapBlock(uint32 logicalBlock, off_t &physicalBlock);
|
virtual status_t MapBlock(uint32 logicalBlock, off_t &physicalBlock);
|
||||||
|
|
||||||
@@ -37,11 +37,13 @@ public:
|
|||||||
uint16 AlignmentUnitSize() const { return fAlignmentUnitSize; }
|
uint16 AlignmentUnitSize() const { return fAlignmentUnitSize; }
|
||||||
uint32 MetadataIsDuplicated() const { return fMetadataIsDuplicated; }
|
uint32 MetadataIsDuplicated() const { return fMetadataIsDuplicated; }
|
||||||
private:
|
private:
|
||||||
|
uint16 fPartition;
|
||||||
Partition &fParentPartition;
|
Partition &fParentPartition;
|
||||||
uint32 fAllocationUnitSize;
|
uint32 fAllocationUnitSize;
|
||||||
uint16 fAlignmentUnitSize;
|
uint16 fAlignmentUnitSize;
|
||||||
bool fMetadataIsDuplicated;
|
bool fMetadataIsDuplicated;
|
||||||
status_t fInitStatus;
|
status_t fInitStatus;
|
||||||
|
Icb *fMetadataIcb;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _UDF_METADATA_PARTITION_H
|
#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 "Recognition.h"
|
||||||
|
|
||||||
#include "UdfString.h"
|
#include "UdfString.h"
|
||||||
@@ -18,6 +25,7 @@ walk_volume_recognition_sequence(int device, off_t offset, uint32 blockSize,
|
|||||||
static status_t
|
static status_t
|
||||||
walk_anchor_volume_descriptor_sequences(int device, off_t offset, off_t length,
|
walk_anchor_volume_descriptor_sequences(int device, off_t offset, off_t length,
|
||||||
uint32 blockSize, uint32 blockShift,
|
uint32 blockSize, uint32 blockShift,
|
||||||
|
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||||
partition_descriptor partitionDescriptors[],
|
partition_descriptor partitionDescriptors[],
|
||||||
uint8 &partitionDescriptorCount);
|
uint8 &partitionDescriptorCount);
|
||||||
@@ -25,6 +33,7 @@ walk_anchor_volume_descriptor_sequences(int device, off_t offset, off_t length,
|
|||||||
static status_t
|
static status_t
|
||||||
walk_volume_descriptor_sequence(extent_address descriptorSequence, int device,
|
walk_volume_descriptor_sequence(extent_address descriptorSequence, int device,
|
||||||
uint32 blockSize, uint32 blockShift,
|
uint32 blockSize, uint32 blockShift,
|
||||||
|
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||||
partition_descriptor partitionDescriptors[],
|
partition_descriptor partitionDescriptors[],
|
||||||
uint8 &partitionDescriptorCount);
|
uint8 &partitionDescriptorCount);
|
||||||
@@ -40,7 +49,8 @@ walk_integrity_sequence(int device, uint32 blockSize, uint32 blockShift,
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
udf_recognize(int device, off_t offset, off_t length, uint32 blockSize,
|
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[],
|
partition_descriptor partitionDescriptors[],
|
||||||
uint8 &partitionDescriptorCount)
|
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
|
// Now hunt down a volume descriptor sequence from one of
|
||||||
// the anchor volume pointers (if there are any).
|
// the anchor volume pointers (if there are any).
|
||||||
status = walk_anchor_volume_descriptor_sequences(device, offset, length,
|
status = walk_anchor_volume_descriptor_sequences(device, offset, length,
|
||||||
blockSize, blockShift, logicalVolumeDescriptor, partitionDescriptors,
|
blockSize, blockShift, primaryVolumeDescriptor,
|
||||||
|
logicalVolumeDescriptor, partitionDescriptors,
|
||||||
partitionDescriptorCount);
|
partitionDescriptorCount);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
TRACE_ERROR(("udf_recognize: cannot find volume descriptor. status = %ld\n",
|
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
|
static status_t
|
||||||
walk_anchor_volume_descriptor_sequences(int device, off_t offset, off_t length,
|
walk_anchor_volume_descriptor_sequences(int device, off_t offset, off_t length,
|
||||||
uint32 blockSize, uint32 blockShift,
|
uint32 blockSize, uint32 blockShift,
|
||||||
|
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||||
partition_descriptor partitionDescriptors[],
|
partition_descriptor partitionDescriptors[],
|
||||||
uint8 &partitionDescriptorCount)
|
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
|
// Found an avds, so try the main sequence first, then
|
||||||
// the reserve sequence if the main one fails.
|
// the reserve sequence if the main one fails.
|
||||||
anchorErr = walk_volume_descriptor_sequence(anchor->main_vds(),
|
anchorErr = walk_volume_descriptor_sequence(anchor->main_vds(),
|
||||||
device, blockSize, blockShift, logicalVolumeDescriptor,
|
device, blockSize, blockShift, primaryVolumeDescriptor,
|
||||||
partitionDescriptors, partitionDescriptorCount);
|
logicalVolumeDescriptor, partitionDescriptors,
|
||||||
|
partitionDescriptorCount);
|
||||||
|
|
||||||
if (anchorErr)
|
if (anchorErr)
|
||||||
anchorErr = walk_volume_descriptor_sequence(anchor->reserve_vds(),
|
anchorErr = walk_volume_descriptor_sequence(anchor->reserve_vds(),
|
||||||
device, blockSize, blockShift, logicalVolumeDescriptor,
|
device, blockSize, blockShift, primaryVolumeDescriptor,
|
||||||
partitionDescriptors, partitionDescriptorCount);
|
logicalVolumeDescriptor, partitionDescriptors,
|
||||||
|
partitionDescriptorCount);
|
||||||
}
|
}
|
||||||
if (!anchorErr) {
|
if (!anchorErr) {
|
||||||
PRINT(("block %Ld: found valid vds\n", avds_locations[i]));
|
PRINT(("block %Ld: found valid vds\n", avds_locations[i]));
|
||||||
@@ -225,6 +239,7 @@ static
|
|||||||
status_t
|
status_t
|
||||||
walk_volume_descriptor_sequence(extent_address descriptorSequence,
|
walk_volume_descriptor_sequence(extent_address descriptorSequence,
|
||||||
int device, uint32 blockSize, uint32 blockShift,
|
int device, uint32 blockSize, uint32 blockShift,
|
||||||
|
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||||
partition_descriptor partitionDescriptors[],
|
partition_descriptor partitionDescriptors[],
|
||||||
uint8 &partitionDescriptorCount)
|
uint8 &partitionDescriptorCount)
|
||||||
@@ -271,7 +286,7 @@ walk_volume_descriptor_sequence(extent_address descriptorSequence,
|
|||||||
{
|
{
|
||||||
primary_volume_descriptor *primary = reinterpret_cast<primary_volume_descriptor*>(tag);
|
primary_volume_descriptor *primary = reinterpret_cast<primary_volume_descriptor*>(tag);
|
||||||
PDUMP(primary);
|
PDUMP(primary);
|
||||||
(void)primary; // kill the warning
|
primaryVolumeDescriptor = *primary;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
//----------------------------------------------------------------------
|
/*
|
||||||
// This software is part of the OpenBeOS distribution and is covered
|
* Copyright 2012, Jérôme Duval, [email protected].
|
||||||
// by the OpenBeOS license.
|
* Copyright 2003, Tyler Dauwalder, [email protected].
|
||||||
//
|
* Distributed under the terms of the MIT License.
|
||||||
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
*/
|
||||||
//---------------------------------------------------------------------
|
|
||||||
#ifndef _UDF_RECOGNITION_H
|
#ifndef _UDF_RECOGNITION_H
|
||||||
#define _UDF_RECOGNITION_H
|
#define _UDF_RECOGNITION_H
|
||||||
|
|
||||||
@@ -14,9 +13,10 @@
|
|||||||
#include "UdfDebug.h"
|
#include "UdfDebug.h"
|
||||||
|
|
||||||
status_t udf_recognize(int device, off_t offset, off_t length,
|
status_t udf_recognize(int device, off_t offset, off_t length,
|
||||||
uint32 blockSize, uint32 &blockShift,
|
uint32 blockSize, uint32 &blockShift,
|
||||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
primary_volume_descriptor &primaryVolumeDescriptor,
|
||||||
partition_descriptor partitionDescriptors[],
|
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||||
uint8 &partitionDescriptorCount);
|
partition_descriptor partitionDescriptors[],
|
||||||
|
uint8 &partitionDescriptorCount);
|
||||||
|
|
||||||
#endif // _UDF_RECOGNITION_H
|
#endif // _UDF_RECOGNITION_H
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
//----------------------------------------------------------------------
|
/*
|
||||||
// This software is part of the OpenBeOS distribution and is covered
|
* Copyright 2012, Jérôme Duval, [email protected].
|
||||||
// by the OpenBeOS license.
|
* Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
||||||
//
|
* This file may be used under the terms of the MIT License.
|
||||||
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
*/
|
||||||
//----------------------------------------------------------------------
|
|
||||||
|
|
||||||
/*! \file UdfStructures.cpp
|
/*! \file UdfStructures.cpp
|
||||||
|
|
||||||
@@ -38,20 +38,6 @@ const char* kVSDID_ECMA167_2 = "NSR02";
|
|||||||
const char* kVSDID_ECMA167_3 = "NSR03";
|
const char* kVSDID_ECMA167_3 = "NSR03";
|
||||||
const char* kVSDID_ECMA168 = "CDW02";
|
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
|
//! crc 010041 table, as generated by crc_table.cpp
|
||||||
const uint16 kCrcTable[256] = {
|
const uint16 kCrcTable[256] = {
|
||||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
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_MAPS
|
||||||
* UDF_MAX_PARTITION_MAP_SIZE);
|
* 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
|
// Helper functions
|
||||||
@@ -527,7 +547,7 @@ descriptor_tag::init_check(uint32 block, bool calculateCrc)
|
|||||||
{
|
{
|
||||||
DEBUG_INIT_ETC("descriptor_tag", ("location: %ld, calculateCrc: %s",
|
DEBUG_INIT_ETC("descriptor_tag", ("location: %ld, calculateCrc: %s",
|
||||||
block, bool_to_string(calculateCrc)));
|
block, bool_to_string(calculateCrc)));
|
||||||
PRINT(("location (paramater) == %ld\n", block));
|
PRINT(("location (parameter) == %ld\n", block));
|
||||||
PRINT(("location (in structure) == %ld\n", location()));
|
PRINT(("location (in structure) == %ld\n", location()));
|
||||||
if (calculateCrc) {
|
if (calculateCrc) {
|
||||||
PRINT(("crc (calculated) == %d\n",
|
PRINT(("crc (calculated) == %d\n",
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
//----------------------------------------------------------------------
|
/*
|
||||||
// This software is part of the OpenBeOS distribution and is covered
|
* Copyright 2012, Jérôme Duval, [email protected].
|
||||||
// by the OpenBeOS license.
|
* Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
||||||
//
|
* This file may be used under the terms of the MIT License.
|
||||||
// Copyright (c) 2003 Tyler Dauwalder, [email protected]
|
*/
|
||||||
//---------------------------------------------------------------------
|
|
||||||
#ifndef _UDF_DISK_STRUCTURES_H
|
#ifndef _UDF_DISK_STRUCTURES_H
|
||||||
#define _UDF_DISK_STRUCTURES_H
|
#define _UDF_DISK_STRUCTURES_H
|
||||||
|
|
||||||
@@ -121,7 +120,8 @@ public:
|
|||||||
uint8 microsecond() const { return _microsecond; }
|
uint8 microsecond() const { return _microsecond; }
|
||||||
|
|
||||||
// Set functions
|
// 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) {
|
void set_type(uint8 type) {
|
||||||
type_and_timezone_accessor t;
|
type_and_timezone_accessor t;
|
||||||
t.type_and_timezone = type_and_timezone();
|
t.type_and_timezone = type_and_timezone();
|
||||||
@@ -141,7 +141,8 @@ public:
|
|||||||
void set_minute(uint8 minute) { _minute = minute; }
|
void set_minute(uint8 minute) { _minute = minute; }
|
||||||
void set_second(uint8 second) { _second = second; }
|
void set_second(uint8 second) { _second = second; }
|
||||||
void set_centisecond(uint8 centisecond) { _centisecond = centisecond; }
|
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; }
|
void set_microsecond(uint8 microsecond) { _microsecond = microsecond; }
|
||||||
private:
|
private:
|
||||||
void _clear();
|
void _clear();
|
||||||
@@ -293,17 +294,18 @@ private:
|
|||||||
array<uint8, kIdentifierSuffixLength> _identifier_suffix;
|
array<uint8, kIdentifierSuffixLength> _identifier_suffix;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
extern const entity_id kMetadataPartitionMapId;
|
extern entity_id kMetadataPartitionMapId;
|
||||||
extern const entity_id kSparablePartitionMapId;
|
extern entity_id kSparablePartitionMapId;
|
||||||
extern const entity_id kVirtualPartitionMapId;
|
extern entity_id kVirtualPartitionMapId;
|
||||||
extern const entity_id kImplementationId;
|
extern entity_id kImplementationId;
|
||||||
extern const entity_id kPartitionContentsId1xx;
|
extern entity_id kPartitionContentsId1xx;
|
||||||
extern const entity_id kPartitionContentsId2xx;
|
extern entity_id kPartitionContentsId2xx;
|
||||||
extern const entity_id kUdfId;
|
extern entity_id kUdfId;
|
||||||
extern const entity_id kLogicalVolumeInfoId150;
|
extern entity_id kLogicalVolumeInfoId150;
|
||||||
extern const entity_id kLogicalVolumeInfoId201;
|
extern entity_id kLogicalVolumeInfoId201;
|
||||||
extern const entity_id kDomainId150;
|
extern entity_id kDomainId150;
|
||||||
extern const entity_id kDomainId201;
|
extern entity_id kDomainId201;
|
||||||
|
extern void init_entities(void);
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// ECMA-167 Part 2
|
// ECMA-167 Part 2
|
||||||
@@ -1307,6 +1309,49 @@ private:
|
|||||||
See also: UDF-2.50 2.2.10
|
See also: UDF-2.50 2.2.10
|
||||||
*/
|
*/
|
||||||
struct metadata_partition_map {
|
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 type;
|
||||||
uint8 length;
|
uint8 length;
|
||||||
uint8 reserved1[2];
|
uint8 reserved1[2];
|
||||||
@@ -1315,14 +1360,20 @@ struct metadata_partition_map {
|
|||||||
- identifier: "*UDF Metadata Partition"
|
- identifier: "*UDF Metadata Partition"
|
||||||
- identifier_suffix: per UDF-2.50 2.1.5
|
- identifier_suffix: per UDF-2.50 2.1.5
|
||||||
*/
|
*/
|
||||||
entity_id partition_type_id;
|
entity_id _partition_type_id;
|
||||||
uint16 volume_sequence_number;
|
uint16 _volume_sequence_number;
|
||||||
|
|
||||||
/*! corresponding type 1 or type 2 sparable partition
|
/*! corresponding type 1 or type 2 sparable partition
|
||||||
map in same logical volume
|
map in same logical volume
|
||||||
*/
|
*/
|
||||||
uint16 partition_number;
|
uint16 _partition_number;
|
||||||
uint8 reserved2[24];
|
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));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
@@ -1470,7 +1521,7 @@ enum {
|
|||||||
|
|
||||||
/*! \brief Highest currently supported UDF read revision.
|
/*! \brief Highest currently supported UDF read revision.
|
||||||
*/
|
*/
|
||||||
#define UDF_MAX_READ_REVISION 0x0201
|
#define UDF_MAX_READ_REVISION 0x0250
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// ECMA-167 Part 4
|
// 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.
|
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -79,8 +80,16 @@ get_block_shift(uint32 blockSize, uint32 &blockShift)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
time_t
|
#define EPOCH_YEAR 1970
|
||||||
make_time(timestamp ×tamp)
|
#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, "
|
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(),
|
"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.timezone(),timestamp.year(),
|
||||||
timestamp.month(), timestamp.day(), timestamp.hour(), timestamp.minute(), timestamp.second()));
|
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;
|
time_t result = 0;
|
||||||
|
const int monthLengths[12]
|
||||||
|
= { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||||
|
|
||||||
if (timestamp.year() >= 1970) {
|
int year = timestamp.year();
|
||||||
const int monthLengths[12]
|
int month = timestamp.month();
|
||||||
= { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
int day = timestamp.day();
|
||||||
|
int hour = timestamp.hour();
|
||||||
|
int minute = timestamp.minute();
|
||||||
|
int second = timestamp.second();
|
||||||
|
|
||||||
int year = timestamp.year();
|
// Range check the timezone offset, then round it down
|
||||||
int month = timestamp.month();
|
// to the nearest hour, since no one I know treats timezones
|
||||||
int day = timestamp.day();
|
// with a per-minute granularity, and none of the other OSes
|
||||||
int hour = timestamp.hour();
|
// I've looked at appear to either.
|
||||||
int minute = timestamp.minute();
|
int timezone_offset = 0;
|
||||||
int second = timestamp.second();
|
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
|
int previousLeapYears = (year - 1968) / 4;
|
||||||
// to the nearest hour, since no one I know treats timezones
|
bool isLeapYear = (year - 1968) % 4 == 0;
|
||||||
// with a per-minute granularity, and none of the other OSes
|
if (isLeapYear)
|
||||||
// I've looked at appear to either.
|
--previousLeapYears;
|
||||||
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;
|
// Years to days
|
||||||
bool isLeapYear = (year - 1968) % 4 == 0;
|
result = (year - EPOCH_YEAR) * DAYSPERNYEAR + previousLeapYears;
|
||||||
if (isLeapYear)
|
// Months to days
|
||||||
--previousLeapYears;
|
for (int i = 0; i < month-1; i++) {
|
||||||
|
result += monthLengths[i];
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
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);
|
uint16 calculate_crc(uint8 *data, uint16 length);
|
||||||
status_t check_size_error(ssize_t bytesReturned, ssize_t bytesExpected);
|
status_t check_size_error(ssize_t bytesReturned, ssize_t bytesExpected);
|
||||||
status_t get_block_shift(uint32 blockSize, uint32 &blockShift);
|
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);
|
long_address to_long_address(ino_t id, uint32 length = 0);
|
||||||
ino_t to_vnode_id(long_address address);
|
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 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com
|
||||||
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
|
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@@ -8,6 +9,7 @@
|
|||||||
|
|
||||||
#include "Icb.h"
|
#include "Icb.h"
|
||||||
#include "MemoryChunk.h"
|
#include "MemoryChunk.h"
|
||||||
|
#include "MetadataPartition.h"
|
||||||
#include "PhysicalPartition.h"
|
#include "PhysicalPartition.h"
|
||||||
#include "Recognition.h"
|
#include "Recognition.h"
|
||||||
|
|
||||||
@@ -62,6 +64,7 @@ Volume::Mount(const char *deviceName, off_t offset, off_t length,
|
|||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_INIT_ETC("Volume", ("deviceName: %s", deviceName));
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
// If the device is actually a normal file, try to disable the cache
|
// 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
|
// Run through the volume recognition and descriptor sequences to
|
||||||
// see if we have a potentially valid UDF volume on our hands
|
// see if we have a potentially valid UDF volume on our hands
|
||||||
status = udf_recognize(device, offset, length, blockSize, blockShift,
|
status = udf_recognize(device, offset, length, blockSize, blockShift,
|
||||||
logicalVolumeDescriptor, partitionDescriptors,
|
fPrimaryVolumeDescriptor, logicalVolumeDescriptor,
|
||||||
partitionDescriptorCount);
|
partitionDescriptors, partitionDescriptorCount);
|
||||||
|
|
||||||
// Set up the block cache
|
// Set up the block cache
|
||||||
if (!status) {
|
if (!status) {
|
||||||
@@ -163,8 +166,43 @@ Volume::Mount(const char *deviceName, off_t offset, off_t length,
|
|||||||
TRACE(("map type: metadata\n"));
|
TRACE(("map type: metadata\n"));
|
||||||
metadata_partition_map* map =
|
metadata_partition_map* map =
|
||||||
reinterpret_cast<metadata_partition_map*>(header);
|
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 {
|
} else {
|
||||||
TRACE(("map type: unrecognized (`%.23s')\n",
|
TRACE(("map type: unrecognized (`%.23s')\n",
|
||||||
typeId.identifier()));
|
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.
|
// Do some checking as to what sorts of partitions we've actually found.
|
||||||
if (!status) {
|
if (!status) {
|
||||||
status = (physicalCount == 1 && virtualCount == 0
|
status = (physicalCount == 1 && virtualCount == 0
|
||||||
&& sparableCount == 0 && metadataCount == 0)
|
&& sparableCount == 0)
|
||||||
|| (physicalCount == 2 && virtualCount == 0
|
|| (physicalCount == 2 && virtualCount == 0
|
||||||
&& sparableCount == 0 && metadataCount == 0)
|
&& sparableCount == 0)
|
||||||
? B_OK : B_ERROR;
|
? B_OK : B_ERROR;
|
||||||
if (status) {
|
if (status) {
|
||||||
TRACE(("Invalid partition layout found:\n"));
|
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",
|
TRACE(("Volume::MapBlock: partition = %d, block = %ld, mappedBlock = %p\n",
|
||||||
address.partition(), address.block(), mappedBlock));
|
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;
|
status_t error = mappedBlock ? B_OK : B_BAD_VALUE;
|
||||||
if (!error) {
|
if (!error) {
|
||||||
Partition *partition = _GetPartition(address.partition());
|
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 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com
|
||||||
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
|
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@@ -50,6 +51,8 @@ public:
|
|||||||
uint32 BlockShift() const { return fBlockShift; }
|
uint32 BlockShift() const { return fBlockShift; }
|
||||||
bool Mounted() const { return fMounted; }
|
bool Mounted() const { return fMounted; }
|
||||||
Icb* RootIcb() { return fRootIcb; }
|
Icb* RootIcb() { return fRootIcb; }
|
||||||
|
primary_volume_descriptor *PrimaryVolumeDescriptor()
|
||||||
|
{ return &fPrimaryVolumeDescriptor; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _Unset();
|
void _Unset();
|
||||||
@@ -69,6 +72,7 @@ private:
|
|||||||
off_t fOffset;
|
off_t fOffset;
|
||||||
Partition *fPartitions[UDF_MAX_PARTITION_MAPS];
|
Partition *fPartitions[UDF_MAX_PARTITION_MAPS];
|
||||||
Icb *fRootIcb; // Destroyed by vfs via callback to put_node()
|
Icb *fRootIcb; // Destroyed by vfs via callback to put_node()
|
||||||
|
primary_volume_descriptor fPrimaryVolumeDescriptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _UDF_VOLUME_H
|
#endif // _UDF_VOLUME_H
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
|
* Copyright 2012, Jérôme Duval, korli@users.berlios.de.
|
||||||
* Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com.
|
|
||||||
* Copyright 2010, Michael Lotz, mmlr@mlotz.ch.
|
* 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.
|
* 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->offset, partition->size, partition->content_size,
|
||||||
partition->block_size));
|
partition->block_size));
|
||||||
|
|
||||||
|
primary_volume_descriptor primaryVolumeDescriptor;
|
||||||
logical_volume_descriptor logicalVolumeDescriptor;
|
logical_volume_descriptor logicalVolumeDescriptor;
|
||||||
partition_descriptor partitionDescriptors[kMaxPartitionDescriptors];
|
partition_descriptor partitionDescriptors[kMaxPartitionDescriptors];
|
||||||
uint8 descriptorCount = kMaxPartitionDescriptors;
|
uint8 descriptorCount = kMaxPartitionDescriptors;
|
||||||
uint32 blockShift;
|
uint32 blockShift;
|
||||||
status_t error = udf_recognize(fd, partition->offset, partition->size,
|
status_t error = udf_recognize(fd, partition->offset, partition->size,
|
||||||
partition->block_size, blockShift, logicalVolumeDescriptor,
|
partition->block_size, blockShift, primaryVolumeDescriptor,
|
||||||
partitionDescriptors, descriptorCount);
|
logicalVolumeDescriptor, partitionDescriptors, descriptorCount);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return -1;
|
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
|
// File times. For now, treat the modification time as creation
|
||||||
// time as well, since true creation time is an optional extended
|
// time as well, since true creation time is an optional extended
|
||||||
// attribute, and supporting EAs is going to be a PITA. ;-)
|
// attribute, and supporting EAs is going to be a PITA. ;-)
|
||||||
stat->st_atime = icb->AccessTime();
|
icb->GetAccessTime(stat->st_atim);
|
||||||
stat->st_mtime = stat->st_ctime = stat->st_crtime = icb->ModificationTime();
|
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,
|
TRACE(("udf_read_stat: mode = 0x%x, st_ino: %Ld\n", stat->st_mode,
|
||||||
stat->st_ino));
|
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));
|
((Volume *)volume->private_volume)->ID(), pos, *length));
|
||||||
|
|
||||||
Icb *icb = (Icb *)vnode->private_node;
|
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()) {
|
// if (!inode->HasUserAccessableStream()) {
|
||||||
// *_length = 0;
|
// *_length = 0;
|
||||||
@@ -385,6 +393,8 @@ 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)
|
||||||
{
|
{
|
||||||
TRACE(("udf_open_dir: volume = %p, vnode = %p\n", volume, vnode));
|
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)
|
if (!volume || !vnode || !cookie)
|
||||||
RETURN(B_BAD_VALUE);
|
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;
|
Icb *dir = (Icb *)vnode->private_node;
|
||||||
DirectoryIterator *iterator = (DirectoryIterator *)cookie;
|
DirectoryIterator *iterator = (DirectoryIterator *)cookie;
|
||||||
|
|
||||||
|
DEBUG_INIT_ETC("udf_read_dir", ("ID = %ld", volume->ID()));
|
||||||
|
|
||||||
if (dir != iterator->Parent()) {
|
if (dir != iterator->Parent()) {
|
||||||
TRACE_ERROR(("udf_read_dir: Icb does not match parent Icb of given "
|
TRACE_ERROR(("udf_read_dir: Icb does not match parent Icb of given "
|
||||||
"DirectoryIterator! (iterator->Parent = %p)\n", iterator->Parent()));
|
"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",
|
TRACE(("udf_rewind_dir: volume = %p, vnode = %p, cookie = %p\n",
|
||||||
volume, vnode, cookie));
|
volume, vnode, cookie));
|
||||||
|
DEBUG_INIT_ETC("udf_rewind_dir", ("ID = %ld",
|
||||||
|
((Volume *)volume->private_volume)->ID()));
|
||||||
|
|
||||||
if (!volume || !vnode || !cookie)
|
if (!volume || !vnode || !cookie)
|
||||||
RETURN(B_BAD_VALUE);
|
RETURN(B_BAD_VALUE);
|
||||||
@@ -604,6 +618,8 @@ udf_std_ops(int32 op, ...)
|
|||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case B_MODULE_INIT:
|
case B_MODULE_INIT:
|
||||||
|
init_entities();
|
||||||
|
return B_OK;
|
||||||
case B_MODULE_UNINIT:
|
case B_MODULE_UNINIT:
|
||||||
return B_OK;
|
return B_OK;
|
||||||
default:
|
default:
|
||||||
|
|||||||
Reference in New Issue
Block a user