1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4
* Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
6
* Libbrasero-media 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.
11
* The Libbrasero-media authors hereby grant permission for non-GPL compatible
12
* GStreamer plugins to be used and distributed together with GStreamer
13
* and Libbrasero-media. This permission is above and beyond the permissions granted
14
* by the GPL license by which Libbrasero-media 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.
19
* Libbrasero-media 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.
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.
41
#include <glib/gi18n-lib.h>
43
#include "burn-volume-source.h"
44
#include "burn-volume.h"
45
#include "burn-iso9660.h"
46
#include "brasero-media.h"
47
#include "brasero-media-private.h"
48
#include "brasero-units.h"
50
struct _BraseroTagDesc {
60
typedef struct _BraseroTagDesc BraseroTagDesc;
62
struct _BraseroAnchorDesc {
65
guchar main_extent [8];
66
guchar reserve_extent [8];
68
typedef struct _BraseroAnchorDesc BraseroAnchorDesc;
70
#define SYSTEM_AREA_SECTORS 16
71
#define ANCHOR_AREA_SECTORS 256
75
brasero_volume_file_free (BraseroVolFile *file)
83
if (file->isdir_loaded) {
84
for (iter = file->specific.dir.children; iter; iter = iter->next)
85
brasero_volume_file_free (iter->data);
87
g_list_free (file->specific.dir.children);
91
g_slist_foreach (file->specific.file.extents,
94
g_slist_free (file->specific.file.extents);
97
g_free (file->rr_name);
103
brasero_volume_get_primary_from_file (BraseroVolSrc *vol,
107
BraseroVolDesc *desc;
109
/* skip the first 16 blocks */
110
if (BRASERO_VOL_SRC_SEEK (vol, SYSTEM_AREA_SECTORS, SEEK_CUR, error) == -1)
113
if (!BRASERO_VOL_SRC_READ (vol, primary_vol, 1, error))
116
/* make a few checks to ensure this is an ECMA volume */
117
desc = (BraseroVolDesc *) primary_vol;
118
if (memcmp (desc->id, "CD001", 5)
119
&& memcmp (desc->id, "BEA01", 5)
120
&& memcmp (desc->id, "BOOT2", 5)
121
&& memcmp (desc->id, "CDW02", 5)
122
&& memcmp (desc->id, "NSR02", 5) /* usually UDF */
123
&& memcmp (desc->id, "NSR03", 5) /* usually UDF */
124
&& memcmp (desc->id, "TEA01", 5)) {
127
BRASERO_MEDIA_ERROR_IMAGE_INVALID,
128
_("It does not appear to be a valid ISO image"));
129
BRASERO_MEDIA_LOG ("Wrong volume descriptor, got %.5s", desc->id);
137
brasero_volume_get_size (BraseroVolSrc *vol,
143
gchar buffer [ISO9660_BLOCK_SIZE];
145
if (block && BRASERO_VOL_SRC_SEEK (vol, block, SEEK_SET, error) == -1)
148
result = brasero_volume_get_primary_from_file (vol, buffer, error);
152
if (!brasero_iso9660_is_primary_descriptor (buffer, error))
155
return brasero_iso9660_get_size (buffer, nb_blocks, error);
159
brasero_volume_get_files (BraseroVolSrc *vol,
166
gchar buffer [ISO9660_BLOCK_SIZE];
168
if (BRASERO_VOL_SRC_SEEK (vol, block, SEEK_SET, error) == -1)
171
if (!brasero_volume_get_primary_from_file (vol, buffer, error))
174
if (!brasero_iso9660_is_primary_descriptor (buffer, error))
178
&& !brasero_iso9660_get_label (buffer, label, error))
182
&& !brasero_iso9660_get_size (buffer, nb_blocks, error))
185
return brasero_iso9660_get_contents (vol,
192
brasero_volume_load_directory_contents (BraseroVolSrc *vol,
193
gint64 session_block,
197
gchar buffer [ISO9660_BLOCK_SIZE];
199
if (BRASERO_VOL_SRC_SEEK (vol, session_block, SEEK_SET, error) == -1)
202
if (!brasero_volume_get_primary_from_file (vol, buffer, error))
205
if (!brasero_iso9660_is_primary_descriptor (buffer, error))
208
return brasero_iso9660_get_directory_contents (vol,
215
brasero_volume_get_file (BraseroVolSrc *vol,
217
gint64 volume_start_block,
220
gchar buffer [ISO9660_BLOCK_SIZE];
222
if (BRASERO_VOL_SRC_SEEK (vol, volume_start_block, SEEK_SET, error) == -1)
225
if (!brasero_volume_get_primary_from_file (vol, buffer, error))
228
if (!brasero_iso9660_is_primary_descriptor (buffer, error))
231
return brasero_iso9660_get_file (vol, path, buffer, error);
235
brasero_volume_file_to_path (BraseroVolFile *file)
238
BraseroVolFile *parent;
239
GSList *components = NULL, *iter, *next;
244
/* make a list of all the components of the path by going up to root */
245
parent = file->parent;
246
while (parent && parent->name) {
247
components = g_slist_prepend (components, BRASERO_VOLUME_FILE_NAME (parent));
248
parent = parent->parent;
254
path = g_string_new (NULL);
255
for (iter = components; iter; iter = next) {
260
components = g_slist_remove (components, name);
262
g_string_append_c (path, G_DIR_SEPARATOR);
263
g_string_append (path, name);
266
g_slist_free (components);
267
return g_string_free (path, FALSE);
271
brasero_volume_file_from_path (const gchar *ptr,
272
BraseroVolFile *parent)
278
/* first determine the name of the directory / file to look for */
279
if (!ptr || ptr [0] != '/' || !parent)
283
next = g_utf8_strchr (ptr, -1, G_DIR_SEPARATOR);
289
for (iter = parent->specific.dir.children; iter; iter = iter->next) {
290
BraseroVolFile *file;
293
if (!strncmp (ptr, BRASERO_VOLUME_FILE_NAME (file), len)) {
294
/* we've found it seek for the next if any */
299
return brasero_volume_file_from_path (ptr, file);
307
brasero_volume_file_size (BraseroVolFile *file)
315
for (extents = file->specific.file.extents; extents; extents = extents->next) {
316
BraseroVolFileExtent *extent;
318
extent = extents->data;
319
size += extent->size;
321
return BRASERO_BYTES_TO_SECTORS (size, 2048);
324
for (iter = file->specific.dir.children; iter; iter = iter->next) {
328
size += brasero_volume_file_size (file);
330
size += BRASERO_BYTES_TO_SECTORS (file->specific.file.size_bytes, 2048);
337
brasero_volume_file_merge (BraseroVolFile *file1,
338
BraseroVolFile *file2)
340
file1->specific.file.size_bytes += file2->specific.file.size_bytes;
341
file1->specific.file.extents = g_slist_concat (file1->specific.file.extents,
342
file2->specific.file.extents);
344
file2->specific.file.extents = NULL;
345
brasero_volume_file_free (file2);