Search
lxdream.org :: lxdream/src/drivers/cdrom/isofs.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/cdrom/isofs.c
changeset 1298:d0eb2307b847
prev1296:30ecee61f811
author nkeynes
date Wed Feb 04 08:38:23 2015 +1000 (5 years ago)
permissions -rw-r--r--
last change Fix assorted compile warnings reported by Clang
file annotate diff log raw
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@1108
    20
#include <stdio.h>
nkeynes@1108
    21
#include <unistd.h>
nkeynes@1296
    22
#include <glib.h>
nkeynes@1107
    23
nkeynes@1107
    24
#define LIBISOFS_WITHOUT_LIBBURN 1
nkeynes@1107
    25
nkeynes@1107
    26
#include "drivers/cdrom/cdrom.h"
nkeynes@1107
    27
#include "drivers/cdrom/isofs.h"
nkeynes@1107
    28
nkeynes@1107
    29
static int isofs_dummy_fn(IsoDataSource *src)
nkeynes@1107
    30
{
nkeynes@1107
    31
    return 1;
nkeynes@1107
    32
}
nkeynes@1107
    33
nkeynes@1107
    34
static int isofs_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
nkeynes@1107
    35
{
nkeynes@1107
    36
    sector_source_t source = (sector_source_t)src->data;
nkeynes@1107
    37
    cdrom_error_t err = sector_source_read_sectors(source, lba, 1,
nkeynes@1107
    38
            CDROM_READ_MODE2_FORM1|CDROM_READ_DATA, buffer, NULL );
nkeynes@1107
    39
    if( err != CDROM_ERROR_OK ) {
nkeynes@1107
    40
        return ISO_DATA_SOURCE_FAILURE;
nkeynes@1107
    41
    }
nkeynes@1107
    42
    return 1;
nkeynes@1107
    43
}
nkeynes@1107
    44
nkeynes@1107
    45
static void isofs_release(IsoDataSource *src)
nkeynes@1107
    46
{
nkeynes@1107
    47
    sector_source_unref((sector_source_t)src->data);
nkeynes@1107
    48
}
nkeynes@1107
    49
nkeynes@1107
    50
static IsoDataSource *iso_data_source_new( sector_source_t source )
nkeynes@1107
    51
{
nkeynes@1107
    52
    IsoDataSource *src = g_malloc0(sizeof(IsoDataSource));
nkeynes@1107
    53
    src->refcount = 1;
nkeynes@1107
    54
    src->open = isofs_dummy_fn;
nkeynes@1107
    55
    src->close = isofs_dummy_fn;
nkeynes@1107
    56
    src->read_block = isofs_read_block;
nkeynes@1107
    57
    src->free_data = isofs_release;
nkeynes@1107
    58
    src->data = source;
nkeynes@1107
    59
    sector_source_ref(source);
nkeynes@1107
    60
    return src;
nkeynes@1107
    61
}
nkeynes@1107
    62
nkeynes@1109
    63
static void iso_error_convert( int status, ERROR *err )
nkeynes@1109
    64
{
nkeynes@1109
    65
    switch( status ) {
nkeynes@1109
    66
    case ISO_SUCCESS:
nkeynes@1109
    67
        err->code = LX_ERR_NONE;
nkeynes@1109
    68
        break;
nkeynes@1109
    69
    case ISO_OUT_OF_MEM:
nkeynes@1109
    70
        SET_ERROR( err, LX_ERR_NOMEM, "Unable to allocate memory for ISO filesystem" );
nkeynes@1109
    71
        break;
nkeynes@1109
    72
    case ISO_FILE_READ_ERROR:
nkeynes@1109
    73
        SET_ERROR( err, LX_ERR_FILE_IOERROR, "Read error" );
nkeynes@1109
    74
        break;
nkeynes@1109
    75
    default:
nkeynes@1109
    76
        SET_ERROR( err, LX_ERR_UNHANDLED, "Unknown error in ISO filesystem" );
nkeynes@1109
    77
        break;
nkeynes@1109
    78
    }
nkeynes@1109
    79
}
nkeynes@1109
    80
