1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * Libbrasero-burn
4 * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
5 *
6 * Libbrasero-burn is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
12 * GStreamer plugins to be used and distributed together with GStreamer
13 * and Libbrasero-burn. This permission is above and beyond the permissions granted
14 * by the GPL license by which Libbrasero-burn is covered. If you modify this code
15 * you may extend this exception to your version of the code, but you are not
16 * obligated to do so. If you do not wish to do so, delete this exception
17 * statement from your version.
18 *
19 * Libbrasero-burn is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to:
26 * The Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor
28 * Boston, MA 02110-1301, USA.
29 */
30
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34
35 #include <errno.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <stdlib.h>
39 #include <sys/param.h>
40
41 #include <glib.h>
42 #include <glib/gstdio.h>
43 #include <glib/gi18n-lib.h>
44
45 #include "burn-basics.h"
46 #include "burn-debug.h"
47 #include "burn-image-format.h"
48
49 static const gchar *
brasero_image_format_read_path(const gchar * ptr,gchar ** path)50 brasero_image_format_read_path (const gchar *ptr,
51 gchar **path)
52 {
53 const gchar *start, *end;
54
55 /* make sure there is a white space */
56 if (!isspace (*ptr))
57 return NULL;
58
59 /* jump over the white spaces */
60 while (isspace (*ptr)) ptr ++;
61
62 /* seek the first '"' if any */
63 start = g_utf8_strchr (ptr, -1, '"');
64 if (start) {
65 start ++;
66
67 /* seek the last '"' */
68 end = g_utf8_strchr (start, -1, '"');
69 if (!end)
70 return NULL;
71
72 ptr = end + 1;
73 }
74 else {
75 /* there is no starting '"' seek last space */
76 start = ptr;
77 end = ptr;
78 while (!isspace (*end)) end ++;
79
80 ptr = end;
81 if (isspace (*end))
82 end --;
83 }
84
85 if (path)
86 *path = g_strndup (start, end-start);
87
88 return ptr;
89 }
90
91 static gchar *
brasero_image_format_get_cue_file_complement(const gchar * path)92 brasero_image_format_get_cue_file_complement (const gchar *path)
93 {
94 FILE *file;
95 gchar *ptr;
96 gchar *complement = NULL;
97 /* a path can't be over MAXPATHLEN then buffer doesn't need to be over
98 * this value + 4 + white space + commas */
99 gchar buffer [MAXPATHLEN+8+3];
100
101 file = fopen (path, "r");
102 if (!file) {
103 if (g_str_has_suffix (path, ".cue"))
104 return g_strdup_printf ("%.*sbin",
105 (int) strlen (path) - 3,
106 path);
107
108 return g_strdup_printf ("%s.bin", path);
109 }
110
111 while (fgets (buffer, sizeof (buffer), file)) {
112 ptr = strstr (buffer, "FILE");
113 if (ptr) {
114 ptr += 4;
115 if (brasero_image_format_read_path (ptr, &complement))
116 break;
117 }
118 }
119 fclose (file);
120
121 /* check if the path is relative, if so then add the root path */
122 if (complement && !g_path_is_absolute (complement)) {
123 gchar *directory;
124 gchar *tmp;
125
126 directory = g_path_get_dirname (path);
127
128 tmp = complement;
129 complement = g_build_path (G_DIR_SEPARATOR_S,
130 directory,
131 complement,
132 NULL);
133 g_free (tmp);
134 }
135
136 return complement;
137 }
138
139 static gchar *
brasero_image_format_get_toc_file_complement(const gchar * path)140 brasero_image_format_get_toc_file_complement (const gchar *path)
141 {
142 FILE *file;
143 gchar *ptr;
144 gchar *complement = NULL;
145 /* a path can't be over MAXPATHLEN then buffer doesn't need to be over
146 * this value + keyword size + white space + commas */
147 gchar buffer [MAXPATHLEN+8+3];
148
149 /* NOTE: the problem here is that cdrdao files can have references to
150 * multiple files. Which is great but not for us ... */
151 file = fopen (path, "r");
152 if (!file) {
153 if (g_str_has_suffix (path, ".cue"))
154 return g_strdup_printf ("%.*sbin",
155 (int) strlen (path) - 3,
156 path);
157
158 return g_strdup_printf ("%s.bin", path);
159 }
160
161 while (fgets (buffer, sizeof (buffer), file)) {
162 ptr = strstr (buffer, "DATAFILE");
163 if (ptr) {
164 ptr += 8;
165 if (brasero_image_format_read_path (ptr, &complement))
166 break;
167 }
168
169 ptr = strstr (buffer, "FILE");
170 if (ptr) {
171 ptr += 4;
172 if (brasero_image_format_read_path (ptr, &complement))
173 break;
174 }
175 }
176 fclose (file);
177
178 /* check if the path is relative, if so then add the root path */
179 if (complement && !g_path_is_absolute (complement)) {
180 gchar *directory;
181 gchar *tmp;
182
183 directory = g_path_get_dirname (path);
184
185 tmp = complement;
186 complement = g_build_path (G_DIR_SEPARATOR_S,
187 directory,
188 complement,
189 NULL);
190 g_free (tmp);
191 }
192
193 return complement;
194 }
195
196 /* FIXME this function is flawed at the moment. A cue file or toc file can
197 * hold different paths */
198 gchar *
brasero_image_format_get_complement(BraseroImageFormat format,const gchar * path)199 brasero_image_format_get_complement (BraseroImageFormat format,
200 const gchar *path)
201 {
202 gchar *retval = NULL;
203
204 if (format == BRASERO_IMAGE_FORMAT_CLONE) {
205 /* These are set rules no need to parse:
206 * the toc file has to end with .toc suffix */
207 if (g_str_has_suffix (path, ".toc"))
208 retval = g_strndup (path, strlen (path) - 4);
209 }
210 else if (format == BRASERO_IMAGE_FORMAT_CUE) {
211 /* need to parse */
212 retval = brasero_image_format_get_cue_file_complement (path);
213 }
214 else if (format == BRASERO_IMAGE_FORMAT_CDRDAO) {
215 /* need to parse */
216 retval = brasero_image_format_get_toc_file_complement (path);
217 }
218 else
219 retval = NULL;
220
221 return retval;
222 }
223
224 static gchar *
brasero_image_format_get_MSF_address(const gchar * ptr,gint64 * block)225 brasero_image_format_get_MSF_address (const gchar *ptr,
226 gint64 *block)
227 {
228 gchar *next;
229 gint64 address = 0;
230
231 address = strtoll (ptr, &next, 10);
232 if (isspace (*next)) {
233 *block = address;
234 return next;
235 }
236
237 if (*next != ':')
238 return NULL;
239
240 next ++;
241 ptr = next;
242 address *= 60;
243 address += strtoll (ptr, &next, 10);
244 if (ptr == next)
245 return NULL;
246
247 if (*next != ':')
248 return NULL;
249
250 next ++;
251 ptr = next;
252 address *= 75;
253 address += strtoll (ptr, &next, 10);
254 if (ptr == next)
255 return NULL;
256
257 if (block)
258 *block = address;
259
260 return next;
261 }
262
263 static gboolean
brasero_image_format_get_DATAFILE_info(const gchar * ptr,GFile * parent,gint64 * size_file,GError ** error)264 brasero_image_format_get_DATAFILE_info (const gchar *ptr,
265 GFile *parent,
266 gint64 *size_file,
267 GError **error)
268 {
269 gchar *path = NULL;
270 GFileInfo *info;
271 GFile *file;
272
273 /* get the path. NOTE: no need to check if it's relative since that's
274 * just to skip it. */
275 ptr = brasero_image_format_read_path (ptr, &path);
276 if (!ptr)
277 return FALSE;
278
279 /* skip white spaces */
280 while (isspace (*ptr)) ptr++;
281
282 if (ptr [0] == '\0'
283 || (ptr [0] == '/' && ptr [1] == '/'))
284 goto stat_end;
285
286 if (!brasero_image_format_get_MSF_address (ptr, size_file)) {
287 g_free (path);
288 return FALSE;
289 }
290
291 g_free (path);
292 return TRUE;
293
294 stat_end:
295
296 /* check if the path is relative, if so then add the root path */
297 if (path && !g_path_is_absolute (path))
298 file = g_file_resolve_relative_path (parent, path);
299 else if (path) {
300 gchar *img_uri;
301 gchar *scheme;
302
303 scheme = g_file_get_uri_scheme (parent);
304 img_uri = g_strconcat (scheme, "://", path, NULL);
305 g_free (scheme);
306
307 file = g_file_new_for_commandline_arg (img_uri);
308 g_free (img_uri);
309 }
310 else
311 return FALSE;
312
313 g_free (path);
314
315 /* NOTE: follow symlink if any */
316 info = g_file_query_info (file,
317 G_FILE_ATTRIBUTE_STANDARD_SIZE,
318 G_FILE_QUERY_INFO_NONE,
319 NULL,
320 error);
321 g_object_unref (file);
322 if (!info)
323 return FALSE;
324
325 if (size_file)
326 *size_file = BRASERO_BYTES_TO_SECTORS (g_file_info_get_size (info), 2352);
327
328 g_object_unref (info);
329
330 return TRUE;
331 }
332
333 static gboolean
brasero_image_format_get_FILE_info(const gchar * ptr,GFile * parent,gint64 * size_img,GError ** error)334 brasero_image_format_get_FILE_info (const gchar *ptr,
335 GFile *parent,
336 gint64 *size_img,
337 GError **error)
338 {
339 gchar *path = NULL;
340 gint64 start = 0;
341 GFileInfo *info;
342 GFile *file = NULL;
343 gchar *tmp;
344
345 /* get the path and skip it */
346 ptr = brasero_image_format_read_path (ptr, &path);
347 if (!ptr)
348 return FALSE;
349
350 /* skip white spaces */
351 while (isspace (*ptr)) ptr++;
352
353 /* skip a possible #.... (offset in bytes) */
354 tmp = g_utf8_strchr (ptr, -1, '#');
355 if (tmp) {
356 tmp ++;
357 while (isdigit (*tmp)) tmp ++;
358 while (isspace (*tmp)) tmp++;
359 ptr = tmp;
360 }
361
362 /* get the start */
363 ptr = brasero_image_format_get_MSF_address (ptr, &start);
364 if (!ptr) {
365 g_free (path);
366 return FALSE;
367 }
368
369 /* skip white spaces */
370 while (isspace (*ptr)) ptr++;
371
372 if (ptr [0] == '\0'
373 || (ptr [0] == '/' && ptr [1] == '/'))
374 goto stat_end;
375
376 /* get the size */
377 if (!brasero_image_format_get_MSF_address (ptr, size_img)) {
378 g_free (path);
379 return FALSE;
380 }
381
382 g_free (path);
383 return TRUE;
384
385 stat_end:
386
387 /* check if the path is relative, if so then add the root path */
388 if (path && !g_path_is_absolute (path))
389 file = g_file_resolve_relative_path (parent, path);
390 else if (path) {
391 gchar *img_uri;
392 gchar *scheme;
393
394 scheme = g_file_get_uri_scheme (parent);
395 img_uri = g_strconcat (scheme, "://", path, NULL);
396 g_free (scheme);
397
398 file = g_file_new_for_commandline_arg (img_uri);
399 g_free (img_uri);
400 }
401 else
402 return FALSE;
403
404 g_free (path);
405
406 /* NOTE: follow symlink if any */
407 info = g_file_query_info (file,
408 G_FILE_ATTRIBUTE_STANDARD_SIZE,
409 G_FILE_QUERY_INFO_NONE,
410 NULL,
411 error);
412 g_object_unref (file);
413 if (!info)
414 return FALSE;
415
416 if (size_img)
417 *size_img = BRASERO_BYTES_TO_SECTORS (g_file_info_get_size (info), 2352) - start;
418
419 g_object_unref (info);
420
421 return TRUE;
422 }
423
424 gboolean
brasero_image_format_get_cdrdao_size(gchar * uri,guint64 * sectors,guint64 * size_img,GCancellable * cancel,GError ** error)425 brasero_image_format_get_cdrdao_size (gchar *uri,
426 guint64 *sectors,
427 guint64 *size_img,
428 GCancellable *cancel,
429 GError **error)
430 {
431 GFile *file;
432 gchar *line;
433 GFile *parent;
434 gint64 cue_size = 0;
435 GFileInputStream *input;
436 GDataInputStream *stream;
437
438 file = g_file_new_for_uri (uri);
439 input = g_file_read (file, cancel, error);
440
441 if (!input) {
442 g_object_unref (file);
443 return FALSE;
444 }
445
446 stream = g_data_input_stream_new (G_INPUT_STREAM (input));
447 g_object_unref (input);
448
449 parent = g_file_get_parent (file);
450 while ((line = g_data_input_stream_read_line (stream, NULL, cancel, error))) {
451 gchar *ptr;
452
453 if ((ptr = strstr (line, "DATAFILE"))) {
454 gint64 size_file;
455
456 ptr += 8;
457 if (brasero_image_format_get_DATAFILE_info (ptr, parent, &size_file, error))
458 cue_size += size_file;
459 }
460 else if ((ptr = strstr (line, "FILE"))) {
461 gint64 size_file;
462
463 ptr += 4;
464 /* first number is the position, the second the size,
465 * number after '#' is the offset (in bytes). */
466 if (brasero_image_format_get_FILE_info (ptr, parent, &size_file, error))
467 cue_size += size_file;
468 }
469 else if ((ptr = strstr (line, "AUDIOFILE"))) {
470 gint64 size_file;
471
472 ptr += 4;
473 /* first number is the position, the second the size,
474 * number after '#' is the offset (in bytes). */
475 if (brasero_image_format_get_FILE_info (ptr, parent, &size_file, error))
476 cue_size += size_file;
477 }
478 else if ((ptr = strstr (line, "SILENCE"))) {
479 gint64 size_silence;
480
481 ptr += 7;
482 if (isspace (*ptr)
483 && brasero_image_format_get_MSF_address (ptr, &size_silence))
484 cue_size += size_silence;
485 }
486 else if ((ptr = strstr (line, "PREGAP"))) {
487 gint64 size_pregap;
488
489 ptr += 6;
490 if (isspace (*ptr)
491 && brasero_image_format_get_MSF_address (ptr, &size_pregap))
492 cue_size += size_pregap;
493 }
494 else if ((ptr = strstr (line, "ZERO"))) {
495 gint64 size_zero;
496
497 ptr += 4;
498 if (isspace (*ptr)
499 && brasero_image_format_get_MSF_address (ptr, &size_zero))
500 cue_size += size_zero;
501 }
502
503 g_free (line);
504 }
505 g_object_unref (parent);
506
507 g_object_unref (stream);
508 g_object_unref (file);
509
510 if (sectors)
511 *sectors = cue_size;
512
513 if (size_img)
514 *size_img = cue_size * 2352;
515
516 return TRUE;
517 }
518
519 gboolean
brasero_image_format_cue_bin_byte_swap(gchar * uri,GCancellable * cancel,GError ** error)520 brasero_image_format_cue_bin_byte_swap (gchar *uri,
521 GCancellable *cancel,
522 GError **error)
523 {
524 GFile *file;
525 gchar *line;
526 GFileInputStream *input;
527 GDataInputStream *stream;
528 gboolean is_audio = FALSE;
529 gboolean is_binary = FALSE;
530
531 file = g_file_new_for_uri (uri);
532 input = g_file_read (file, cancel, error);
533
534 if (!input) {
535 g_object_unref (file);
536 return FALSE;
537 }
538
539 stream = g_data_input_stream_new (G_INPUT_STREAM (input));
540 g_object_unref (input);
541
542 while ((line = g_data_input_stream_read_line (stream, NULL, cancel, error))) {
543 const gchar *ptr;
544
545 if ((ptr = strstr (line, "FILE"))) {
546 if (strstr (ptr, "BINARY"))
547 is_binary = TRUE;
548 }
549 else if ((ptr = strstr (line, "TRACK"))) {
550 if (strstr (ptr, "AUDIO"))
551 is_audio = TRUE;
552 }
553 g_free (line);
554 }
555
556 g_object_unref (stream);
557 g_object_unref (file);
558
559 return is_binary && is_audio;
560 }
561
562 /**
563 * .cue can use various data files but have to use them ALL. So we don't need
564 * to care about a start/size address. We just go through the whole file and
565 * stat every time we catch a FILE keyword.
566 */
567
568 gboolean
brasero_image_format_get_cue_size(gchar * uri,guint64 * blocks,guint64 * size_img,GCancellable * cancel,GError ** error)569 brasero_image_format_get_cue_size (gchar *uri,
570 guint64 *blocks,
571 guint64 *size_img,
572 GCancellable *cancel,
573 GError **error)
574 {
575 GFile *file;
576 gchar *line;
577 gint64 cue_size = 0;
578 GFileInputStream *input;
579 GDataInputStream *stream;
580
581 file = g_file_new_for_uri (uri);
582 input = g_file_read (file, cancel, error);
583
584 if (!input) {
585 g_object_unref (file);
586 return FALSE;
587 }
588
589 stream = g_data_input_stream_new (G_INPUT_STREAM (input));
590 g_object_unref (input);
591
592 while ((line = g_data_input_stream_read_line (stream, NULL, cancel, error))) {
593 const gchar *ptr;
594
595 if ((ptr = strstr (line, "FILE"))) {
596 GFileInfo *info;
597 gchar *file_path;
598 GFile *file_img = NULL;
599
600 ptr += 4;
601
602 /* get the path (NOTE: if ptr is NULL file_path as well) */
603 ptr = brasero_image_format_read_path (ptr, &file_path);
604 if (!ptr) {
605 g_object_unref (stream);
606 g_object_unref (file);
607 g_free (line);
608 return FALSE;
609 }
610
611 /* check if the path is relative, if so then add the root path */
612 if (file_path && !g_path_is_absolute (file_path)) {
613 GFile *parent;
614
615 parent = g_file_get_parent (file);
616 file_img = g_file_resolve_relative_path (parent, file_path);
617 g_object_unref (parent);
618 }
619 else if (file_path) {
620 gchar *img_uri;
621 gchar *scheme;
622
623 scheme = g_file_get_uri_scheme (file);
624 img_uri = g_strconcat (scheme, "://", file_path, NULL);
625 g_free (scheme);
626
627 file_img = g_file_new_for_commandline_arg (img_uri);
628 g_free (img_uri);
629 }
630
631 g_free (file_path);
632
633 /* NOTE: follow symlink if any */
634 info = g_file_query_info (file_img,
635 G_FILE_ATTRIBUTE_STANDARD_SIZE,
636 G_FILE_QUERY_INFO_NONE,
637 NULL,
638 error);
639 g_object_unref (file_img);
640
641 if (!info) {
642 g_free (line);
643 g_object_unref (file);
644 g_object_unref (stream);
645 return FALSE;
646 }
647
648 cue_size += g_file_info_get_size (info);
649 g_object_unref (info);
650 }
651 else if ((ptr = strstr (line, "PREGAP"))) {
652 ptr += 6;
653 if (isspace (*ptr)) {
654 gint64 size_pregap;
655
656 ptr ++;
657 ptr = brasero_image_format_get_MSF_address (ptr, &size_pregap);
658 if (ptr)
659 cue_size += size_pregap * 2352;
660 }
661 }
662 else if ((ptr = strstr (line, "POSTGAP"))) {
663 ptr += 7;
664 if (isspace (*ptr)) {
665 gint64 size_postgap;
666
667 ptr ++;
668 ptr = brasero_image_format_get_MSF_address (ptr, &size_postgap);
669 if (ptr)
670 cue_size += size_postgap * 2352;
671 }
672 }
673
674 g_free (line);
675 }
676
677 g_object_unref (stream);
678 g_object_unref (file);
679
680 if (size_img)
681 *size_img = cue_size;
682 if (blocks)
683 *blocks = BRASERO_BYTES_TO_SECTORS (cue_size, 2352);
684
685 return TRUE;
686 }
687
688 BraseroImageFormat
brasero_image_format_identify_cuesheet(const gchar * uri,GCancellable * cancel,GError ** error)689 brasero_image_format_identify_cuesheet (const gchar *uri,
690 GCancellable *cancel,
691 GError **error)
692 {
693 GFile *file;
694 gchar *line;
695 GFileInputStream *input;
696 GDataInputStream *stream;
697 BraseroImageFormat format;
698
699 file = g_file_new_for_uri (uri);
700 input = g_file_read (file, cancel, error);
701 if (!input) {
702 g_object_unref (file);
703 return FALSE;
704 }
705
706 stream = g_data_input_stream_new (G_INPUT_STREAM (input));
707 g_object_unref (input);
708
709 format = BRASERO_IMAGE_FORMAT_NONE;
710 while ((line = g_data_input_stream_read_line (stream, NULL, cancel, error))) {
711 /* Keywords for cdrdao cuesheets */
712 if (strstr (line, "CD_ROM_XA")
713 || strstr (line, "CD_ROM")
714 || strstr (line, "CD_DA")
715 || strstr (line, "CD_TEXT")) {
716 format = BRASERO_IMAGE_FORMAT_CDRDAO;
717 g_free (line);
718 break;
719 }
720 else if (strstr (line, "TRACK")) {
721 /* NOTE: there is also "AUDIO" but it's common to both */
722
723 /* CDRDAO */
724 if (strstr (line, "MODE1")
725 || strstr (line, "MODE1_RAW")
726 || strstr (line, "MODE2_FORM1")
727 || strstr (line, "MODE2_FORM2")
728 || strstr (line, "MODE_2_RAW")
729 || strstr (line, "MODE2_FORM_MIX")
730 || strstr (line, "MODE2")) {
731 format = BRASERO_IMAGE_FORMAT_CDRDAO;
732 g_free (line);
733 break;
734 }
735
736 /* .CUE file */
737 else if (strstr (line, "CDG")
738 || strstr (line, "MODE1/2048")
739 || strstr (line, "MODE1/2352")
740 || strstr (line, "MODE2/2336")
741 || strstr (line, "MODE2/2352")
742 || strstr (line, "CDI/2336")
743 || strstr (line, "CDI/2352")) {
744 format = BRASERO_IMAGE_FORMAT_CUE;
745 g_free (line);
746 break;
747 }
748 }
749 else if (strstr (line, "FILE")) {
750 if (strstr (line, "MOTOROLA")
751 || strstr (line, "BINARY")
752 || strstr (line, "AIFF")
753 || strstr (line, "WAVE")
754 || strstr (line, "MP3")) {
755 format = BRASERO_IMAGE_FORMAT_CUE;
756 g_free (line);
757 break;
758 }
759 }
760 g_free (line);
761 line = NULL;
762 }
763
764 g_object_unref (stream);
765 g_object_unref (file);
766
767 BRASERO_BURN_LOG_WITH_FULL_TYPE (BRASERO_TRACK_TYPE_IMAGE,
768 format,
769 BRASERO_BURN_FLAG_NONE,
770 "Detected");
771 return format;
772 }
773
774 gboolean
brasero_image_format_get_iso_size(gchar * uri,guint64 * blocks,guint64 * size_img,GCancellable * cancel,GError ** error)775 brasero_image_format_get_iso_size (gchar *uri,
776 guint64 *blocks,
777 guint64 *size_img,
778 GCancellable *cancel,
779 GError **error)
780 {
781 GFileInfo *info;
782 GFile *file;
783
784 if (!uri)
785 return FALSE;
786
787 /* NOTE: follow symlink if any */
788 file = g_file_new_for_uri (uri);
789 info = g_file_query_info (file,
790 G_FILE_ATTRIBUTE_STANDARD_SIZE,
791 G_FILE_QUERY_INFO_NONE,
792 cancel,
793 error);
794 g_object_unref (file);
795 if (!info)
796 return FALSE;
797
798 if (size_img)
799 *size_img = g_file_info_get_size (info);
800
801 if (blocks)
802 *blocks = BRASERO_BYTES_TO_SECTORS (g_file_info_get_size (info), 2048);
803
804 g_object_unref (info);
805 return TRUE;
806 }
807
808 gboolean
brasero_image_format_get_clone_size(gchar * uri,guint64 * blocks,guint64 * size_img,GCancellable * cancel,GError ** error)809 brasero_image_format_get_clone_size (gchar *uri,
810 guint64 *blocks,
811 guint64 *size_img,
812 GCancellable *cancel,
813 GError **error)
814 {
815 GFileInfo *info;
816 GFile *file;
817
818 if (!uri)
819 return FALSE;
820
821 /* NOTE: follow symlink if any */
822 file = g_file_new_for_uri (uri);
823 info = g_file_query_info (file,
824 G_FILE_ATTRIBUTE_STANDARD_SIZE,
825 G_FILE_QUERY_INFO_NONE,
826 cancel,
827 error);
828 g_object_unref (file);
829
830 if (!info)
831 return FALSE;
832
833 if (size_img)
834 *size_img = g_file_info_get_size (info);
835
836 if (blocks)
837 *blocks = BRASERO_BYTES_TO_SECTORS (g_file_info_get_size (info), 2448);
838
839 g_object_unref (info);
840
841 return TRUE;
842 }
843
844 gchar *
brasero_image_format_get_default_path(BraseroImageFormat format,const gchar * name)845 brasero_image_format_get_default_path (BraseroImageFormat format,
846 const gchar *name)
847 {
848 const gchar *suffixes [] = {".iso",
849 ".toc",
850 ".cue",
851 ".toc",
852 NULL };
853 const gchar *suffix = NULL;
854 gchar *path;
855 gint i = 0;
856
857 if (format & BRASERO_IMAGE_FORMAT_BIN)
858 suffix = suffixes [0];
859 else if (format & BRASERO_IMAGE_FORMAT_CLONE)
860 suffix = suffixes [1];
861 else if (format & BRASERO_IMAGE_FORMAT_CUE)
862 suffix = suffixes [2];
863 else if (format & BRASERO_IMAGE_FORMAT_CDRDAO)
864 suffix = suffixes [3];
865
866 path = g_strdup_printf ("%s/%s%s",
867 g_get_home_dir (),
868 name? name:"brasero",
869 suffix);
870
871 while (g_file_test (path, G_FILE_TEST_EXISTS)) {
872 g_free (path);
873
874 path = g_strdup_printf ("%s/%s-%i%s",
875 g_get_home_dir (),
876 name? name:"brasero",
877 i,
878 suffix);
879 i ++;
880 }
881
882 return path;
883 }
884
885 gchar *
brasero_image_format_fix_path_extension(BraseroImageFormat format,gboolean check_existence,const gchar * path)886 brasero_image_format_fix_path_extension (BraseroImageFormat format,
887 gboolean check_existence,
888 const gchar *path)
889 {
890 gchar *dot;
891 guint i = 0;
892 gchar *retval = NULL;
893 const gchar *suffix = NULL;;
894 const gchar *suffixes [] = {".iso",
895 ".toc",
896 ".cue",
897 ".toc",
898 NULL };
899
900 /* search the last dot to check extension */
901 dot = g_utf8_strrchr (path, -1, '.');
902 if (dot && strlen (dot) < 5 && strlen (dot) > 1) {
903 if (format & BRASERO_IMAGE_FORMAT_BIN
904 && strcmp (suffixes [0], dot))
905 *dot = '\0';
906 else if (format & BRASERO_IMAGE_FORMAT_CLONE
907 && strcmp (suffixes [1], dot))
908 *dot = '\0';
909 else if (format & BRASERO_IMAGE_FORMAT_CUE
910 && strcmp (suffixes [2], dot))
911 *dot = '\0';
912 else if (format & BRASERO_IMAGE_FORMAT_CDRDAO
913 && strcmp (suffixes [3], dot))
914 *dot = '\0';
915 else
916 return g_strdup (path);
917 }
918
919 /* determine the proper suffix */
920 if (format & BRASERO_IMAGE_FORMAT_BIN)
921 suffix = suffixes [0];
922 else if (format & BRASERO_IMAGE_FORMAT_CLONE)
923 suffix = suffixes [1];
924 else if (format & BRASERO_IMAGE_FORMAT_CUE)
925 suffix = suffixes [2];
926 else if (format & BRASERO_IMAGE_FORMAT_CDRDAO)
927 suffix = suffixes [3];
928 else
929 return g_strdup (path);
930
931 /* make sure the file doesn't exist */
932 retval = g_strdup_printf ("%s%s", path, suffix);
933 if (!check_existence)
934 return retval;
935
936 while (g_file_test (retval, G_FILE_TEST_EXISTS)) {
937 g_free (retval);
938 retval = g_strdup_printf ("%s-%i%s", path, i, suffix);
939 i ++;
940 }
941
942 return retval;
943 }
944