170081c0dSSalvatore Benedetto /*
2c530d46cSJérôme Duval * Copyright 2012, Jérôme Duval, korli@users.berlios.de.
370081c0dSSalvatore Benedetto * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net.
470081c0dSSalvatore Benedetto * Distributed under the terms of the MIT License.
524ec5f43STyler Dauwalder */
624ec5f43STyler Dauwalder
770081c0dSSalvatore Benedetto /*! \file Utils.cpp - Miscellaneous Udf utility functions. */
870081c0dSSalvatore Benedetto
920d84995SRene Gollent #include "UdfStructures.h"
1024ec5f43STyler Dauwalder #include "Utils.h"
1124ec5f43STyler Dauwalder
12fb8ce469STyler Dauwalder extern "C" {
13fb8ce469STyler Dauwalder extern int32 timezone_offset;
14fb8ce469STyler Dauwalder }
15fb8ce469STyler Dauwalder
1670081c0dSSalvatore Benedetto /*! \brief Returns "true" if \a value is true, "false" otherwise. */
1770081c0dSSalvatore Benedetto const char*
bool_to_string(bool value)1870081c0dSSalvatore Benedetto bool_to_string(bool value)
1924ec5f43STyler Dauwalder {
2070081c0dSSalvatore Benedetto return value ? "true" : "false";
2124ec5f43STyler Dauwalder }
2224ec5f43STyler Dauwalder
2370081c0dSSalvatore Benedetto
2470081c0dSSalvatore Benedetto /*! \brief Calculates the UDF crc checksum for the given byte stream.
2570081c0dSSalvatore Benedetto
2670081c0dSSalvatore Benedetto Based on crc code from UDF-2.50 6.5, as permitted.
2770081c0dSSalvatore Benedetto
2870081c0dSSalvatore Benedetto \param data Pointer to the byte stream.
2970081c0dSSalvatore Benedetto \param length Length of the byte stream in bytes.
3070081c0dSSalvatore Benedetto
3170081c0dSSalvatore Benedetto \return The crc checksum, or 0 if an error occurred.
3270081c0dSSalvatore Benedetto */
3370081c0dSSalvatore Benedetto uint16
calculate_crc(uint8 * data,uint16 length)3470081c0dSSalvatore Benedetto calculate_crc(uint8 *data, uint16 length)
3524ec5f43STyler Dauwalder {
3670081c0dSSalvatore Benedetto uint16 crc = 0;
3770081c0dSSalvatore Benedetto if (data) {
3870081c0dSSalvatore Benedetto for ( ; length > 0; length--, data++)
3970081c0dSSalvatore Benedetto crc = kCrcTable[(crc >> 8 ^ *data) & 0xff] ^ (crc << 8);
4024ec5f43STyler Dauwalder }
4170081c0dSSalvatore Benedetto return crc;
4270081c0dSSalvatore Benedetto }
4370081c0dSSalvatore Benedetto
4470081c0dSSalvatore Benedetto
4570081c0dSSalvatore Benedetto /*! \brief Takes an overloaded ssize_t return value like those returned
4670081c0dSSalvatore Benedetto by BFile::Read() and friends, as well as an expected number of bytes,
4770081c0dSSalvatore Benedetto and returns B_OK if the byte counts match, or the appropriate error
4870081c0dSSalvatore Benedetto code otherwise.
4970081c0dSSalvatore Benedetto */
5070081c0dSSalvatore Benedetto status_t
check_size_error(ssize_t bytesReturned,ssize_t bytesExpected)5170081c0dSSalvatore Benedetto check_size_error(ssize_t bytesReturned, ssize_t bytesExpected)
5270081c0dSSalvatore Benedetto {
5370081c0dSSalvatore Benedetto return bytesReturned == bytesExpected
5470081c0dSSalvatore Benedetto ? B_OK : (bytesReturned >= 0 ? B_IO_ERROR : status_t(bytesReturned));
5570081c0dSSalvatore Benedetto }
5670081c0dSSalvatore Benedetto
5770081c0dSSalvatore Benedetto
5870081c0dSSalvatore Benedetto /*! \brief Calculates the block shift amount for the given
5970081c0dSSalvatore Benedetto block size, which must be a positive power of 2.
6070081c0dSSalvatore Benedetto */
6170081c0dSSalvatore Benedetto status_t
get_block_shift(uint32 blockSize,uint32 & blockShift)6270081c0dSSalvatore Benedetto get_block_shift(uint32 blockSize, uint32 &blockShift)
6370081c0dSSalvatore Benedetto {
6470081c0dSSalvatore Benedetto if (blockSize == 0)
6570081c0dSSalvatore Benedetto return B_BAD_VALUE;
6670081c0dSSalvatore Benedetto uint32 bitCount = 0;
6770081c0dSSalvatore Benedetto uint32 result = 0;
6870081c0dSSalvatore Benedetto for (int i = 0; i < 32; i++) {
6970081c0dSSalvatore Benedetto // Zero out all bits except bit i
7070081c0dSSalvatore Benedetto uint32 block = blockSize & (uint32(1) << i);
7170081c0dSSalvatore Benedetto if (block) {
7270081c0dSSalvatore Benedetto if (++bitCount > 1)
7370081c0dSSalvatore Benedetto return B_BAD_VALUE;
7470081c0dSSalvatore Benedetto else
7570081c0dSSalvatore Benedetto result = i;
7670081c0dSSalvatore Benedetto }
7770081c0dSSalvatore Benedetto }
7870081c0dSSalvatore Benedetto blockShift = result;
7970081c0dSSalvatore Benedetto return B_OK;
8070081c0dSSalvatore Benedetto }
8170081c0dSSalvatore Benedetto
8224ec5f43STyler Dauwalder
83c530d46cSJérôme Duval #define EPOCH_YEAR 1970
84c530d46cSJérôme Duval #define MAX_YEAR 69
85c530d46cSJérôme Duval #define SECSPERMIN 60
86c530d46cSJérôme Duval #define MINSPERHOUR 60
87c530d46cSJérôme Duval #define HOURSPERDAY 24
88c530d46cSJérôme Duval #define SECSPERDAY (SECSPERMIN * MINSPERHOUR * HOURSPERDAY)
89c530d46cSJérôme Duval #define DAYSPERNYEAR 365
90c530d46cSJérôme Duval
91c530d46cSJérôme Duval status_t
decode_time(timestamp & timestamp,struct timespec & timespec)92c530d46cSJérôme Duval decode_time(timestamp ×tamp, struct timespec ×pec)
93fb8ce469STyler Dauwalder {
9421ea9aeaSTyler Dauwalder DEBUG_INIT_ETC(NULL, ("timestamp: (tnt: 0x%x, type: %d, timezone: %d = 0x%x, year: %d, "
95fb8ce469STyler Dauwalder "month: %d, day: %d, hour: %d, minute: %d, second: %d)", timestamp.type_and_timezone(),
96fb8ce469STyler Dauwalder timestamp.type(), timestamp.timezone(),
97fb8ce469STyler Dauwalder timestamp.timezone(),timestamp.year(),
98fb8ce469STyler Dauwalder timestamp.month(), timestamp.day(), timestamp.hour(), timestamp.minute(), timestamp.second()));
99fb8ce469STyler Dauwalder
100c530d46cSJérôme Duval if (timestamp.year() < EPOCH_YEAR || timestamp.year() >= EPOCH_YEAR + MAX_YEAR)
101c530d46cSJérôme Duval return B_BAD_VALUE;
102fb8ce469STyler Dauwalder
103c530d46cSJérôme Duval time_t result = 0;
10470081c0dSSalvatore Benedetto const int monthLengths[12]
10570081c0dSSalvatore Benedetto = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
106fb8ce469STyler Dauwalder
107fb8ce469STyler Dauwalder int year = timestamp.year();
108fb8ce469STyler Dauwalder int month = timestamp.month();
109fb8ce469STyler Dauwalder int day = timestamp.day();
110fb8ce469STyler Dauwalder int hour = timestamp.hour();
111fb8ce469STyler Dauwalder int minute = timestamp.minute();
112fb8ce469STyler Dauwalder int second = timestamp.second();
113fb8ce469STyler Dauwalder
114fb8ce469STyler Dauwalder // Range check the timezone offset, then round it down
115fb8ce469STyler Dauwalder // to the nearest hour, since no one I know treats timezones
116fb8ce469STyler Dauwalder // with a per-minute granularity, and none of the other OSes
117fb8ce469STyler Dauwalder // I've looked at appear to either.
118c530d46cSJérôme Duval int timezone_offset = 0;
119c530d46cSJérôme Duval if (timestamp.type() == 1)
120c530d46cSJérôme Duval timezone_offset = timestamp.timezone();
121c530d46cSJérôme Duval if (-SECSPERDAY > timezone_offset || timezone_offset > SECSPERDAY)
122fb8ce469STyler Dauwalder timezone_offset = 0;
123fb8ce469STyler Dauwalder timezone_offset -= timezone_offset % 60;
124fb8ce469STyler Dauwalder
125fb8ce469STyler Dauwalder int previousLeapYears = (year - 1968) / 4;
126fb8ce469STyler Dauwalder bool isLeapYear = (year - 1968) % 4 == 0;
127fb8ce469STyler Dauwalder if (isLeapYear)
128fb8ce469STyler Dauwalder --previousLeapYears;
129fb8ce469STyler Dauwalder
130fb8ce469STyler Dauwalder // Years to days
131c530d46cSJérôme Duval result = (year - EPOCH_YEAR) * DAYSPERNYEAR + previousLeapYears;
132fb8ce469STyler Dauwalder // Months to days
133fb8ce469STyler Dauwalder for (int i = 0; i < month-1; i++) {
134fb8ce469STyler Dauwalder result += monthLengths[i];
135fb8ce469STyler Dauwalder }
136fb8ce469STyler Dauwalder if (month > 2 && isLeapYear)
137fb8ce469STyler Dauwalder ++result;
138fb8ce469STyler Dauwalder // Days to hours
139c530d46cSJérôme Duval result = (result + day - 1) * HOURSPERDAY;
140fb8ce469STyler Dauwalder // Hours to minutes
141c530d46cSJérôme Duval result = (result + hour) * MINSPERHOUR + timezone_offset;
142fb8ce469STyler Dauwalder // Minutes to seconds
143c530d46cSJérôme Duval result = (result + minute) * SECSPERMIN + second;
144fb8ce469STyler Dauwalder
145c530d46cSJérôme Duval timespec.tv_sec = result;
146c530d46cSJérôme Duval timespec.tv_nsec = 1000 * (timestamp.microsecond()
147c530d46cSJérôme Duval + timestamp.hundred_microsecond() * 100
148c530d46cSJérôme Duval + timestamp.centisecond() * 10000);
149c530d46cSJérôme Duval return B_OK;
150fb8ce469STyler Dauwalder }
151fb8ce469STyler Dauwalder
15270081c0dSSalvatore Benedetto
15370081c0dSSalvatore Benedetto long_address
to_long_address(ino_t id,uint32 length)15470081c0dSSalvatore Benedetto to_long_address(ino_t id, uint32 length)
155f79d99c8STyler Dauwalder {
156*7e5b0f96SJérôme Duval TRACE(("udf_to_long_address: ino_t = %" B_PRIdINO ", length = %" B_PRIu32,
157*7e5b0f96SJérôme Duval id, length));
15870081c0dSSalvatore Benedetto long_address result;
15970081c0dSSalvatore Benedetto result.set_block((id >> 16) & 0xffffffff);
16070081c0dSSalvatore Benedetto result.set_partition(id & 0xffff);
16170081c0dSSalvatore Benedetto result.set_length(length);
16270081c0dSSalvatore Benedetto DUMP(result);
16370081c0dSSalvatore Benedetto return result;
164f79d99c8STyler Dauwalder }
165f79d99c8STyler Dauwalder
16670081c0dSSalvatore Benedetto
16770081c0dSSalvatore Benedetto ino_t
to_vnode_id(long_address address)16870081c0dSSalvatore Benedetto to_vnode_id(long_address address)
169af44f8e6STyler Dauwalder {
17070081c0dSSalvatore Benedetto DEBUG_INIT(NULL);
17170081c0dSSalvatore Benedetto ino_t result = address.block();
17270081c0dSSalvatore Benedetto result <<= 16;
17370081c0dSSalvatore Benedetto result |= address.partition();
174*7e5b0f96SJérôme Duval TRACE(("block: %" B_PRIu32 ", 0x%" B_PRIx32 "\n", address.block(),
175*7e5b0f96SJérôme Duval address.block()));
176c9334140SSalvatore Benedetto TRACE(("partition: %d, 0x%x\n", address.partition(), address.partition()));
177*7e5b0f96SJérôme Duval TRACE(("length: %" B_PRIu32 ", 0x%" B_PRIx32 "\n", address.length(),
178*7e5b0f96SJérôme Duval address.length()));
179*7e5b0f96SJérôme Duval TRACE(("ino_t: %" B_PRIdINO "\n", result));
18070081c0dSSalvatore Benedetto return result;
181af44f8e6STyler Dauwalder }
182