2 * Copyright 2003-2013, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
22 Stream(int device
, FileBlock
&node
);
26 ssize_t
ReadAt(off_t offset
, uint8
*buffer
, size_t size
);
29 int32
BlockOffset(off_t offset
) const;
30 int32
BlockIndex(off_t offset
) const;
31 int32
ExtensionBlockOffset(off_t offset
) const;
32 status_t
ReadNextExtension();
37 int32 fExtensionBlockOffset
;
41 Stream::Stream(int device
, FileBlock
&node
)
46 void *buffer
= malloc(fNode
.BlockSize());
50 fExtensionBlockOffset
= 0;
51 fBlock
.SetTo(buffer
, fNode
.BlockSize());
57 free(fBlock
.BlockData());
64 return fBlock
.BlockData() != NULL
? B_OK
: B_NO_MEMORY
;
69 Stream::BlockOffset(off_t offset
) const
71 return offset
% fNode
.BlockSize();
76 Stream::BlockIndex(off_t offset
) const
78 return (offset
% (fNode
.BlockSize() * fNode
.NumDataBlocks())) / fNode
.BlockSize();
83 Stream::ExtensionBlockOffset(off_t offset
) const
85 return offset
/ (fNode
.BlockSize() * fNode
.NumDataBlocks());
90 Stream::ReadNextExtension()
93 if (fExtensionBlockOffset
== 0)
94 next
= fNode
.NextExtension();
96 next
= fBlock
.NextExtension();
98 if (read_pos(fDevice
, next
* fNode
.BlockSize(), fBlock
.BlockData(), fNode
.BlockSize()) < B_OK
)
101 return fBlock
.ValidateCheckSum();
106 Stream::ReadAt(off_t offset
, uint8
*buffer
, size_t size
)
110 if (offset
+ (off_t
)size
> fNode
.Size())
111 size
= fNode
.Size() - offset
;
113 ssize_t bytesLeft
= (ssize_t
)size
;
115 while (bytesLeft
!= 0) {
116 int32 extensionBlock
= ExtensionBlockOffset(offset
);
118 // get the right extension block
120 if (extensionBlock
< fExtensionBlockOffset
)
121 fExtensionBlockOffset
= 1;
123 while (fExtensionBlockOffset
< extensionBlock
) {
124 if (ReadNextExtension() != B_OK
)
127 fExtensionBlockOffset
++;
130 // read the data block into memory
133 if (extensionBlock
== 0)
134 block
= fNode
.DataBlock(BlockIndex(offset
));
136 block
= fBlock
.DataBlock(BlockIndex(offset
));
138 int32 blockOffset
= BlockOffset(offset
);
139 int32 toRead
= fNode
.BlockSize() - blockOffset
;
140 if (toRead
> bytesLeft
)
143 ssize_t bytesRead
= read_pos(fDevice
, block
* fNode
.BlockSize() + blockOffset
,
148 bytesLeft
-= bytesRead
;
150 offset
+= fNode
.BlockSize() - blockOffset
;
160 File::File(Volume
&volume
, int32 block
)
164 void *data
= malloc(volume
.BlockSize());
168 if (read_pos(volume
.Device(), block
* volume
.BlockSize(), data
, volume
.BlockSize()) == volume
.BlockSize())
169 fNode
.SetTo(data
, volume
.BlockSize());
184 return fNode
.ValidateCheckSum();
189 File::Open(void **_cookie
, int mode
)
191 Stream
*stream
= new(nothrow
) Stream(fVolume
.Device(), fNode
);
195 if (stream
->InitCheck() != B_OK
) {
200 *_cookie
= (void *)stream
;
206 File::Close(void *cookie
)
208 Stream
*stream
= (Stream
*)cookie
;
216 File::ReadAt(void *cookie
, off_t pos
, void *buffer
, size_t bufferSize
)
218 Stream
*stream
= (Stream
*)cookie
;
222 return stream
->ReadAt(pos
, (uint8
*)buffer
, bufferSize
);
227 File::WriteAt(void *cookie
, off_t pos
, const void *buffer
, size_t bufferSize
)
234 File::GetName(char *nameBuffer
, size_t bufferSize
) const
236 return fNode
.GetName(nameBuffer
, bufferSize
);
257 return fNode
.HeaderKey();