* 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.
*/
#include "UdfStructures.h"
#include "Utils.h"
extern "C" {
extern int32 timezone_offset;
}
const char*
bool_to_string(bool value)
{
return value ? "true" : "false";
}
Based on crc code from UDF-2.50 6.5, as permitted.
\param data Pointer to the byte stream.
\param length Length of the byte stream in bytes.
\return The crc checksum, or 0 if an error occurred.
*/
uint16
calculate_crc(uint8 *data, uint16 length)
{
uint16 crc = 0;
if (data) {
for ( ; length > 0; length--, data++)
crc = kCrcTable[(crc >> 8 ^ *data) & 0xff] ^ (crc << 8);
}
return crc;
}
by BFile::Read() and friends, as well as an expected number of bytes,
and returns B_OK if the byte counts match, or the appropriate error
code otherwise.
*/
status_t
check_size_error(ssize_t bytesReturned, ssize_t bytesExpected)
{
return bytesReturned == bytesExpected
? B_OK : (bytesReturned >= 0 ? B_IO_ERROR : status_t(bytesReturned));
}
block size, which must be a positive power of 2.
*/
status_t
get_block_shift(uint32 blockSize, uint32 &blockShift)
{
if (blockSize == 0)
return B_BAD_VALUE;
uint32 bitCount = 0;
uint32 result = 0;
for (int i = 0; i < 32; i++) {
uint32 block = blockSize & (uint32(1) << i);
if (block) {
if (++bitCount > 1)
return B_BAD_VALUE;
else
result = i;
}
}
blockShift = result;
return B_OK;
}
#define EPOCH_YEAR 1970
#define MAX_YEAR 69
#define SECSPERMIN 60
#define MINSPERHOUR 60
#define HOURSPERDAY 24
#define SECSPERDAY (SECSPERMIN * MINSPERHOUR * HOURSPERDAY)
#define DAYSPERNYEAR 365
status_t
decode_time(timestamp ×tamp, struct timespec ×pec)
{
DEBUG_INIT_ETC(NULL, ("timestamp: (tnt: 0x%x, type: %d, timezone: %d = 0x%x, year: %d, "
"month: %d, day: %d, hour: %d, minute: %d, second: %d)", timestamp.type_and_timezone(),
timestamp.type(), timestamp.timezone(),
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 };
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 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;
int previousLeapYears = (year - 1968) / 4;
bool isLeapYear = (year - 1968) % 4 == 0;
if (isLeapYear)
--previousLeapYears;
result = (year - EPOCH_YEAR) * DAYSPERNYEAR + previousLeapYears;
for (int i = 0; i < month-1; i++) {
result += monthLengths[i];
}
if (month > 2 && isLeapYear)
++result;
result = (result + day - 1) * HOURSPERDAY;
result = (result + hour) * MINSPERHOUR + timezone_offset;
result = (result + minute) * SECSPERMIN + second;
timespec.tv_sec = result;
timespec.tv_nsec = 1000 * (timestamp.microsecond()
+ timestamp.hundred_microsecond() * 100
+ timestamp.centisecond() * 10000);
return B_OK;
}
long_address
to_long_address(ino_t id, uint32 length)
{
TRACE(("udf_to_long_address: ino_t = %" B_PRIdINO ", length = %" B_PRIu32,
id, length));
long_address result;
result.set_block((id >> 16) & 0xffffffff);
result.set_partition(id & 0xffff);
result.set_length(length);
DUMP(result);
return result;
}
ino_t
to_vnode_id(long_address address)
{
DEBUG_INIT(NULL);
ino_t result = address.block();
result <<= 16;
result |= address.partition();
TRACE(("block: %" B_PRIu32 ", 0x%" B_PRIx32 "\n", address.block(),
address.block()));
TRACE(("partition: %d, 0x%x\n", address.partition(), address.partition()));
TRACE(("length: %" B_PRIu32 ", 0x%" B_PRIx32 "\n", address.length(),
address.length()));
TRACE(("ino_t: %" B_PRIdINO "\n", result));
return result;
}