filename | src/drivers/cdrom/isofs.c |
changeset | 1108:305ef2082079 |
prev | 1107:7b279d10f46f |
next | 1109:700c5ab26a63 |
author | nkeynes |
date | Fri Jun 04 09:13:40 2010 +1000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Add ability to wrap a binary program up in a virtual cd image (so that we can boot it normally) |
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 /**
64 * Construct an isofs image from an existing sector source.
65 */
66 IsoImage *iso_image_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
67 {
68 IsoImage *iso = NULL;
69 IsoReadOpts *opts;
70 IsoDataSource *src;
72 int status = iso_image_new(NULL, &iso);
73 if( status != 1 )
74 return NULL;
76 status = iso_read_opts_new(&opts,0);
77 if( status != 1 ) {
78 iso_image_unref( iso );
79 return NULL;
80 }
82 iso_read_opts_set_start_block(opts, start);
83 src = iso_data_source_new(source);
84 status = iso_image_import(iso, src, opts, NULL);
85 iso_data_source_unref(src);
86 iso_read_opts_free(opts);
87 if( status != 1 ) {
88 iso_image_unref(iso);
89 return NULL;
90 }
91 return iso;
92 }
94 IsoImage *iso_image_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
95 {
96 return iso_image_new_from_source( &disc->source, start_sector, err );
97 }
99 IsoImage *iso_image_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
100 {
101 return iso_image_new_from_source( &disc->source, track->lba, err );
102 }
105 IsoImageFilesystem *iso_filesystem_new_from_source( sector_source_t source, cdrom_lba_t start, ERROR *err )
106 {
107 IsoImageFilesystem *iso = NULL;
108 IsoReadOpts *opts;
109 IsoDataSource *src;
111 int status = iso_read_opts_new(&opts,0);
112 if( status != 1 ) {
113 return NULL;
114 }
116 iso_read_opts_set_start_block(opts, start);
117 src = iso_data_source_new(source);
118 status = iso_image_filesystem_new(src, opts, 0x1FFFFF, &iso);
119 iso_data_source_unref(src);
120 iso_read_opts_free(opts);
121 if( status != 1 ) {
122 return NULL;
123 }
124 return iso;
126 }
128 IsoImageFilesystem *iso_filesystem_new_from_disc( cdrom_disc_t disc, cdrom_lba_t start_sector, ERROR *err )
129 {
130 return iso_filesystem_new_from_source( &disc->source, start_sector, err );
131 }
133 IsoImageFilesystem *iso_filesystem_new_from_track( cdrom_disc_t disc, cdrom_track_t track, ERROR *err )
134 {
135 return iso_filesystem_new_from_source( &disc->source, track->lba, err );
136 }
139 /**
140 * Construct a sector source from a given IsoImage.
141 */
142 sector_source_t iso_sector_source_new( IsoImage *image, sector_mode_t mode, cdrom_lba_t start_sector,
143 const char *bootstrap, ERROR *err )
144 {
145 assert( mode == SECTOR_MODE1 || mode == SECTOR_MODE2_FORM1 );
147 IsoWriteOpts *opts;
148 struct burn_source *burn;
150 int status = iso_write_opts_new(&opts, 0);
151 if( status != 1 )
152 return NULL;
153 iso_write_opts_set_appendable(opts,0);
154 iso_write_opts_set_ms_block(opts, start_sector);
155 iso_write_opts_set_system_area(opts, (char *)bootstrap, 0, 0);
157 status = iso_image_create_burn_source(image, opts, &burn);
158 iso_write_opts_free(opts);
159 if( status != 1 ) {
160 return NULL;
161 }
163 off_t size = burn->get_size(burn);
164 sector_source_t source = tmpfile_sector_source_new(mode);
165 if( source == NULL ) {
166 burn->free_data(burn);
167 free(burn);
168 return NULL;
169 }
171 char buf[2048];
172 cdrom_count_t expect = size/2048;
173 cdrom_count_t count = 0;
174 int fd = file_sector_source_get_fd(source);
175 source->size = expect;
176 lseek( fd, 0, SEEK_SET );
177 for( cdrom_count_t count = 0; count < expect; count++ ) {
178 if( burn->read == NULL ) {
179 status = burn->read_xt(burn, buf, 2048);
180 } else {
181 status = burn->read(burn, buf, 2048);
182 }
183 if( status == 0 ) {
184 /* EOF */
185 break;
186 } else if( status != 2048 ) {
187 /* Error */
188 sector_source_unref(source);
189 source = NULL;
190 break;
191 }
192 write( fd, buf, 2048 );
193 }
194 burn->free_data(burn);
195 free(burn);
196 return source;
197 }
.