1/*	$NetBSD: cd9660_conversion.c,v 1.4 2007/03/14 14:11:17 christos Exp $	*/
2
3/*
4 * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
5 * Perez-Rathke and Ram Vedam.  All rights reserved.
6 *
7 * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
8 * Alan Perez-Rathke and Ram Vedam.
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above
16 *    copyright notice, this list of conditions and the following
17 *    disclaimer in the documentation and/or other materials provided
18 *    with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
21 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED.  IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
25 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 * OF SUCH DAMAGE.
33 */
34#include "cd9660.h"
35
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD$");
38
39static char cd9660_compute_gm_offset(time_t);
40
41#if 0
42static inline int
43cd9660_pad_even(length)
44int length;
45{
46	return length + (length & 0x01);
47}
48#endif
49
50/*
51* These can probably be implemented using a macro
52*/
53
54/* Little endian */
55void
56cd9660_721(uint16_t w, unsigned char *twochar)
57{
58#if BYTE_ORDER == BIG_ENDIAN
59	w = bswap16(w);
60#endif
61	memcpy(twochar,&w,2);
62}
63
64void
65cd9660_731(uint32_t w, unsigned char *fourchar)
66{
67#if BYTE_ORDER == BIG_ENDIAN
68	w = bswap32(w);
69#endif
70	memcpy(fourchar,&w,4);
71}
72
73/* Big endian */
74void
75cd9660_722(uint16_t w, unsigned char *twochar)
76{
77#if BYTE_ORDER == LITTLE_ENDIAN
78	w = bswap16(w);
79#endif
80	memcpy(twochar,&w,2);
81}
82
83void
84cd9660_732(uint32_t w, unsigned char *fourchar)
85{
86#if BYTE_ORDER == LITTLE_ENDIAN
87	w = bswap32(w);
88#endif
89	memcpy(fourchar,&w,4);
90}
91
92/**
93* Convert a dword into a double endian string of eight characters
94* @param int The double word to convert
95* @param char* The string to write the both endian double word to - It is assumed this is allocated and at least
96*		eight characters long
97*/
98void
99cd9660_bothendian_dword(uint32_t dw, unsigned char *eightchar)
100{
101	uint32_t le, be;
102#if BYTE_ORDER == LITTLE_ENDIAN
103	le = dw;
104	be = bswap32(dw);
105#endif
106#if BYTE_ORDER == BIG_ENDIAN
107	be = dw;
108	le = bswap32(dw);
109#endif
110	memcpy(eightchar, &le, 4);
111	memcpy((eightchar+4), &be, 4);
112}
113
114/**
115* Convert a word into a double endian string of four characters
116* @param int The word to convert
117* @param char* The string to write the both endian word to - It is assumed this is allocated and at least
118*		four characters long
119*/
120void
121cd9660_bothendian_word(uint16_t dw, unsigned char *fourchar)
122{
123	uint16_t le, be;
124#if BYTE_ORDER == LITTLE_ENDIAN
125	le = dw;
126	be = bswap16(dw);
127#endif
128#if BYTE_ORDER == BIG_ENDIAN
129	be = dw;
130	le = bswap16(dw);
131#endif
132	memcpy(fourchar, &le, 2);
133	memcpy((fourchar+2), &be, 2);
134}
135
136void
137cd9660_pad_string_spaces(char *str, int len)
138{
139	int i;
140
141	for (i = 0; i < len; i ++) {
142		if (str[i] == '\0')
143			str[i] = 0x20;
144	}
145}
146
147static char
148cd9660_compute_gm_offset(time_t tim)
149{
150	struct tm t, gm;
151
152	(void)localtime_r(&tim, &t);
153	(void)gmtime_r(&tim, &gm);
154	gm.tm_year -= t.tm_year;
155	gm.tm_yday -= t.tm_yday;
156	gm.tm_hour -= t.tm_hour;
157	gm.tm_min  -= t.tm_min;
158	if (gm.tm_year < 0)
159		gm.tm_yday = -1;
160	else if (gm.tm_year > 0)
161		gm.tm_yday = 1;
162
163	return (char)(-(gm.tm_min + 60* (24 * gm.tm_yday + gm.tm_hour)) / 15);
164}
165
166/* Long dates: 17 characters */
167void
168cd9660_time_8426(unsigned char *buf, time_t tim)
169{
170	struct tm t;
171	char temp[18];
172
173	(void)localtime_r(&tim, &t);
174	(void)snprintf(temp, sizeof(temp), "%04i%02i%02i%02i%02i%02i%02i",
175		1900+(int)t.tm_year,
176		(int)t.tm_mon+1,
177		(int)t.tm_mday,
178		(int)t.tm_hour,
179		(int)t.tm_min,
180		(int)t.tm_sec,
181		0);
182	(void)memcpy(buf, temp, 16);
183	buf[16] = cd9660_compute_gm_offset(tim);
184}
185
186/* Short dates: 7 characters */
187void
188cd9660_time_915(unsigned char *buf, time_t tim)
189{
190	struct tm t;
191
192	(void)localtime_r(&tim, &t);
193	buf[0] = t.tm_year;
194	buf[1] = t.tm_mon+1;
195	buf[2] = t.tm_mday;
196	buf[3] = t.tm_hour;
197	buf[4] = t.tm_min;
198	buf[5] = t.tm_sec;
199	buf[6] = cd9660_compute_gm_offset(tim);
200}
201