2 * Copyright 2012, Jérôme Duval, korli@users.berlios.de.
3 * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
4 * Distributed under the terms of the MIT License.
7 /*! \file Utils.cpp - Miscellaneous Udf utility functions. */
9 #include "UdfStructures.h"
13 extern int32 timezone_offset
;
16 /*! \brief Returns "true" if \a value is true, "false" otherwise. */
18 bool_to_string(bool value
)
20 return value
? "true" : "false";
24 /*! \brief Calculates the UDF crc checksum for the given byte stream.
26 Based on crc code from UDF-2.50 6.5, as permitted.
28 \param data Pointer to the byte stream.
29 \param length Length of the byte stream in bytes.
31 \return The crc checksum, or 0 if an error occurred.
34 calculate_crc(uint8
*data
, uint16 length
)
38 for ( ; length
> 0; length
--, data
++)
39 crc
= kCrcTable
[(crc
>> 8 ^ *data
) & 0xff] ^ (crc
<< 8);
45 /*! \brief Takes an overloaded ssize_t return value like those returned
46 by BFile::Read() and friends, as well as an expected number of bytes,
47 and returns B_OK if the byte counts match, or the appropriate error
51 check_size_error(ssize_t bytesReturned
, ssize_t bytesExpected
)
53 return bytesReturned
== bytesExpected
54 ? B_OK
: (bytesReturned
>= 0 ? B_IO_ERROR
: status_t(bytesReturned
));
58 /*! \brief Calculates the block shift amount for the given
59 block size, which must be a positive power of 2.
62 get_block_shift(uint32 blockSize
, uint32
&blockShift
)
68 for (int i
= 0; i
< 32; i
++) {
69 // Zero out all bits except bit i
70 uint32 block
= blockSize
& (uint32(1) << i
);
83 #define EPOCH_YEAR 1970
86 #define MINSPERHOUR 60
87 #define HOURSPERDAY 24
88 #define SECSPERDAY (SECSPERMIN * MINSPERHOUR * HOURSPERDAY)
89 #define DAYSPERNYEAR 365
92 decode_time(timestamp
×tamp
, struct timespec
×pec
)
94 DEBUG_INIT_ETC(NULL
, ("timestamp: (tnt: 0x%x, type: %d, timezone: %d = 0x%x, year: %d, "
95 "month: %d, day: %d, hour: %d, minute: %d, second: %d)", timestamp
.type_and_timezone(),
96 timestamp
.type(), timestamp
.timezone(),
97 timestamp
.timezone(),timestamp
.year(),
98 timestamp
.month(), timestamp
.day(), timestamp
.hour(), timestamp
.minute(), timestamp
.second()));
100 if (timestamp
.year() < EPOCH_YEAR
|| timestamp
.year() >= EPOCH_YEAR
+ MAX_YEAR
)
104 const int monthLengths
[12]
105 = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
107 int year
= timestamp
.year();
108 int month
= timestamp
.month();
109 int day
= timestamp
.day();
110 int hour
= timestamp
.hour();
111 int minute
= timestamp
.minute();
112 int second
= timestamp
.second();
114 // Range check the timezone offset, then round it down
115 // to the nearest hour, since no one I know treats timezones
116 // with a per-minute granularity, and none of the other OSes
117 // I've looked at appear to either.
118 int timezone_offset
= 0;
119 if (timestamp
.type() == 1)
120 timezone_offset
= timestamp
.timezone();
121 if (-SECSPERDAY
> timezone_offset
|| timezone_offset
> SECSPERDAY
)
123 timezone_offset
-= timezone_offset
% 60;
125 int previousLeapYears
= (year
- 1968) / 4;
126 bool isLeapYear
= (year
- 1968) % 4 == 0;
131 result
= (year
- EPOCH_YEAR
) * DAYSPERNYEAR
+ previousLeapYears
;
133 for (int i
= 0; i
< month
-1; i
++) {
134 result
+= monthLengths
[i
];
136 if (month
> 2 && isLeapYear
)
139 result
= (result
+ day
- 1) * HOURSPERDAY
;
141 result
= (result
+ hour
) * MINSPERHOUR
+ timezone_offset
;
142 // Minutes to seconds
143 result
= (result
+ minute
) * SECSPERMIN
+ second
;
145 timespec
.tv_sec
= result
;
146 timespec
.tv_nsec
= 1000 * (timestamp
.microsecond()
147 + timestamp
.hundred_microsecond() * 100
148 + timestamp
.centisecond() * 10000);
154 to_long_address(ino_t id
, uint32 length
)
156 TRACE(("udf_to_long_address: ino_t = %" B_PRIdINO
", length = %" B_PRIu32
,
159 result
.set_block((id
>> 16) & 0xffffffff);
160 result
.set_partition(id
& 0xffff);
161 result
.set_length(length
);
168 to_vnode_id(long_address address
)
171 ino_t result
= address
.block();
173 result
|= address
.partition();
174 TRACE(("block: %" B_PRIu32
", 0x%" B_PRIx32
"\n", address
.block(),
176 TRACE(("partition: %d, 0x%x\n", address
.partition(), address
.partition()));
177 TRACE(("length: %" B_PRIu32
", 0x%" B_PRIx32
"\n", address
.length(),
179 TRACE(("ino_t: %" B_PRIdINO
"\n", result
));