1/*
2	Copyright 1999-2001, Be Incorporated.   All Rights Reserved.
3	This file may be used under the terms of the Be Sample Code License.
4*/
5
6
7#include "system_dependencies.h"
8
9#ifndef FS_SHELL
10#include <real_time_clock.h>
11#endif
12
13#include "dosfs.h"
14#include "fat.h"
15#include "util.h"
16
17static int32 tzoffset = -1; /* in minutes */
18
19#ifdef DEBUG
20
21int
22_assert_(char *a, int b, char *c)
23{
24	dprintf("tripped assertion in %s/%d (%s)\n", a, b, c);
25	kernel_debugger("tripped assertion");
26	return 0;
27}
28
29#endif
30
31static void
32print_byte(uint8 c)
33{
34	dprintf("%c", ((c >= ' ') && (c <= '~')) ? c : '.');
35}
36
37
38void
39dump_bytes(uint8 *buffer, uint32 count)
40{
41	uint32 i, j, k;
42	for (i = 0; i < 0x10; i++)
43		dprintf(" %" B_PRIu32 " ", i);
44
45	dprintf("\n");
46	for (i = 0; i < count; i += 0x10) {
47		j = (i + 0x10 > count) ? count - i : 0x10;
48		for (k = i; k < i + j; k++)
49			dprintf("%2.2X ", buffer[k]);
50		for (; k < i + 0x10; k++)
51			dprintf("   ");
52		dprintf(" ");
53		for (k = i; k < i + j; k++)
54			print_byte(buffer[k]);
55		dprintf("\n");
56	}
57}
58
59
60void
61dump_directory(uint8 *buffer)
62{
63	dump_bytes(buffer, 32);
64}
65
66
67static void
68get_tzoffset()
69{
70	if (tzoffset != -1)
71		return;
72
73	#ifdef FS_SHELL
74	// We just assume UTC ;-)
75	tzoffset = 0;
76	#else
77	tzoffset = get_timezone_offset() / 60;
78	#endif
79}
80
81
82// If divisible by 4, but not divisible by 100, but divisible by 400, it's a leap year
83// 1996 is leap, 1900 is not, 2000 is, 2100 is not
84#define IS_LEAP_YEAR(y) ((((y) % 4) == 0) && (((y) % 100) || ((((y)) % 400) == 0)))
85
86/* returns leap days since 1970 */
87static int leaps(int yr, int mon)
88{
89	// yr is 1970-based, mon 0-based
90	int result = (yr+2)/4 - (yr + 70) / 100;
91	if((yr+70) >= 100) result++; // correct for 2000
92	if (IS_LEAP_YEAR(yr + 1970))
93		if (mon < 2) result--;
94	return result;
95}
96
97static int daze[] = { 0,0,31,59,90,120,151,181,212,243,273,304,334,0,0,0 };
98
99time_t
100dos2time_t(uint32 t)
101{
102	time_t days;
103
104	get_tzoffset();
105
106	//dprintf("%d/%d/%d %d:%2.2d:%2.2d\n",
107	//	(t>>25)+1980,((t>>21)&15),((t>>16)&31),
108	//	(t>>11)&31,(t>>5)&63,2*(t&31));
109
110	days = daze[(t>>21)&15] + ((t>>25)+10)*365 + leaps((t>>25)+10,((t>>21)&15)-1)+((t>>16)&31)-1;
111
112	return (((days * 24) + ((t>>11)&31)) * 60 + ((t>>5)&63) - tzoffset) * 60 + 2*(t&31);
113}
114
115
116uint32
117time_t2dos(time_t s)
118{
119	uint32 t, d, y;
120	int days;
121
122	get_tzoffset();
123
124	t = (s % 60) / 2;	s /= 60; s += tzoffset;
125	t += (s % 60) << 5;	s /= 60;
126	t += (s % 24) << 11;s /= 24;
127
128	s -= 10*365 + 2; // convert from 1970-based year to 1980-based year
129
130	for (y=0;;y++) {
131		days = IS_LEAP_YEAR(1980+y) ? 366 : 365;
132		if (s < days) break;
133		s -= days;
134	}
135
136	if (IS_LEAP_YEAR(1980+y)) {
137		if (s == 59) {
138			d = (1 << 5) + 28; /* 2/29, 0 based */
139			goto bi;
140		} else if (s > 59)
141			s--;
142	}
143
144	for (d=0;d<11;d++)
145		if (daze[d+2] > s)
146			break;
147	d = (d << 5) + (s - daze[d+1]);
148
149bi:
150	d += (1 << 5) + 1; // make date 1-based
151
152	return t + (d << 16) + (y << 25);
153}
154
155
156uint8
157hash_msdos_name(const char *name)
158{
159	const uint8 *p = (const uint8 *)name;
160	int i;
161	uint8 c = 0;
162	for (i=0;i<11;i++)
163		c = (c << 7) + (c >> 1) + *(p++);
164	return c;
165}
166
167
168void
169sanitize_name(char *name, int length)
170{
171	int i;
172
173	for (i = length - 1; i > 0; i--) {
174		if (name[i] != ' ')
175			break;
176	}
177	name[i + 1] = 0;
178	for (; i >= 0; i--) {
179		if (name[i] >= 'A' && name[i] <= 'Z')
180			name[i] += 'a' - 'A';
181	}
182}
183