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