00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifdef SAVE_RCSID
00011 static char *rcsid =
00012 "@(#) $Id: fs.c,v 1.18 2006/03/10 15:20:24 trikalio Exp $";
00013 #endif
00014
00015 #include "d64copy_int.h"
00016
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020
00021 #include "arch.h"
00022
00023 static d64copy_settings *fs_settings;
00024
00025 static FILE *the_file;
00026 static char *error_map;
00027 static int block_count;
00028
00029 static int block_offset(int tr, int se)
00030 {
00031 int sectors = 0, i;
00032 for(i = 1; i < tr; i++)
00033 {
00034 sectors += d64copy_sector_count(fs_settings->two_sided, i);
00035 }
00036 return (sectors + se) * BLOCKSIZE;
00037 }
00038
00039 static int read_block(__u_char tr, __u_char se, __u_char *block)
00040 {
00041 if(fseek(the_file, block_offset(tr, se), SEEK_SET) == 0)
00042 {
00043 return fread(block, BLOCKSIZE, 1, the_file) != 1;
00044 }
00045 return 1;
00046 }
00047
00048
00049
00050
00051 static int atom_execute = 0;
00052 static __u_char atom_tr;
00053 static __u_char atom_se;
00054 static const unsigned char *atom_blk;
00055 static int atom_size;
00056 static int atom_read_status;
00057
00058 static int write_block(__u_char tr, __u_char se, const unsigned char *blk, int size, int read_status)
00059 {
00060 long ofs;
00061 int ret;
00062
00063 atom_tr = tr;
00064 atom_se = se;
00065 atom_blk = blk;
00066 atom_size = size;
00067 atom_read_status = read_status;
00068
00069 atom_execute = 1;
00070
00071 ofs = block_offset(tr, se);
00072 if(fseek(the_file, ofs, SEEK_SET) == 0)
00073 {
00074 error_map[ofs / BLOCKSIZE] = (char) read_status;
00075 ret = fwrite(blk, size, 1, the_file) != 1;
00076 }
00077 else
00078 {
00079 ret = 1;
00080 }
00081
00082 atom_execute = 0;
00083
00084 return ret;
00085 }
00086
00087 static int open_disk(CBM_FILE fd, d64copy_settings *settings,
00088 const void *arg, int for_writing,
00089 turbo_start start, d64copy_message_cb message_cb)
00090 {
00091 off_t filesize;
00092 int stat_ok, is_image, error_info;
00093 int tr = 0;
00094 char *name = (char*)arg;
00095
00096 the_file = NULL;
00097 fs_settings = settings;
00098 block_count = 0;
00099
00100 stat_ok = arch_filesize(name, &filesize) == 0;
00101 is_image = error_info = 0;
00102
00103 if(stat_ok)
00104 {
00105 if(filesize == D71_BLOCKS * BLOCKSIZE)
00106 {
00107 is_image = 1;
00108 block_count = D71_BLOCKS;
00109 tr = D71_TRACKS;
00110 }
00111 else if(filesize == D71_BLOCKS * (BLOCKSIZE + 1))
00112 {
00113 is_image = 1;
00114 error_info = 1;
00115 block_count = D71_BLOCKS;
00116 tr = D71_TRACKS;
00117 }
00118 else
00119 {
00120 block_count = STD_BLOCKS;
00121 for( tr = STD_TRACKS; !is_image && tr <= TOT_TRACKS; )
00122 {
00123 is_image = filesize == block_count * BLOCKSIZE;
00124 if(!is_image)
00125 {
00126 error_info = is_image =
00127 filesize == block_count * (BLOCKSIZE + 1);
00128 }
00129 if(!is_image)
00130 {
00131 block_count += d64copy_sector_count( 0, tr++ );
00132 }
00133 }
00134 if( is_image && tr != STD_TRACKS )
00135 {
00136 message_cb(1, "non-standard number or tracks: %d", tr);
00137 }
00138 }
00139 }
00140
00141 if(!for_writing)
00142 {
00143 if(stat_ok)
00144 {
00145 if(is_image)
00146 {
00147 the_file = fopen(name, "rb");
00148 if(the_file == NULL)
00149 {
00150 message_cb(0, "could not open %s", name);
00151 }
00152 if(error_info)
00153 {
00154 message_cb(1, "image contains error information");
00155 }
00156 if(settings->end_track == -1)
00157 {
00158 settings->end_track = tr;
00159 }
00160 else if(settings->end_track > tr)
00161 {
00162 message_cb(1, "resetting end track to %d", tr);
00163 settings->end_track = tr;
00164 }
00165
00166 }
00167 else
00168 {
00169 message_cb(0, "neither a .d64 not .d71 file: %s", name);
00170 }
00171 }
00172 else
00173 {
00174 message_cb(0, "could not stat %s", name);
00175 }
00176 }
00177 else
00178 {
00179 the_file = fopen(name, is_image ? "r+b" : "wb");
00180 if(the_file)
00181 {
00182
00183 int new_tr;
00184 if(settings->two_sided)
00185 {
00186 new_tr = D71_TRACKS;
00187 }
00188 else if(settings->end_track <= STD_TRACKS)
00189 {
00190 new_tr = STD_TRACKS;
00191 }
00192 else if(settings->end_track <= EXT_TRACKS)
00193 {
00194 new_tr = EXT_TRACKS;
00195 }
00196 else
00197 {
00198 new_tr = TOT_TRACKS;
00199 }
00200
00201
00202 error_map = calloc(D71_BLOCKS, 1);
00203 if(!error_map)
00204 {
00205 message_cb(0, "no memory for error map");
00206 fclose(the_file);
00207 if(!is_image)
00208 {
00209 arch_unlink(name);
00210 }
00211 return 1;
00212 }
00213
00214 if(is_image)
00215 {
00216 if(error_info)
00217 {
00218 if(fseek(the_file, block_count * BLOCKSIZE, SEEK_SET) != 0 ||
00219 fread(error_map, block_count, 1, the_file) != 1)
00220 {
00221 message_cb(0, "%s: could not read error map", name);
00222 fclose(the_file);
00223 return 1;
00224 }
00225 }
00226 if(fseek(the_file, block_count * BLOCKSIZE, SEEK_SET) != 0)
00227 {
00228 message_cb(0, "%s: could not seek to end of file", name);
00229 fclose(the_file);
00230 return 1;
00231 }
00232 }
00233
00234 if(new_tr > tr)
00235 {
00236
00237 char block[BLOCKSIZE];
00238 memset(block, '\0', BLOCKSIZE);
00239 while(tr < new_tr)
00240 {
00241 int s;
00242 s = d64copy_sector_count(settings->two_sided, ++tr);
00243 if(fwrite(block, BLOCKSIZE, s, the_file) != (size_t)s)
00244 {
00245 message_cb(0, "could not write %s", name);
00246 fclose(the_file);
00247 if(!is_image)
00248 arch_unlink(name);
00249 return 1;
00250 }
00251 block_count += s;
00252 }
00253 }
00254 }
00255 else
00256 {
00257 message_cb(0, "could not open %s", name);
00258 }
00259 }
00260 return the_file == NULL;
00261 }
00262
00263 static void close_disk(void)
00264 {
00265 int i, has_errors = 0;
00266
00267
00268
00269
00270
00271 if (the_file && atom_execute)
00272 {
00273 atom_execute = 0;
00274 write_block(atom_tr, atom_se, atom_blk, atom_size, atom_read_status);
00275 }
00276
00277 if (fs_settings)
00278 {
00279 switch(fs_settings->error_mode)
00280 {
00281 case em_always:
00282 has_errors = 1;
00283 break;
00284 case em_never:
00285 has_errors = 0;
00286 break;
00287 default:
00288 if(error_map)
00289 {
00290 for(i = 0; !has_errors && i < block_count; i++)
00291 {
00292 has_errors = error_map[i] != 0;
00293 }
00294 }
00295 break;
00296 }
00297 }
00298
00299 if(the_file)
00300 {
00301 if(has_errors)
00302 {
00303 if(fseek(the_file, block_count * BLOCKSIZE, SEEK_SET) == 0)
00304 {
00305 fwrite(error_map, block_count, 1, the_file);
00306 }
00307 }
00308 else
00309 {
00310 arch_ftruncate(arch_fileno(the_file), block_count * BLOCKSIZE);
00311 }
00312 }
00313
00314 if(error_map)
00315 {
00316 free(error_map);
00317 error_map = NULL;
00318 }
00319 if(the_file)
00320 {
00321 fclose(the_file);
00322 the_file = NULL;
00323 }
00324 }
00325
00326 DECLARE_TRANSFER_FUNCS(fs_transfer, 0, 0);