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 1114:2fbf712e53f0
prev1109:700c5ab26a63
next1296:30ecee61f811
author nkeynes
date Mon Mar 05 22:20:33 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Fix boundary of the first vertical gap in view
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * libisofs adapter
     5  *
     6  * Copyright (c) 2010 Nathan Keynes.
     7  *
     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.
    12  *
    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.
    17  */
    19 #include <assert.h>
    20 #include <stdio.h>
    21 #include <unistd.h>
    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)
    30 {
    31     return 1;
    32 }
    34 static int isofs_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
    35 {
    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;
    41     }
    42     return 1;
    43 }
    45 static void isofs_release(IsoDataSource *src)
    46 {
    47     sector_source_unref((sector_source_t)src->data);
    48 }
    50 static IsoDataSource *iso_data_source_new( sector_source_t source )
    51 {
    52     IsoDataSource *src = g_malloc0(sizeof(IsoDataSource));
    53     src->refcount = 1;
    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;
    58     src->data = source;
    59     sector_source_ref(source);
    60     return src;
    61 }
    63 static void iso_error_convert( int status, ERROR *err )
    64 {
    65     switch( status ) {
    66     case ISO_SUCCESS:
    67         err->code = LX_ERR_NONE;
    68         break;
    69     case ISO_OUT_OF_MEM:
    70         SET_ERROR( err, LX_ERR_NOMEM, "Unable to allocate memory for ISO filesystem" );
    71         break;
    72     case ISO_FILE_READ_ERROR:
    73         SET_ERROR( err, LX_ERR_FILE_IOERROR, "Read error" );
    74         break;
    75     default:
    76         SET_ERROR( err, LX_ERR_UNHANDLED, "Unknown error in ISO filesystem" );
    77         break;
    78     }
    79 }
    81 /**
    82  * Construct an isofs image from an existing sector source.
    83  */
    84 IsoImage *iso_image_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
    85 {
    86     IsoImage *iso = NULL;
    87     IsoReadOpts *opts;
    88     IsoDataSource *src;
    90     int status = iso_image_new(NULL, &iso);
    91     if( status != 1 )
    92         return NULL;
    94     status = iso_read_opts_new(&opts,0);
    95     if( status != 1 ) {
    96         iso_image_unref( iso );
    97         return NULL;
    98     }
   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);
   105     if( status != 1 ) {
   106         iso_image_unref(iso);
   107         return NULL;
   108     }
   109     return iso;
   110 }
   112 IsoImage *iso_image_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
   113 {
   114     return iso_image_new_from_source( &disc->source, start_sector, err );
   115 }
   117 IsoImage *iso_image_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
   118 {
   119     return iso_image_new_from_source( &disc->source, track->lba, err );
   120 }
   123 IsoImageFilesystem *iso_filesystem_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
   124 {
   125     IsoImageFilesystem *iso = NULL;
   126     IsoReadOpts *opts;
   127     IsoDataSource *src;
   129     int status = iso_read_opts_new(&opts,0);
   130     if( status != 1 ) {
   131         iso_error_convert(status, err);
   132         return NULL;
   133     }
   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);
   140     if( status != 1 ) {
   141         iso_error_convert(status, err);
   142         return NULL;
   143     }
   144     return iso;
   146 }
   148 IsoImageFilesystem *iso_filesystem_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
   149 {
   150     return iso_filesystem_new_from_source( &disc->source, start_sector, err );
   151 }
   153 IsoImageFilesystem *iso_filesystem_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
   154 {
   155     return iso_filesystem_new_from_source( &disc->source, track->lba, err );
   156 }
   159 /**
   160  * Construct a sector source from a given IsoImage.
   161  */
   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 )
   164 {
   165     assert( mode == SECTOR_MODE1 || mode == SECTOR_MODE2_FORM1 );
   167     IsoWriteOpts *opts;
   168     struct burn_source *burn;
   170     int status = iso_write_opts_new(&opts, 0);
   171     if( status != 1 ) {
   172         iso_error_convert(status, err);
   173         return NULL;
   174     }
   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);
   180     if( status != 1 ) {
   181         iso_error_convert(status, err);
   182         return NULL;
   183     }
   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);
   189         free(burn);
   190         return NULL;
   191     }
   193     char buf[2048];
   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);
   203         } else {
   204             status = burn->read(burn, buf, 2048);
   205         }
   206         if( status == 0 ) {
   207             /* EOF */
   208             break;
   209         } else if( status != 2048 ) {
   210             /* Error */
   211             sector_source_unref(source);
   212             source = NULL;
   213             break;
   214         }
   215         /* Discard first 16 sectors, replaced with the bootstrap */
   216         if( count >= (32768/2048) )
   217             write( fd, buf, 2048 );
   218     }
   219     burn->free_data(burn);
   220     free(burn);
   221     return source;
   222 }
.