6 * Copyright (c) 2010 Nathan Keynes.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
22 #include <glib/gmem.h>
24 #define LIBISOFS_WITHOUT_LIBBURN 1
26 #include "drivers/cdrom/cdrom.h"
27 #include "drivers/cdrom/isofs.h"
29 static int isofs_dummy_fn(IsoDataSource *src)
34 static int isofs_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
36 sector_source_t source = (sector_source_t)src->data;
37 cdrom_error_t err = sector_source_read_sectors(source, lba, 1,
38 CDROM_READ_MODE2_FORM1|CDROM_READ_DATA, buffer, NULL );
39 if( err != CDROM_ERROR_OK ) {
40 return ISO_DATA_SOURCE_FAILURE;
45 static void isofs_release(IsoDataSource *src)
47 sector_source_unref((sector_source_t)src->data);
50 static IsoDataSource *iso_data_source_new( sector_source_t source )
52 IsoDataSource *src = g_malloc0(sizeof(IsoDataSource));
54 src->open = isofs_dummy_fn;
55 src->close = isofs_dummy_fn;
56 src->read_block = isofs_read_block;
57 src->free_data = isofs_release;
59 sector_source_ref(source);
63 static void iso_error_convert( int status, ERROR *err )
67 err->code = LX_ERR_NONE;
70 SET_ERROR( err, LX_ERR_NOMEM, "Unable to allocate memory for ISO filesystem" );
72 case ISO_FILE_READ_ERROR:
73 SET_ERROR( err, LX_ERR_FILE_IOERROR, "Read error" );
76 SET_ERROR( err, LX_ERR_UNHANDLED, "Unknown error in ISO filesystem" );
82 * Construct an isofs image from an existing sector source.
84 IsoImage *iso_image_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
90 int status = iso_image_new(NULL, &iso);
94 status = iso_read_opts_new(&opts,0);
96 iso_image_unref( iso );
100 iso_read_opts_set_start_block(opts, start);
101 src = iso_data_source_new(source);
102 status = iso_image_import(iso, src, opts, NULL);
103 iso_data_source_unref(src);
104 iso_read_opts_free(opts);
106 iso_image_unref(iso);
112 IsoImage *iso_image_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
114 return iso_image_new_from_source( &disc->source, start_sector, err );
117 IsoImage *iso_image_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
119 return iso_image_new_from_source( &disc->source, track->lba, err );
123 IsoImageFilesystem *iso_filesystem_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
125 IsoImageFilesystem *iso = NULL;
129 int status = iso_read_opts_new(&opts,0);
131 iso_error_convert(status, err);
135 iso_read_opts_set_start_block(opts, start);
136 src = iso_data_source_new(source);
137 status = iso_image_filesystem_new(src, opts, 0x1FFFFF, &iso);
138 iso_data_source_unref(src);
139 iso_read_opts_free(opts);
141 iso_error_convert(status, err);
148 IsoImageFilesystem *iso_filesystem_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
150 return iso_filesystem_new_from_source( &disc->source, start_sector, err );
153 IsoImageFilesystem *iso_filesystem_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
155 return iso_filesystem_new_from_source( &disc->source, track->lba, err );
160 * Construct a sector source from a given IsoImage.
162 sector_source_t iso_sector_source_new( IsoImage *image, sector_mode_t mode, cdrom_lba_t start_sector,
163 const char *bootstrap, ERROR *err )
165 assert( mode == SECTOR_MODE1 || mode == SECTOR_MODE2_FORM1 );
168 struct burn_source *burn;
170 int status = iso_write_opts_new(&opts, 0);
172 iso_error_convert(status, err);
175 iso_write_opts_set_appendable(opts,0);
176 iso_write_opts_set_ms_block(opts, start_sector);
178 status = iso_image_create_burn_source(image, opts, &burn);
179 iso_write_opts_free(opts);
181 iso_error_convert(status, err);
185 off_t size = burn->get_size(burn);
186 sector_source_t source = tmpfile_sector_source_new(mode);
187 if( source == NULL ) {
188 burn->free_data(burn);
194 cdrom_count_t expect = size/2048;
195 cdrom_count_t count = 0;
196 int fd = file_sector_source_get_fd(source);
197 source->size = expect;
198 lseek( fd, 0, SEEK_SET );
199 write( fd, bootstrap, 32768 );
200 for( cdrom_count_t count = 0; count < expect; count++ ) {
201 if( burn->read == NULL ) {
202 status = burn->read_xt(burn, buf, 2048);
204 status = burn->read(burn, buf, 2048);
209 } else if( status != 2048 ) {
211 sector_source_unref(source);
215 /* Discard first 16 sectors, replaced with the bootstrap */
216 if( count >= (32768/2048) )
217 write( fd, buf, 2048 );
219 burn->free_data(burn);
.