nkeynes@1107
    81
/**
nkeynes@1107
    82
 * Construct an isofs image from an existing sector source.
nkeynes@1107
    83
 */
nkeynes@1107
    84
IsoImage *iso_image_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
nkeynes@1107
    85
{
nkeynes@1107
    86
    IsoImage *iso = NULL;
nkeynes@1107
    87
    IsoReadOpts *opts;
nkeynes@1107
    88
    IsoDataSource *src;
nkeynes@1107
    89
nkeynes@1107
    90
    int status = iso_image_new(NULL, &iso);
nkeynes@1107
    91
    if( status != 1 )
nkeynes@1107
    92
        return NULL;
nkeynes@1107
    93
nkeynes@1107
    94
    status = iso_read_opts_new(&opts,0);
nkeynes@1107
    95
    if( status != 1 ) {
nkeynes@1107
    96
        iso_image_unref( iso );
nkeynes@1107
    97
        return NULL;
nkeynes@1107
    98
    }
nkeynes@1107
    99
nkeynes@1107
   100
    iso_read_opts_set_start_block(opts, start);
nkeynes@1107
   101
    src = iso_data_source_new(source);
nkeynes@1107
   102
    status = iso_image_import(iso, src, opts, NULL);
nkeynes@1107
   103
    iso_data_source_unref(src);
nkeynes@1107
   104
    iso_read_opts_free(opts);
nkeynes@1107
   105
    if( status != 1 ) {
nkeynes@1107
   106
        iso_image_unref(iso);
nkeynes@1107
   107
        return NULL;
nkeynes@1107
   108
    }
nkeynes@1107
   109
    return iso;
nkeynes@1107
   110
}
nkeynes@1107
   111
nkeynes@1107
   112
IsoImage *iso_image_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
nkeynes@1107
   113
{
nkeynes@1107
   114
    return iso_image_new_from_source( &disc->source, start_sector, err );
nkeynes@1107
   115
}
nkeynes@1107
   116
nkeynes@1107
   117
IsoImage *iso_image_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
nkeynes@1107
   118
{
nkeynes@1107
   119
    return iso_image_new_from_source( &disc->source, track->lba, err );
nkeynes@1107
   120
}
nkeynes@1107
   121
nkeynes@1107
   122
nkeynes@1107
   123
IsoImageFilesystem *iso_filesystem_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
nkeynes@1107
   124
{
nkeynes@1107
   125
    IsoImageFilesystem *iso = NULL;
nkeynes@1107
   126
    IsoReadOpts *opts;
nkeynes@1107
   127
    IsoDataSource *src;
nkeynes@1107
   128
nkeynes@1107
   129
    int status = iso_read_opts_new(&opts,0);
nkeynes@1107
   130
    if( status != 1 ) {
nkeynes@1109
   131
        iso_error_convert(status, err);
nkeynes@1107
   132
        return NULL;
nkeynes@1107
   133
    }
nkeynes@1107
   134
nkeynes@1107
   135
    iso_read_opts_set_start_block(opts, start);
nkeynes@1107
   136
    src = iso_data_source_new(source);
nkeynes@1107
   137
    status = iso_image_filesystem_new(src, opts, 0x1FFFFF, &iso);
nkeynes@1107
   138
    iso_data_source_unref(src);
nkeynes@1107
   139
    iso_read_opts_free(opts);
nkeynes@1107
   140
    if( status != 1 ) {
nkeynes@1109
   141
        iso_error_convert(status, err);
nkeynes@1107
   142
        return NULL;
nkeynes@1107
   143
    }
nkeynes@1107
   144
    return iso;
nkeynes@1107
   145
nkeynes@1107
   146
}
nkeynes@1107
   147
nkeynes@1107
   148
IsoImageFilesystem *iso_filesystem_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
nkeynes@1107
   149
{
nkeynes@1107
   150
    return iso_filesystem_new_from_source( &disc->source, start_sector, err );
nkeynes@1107
   151
}
nkeynes@1107
   152
nkeynes@1107
   153
