xref: /haiku/src/add-ons/kernel/file_systems/udf/Volume.h (revision 51978af14a173e7fae0563b562be5603bc652aeb)
1 //----------------------------------------------------------------------
2 //  This software is part of the OpenBeOS distribution and is covered
3 //  by the OpenBeOS license.
4 //
5 //  Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
6 //  Mad props to Axel Dörfler and his BFS implementation, from which
7 //  this UDF implementation draws much influence (and a little code :-P).
8 //---------------------------------------------------------------------
9 #ifndef _UDF_VOLUME_H
10 #define _UDF_VOLUME_H
11 
12 /*! \file Volume.h
13 */
14 
15 #include <KernelExport.h>
16 extern "C" {
17 	#ifndef _IMPEXP_KERNEL
18 	#	define _IMPEXP_KERNEL
19 	#endif
20 
21 	#include <fsproto.h>
22 }
23 
24 #include "kernel_cpp.h"
25 #include "UdfDebug.h"
26 
27 #include "CS0String.h"
28 #include "DiskStructures.h"
29 #include "PartitionMap.h"
30 
31 namespace Udf {
32 
33 class Icb;
34 
35 class Volume {
36 public:
37 	static status_t Identify(int device, off_t offset, off_t length, uint32 blockSize, char *volumeName);
38 
39 	Volume(nspace_id id);
40 
41 	status_t Mount(const char *deviceName, off_t volumeStart, off_t volumeLength, uint32 flags,
42 	               uint32 blockSize = 2048);
43 	status_t Unmount();
44 
45 	const char *Name() const;
46 	int Device() const { return fDevice; }
47 	nspace_id Id() const { return fId; }
48 
49 	off_t Offset() const { return fOffset; }
50 	off_t Length() const { return fLength; }
51 
52 	uint32 BlockSize() const { return fBlockSize; }
53 	uint32 BlockShift() const { return fBlockShift; }
54 
55 	off_t AddressForRelativeBlock(off_t block) { return (Offset() + block) * BlockSize(); }
56 	off_t RelativeAddress(off_t address) { return Offset() * BlockSize() + address; }
57 
58 	bool IsReadOnly() const { return fReadOnly; }
59 
60 	vnode_id ToVnodeId(off_t block) const { return (vnode_id)block; }
61 
62 	template <class AddressType>
63 		ssize_t Read(AddressType address, ssize_t length, void *data);
64 
65 #if (!DRIVE_SETUP_ADDON)
66 	Icb* RootIcb() { return fRootIcb; }
67 #endif
68 
69 	status_t MapAddress(udf_long_address address, off_t *mappedAddress);
70 	off_t MapAddress(udf_extent_address address);
71 	status_t MapBlock(udf_long_address address, off_t *mappedBlock);
72 	off_t MapAddress(udf_short_address address);
73 private:
74 	Volume();						// unimplemented
75 	Volume(const Volume &ref);		// unimplemented
76 	Volume& operator=(const Volume &ref);	// unimplemented
77 
78 	status_t _InitStatus() const { return fInitStatus; }
79 	// Private _InitStatus() status_t values
80 	enum {
81 		B_UNINITIALIZED = B_ERRORS_END+1,	//!< Completely uninitialized
82 		B_DEVICE_INITIALIZED,				//!< Initialized enough to access underlying device safely
83 		B_IDENTIFIED,						//!< Verified to be a UDF volume on disc
84 		B_LOGICAL_VOLUME_INITIALIZED,		//!< Initialized enough to map addresses
85 
86 		B_INITIALIZED = B_OK,
87 	};
88 
89 
90 	// Called by Mount(), either directly or indirectly
91 	status_t _Init(int device, off_t offset, off_t length, int blockSize);
92 	status_t _Identify();
93 	status_t _Mount();
94 	status_t _WalkVolumeRecognitionSequence();
95 	status_t _WalkAnchorVolumeDescriptorSequences();
96 	status_t _WalkVolumeDescriptorSequence(udf_extent_address extent);
97 	status_t _InitFileSetDescriptor();
98 
99 private:
100 	nspace_id fId;
101 	int fDevice;
102 	bool fReadOnly;
103 
104 	off_t fOffset;	//!< Starting block of the volume on the given device
105 	off_t fLength;	//!< Block length of volume on the given device
106 	uint32 fBlockSize;
107 	uint32 fBlockShift;
108 
109 	status_t fInitStatus;
110 
111 	udf_logical_descriptor fLogicalVD;
112 	PartitionMap fPartitionMap;
113 #if (!DRIVE_SETUP_ADDON)
114 	Icb *fRootIcb;	// Destroyed by vfs via callback to udf_release_node()
115 #endif
116 	CS0String fName;
117 };
118 
119 //----------------------------------------------------------------------
120 // Template functions
121 //----------------------------------------------------------------------
122 
123 
124 template <class AddressType>
125 status_t
126 Volume::Read(AddressType address, ssize_t length, void *data)
127 {
128 	DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume");
129 	off_t mappedAddress;
130 	status_t err = data ? B_OK : B_BAD_VALUE;
131 	if (!err)
132 		err = MapAddress(address, &mappedAddress);
133 	if (!err) {
134 		ssize_t bytesRead = read_pos(fDevice, mappedAddress, data, BlockSize());
135 		if (bytesRead != (ssize_t)BlockSize()) {
136 			err = B_IO_ERROR;
137 			PRINT(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", mappedAddress,
138 			       length, bytesRead));
139 		}
140 	}
141 	RETURN(err);
142 }
143 
144 
145 };	// namespace Udf
146 
147 #endif	// _UDF_VOLUME_H
148