xref: /haiku/src/add-ons/kernel/file_systems/udf/Utils.cpp (revision af44f8e6596bb81b7d471c9fb6a8c6e3596858a4)
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 //---------------------------------------------------------------------
7 
8 /*! \file Utils.cpp
9 
10 	Miscellaneous Udf utility functions.
11 */
12 
13 #include "Utils.h"
14 
15 extern "C" {
16 	#ifndef _IMPEXP_KERNEL
17 	#	define _IMPEXP_KERNEL
18 	#endif
19 
20 	extern int32 timezone_offset;
21 }
22 
23 
24 namespace Udf {
25 
26 long_address
27 to_long_address(vnode_id id, uint32 length)
28 {
29 	DEBUG_INIT_ETC(NULL, ("vnode_id: %Ld (0x%Lx), length: %ld", id, id, length));
30 	long_address result;
31 	result.set_block((id >> 16) & 0xffffffff);
32 	result.set_partition(id & 0xffff);
33 	result.set_length(length);
34 	DUMP(result);
35 	return result;
36 }
37 
38 vnode_id
39 to_vnode_id(long_address address)
40 {
41 	DEBUG_INIT(NULL);
42 	vnode_id result = address.block();
43 	result <<= 16;
44 	result |= address.partition();
45 	PRINT(("block:     %ld, 0x%lx\n", address.block(), address.block()));
46 	PRINT(("partition: %d, 0x%x\n", address.partition(), address.partition()));
47 	PRINT(("length:    %ld, 0x%lx\n", address.length(), address.length()));
48 	PRINT(("vnode_id:  %Ld, 0x%Lx\n", result, result));
49 	return result;
50 }
51 
52 time_t
53 make_time(timestamp &timestamp)
54 {
55 	DEBUG_INIT_ETC(NULL, ("timestamp: (tnt: 0x%x, type: %d, timezone: %d = 0x%x, year: %d, "
56 	           "month: %d, day: %d, hour: %d, minute: %d, second: %d)", timestamp.type_and_timezone(),
57 	           timestamp.type(), timestamp.timezone(),
58 	            timestamp.timezone(),timestamp.year(),
59 	           timestamp.month(), timestamp.day(), timestamp.hour(), timestamp.minute(), timestamp.second()));
60 
61 	time_t result = 0;
62 
63 	if (timestamp.year() >= 1970) {
64 		const int monthLengths[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
65 
66 		int year = timestamp.year();
67 		int month = timestamp.month();
68 		int day = timestamp.day();
69 		int hour = timestamp.hour();
70 		int minute = timestamp.minute();
71 		int second = timestamp.second();
72 
73 		// Range check the timezone offset, then round it down
74 		// to the nearest hour, since no one I know treats timezones
75 		// with a per-minute granularity, and none of the other OSes
76 		// I've looked at appear to either.
77 		int timezone_offset = timestamp.timezone();
78 		if (-1440 > timezone_offset || timezone_offset > 1440)
79 			timezone_offset = 0;
80 		timezone_offset -= timezone_offset % 60;
81 
82 		int previousLeapYears = (year - 1968) / 4;
83 		bool isLeapYear = (year - 1968) % 4 == 0;
84 		if (isLeapYear)
85 			--previousLeapYears;
86 
87 		// Years to days
88 		result = (year - 1970) * 365 + previousLeapYears;
89 		// Months to days
90 		for (int i = 0; i < month-1; i++) {
91 			result += monthLengths[i];
92 		}
93 		if (month > 2 && isLeapYear)
94 			++result;
95 		// Days to hours
96 		result = (result + day - 1) * 24;
97 		// Hours to minutes
98 		result = (result + hour) * 60 + timezone_offset;
99 		// Minutes to seconds
100 		result = (result + minute) * 60 + second;
101 	}
102 
103 	return result;
104 }
105 
106 /*! \brief Calculates the block shift amount for the given
107  	block size, which must be a positive power of 2.
108 */
109 status_t
110 Udf::get_block_shift(uint32 blockSize, uint32 &blockShift)
111 {
112 	if (blockSize == 0)
113 		return B_BAD_VALUE;
114 	uint32 bitCount = 0;
115 	uint32 result = 0;
116 	for (int i = 0; i < 32; i++) {
117 		// Zero out all bits except bit i
118 		uint32 block = blockSize & (uint32(1) << i);
119 		if (block) {
120 			if (++bitCount > 1) {
121 				return B_BAD_VALUE;
122 			} else {
123 				result = i;
124 			}
125 		}
126 	}
127 	blockShift = result;
128 	return B_OK;
129 }
130 
131 /*! \brief Returns "true" if \a value is true, "false" otherwise.
132 */
133 const char*
134 Udf::bool_to_string(bool value)
135 {
136 	return value ? "true" : "false";
137 }
138 
139 /*! \brief Takes an overloaded ssize_t return value like those returned
140 	by BFile::Read() and friends, as well as an expected number of bytes,
141 	and returns B_OK if the byte counts match, or the appropriate error
142 	code otherwise.
143 */
144 status_t
145 Udf::check_size_error(ssize_t bytesReturned, ssize_t bytesExpected)
146 {
147 	return bytesReturned == bytesExpected
148 	       ? B_OK
149 	       : (bytesReturned >= 0 ? B_ERROR : status_t(bytesReturned));
150 }
151 
152 } // namespace Udf
153 
154