IsoImageFilesystem *iso_filesystem_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
nkeynes@1107
   154
{
nkeynes@1107
   155
    return iso_filesystem_new_from_source( &disc->source, track->lba, err );
nkeynes@1107
   156
}
nkeynes@1107
   157
nkeynes@1107
   158
nkeynes@1107
   159
/**
nkeynes@1107
   160
 * Construct a sector source from a given IsoImage.
nkeynes@1107
   161
 */
nkeynes@1107
   162
sector_source_t iso_sector_source_new( IsoImage *image, sector_mode_t mode, cdrom_lba_t start_sector,
nkeynes@1107
   163
                                       const char *bootstrap, ERROR *err )
nkeynes@1107
   164
{
nkeynes@1107
   165
    assert( mode == SECTOR_MODE1 || mode == SECTOR_MODE2_FORM1 );
nkeynes@1107
   166
nkeynes@1107
   167
    IsoWriteOpts *opts;
nkeynes@1107
   168
    struct burn_source *burn;
nkeynes@1107
   169
nkeynes@1107
   170
    int status = iso_write_opts_new(&opts, 0);
nkeynes@1109
   171
    if( status != 1 ) {
nkeynes@1109
   172
        iso_error_convert(status, err);
nkeynes@1107
   173
        return NULL;
nkeynes@1109
   174
    }
nkeynes@1107
   175
    iso_write_opts_set_appendable(opts,0);
nkeynes@1107
   176
    iso_write_opts_set_ms_block(opts, start_sector);
nkeynes@1107
   177
nkeynes@1107
   178
    status = iso_image_create_burn_source(image, opts, &burn);
nkeynes@1107
   179
    iso_write_opts_free(opts);
nkeynes@1107
   180
    if( status != 1 ) {
nkeynes@1109
   181
        iso_error_convert(status, err);
nkeynes@1107
   182
        return NULL;
nkeynes@1107
   183
    }
nkeynes@1107
   184
nkeynes@1107
   185
    off_t size = burn->get_size(burn);
nkeynes@1107
   186
    sector_source_t source = tmpfile_sector_source_new(mode);
nkeynes@1107
   187
    if( source == NULL ) {
nkeynes@1107
   188
        burn->free_data(burn);
nkeynes@1107
   189
        free(burn);
nkeynes@1107
   190
        return NULL;
nkeynes@1107
   191
    }
nkeynes@1107
   192
nkeynes@1298
   193
    unsigned char buf[2048];
nkeynes@1107
   194
    cdrom_count_t expect = size/2048;
nkeynes@1108
   195
    int fd = file_sector_source_get_fd(source);
nkeynes@1108
   196
    source->size = expect;
nkeynes@1108
   197
    lseek( fd, 0, SEEK_SET );
nkeynes@1114
   198
    write( fd, bootstrap, 32768 );
nkeynes@1107
   199
    for( cdrom_count_t count = 0; count < expect; count++ ) {
nkeynes@1108
   200
        if( burn->read == NULL ) {
nkeynes@1108
   201
            status = burn->read_xt(burn, buf, 2048);
nkeynes@1108
   202
        } else {
nkeynes@1108
   203
            status = burn->read(burn, buf, 2048);
nkeynes@1108
   204
        }
nkeynes@1107
   205
        if( status == 0 ) {
nkeynes@1107
   206
            /* EOF */
nkeynes@1107
   207
            break;
nkeynes@1107
   208
        } else if( status != 2048 ) {
nkeynes@1107
   209
            /* Error */
nkeynes@1107
   210
            sector_source_unref(source);
nkeynes@1107
   211
            source = NULL;
nkeynes@1107
   212
            break;
nkeynes@1107
   213
        }
nkeynes@1114
   214
        /* Discard first 16 sectors, replaced with the bootstrap */
nkeynes@1114
   215
        if( count >= (32768/2048) )
nkeynes@1114
   216
            write( fd, buf, 2048 );
nkeynes@1107
   217
    }
nkeynes@1107
   218
    burn->free_data(burn);
nkeynes@1107
   219
    free(burn);
nkeynes@1107
   220
    return source;
nkeynes@1107
   221
}
nkeynes@1107
   222
.