nkeynes@1107 | 1 | /**
|
nkeynes@1107 | 2 | * $Id$
|
nkeynes@1107 | 3 | *
|
nkeynes@1107 | 4 | * libisofs adapter
|
nkeynes@1107 | 5 | *
|
nkeynes@1107 | 6 | * Copyright (c) 2010 Nathan Keynes.
|
nkeynes@1107 | 7 | *
|
nkeynes@1107 | 8 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@1107 | 9 | * it under the terms of the GNU General Public License as published by
|
nkeynes@1107 | 10 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@1107 | 11 | * (at your option) any later version.
|
nkeynes@1107 | 12 | *
|
nkeynes@1107 | 13 | * This program is distributed in the hope that it will be useful,
|
nkeynes@1107 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@1107 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@1107 | 16 | * GNU General Public License for more details.
|
nkeynes@1107 | 17 | */
|
nkeynes@1107 | 18 |
|
nkeynes@1107 | 19 | #include <assert.h>
|
nkeynes@1107 | 20 | #include <glib/gmem.h>
|
nkeynes@1107 | 21 |
|
nkeynes@1107 | 22 | #define LIBISOFS_WITHOUT_LIBBURN 1
|
nkeynes@1107 | 23 |
|
nkeynes@1107 | 24 | #include "drivers/cdrom/cdrom.h"
|
nkeynes@1107 | 25 | #include "drivers/cdrom/isofs.h"
|
nkeynes@1107 | 26 |
|
nkeynes@1107 | 27 | static int isofs_dummy_fn(IsoDataSource *src)
|
nkeynes@1107 | 28 | {
|
nkeynes@1107 | 29 | return 1;
|
nkeynes@1107 | 30 | }
|
nkeynes@1107 | 31 |
|
nkeynes@1107 | 32 | static int isofs_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
|
nkeynes@1107 | 33 | {
|
nkeynes@1107 | 34 | sector_source_t source = (sector_source_t)src->data;
|
nkeynes@1107 | 35 | cdrom_error_t err = sector_source_read_sectors(source, lba, 1,
|
nkeynes@1107 | 36 | CDROM_READ_MODE2_FORM1|CDROM_READ_DATA, buffer, NULL );
|
nkeynes@1107 | 37 | if( err != CDROM_ERROR_OK ) {
|
nkeynes@1107 | 38 | return ISO_DATA_SOURCE_FAILURE;
|
nkeynes@1107 | 39 | }
|
nkeynes@1107 | 40 | return 1;
|
nkeynes@1107 | 41 | }
|
nkeynes@1107 | 42 |
|
nkeynes@1107 | 43 | static void isofs_release(IsoDataSource *src)
|
nkeynes@1107 | 44 | {
|
nkeynes@1107 | 45 | sector_source_unref((sector_source_t)src->data);
|
nkeynes@1107 | 46 | }
|
nkeynes@1107 | 47 |
|
nkeynes@1107 | 48 | static IsoDataSource *iso_data_source_new( sector_source_t source )
|
nkeynes@1107 | 49 | {
|
nkeynes@1107 | 50 | IsoDataSource *src = g_malloc0(sizeof(IsoDataSource));
|
nkeynes@1107 | 51 | src->refcount = 1;
|
nkeynes@1107 | 52 | src->open = isofs_dummy_fn;
|
nkeynes@1107 | 53 | src->close = isofs_dummy_fn;
|
nkeynes@1107 | 54 | src->read_block = isofs_read_block;
|
nkeynes@1107 | 55 | src->free_data = isofs_release;
|
nkeynes@1107 | 56 | src->data = source;
|
nkeynes@1107 | 57 | sector_source_ref(source);
|
nkeynes@1107 | 58 | return src;
|
nkeynes@1107 | 59 | }
|
nkeynes@1107 | 60 |
|
nkeynes@1107 | 61 | /**
|
nkeynes@1107 | 62 | * Construct an isofs image from an existing sector source.
|
nkeynes@1107 | 63 | */
|
nkeynes@1107 | 64 | IsoImage *iso_image_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
|
nkeynes@1107 | 65 | {
|
nkeynes@1107 | 66 | IsoImage *iso = NULL;
|
nkeynes@1107 | 67 | IsoReadOpts *opts;
|
nkeynes@1107 | 68 | IsoDataSource *src;
|
nkeynes@1107 | 69 |
|
nkeynes@1107 | 70 | int status = iso_image_new(NULL, &iso);
|
nkeynes@1107 | 71 | if( status != 1 )
|
nkeynes@1107 | 72 | return NULL;
|
nkeynes@1107 | 73 |
|
nkeynes@1107 | 74 | status = iso_read_opts_new(&opts,0);
|
nkeynes@1107 | 75 | if( status != 1 ) {
|
nkeynes@1107 | 76 | iso_image_unref( iso );
|
nkeynes@1107 | 77 | return NULL;
|
nkeynes@1107 | 78 | }
|
nkeynes@1107 | 79 |
|
nkeynes@1107 | 80 | iso_read_opts_set_start_block(opts, start);
|
nkeynes@1107 | 81 | src = iso_data_source_new(source);
|
nkeynes@1107 | 82 | status = iso_image_import(iso, src, opts, NULL);
|
nkeynes@1107 | 83 | iso_data_source_unref(src);
|
nkeynes@1107 | 84 | iso_read_opts_free(opts);
|
nkeynes@1107 | 85 | if( status != 1 ) {
|
nkeynes@1107 | 86 | iso_image_unref(iso);
|
nkeynes@1107 | 87 | return NULL;
|
nkeynes@1107 | 88 | }
|
nkeynes@1107 | 89 | return iso;
|
nkeynes@1107 | 90 | }
|
nkeynes@1107 | 91 |
|
nkeynes@1107 | 92 | IsoImage *iso_image_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
|
nkeynes@1107 | 93 | {
|
nkeynes@1107 | 94 | return iso_image_new_from_source( &disc->source, start_sector, err );
|
nkeynes@1107 | 95 | }
|
nkeynes@1107 | 96 |
|
nkeynes@1107 | 97 | IsoImage *iso_image_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
|
nkeynes@1107 | 98 | {
|
nkeynes@1107 | 99 | return iso_image_new_from_source( &disc->source, track->lba, err );
|
nkeynes@1107 | 100 | }
|
nkeynes@1107 | 101 |
|
nkeynes@1107 | 102 |
|
nkeynes@1107 | 103 | IsoImageFilesystem *iso_filesystem_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
|
nkeynes@1107 | 104 | {
|
nkeynes@1107 | 105 | IsoImageFilesystem *iso = NULL;
|
nkeynes@1107 | 106 | IsoReadOpts *opts;
|
nkeynes@1107 | 107 | IsoDataSource *src;
|
nkeynes@1107 | 108 |
|
nkeynes@1107 | 109 | int status = iso_read_opts_new(&opts,0);
|
nkeynes@1107 | 110 | if( status != 1 ) {
|
nkeynes@1107 | 111 | return NULL;
|
nkeynes@1107 | 112 | }
|
nkeynes@1107 | 113 |
|
nkeynes@1107 | 114 | iso_read_opts_set_start_block(opts, start);
|
nkeynes@1107 | 115 | src = iso_data_source_new(source);
|
nkeynes@1107 | 116 | status = iso_image_filesystem_new(src, opts, 0x1FFFFF, &iso);
|
nkeynes@1107 | 117 | iso_data_source_unref(src);
|
nkeynes@1107 | 118 | iso_read_opts_free(opts);
|
nkeynes@1107 | 119 | if( status != 1 ) {
|
nkeynes@1107 | 120 | return NULL;
|
nkeynes@1107 | 121 | }
|
nkeynes@1107 | 122 | return iso;
|
nkeynes@1107 | 123 |
|
nkeynes@1107 | 124 | }
|
nkeynes@1107 | 125 |
|
nkeynes@1107 | 126 | IsoImageFilesystem *iso_filesystem_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
|
nkeynes@1107 | 127 | {
|
nkeynes@1107 | 128 | return iso_filesystem_new_from_source( &disc->source, start_sector, err );
|
nkeynes@1107 | 129 | }
|
nkeynes@1107 | 130 |
|
nkeynes@1107 | 131 | IsoImageFilesystem *iso_filesystem_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
|
nkeynes@1107 | 132 | {
|
nkeynes@1107 | 133 | return iso_filesystem_new_from_source( &disc->source, track->lba, err );
|
nkeynes@1107 | 134 | }
|
nkeynes@1107 | 135 |
|
nkeynes@1107 | 136 |
|
nkeynes@1107 | 137 | /**
|
nkeynes@1107 | 138 | * Construct a sector source from a given IsoImage.
|
nkeynes@1107 | 139 | */
|
nkeynes@1107 | 140 | sector_source_t iso_sector_source_new( IsoImage *image, sector_mode_t mode, cdrom_lba_t start_sector,
|
nkeynes@1107 | 141 | const char *bootstrap, ERROR *err )
|
nkeynes@1107 | 142 | {
|
nkeynes@1107 | 143 | assert( mode == SECTOR_MODE1 || mode == SECTOR_MODE2_FORM1 );
|
nkeynes@1107 | 144 |
|
nkeynes@1107 | 145 | IsoWriteOpts *opts;
|
nkeynes@1107 | 146 | struct burn_source *burn;
|
nkeynes@1107 | 147 |
|
nkeynes@1107 | 148 | int status = iso_write_opts_new(&opts, 0);
|
nkeynes@1107 | 149 | if( status != 1 )
|
nkeynes@1107 | 150 | return NULL;
|
nkeynes@1107 | 151 | iso_write_opts_set_appendable(opts,0);
|
nkeynes@1107 | 152 | iso_write_opts_set_ms_block(opts, start_sector);
|
nkeynes@1107 | 153 | iso_write_opts_set_system_area(opts, (char *)bootstrap, 0, 0);
|
nkeynes@1107 | 154 |
|
nkeynes@1107 | 155 | status = iso_image_create_burn_source(image, opts, &burn);
|
nkeynes@1107 | 156 | iso_write_opts_free(opts);
|
nkeynes@1107 | 157 | if( status != 1 ) {
|
nkeynes@1107 | 158 | return NULL;
|
nkeynes@1107 | 159 | }
|
nkeynes@1107 | 160 |
|
nkeynes@1107 | 161 | off_t size = burn->get_size(burn);
|
nkeynes@1107 | 162 | sector_source_t source = tmpfile_sector_source_new(mode);
|
nkeynes@1107 | 163 | if( source == NULL ) {
|
nkeynes@1107 | 164 | burn->free_data(burn);
|
nkeynes@1107 | 165 | free(burn);
|
nkeynes@1107 | 166 | return NULL;
|
nkeynes@1107 | 167 | }
|
nkeynes@1107 | 168 |
|
nkeynes@1107 | 169 | char buf[2048];
|
nkeynes@1107 | 170 | cdrom_count_t expect = size/2048;
|
nkeynes@1107 | 171 | cdrom_count_t count = 0;
|
nkeynes@1107 | 172 | for( cdrom_count_t count = 0; count < expect; count++ ) {
|
nkeynes@1107 | 173 | status = burn->read(burn, buf, 2048);
|
nkeynes@1107 | 174 | if( status == 0 ) {
|
nkeynes@1107 | 175 | /* EOF */
|
nkeynes@1107 | 176 | break;
|
nkeynes@1107 | 177 | } else if( status != 2048 ) {
|
nkeynes@1107 | 178 | /* Error */
|
nkeynes@1107 | 179 | sector_source_unref(source);
|
nkeynes@1107 | 180 | source = NULL;
|
nkeynes@1107 | 181 | break;
|
nkeynes@1107 | 182 | }
|
nkeynes@1107 | 183 | }
|
nkeynes@1107 | 184 | burn->free_data(burn);
|
nkeynes@1107 | 185 | free(burn);
|
nkeynes@1107 | 186 | return source;
|
nkeynes@1107 | 187 | }
|
nkeynes@1107 | 188 |
|