1 
2 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
3    Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
4    Provided under GPL version 2 or later.
5 */
6 
7 #ifdef HAVE_CONFIG_H
8 #include "../config.h"
9 #endif
10 
11 #include <string.h>
12 
13 /* ts A61008 */
14 /* #include <a ssert.h> */
15 
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <time.h>
19 #include <sys/time.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 
24 
25 /* ts A80914 : This is unneeded. Version info comes from libburn.h.
26 #include "v ersion.h"
27 */
28 
29 #include "util.h"
30 #include "libburn.h"
31 
32 
burn_version(int * major,int * minor,int * micro)33 void burn_version(int *major, int *minor, int *micro)
34 {
35 /* ts A80408 : switched from configure.ac versioning to libburn.h versioning */
36 	*major = burn_header_version_major;
37 	*minor = burn_header_version_minor;
38 	*micro = burn_header_version_micro;
39 }
40 
41 
42 struct cd_mid_record {
43 	char *manufacturer;
44 	int m_li;
45 	int s_li;
46 	int f_li;
47 	char *other_brands;
48 };
49 typedef struct cd_mid_record cd_mid_record_t;
50 
51 
52 /* ts A90902 */
53 /** API
54    @param flag  Bitfield for control purposes,
55                 bit0= append "(aka %s)",other_brands to reply
56  */
burn_guess_cd_manufacturer(int m_li,int s_li,int f_li,int m_lo,int s_lo,int f_lo,int flag)57 char *burn_guess_cd_manufacturer(int m_li, int s_li, int f_li,
58                                  int m_lo, int s_lo, int f_lo, int flag)
59 {
60 	static cd_mid_record_t mid_list[]= {
61 	{"SKC",                                 96, 40,  0,  ""},
62 	{"Ritek Corp"                         , 96, 43, 30,  ""},
63 	{"TDK / Ritek"                        , 97, 10,  0,  "TRAXDATA"},
64 	{"TDK Corporation"                    , 97, 15,  0,  ""},
65 	{"Ritek Corp"                         , 97, 15, 10,  "7-plus, Aopen, PONY, Power Source, TDK, TRAXDATA, HiCO, PHILIPS, Primdisc, Victor.JVC, OPTI STORAGE, Samsung"},
66 	{"Mitsubishi Chemical Corporation"    , 97, 15, 20,  ""},
67 	{"Nan-Ya Plastics Corporation"        , 97, 15, 30,  "Hatron, MMore, Acer, LITEON"},
68 	{"Delphi"                             , 97, 15, 50,  ""},
69 	{"Shenzhen SG&SAST"                   , 97, 16, 20,  ""},
70 	{"Moser Baer India Limited"           , 97, 17,  0,  "EMTEC, Intenso, YAKUMO, PLATINUM, Silver Circle"},
71 	{"SKY media Manufacturing SA"         , 97, 17, 10,  ""},
72 	{"Wing"                               , 97, 18, 10,  ""},
73 	{"DDT"                                , 97, 18, 20,  ""},
74 	{"Daxon Technology Inc. / Acer"       , 97, 22, 60,  "Maxmax, Diamond Data, BenQ, gold, SONY"},
75 	{"Taiyo Yuden Company Limited"        , 97, 24,  0,  "Maxell, FUJIFILM, SONY"},
76 	{"Sony Corporation"                   , 97, 24, 10,  "LeadData, Imation"},
77 	{"Computer Support Italcard s.r.l"    , 97, 24, 20,  ""},
78 	{"Unitech Japan Inc."                 , 97, 24, 30,  ""},
79 	{"MPO, France"                        , 97, 25,  0,  "TDK"},
80 	{"Hitachi Maxell Ltd."                , 97, 25, 20,  ""},
81 	{"Infodisc Technology Co,Ltd."        , 97, 25, 30,  "MEMOREX, SPEEDA, Lead data"},
82 	{"Xcitec"                             , 97, 25, 60,  ""},
83 	{"Fornet International Pte Ltd"       , 97, 26,  0,  "COMPUSA, Cdhouse"},
84 	{"Postech Corporation"                , 97, 26, 10,  "Mr.Platinum"},
85 	{"SKC Co Ltd."                        , 97, 26, 20,  "Infinite"},
86 	{"Fuji Photo Film Co,Ltd."            , 97, 26, 40,  ""},
87 	{"Lead Data Inc."                     , 97, 26, 50,  "SONY, Gigastorage, MIRAGE"},
88 	{"CMC Magnetics Corporation"          , 97, 26, 60,  "Daxon, Verbatim, Memorex, Bi-Winner, PLEXTOR, YAMAHA, Melody, Office DEPOT, Philips, eMARK, imation, HyperMedia, Samsung, Shintaro, Techworks"},
89 	{"Ricoh Company Limited"              , 97, 27,  0,  "Sony, Digital Storage, Csita"},
90 	{"Plasmon Data Systems Ltd"           , 97, 27, 10,  "Ritek, TDK, EMTEC, ALPHAPET, MANIA"},
91 	{"Princo Corporation"                 , 97, 27, 20,  ""},
92 	{"Pioneer"                            , 97, 27, 30,  ""},
93 	{"Eastman Kodak Company"              , 97, 27, 40,  ""},
94 	{"Mitsui Chemicals Inc."              , 97, 27, 50,  "MAM-A, TDK"},
95 	{"Ricoh Company Limited"              , 97, 27, 60,  "Ritek"},
96 	{"Gigastorage Corporation"            , 97, 28, 10,  "MaxMax, Nan-Ya"},
97 	{"Multi Media Masters&Machinary SA"   , 97, 28, 20,  "King, Mmirex"},
98 	{"Ritek Corp"                         , 97, 31,  0,  "TDK"},
99 	{"Grand Advance Technology Sdn. Bhd." , 97, 31, 30,  ""},
100 	{"TDK Corporation"                    , 97, 32, 00,  ""},
101 	{"Prodisc Technology Inc."            , 97, 32, 10,  "Smartbuy, Mitsubishi, Digmaster, LG, Media Market"},
102 	{"Mitsubishi Chemical Corporation"    , 97, 34, 20,  "YAMAHA, Verbatim"},
103 	{"Mitsui Chemicals Inc."              , 97, 48, 50, ""},
104 	{"TDK Corporation"                    , 97, 49,  0, ""},
105 	{"", 0, 0, 0, ""}
106 	};
107 
108 	int i, f_li_0;
109 	char buf[1024];
110 	char *result = NULL;
111 
112 	if (m_li == 0 && s_li == 2 && f_li == 0) {
113 		result = strdup("(no manufacturer code)");
114 		return result;
115 	}
116 	f_li_0 = f_li - (f_li % 10);
117 	for (i = 0; mid_list[i].manufacturer[0]; i++) {
118 		if (m_li == mid_list[i].m_li &&
119 		    s_li == mid_list[i].s_li &&
120 		    (f_li_0 == mid_list[i].f_li || f_li == mid_list[i].f_li))
121 	break;
122 	}
123 	if (mid_list[i].manufacturer[0] == 0) {
124 		sprintf(buf, "Unknown CD manufacturer. Please report code '%2.2dm%2.2ds%2.2df/%2.2dm%2.2ds%2.2df', the human readable brand, size, and speed to scdbackup@gmx.net.", m_li, s_li, f_li, m_lo, s_lo, f_lo);
125 		result = strdup(buf);
126 		return result;
127 	}
128 
129 	/* Compose, allocate and copy result */
130 	if ((flag & 1) && mid_list[i].other_brands[0]) {
131 		sprintf(buf, "%s  (aka %s)",
132 			mid_list[i].manufacturer, mid_list[i].other_brands);
133 		result = strdup(buf);
134 	} else
135 		result = strdup(mid_list[i].manufacturer);
136 	return result;
137 }
138 
139 
140 /* ts A90904 */
141 struct dvd_mid_record {
142 	char *mc1;
143 	int mc1_sig_len;
144 	char *manufacturer;
145 };
146 typedef struct dvd_mid_record dvd_mid_record_t;
147 
148 /* ts A90904 */
burn_guess_manufacturer(int prf,char * media_code1,char * media_code2,int flag)149 char *burn_guess_manufacturer(int prf,
150 			 char *media_code1, char *media_code2, int flag)
151 {
152 	int i, l = 0, m_li, s_li, f_li, m_lo, s_lo, f_lo;
153 	char buf[1024];
154 	char *result = NULL, *cpt;
155 
156 	/* Important Note: media_code1 and media_code2 are supposed to be
157 	                   encoded by burn_util_make_printable_word().
158 	                   Especially: ' ' -> '_' , {"_%/" unprintables -> %XY)
159 	*/
160 	static dvd_mid_record_t mid_list[]= {
161 	{"AML",         8, "UML"},
162 	{"BeAll",       5, "BeAll Developers, Inc."},
163 	{"CMC",         3, "CMC Magnetics Corporation"},
164 	{"DAXON",       5, "Daxon Technology Inc. / Acer"},
165 	{"Daxon",       5, "Daxon Technology Inc. / Acer"},
166 	{"FUJI",        4, "Fujifilm Holdings Corporation"},
167 	{"INFODISC",    8, "New Star Digital Co., Ltd."},
168 	{"INFOME",      6, "InfoMedia Inc."},
169 	{"ISMMBD",      6, "Info Source Multi Media Ltd."},
170 	{"JVC",         3, "JVC Limited"},
171 	{"KIC01RG",     7, "AMC"},
172 	{"LD",          8, "Lead Data Inc."},
173 	{"LGE",         3, "LG Electronics"},
174 	{"MAM",         8, "Mitsui Advanced Media, Inc. Europe"},
175 	{"MAXELL",      6, "Hitachi Maxell Ltd."},
176 	{"MBI",         3, "Moser Baer India Limited"},
177 	{"MCC",         8, "Mitsubishi Chemical Corporation"},
178 	{"MCI",         8, "Mitsui Chemicals Inc."},
179 	{"MEI",         3, "Panasonic Corporation"},
180 	{"MILLEN",      8, "Millenniata Inc."},
181 	{"MKM",         3, "Mitsubishi Kagaku Media Co."},
182 	{"MMC",         8, "Mitsubishi Kagaku Media Co."},
183 	{"MXL",         8, "Hitachi Maxell Ltd."},
184 	{"NANYA",       5, "Nan-Ya Plastics Corporation"},
185 	{"NSD",         8, "NESA International Inc."},
186 	{"OPTODISC",    8, "Optodisc Technology Corporation"},
187 	{"OTCBDR",      8, "Optodisc Technology Corporation"},
188 	{"PHILIP",      8, "Moser Baer India Limited"},
189 	{"PHILIPS",     8, "Philips"},
190 	{"PRINCO",      6, "Princo Corporation"},
191 	{"PRODISC",     7, "Prodisc Technology Inc."},
192 	{"Prodisc",     7, "Prodisc Technology Inc."},
193 	{"PVC",         3, "Pioneer"},
194 	{"RICOHJPN",    8, "Ricoh Company Limited"},
195 	{"RITEK",       5, "Ritek Corp"},
196 	{"SONY",        4, "Sony Corporation"},
197 	{"TDK",         3, "TDK Corporation"},
198 	{"TTG",         3, "TDK Corporation"},
199 	{"TTH",         3, "TDK Corporation"},
200 	{"TY",          8, "Taiyo Yuden Company Limited"},
201 	{"TYG",         3, "Taiyo Yuden Company Limited"},
202 	{"UME",         3, "UmeDisc Limited"},
203 	{"UTJR001",     7, "Unifino Inc."},
204 	{"VERBAT",      5, "Mitsubishi Kagaku Media Co."},
205 	{"YUDEN",       5, "Taiyo Yuden Company Limited"},
206 	{"", 0, ""}
207 	};
208 
209 	if (media_code2 != NULL &&
210 	    (prf == -1 || prf == 0x09 || prf == 0x0A)) {
211 		if (strlen(media_code2) == 9 && media_code1[0] == '9' &&
212 			media_code1[2] == 'm' && media_code1[5] == 's' &&
213 			media_code1[8] == 'f' &&
214 			strchr(media_code1, '%') == NULL) {
215 			sscanf(media_code1, "%dm%ds%df", &m_li, &s_li, &f_li);
216 			sscanf(media_code2, "%dm%ds%df", &m_lo, &s_lo, &f_lo);
217 			if (m_li >= 96 && m_li <= 97 && m_lo > 0) {
218 				result = burn_guess_cd_manufacturer(
219 					m_li, s_li, f_li, m_lo, s_lo, f_lo, 0);
220 				return result;
221 			}
222 		}
223 	}
224 
225 	/* DVD-R do not keep manufacturer id apart from media id.
226 	   Some manufacturers use a blank as separator which would now be '_'.
227 	*/
228 	cpt = strchr(media_code1, '_');
229 	if (cpt != NULL && (prf == -1 || prf ==  0x11 || prf == 0x13 ||
230 						 prf == 0x14 || prf == 0x15))
231 		l = cpt - media_code1;
232 
233 	for (i = 0; mid_list[i].mc1[0]; i++) {
234 		if (strncmp(mid_list[i].mc1, media_code1,
235 			 mid_list[i].mc1_sig_len) == 0)
236 	break;
237 		if (l > 0)
238 			if (strncmp(mid_list[i].mc1, media_code1, l) == 0)
239 	break;
240 	}
241 	if (mid_list[i].mc1[0] == 0) {
242 		sprintf(buf, "Unknown DVD/BD manufacturer. Please report code '%s/%s', the human readable brand, size, and speed to scdbackup@gmx.net.",
243 			media_code1, media_code2);
244 		result = strdup(buf);
245 		return result;
246 	}
247 	result = strdup(mid_list[i].manufacturer);
248 	return result;
249 }
250 
251 
252 /* ts A90905 */
253 /* Make *text a single printable word */
254 /* IMPORTANT: text must be freeable memory !
255    @param flag bit0=escape '/' too
256                bit1=(overrides bit0) do not escape " _/"
257 */
burn_util_make_printable_word(char ** text,int flag)258 int burn_util_make_printable_word(char **text, int flag)
259 {
260 	int i, esc_add = 0, ret;
261 	char *wpt, *rpt, *new_text = NULL;
262 
263 	if (flag & 2)
264 		flag &= ~1;
265 
266 	for (i = 0; (*text)[i]; i++) {
267 		rpt = (*text) + i;
268 		if (*rpt < 32 || *rpt > 126 || *rpt == 96 ||
269 		    ((*rpt == '_' || *rpt == '%') && (!(flag & 2))) ||
270 		    (*rpt == '/' && (flag & 1)))
271 			esc_add += 2;
272 	}
273 	if (esc_add) {
274 		new_text = calloc(strlen(*text) + esc_add + 1, 1);
275 		if (new_text == NULL) {
276 			ret = -1;
277 			goto ex;
278 		}
279 		wpt = new_text;
280 		for (i = 0; (*text)[i]; i++) {
281 			rpt = (*text) + i;
282 			if (*rpt < 32 || *rpt > 126 || *rpt == 96 ||
283 			    ((*rpt == '_' || *rpt == '%') && (!(flag & 2))) ||
284 			    (*rpt == '/' && (flag & 1))) {
285 				sprintf(wpt, "%%%2.2X",
286 				    (unsigned int) *((unsigned char *) rpt));
287 				wpt+= 3;
288 			} else
289 				*(wpt++) = *rpt;
290 		}
291 		*wpt = 0;
292 		free(*text);
293 		*text = new_text;
294 	}
295 	if (!(flag & 2))
296 		for (i = 0; (*text)[i]; i++)
297 			if ((*text)[i] == ' ')
298 				(*text)[i] = '_';
299 	ret = 1;
300 ex:
301 	return ret;
302 }
303 
304 
305 /* ts B11216 */
306 /** Read a line from fp and strip LF or CRLF */
burn_sfile_fgets(char * line,int maxl,FILE * fp)307 char *burn_sfile_fgets(char *line, int maxl, FILE *fp)
308 {
309 	int l;
310 	char *ret;
311 
312 	ret = fgets(line, maxl, fp);
313 	if (ret == NULL)
314 		return NULL;
315 	l = strlen(line);
316 	if (l > 0)
317 		if (line[l - 1] == '\r')
318 			line[--l] = 0;
319 	if (l > 0)
320 		if (line[l - 1] == '\n')
321 			line[--l] = 0;
322 	if(l > 0)
323 		if(line[l - 1] == '\r')
324 			line[--l] = 0;
325 	return ret;
326 }
327 
328 
burn_printify(char * msg)329 char *burn_printify(char *msg)
330 {
331 	char *cpt;
332 
333 	for (cpt = msg; *cpt != 0; cpt++)
334 		if (*cpt < 32 || *cpt > 126)
335 			*cpt = '#';
336 	return msg;
337 }
338 
339 
340 /* ts B30521 */
burn_int_to_lsb(int val,char * target)341 void burn_int_to_lsb(int val, char *target)
342 {
343 	unsigned char *buf;
344 
345 	buf = (unsigned char *) target;
346 	buf[0] = val & 0xff;
347 	buf[1] = (val >> 8) & 0xff;
348 	buf[2] = (val >> 16) & 0xff;
349 	buf[3] = (val >> 24) & 0xff;
350 }
351 
352 
353 /* ts B30609 */
burn_get_time(int flag)354 double burn_get_time(int flag)
355 {
356 	int ret;
357 	struct timeval tv;
358 
359 #ifdef Libburn_use_clock_gettime_monotoniC
360 #ifdef _POSIX_TIMERS
361 #ifdef _POSIX_MONOTONIC_CLOCK
362 
363 	/* Enable by
364 	     export CFLAGS=-DLibburn_use_clock_gettime_monotoniC
365 	     export LIBS=-lrt
366 	     ./configure ... && make clean && make
367 	*/
368 
369 	struct timespec tp;
370 	ret = clock_gettime(CLOCK_MONOTONIC, &tp);
371 	if (ret == 0)
372 		return ((double) tp.tv_sec) + ((double) tp.tv_nsec) * 1.0e-9;
373 
374 #endif /* _POSIX_MONOTONIC_CLOCK */
375 #endif /* _POSIX_TIMERS */
376 #endif /* Xorriso_use_clock_gettime_monotoniC */
377 
378 	ret = gettimeofday(&tv, NULL);
379 	if (ret == 0)
380 		return ((double) tv.tv_sec) + ((double) tv.tv_usec) * 1.0e-6;
381 	return (double) time(NULL);
382 }
383 
384 /* ts B40609 */
burn_sparse_file_addsize(off_t write_start,struct stat * stbuf)385 off_t burn_sparse_file_addsize(off_t write_start, struct stat *stbuf)
386 {
387 	off_t add_size;
388 
389 	add_size = stbuf->st_blocks * (off_t) 512;
390 	if (add_size < stbuf->st_size) {
391 		/* Sparse file */
392 		if (write_start < stbuf->st_size) {
393 			/* Might write into sparse gaps */
394 			if (write_start > add_size)
395 				add_size = write_start;
396 		} else {
397 			/* Will not write into sparse area */
398 			add_size = stbuf->st_size;
399 		}
400 	}
401 	return add_size;
402 }
403 
404