1214921Scognet/*	$NetBSD: cd9660_conversion.c,v 1.4 2007/03/14 14:11:17 christos Exp $	*/
2214921Scognet
3214921Scognet/*
4214921Scognet * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
5214921Scognet * Perez-Rathke and Ram Vedam.  All rights reserved.
6214921Scognet *
7214921Scognet * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
8214921Scognet * Alan Perez-Rathke and Ram Vedam.
9214921Scognet *
10214921Scognet * Redistribution and use in source and binary forms, with or
11214921Scognet * without modification, are permitted provided that the following
12214921Scognet * conditions are met:
13214921Scognet * 1. Redistributions of source code must retain the above copyright
14214921Scognet *    notice, this list of conditions and the following disclaimer.
15214921Scognet * 2. Redistributions in binary form must reproduce the above
16214921Scognet *    copyright notice, this list of conditions and the following
17214921Scognet *    disclaimer in the documentation and/or other materials provided
18214921Scognet *    with the distribution.
19214921Scognet *
20214921Scognet * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
21214921Scognet * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
22214921Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23214921Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24214921Scognet * DISCLAIMED.  IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
25214921Scognet * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
26214921Scognet * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27214921Scognet * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28214921Scognet * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29214921Scognet * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30214921Scognet * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31214921Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32214921Scognet * OF SUCH DAMAGE.
33214921Scognet */
34214921Scognet#include "cd9660.h"
35214921Scognet
36214921Scognet#include <sys/cdefs.h>
37214921Scognet__FBSDID("$FreeBSD$");
38214921Scognet
39214921Scognetstatic char cd9660_compute_gm_offset(time_t);
40214921Scognet
41214921Scognet#if 0
42214921Scognetstatic inline int
43214921Scognetcd9660_pad_even(length)
44214921Scognetint length;
45214921Scognet{
46214921Scognet	return length + (length & 0x01);
47214921Scognet}
48214921Scognet#endif
49214921Scognet
50214921Scognet/*
51214921Scognet* These can probably be implemented using a macro
52214921Scognet*/
53214921Scognet
54214921Scognet/* Little endian */
55214921Scognetvoid
56214921Scognetcd9660_721(uint16_t w, unsigned char *twochar)
57214921Scognet{
58214921Scognet#if BYTE_ORDER == BIG_ENDIAN
59214921Scognet	w = bswap16(w);
60214921Scognet#endif
61214921Scognet	memcpy(twochar,&w,2);
62214921Scognet}
63214921Scognet
64214921Scognetvoid
65214921Scognetcd9660_731(uint32_t w, unsigned char *fourchar)
66214921Scognet{
67214921Scognet#if BYTE_ORDER == BIG_ENDIAN
68214921Scognet	w = bswap32(w);
69214921Scognet#endif
70214921Scognet	memcpy(fourchar,&w,4);
71214921Scognet}
72214921Scognet
73214921Scognet/* Big endian */
74214921Scognetvoid
75214921Scognetcd9660_722(uint16_t w, unsigned char *twochar)
76214921Scognet{
77214921Scognet#if BYTE_ORDER == LITTLE_ENDIAN
78214921Scognet	w = bswap16(w);
79214921Scognet#endif
80214921Scognet	memcpy(twochar,&w,2);
81214921Scognet}
82214921Scognet
83214921Scognetvoid
84214921Scognetcd9660_732(uint32_t w, unsigned char *fourchar)
85214921Scognet{
86214921Scognet#if BYTE_ORDER == LITTLE_ENDIAN
87214921Scognet	w = bswap32(w);
88214921Scognet#endif
89214921Scognet	memcpy(fourchar,&w,4);
90214921Scognet}
91214921Scognet
92214921Scognet/**
93214921Scognet* Convert a dword into a double endian string of eight characters
94214921Scognet* @param int The double word to convert
95214921Scognet* @param char* The string to write the both endian double word to - It is assumed this is allocated and at least
96214921Scognet*		eight characters long
97214921Scognet*/
98214921Scognetvoid
99214921Scognetcd9660_bothendian_dword(uint32_t dw, unsigned char *eightchar)
100214921Scognet{
101214921Scognet	uint32_t le, be;
102214921Scognet#if BYTE_ORDER == LITTLE_ENDIAN
103214921Scognet	le = dw;
104214921Scognet	be = bswap32(dw);
105214921Scognet#endif
106214921Scognet#if BYTE_ORDER == BIG_ENDIAN
107214921Scognet	be = dw;
108214921Scognet	le = bswap32(dw);
109214921Scognet#endif
110214921Scognet	memcpy(eightchar, &le, 4);
111214921Scognet	memcpy((eightchar+4), &be, 4);
112214921Scognet}
113214921Scognet
114214921Scognet/**
115214921Scognet* Convert a word into a double endian string of four characters
116214921Scognet* @param int The word to convert
117214921Scognet* @param char* The string to write the both endian word to - It is assumed this is allocated and at least
118214921Scognet*		four characters long
119214921Scognet*/
120214921Scognetvoid
121214921Scognetcd9660_bothendian_word(uint16_t dw, unsigned char *fourchar)
122214921Scognet{
123214921Scognet	uint16_t le, be;
124214921Scognet#if BYTE_ORDER == LITTLE_ENDIAN
125214921Scognet	le = dw;
126214921Scognet	be = bswap16(dw);
127214921Scognet#endif
128214921Scognet#if BYTE_ORDER == BIG_ENDIAN
129214921Scognet	be = dw;
130214921Scognet	le = bswap16(dw);
131214921Scognet#endif
132214921Scognet	memcpy(fourchar, &le, 2);
133214921Scognet	memcpy((fourchar+2), &be, 2);
134214921Scognet}
135214921Scognet
136214921Scognetvoid
137214921Scognetcd9660_pad_string_spaces(char *str, int len)
138214921Scognet{
139214921Scognet	int i;
140214921Scognet
141214921Scognet	for (i = 0; i < len; i ++) {
142214921Scognet		if (str[i] == '\0')
143214921Scognet			str[i] = 0x20;
144214921Scognet	}
145214921Scognet}
146214921Scognet
147214921Scognetstatic char
148214921Scognetcd9660_compute_gm_offset(time_t tim)
149214921Scognet{
150214921Scognet	struct tm t, gm;
151214921Scognet
152214921Scognet	(void)localtime_r(&tim, &t);
153214921Scognet	(void)gmtime_r(&tim, &gm);
154214921Scognet	gm.tm_year -= t.tm_year;
155214921Scognet	gm.tm_yday -= t.tm_yday;
156214921Scognet	gm.tm_hour -= t.tm_hour;
157214921Scognet	gm.tm_min  -= t.tm_min;
158214921Scognet	if (gm.tm_year < 0)
159214921Scognet		gm.tm_yday = -1;
160214921Scognet	else if (gm.tm_year > 0)
161214921Scognet		gm.tm_yday = 1;
162214921Scognet
163214921Scognet	return (char)(-(gm.tm_min + 60* (24 * gm.tm_yday + gm.tm_hour)) / 15);
164214921Scognet}
165214921Scognet
166214921Scognet/* Long dates: 17 characters */
167214921Scognetvoid
168214921Scognetcd9660_time_8426(unsigned char *buf, time_t tim)
169214921Scognet{
170214921Scognet	struct tm t;
171214921Scognet	char temp[18];
172214921Scognet
173214921Scognet	(void)localtime_r(&tim, &t);
174214921Scognet	(void)snprintf(temp, sizeof(temp), "%04i%02i%02i%02i%02i%02i%02i",
175214921Scognet		1900+(int)t.tm_year,
176214921Scognet		(int)t.tm_mon+1,
177214921Scognet		(int)t.tm_mday,
178214921Scognet		(int)t.tm_hour,
179214921Scognet		(int)t.tm_min,
180214921Scognet		(int)t.tm_sec,
181214921Scognet		0);
182214921Scognet	(void)memcpy(buf, temp, 16);
183214921Scognet	buf[16] = cd9660_compute_gm_offset(tim);
184214921Scognet}
185214921Scognet
186214921Scognet/* Short dates: 7 characters */
187214921Scognetvoid
188214921Scognetcd9660_time_915(unsigned char *buf, time_t tim)
189214921Scognet{
190214921Scognet	struct tm t;
191214921Scognet
192214921Scognet	(void)localtime_r(&tim, &t);
193214921Scognet	buf[0] = t.tm_year;
194214921Scognet	buf[1] = t.tm_mon+1;
195214921Scognet	buf[2] = t.tm_mday;
196214921Scognet	buf[3] = t.tm_hour;
197214921Scognet	buf[4] = t.tm_min;
198214921Scognet	buf[5] = t.tm_sec;
199214921Scognet	buf[6] = cd9660_compute_gm_offset(tim);
200214921Scognet}
201