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