[1] | 1 | /* SAP2 |
---|
| 2 | * Version 2.1 |
---|
| 3 | * Copyright (C) 2000-2003 Eric Botcazou |
---|
| 4 | * |
---|
| 5 | * This program is free software; you can redistribute it and/or modify |
---|
| 6 | * it under the terms of the GNU General Public License as published by |
---|
| 7 | * the Free Software Foundation; either version 2 of the License, or |
---|
| 8 | * (at your option) any later version. |
---|
| 9 | * |
---|
| 10 | * This program is distributed in the hope that it will be useful, |
---|
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 13 | * GNU General Public License for more details. |
---|
| 14 | * |
---|
| 15 | * You should have received a copy of the GNU General Public License |
---|
| 16 | * along with this program; if not, write to the Free Software |
---|
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
| 18 | */ |
---|
| 19 | |
---|
| 20 | /* version 1.0: programme fonctionnel sous MSDOS et Linux |
---|
| 21 | * 1.1: retour au format PC à la sortie du programme |
---|
| 22 | * 1.2: ajout d'un mode de fonctionnement batch |
---|
| 23 | * 2.0: support des disquettes 5"25 et de deux lecteurs PC |
---|
| 24 | * 2.1: support de la simple densité |
---|
| 25 | */ |
---|
| 26 | |
---|
| 27 | |
---|
| 28 | #include <ctype.h> |
---|
| 29 | #include <stdio.h> |
---|
| 30 | #include <stdlib.h> |
---|
| 31 | #include <string.h> |
---|
| 32 | #include "libsap.h" |
---|
| 33 | #include "floppy.h" |
---|
| 34 | |
---|
| 35 | |
---|
| 36 | #define SAP2_VERSION_STR "2.0.93" |
---|
| 37 | |
---|
| 38 | #ifdef linux |
---|
| 39 | #define SAP2_PLATFORM_STR "Linux" |
---|
| 40 | #else |
---|
| 41 | #define SAP2_PLATFORM_STR "MSDOS" |
---|
| 42 | #endif |
---|
| 43 | |
---|
| 44 | #define FILENAME_LENGTH 128 |
---|
| 45 | |
---|
| 46 | |
---|
| 47 | /* horrible hack pour supporter les accents... */ |
---|
| 48 | #ifdef linux |
---|
| 49 | static char eacute[] = "é"; |
---|
| 50 | static char egrave[] = "è"; |
---|
| 51 | static char agrave[] = "à"; |
---|
| 52 | static char ugrave[] = "ù"; |
---|
| 53 | #else |
---|
| 54 | static char eacute[] = ""; |
---|
| 55 | static char egrave[] = ""; |
---|
| 56 | static char agrave[] = "
"; |
---|
| 57 | static char ugrave[] = ""; |
---|
| 58 | #endif |
---|
| 59 | |
---|
| 60 | |
---|
| 61 | /* pour l'affichage du répertoire */ |
---|
| 62 | #define PAGE_HEIGHT 22 |
---|
| 63 | |
---|
| 64 | |
---|
| 65 | static struct floppy_info fi; |
---|
| 66 | static char *drive_type_name[7] = { "non disponible", |
---|
| 67 | "5\"25 - 360 ko", |
---|
| 68 | "5\"25 - 1.2 Mo", |
---|
| 69 | "3\"5 - 720 ko", |
---|
| 70 | "3\"5 - 1.44 Mo", |
---|
| 71 | "3\"5 - 2.88 Mo", |
---|
| 72 | "3\"5 - 2.88 Mo" }; |
---|
| 73 | |
---|
| 74 | #define IS_5_INCHES(drive) ((fi.drive_type[drive]>0) && (fi.drive_type[drive]<3)) |
---|
| 75 | |
---|
| 76 | |
---|
| 77 | |
---|
| 78 | /* term_puts: |
---|
| 79 | * Affiche une chaîne de caractères en respectant la taille du terminal. |
---|
| 80 | */ |
---|
| 81 | static void term_puts(const char buffer[], int lines, int page_height) |
---|
| 82 | { |
---|
| 83 | const char *start_cur, *end_cur; |
---|
| 84 | char trash[8]; |
---|
| 85 | int i; |
---|
| 86 | char* ret; |
---|
| 87 | |
---|
| 88 | start_cur = end_cur = buffer; |
---|
| 89 | |
---|
| 90 | while (lines>page_height) { |
---|
| 91 | for (i=0; i<page_height; i++) { |
---|
| 92 | while (*end_cur++ != '\n') |
---|
| 93 | ; |
---|
| 94 | } |
---|
| 95 | |
---|
| 96 | fwrite(start_cur, sizeof(char), end_cur-start_cur, stdout); |
---|
| 97 | |
---|
| 98 | ret=fgets(trash, 7, stdin); |
---|
| 99 | printf("Appuyer sur <Return>"); |
---|
| 100 | getchar(); |
---|
| 101 | printf("\n"); |
---|
| 102 | ungetc('\n', stdin); |
---|
| 103 | |
---|
| 104 | start_cur = end_cur; |
---|
| 105 | lines -= page_height; |
---|
| 106 | } |
---|
| 107 | |
---|
| 108 | puts(end_cur); |
---|
| 109 | } |
---|
| 110 | |
---|
| 111 | |
---|
| 112 | |
---|
| 113 | /* ViewDiskDir: |
---|
| 114 | * Affiche le répertoire d'une disquette TO. |
---|
| 115 | */ |
---|
| 116 | static int ViewDiskDir(int drive, int density, int page_height) |
---|
| 117 | { |
---|
| 118 | unsigned char data[512*SAP_NSECTS]; |
---|
| 119 | char buffer[4096]; |
---|
| 120 | int lines; |
---|
| 121 | |
---|
| 122 | if (FloppyReadSector(drive, density, 20, 1, SAP_NSECTS, data) != 0) |
---|
| 123 | return 1; |
---|
| 124 | |
---|
| 125 | /* on réduit la FAT à 80 blocks pour les disquettes 5"25 DD */ |
---|
| 126 | if (IS_5_INCHES(drive) && density == 2) |
---|
| 127 | memset(data + SAP_SECTSIZE1 + 1 + SAP_NTRACKS1, 0xFE, SAP_NTRACKS1); |
---|
| 128 | |
---|
| 129 | /* fonction bas-niveau de libSAP */ |
---|
| 130 | lines = _ExtractDir(buffer, sizeof(buffer), drive, density, data); |
---|
| 131 | |
---|
| 132 | if ((page_height<0) || (lines<=page_height)) |
---|
| 133 | puts(buffer); |
---|
| 134 | else |
---|
| 135 | term_puts(buffer, lines, page_height); |
---|
| 136 | |
---|
| 137 | return 0; |
---|
| 138 | } |
---|
| 139 | |
---|
| 140 | |
---|
| 141 | |
---|
| 142 | /* ViewArchiveDir: |
---|
| 143 | * Affiche le répertoire d'une archive SAP. |
---|
| 144 | */ |
---|
| 145 | static int ViewArchiveDir(const char sap_name[], int page_height) |
---|
| 146 | { |
---|
| 147 | char buffer[4096]; |
---|
| 148 | sapID sap_file; |
---|
| 149 | int format, lines; |
---|
| 150 | |
---|
| 151 | if ((sap_file=sap_OpenArchive(sap_name, &format)) == SAP_ERROR) |
---|
| 152 | return 1; |
---|
| 153 | |
---|
| 154 | lines = sap_ListArchive(sap_file, buffer, sizeof(buffer)); |
---|
| 155 | |
---|
| 156 | if (lines == 0) |
---|
| 157 | return 2; |
---|
| 158 | |
---|
| 159 | if ((page_height<0) || (lines<=page_height)) |
---|
| 160 | puts(buffer); |
---|
| 161 | else |
---|
| 162 | term_puts(buffer, lines, page_height); |
---|
| 163 | |
---|
| 164 | sap_CloseArchive(sap_file); |
---|
| 165 | return 0; |
---|
| 166 | } |
---|
| 167 | |
---|
| 168 | |
---|
| 169 | |
---|
| 170 | /* CreateEmptyArchive: |
---|
| 171 | * Crée une archive SAP vide (mais formatée). |
---|
| 172 | */ |
---|
| 173 | static int CreateEmptyArchive(const char sap_name[], int format, int capacity) |
---|
| 174 | { |
---|
| 175 | sapID sap_file; |
---|
| 176 | |
---|
| 177 | if ((sap_file=sap_CreateArchive(sap_name, format)) == SAP_ERROR) |
---|
| 178 | return 1; |
---|
| 179 | |
---|
| 180 | sap_FormatArchive(sap_file, capacity); |
---|
| 181 | sap_CloseArchive(sap_file); |
---|
| 182 | |
---|
| 183 | return 0; |
---|
| 184 | } |
---|
| 185 | |
---|
| 186 | |
---|
| 187 | |
---|
| 188 | /* BuildSectorMap: |
---|
| 189 | * Construit la carte des secteurs d'une piste |
---|
| 190 | * en fonction du facteur d'entrelacement. |
---|
| 191 | */ |
---|
| 192 | static void BuildSectorMap(int *sector_map, int factor) |
---|
| 193 | { |
---|
| 194 | int sect, loc=0; |
---|
| 195 | |
---|
| 196 | /* mise à zéro de la table */ |
---|
| 197 | memset(sector_map, 0, sizeof(int)*SAP_NSECTS); |
---|
| 198 | |
---|
| 199 | for (sect=1; sect<=SAP_NSECTS; sect++) { |
---|
| 200 | while (sector_map[loc] != 0) |
---|
| 201 | loc=(loc+1)%SAP_NSECTS; |
---|
| 202 | |
---|
| 203 | sector_map[loc]=sect; |
---|
| 204 | |
---|
| 205 | loc=(loc+factor)%SAP_NSECTS; |
---|
| 206 | } |
---|
| 207 | } |
---|
| 208 | |
---|
| 209 | |
---|
| 210 | |
---|
| 211 | /* FormatDisk: |
---|
| 212 | * Formate une disquette 3"5 - 720 ko au format Thomson. |
---|
| 213 | */ |
---|
| 214 | static int FormatDisk(int drive, int density, int factor, int verbose) |
---|
| 215 | { |
---|
| 216 | int num_tracks, sect_size; |
---|
| 217 | int track, sect, pos, i; |
---|
| 218 | int sector_map[SAP_NSECTS]; |
---|
| 219 | unsigned char header_table[512]; |
---|
| 220 | unsigned char buffer[512*SAP_NSECTS]; |
---|
| 221 | |
---|
| 222 | /* détermination du nombre de pistes */ |
---|
| 223 | if (IS_5_INCHES(drive)) |
---|
| 224 | num_tracks = SAP_NTRACKS2; |
---|
| 225 | else |
---|
| 226 | num_tracks = SAP_NTRACKS1; |
---|
| 227 | |
---|
| 228 | /* et de la taille du secteur */ |
---|
| 229 | if (density == 1) |
---|
| 230 | sect_size = SAP_SECTSIZE2; |
---|
| 231 | else |
---|
| 232 | sect_size = SAP_SECTSIZE1; |
---|
| 233 | |
---|
| 234 | /* construction de la carte des secteurs pour chaque piste, |
---|
| 235 | à partir du facteur d'entrelacement */ |
---|
| 236 | BuildSectorMap(sector_map, factor); |
---|
| 237 | |
---|
| 238 | /* formatage des pistes */ |
---|
| 239 | for (track=0; track<num_tracks; track++) { |
---|
| 240 | if (verbose) { |
---|
| 241 | printf("\r formatage piste %d", track); |
---|
| 242 | fflush(stdout); |
---|
| 243 | } |
---|
| 244 | |
---|
| 245 | /* construction de la table des headers */ |
---|
| 246 | for (sect=1, pos=0; sect<=SAP_NSECTS; sect++, pos+=4) { |
---|
| 247 | header_table[pos] = track; |
---|
| 248 | header_table[pos+1] = 0; |
---|
| 249 | header_table[pos+2] = sector_map[sect-1]; |
---|
| 250 | header_table[pos+3] = density - 1; |
---|
| 251 | } |
---|
| 252 | |
---|
| 253 | if (FloppyFormatTrack(drive, density, track, header_table) != 0) |
---|
| 254 | return 1; |
---|
| 255 | } |
---|
| 256 | |
---|
| 257 | if (verbose) { |
---|
| 258 | printf("\n construction de la FAT (piste 20)"); |
---|
| 259 | fflush(stdout); |
---|
| 260 | } |
---|
| 261 | |
---|
| 262 | for (i=0; i<sect_size*SAP_NSECTS; i++) |
---|
| 263 | buffer[i] = 0xFF; |
---|
| 264 | |
---|
| 265 | /* pour MS-DOS (voir teo/src/dos/ddisk.c) */ |
---|
| 266 | buffer[i]=0; |
---|
| 267 | |
---|
| 268 | if (FloppyWriteSector(drive, density, 20, 1, SAP_NSECTS, buffer) != 0) |
---|
| 269 | return 2; |
---|
| 270 | |
---|
| 271 | buffer[0] = 0; |
---|
| 272 | buffer[41] = 0xFE; |
---|
| 273 | buffer[42] = 0xFE; |
---|
| 274 | |
---|
| 275 | /* pour MS-DOS (voir teo/src/dos/ddisk.c) */ |
---|
| 276 | buffer[sect_size] = 0; |
---|
| 277 | |
---|
| 278 | if (FloppyWriteSector(drive, density, 20, 2, 1, buffer) != 0) |
---|
| 279 | return 2; |
---|
| 280 | |
---|
| 281 | if (verbose) |
---|
| 282 | printf("\n"); |
---|
| 283 | |
---|
| 284 | return 0; |
---|
| 285 | } |
---|
| 286 | |
---|
| 287 | |
---|
| 288 | |
---|
| 289 | /* shrink_fat_160_to_80: |
---|
| 290 | * Réduit la taille de la FAT de 160 à 80 blocks. |
---|
| 291 | */ |
---|
| 292 | static void shrink_fat_160_to_80(unsigned char fat_data[]) |
---|
| 293 | { |
---|
| 294 | int i; |
---|
| 295 | |
---|
| 296 | for (i=0; i<SAP_NTRACKS1; i++) { |
---|
| 297 | if (fat_data[1 + SAP_NTRACKS1 + i] != 0xFF) |
---|
| 298 | return; |
---|
| 299 | } |
---|
| 300 | |
---|
| 301 | memset(fat_data + 1 + SAP_NTRACKS1, 0xFE, SAP_NTRACKS1); |
---|
| 302 | } |
---|
| 303 | |
---|
| 304 | |
---|
| 305 | |
---|
| 306 | /* PackArchive: |
---|
| 307 | * Transfère le contenu d'une disquette TO dans une archive SAP. |
---|
| 308 | */ |
---|
| 309 | static int PackArchive(const char sap_name[], int drive, int density, int verbose) |
---|
| 310 | { |
---|
| 311 | int num_tracks, sect_size; |
---|
| 312 | int track, sect; |
---|
| 313 | sapID sap_file; |
---|
| 314 | sapsector_t sapsector; |
---|
| 315 | unsigned char buffer[512*SAP_NSECTS]; |
---|
| 316 | |
---|
| 317 | if ((sap_file=sap_CreateArchive(sap_name, density == 1 ? SAP_FORMAT2 : SAP_FORMAT1)) == SAP_ERROR) |
---|
| 318 | return 1; |
---|
| 319 | |
---|
| 320 | /* détermination du nombre de pistes */ |
---|
| 321 | if (IS_5_INCHES(drive)) |
---|
| 322 | num_tracks = SAP_NTRACKS2; |
---|
| 323 | else |
---|
| 324 | num_tracks = SAP_NTRACKS1; |
---|
| 325 | |
---|
| 326 | /* et de la taille du secteur */ |
---|
| 327 | if (density == 1) |
---|
| 328 | sect_size = SAP_SECTSIZE2; |
---|
| 329 | else |
---|
| 330 | sect_size = SAP_SECTSIZE1; |
---|
| 331 | |
---|
| 332 | for (track=0; track<num_tracks; track++) { |
---|
| 333 | if (verbose) { |
---|
| 334 | printf("\r lecture piste %d", track); |
---|
| 335 | fflush(stdout); |
---|
| 336 | } |
---|
| 337 | |
---|
| 338 | if (FloppyReadSector(drive, density, track, 1, SAP_NSECTS, buffer) != 0) { |
---|
| 339 | /* erreur dans la piste, on essaie secteur par secteur */ |
---|
| 340 | for (sect=1; sect<=SAP_NSECTS; sect++) { |
---|
| 341 | sapsector.format = 0; |
---|
| 342 | sapsector.protection = 0; |
---|
| 343 | sapsector.track = track; |
---|
| 344 | sapsector.sector = sect; |
---|
| 345 | |
---|
| 346 | if (FloppyReadSector(drive, density, track, sect, 1, buffer) != 0) { |
---|
| 347 | /* erreur de lecture du secteur */ |
---|
| 348 | if (verbose) |
---|
| 349 | printf("\n secteur %d illisible", sect); |
---|
| 350 | |
---|
| 351 | sapsector.format = 4; |
---|
| 352 | memset(sapsector.data, 0xF7, sect_size); |
---|
| 353 | } |
---|
| 354 | else { |
---|
| 355 | memcpy(sapsector.data, buffer, sect_size); |
---|
| 356 | } |
---|
| 357 | |
---|
| 358 | /* traitement spécial de la FAT pour les disquettes 5"25 DD */ |
---|
| 359 | if ((track == 20) && (sect == 2) && IS_5_INCHES(drive) && (density == 2)) |
---|
| 360 | shrink_fat_160_to_80(sapsector.data); |
---|
| 361 | |
---|
| 362 | sap_FillArchive(sap_file, &sapsector); |
---|
| 363 | } |
---|
| 364 | |
---|
| 365 | if ((track < num_tracks-1) && verbose) |
---|
| 366 | printf("\n"); |
---|
| 367 | } |
---|
| 368 | else { |
---|
| 369 | for (sect=1; sect<=SAP_NSECTS; sect++) { |
---|
| 370 | sapsector.format = 0; |
---|
| 371 | sapsector.protection = 0; |
---|
| 372 | sapsector.track = track; |
---|
| 373 | sapsector.sector = sect; |
---|
| 374 | |
---|
| 375 | memcpy(sapsector.data, buffer+(sect-1)*sect_size, sect_size); |
---|
| 376 | |
---|
| 377 | /* traitement spécial de la FAT pour les disquettes 5"25 DD */ |
---|
| 378 | if ((track == 20) && (sect == 2) && IS_5_INCHES(drive) && (density == 2)) |
---|
| 379 | shrink_fat_160_to_80(sapsector.data); |
---|
| 380 | |
---|
| 381 | sap_FillArchive(sap_file, &sapsector); |
---|
| 382 | } |
---|
| 383 | } |
---|
| 384 | } |
---|
| 385 | |
---|
| 386 | if (verbose) |
---|
| 387 | printf("\n"); |
---|
| 388 | |
---|
| 389 | sap_CloseArchive(sap_file); |
---|
| 390 | return 0; |
---|
| 391 | } |
---|
| 392 | |
---|
| 393 | |
---|
| 394 | |
---|
| 395 | /* UnpackArchive: |
---|
| 396 | * Transfère le contenu d'une archive SAP vers une disquette TO. |
---|
| 397 | */ |
---|
| 398 | static int UnpackArchive(const char sap_name[], int drive, int density, int verbose) |
---|
| 399 | { |
---|
| 400 | int format, num_tracks, sect_size; |
---|
| 401 | int track, sect; |
---|
| 402 | sapID sap_file; |
---|
| 403 | sapsector_t sapsector; |
---|
| 404 | unsigned char buffer[512*SAP_NSECTS]; |
---|
| 405 | |
---|
| 406 | if ((sap_file=sap_OpenArchive(sap_name, &format)) == SAP_ERROR) |
---|
| 407 | return 1; |
---|
| 408 | |
---|
| 409 | /* vérification du format */ |
---|
| 410 | if (((format == SAP_FORMAT1) && (density != 2)) || ((format == SAP_FORMAT2) && (density != 1))) |
---|
| 411 | return 1; |
---|
| 412 | |
---|
| 413 | /* détermination du nombre de pistes */ |
---|
| 414 | if (IS_5_INCHES(drive)) |
---|
| 415 | num_tracks = SAP_NTRACKS2; |
---|
| 416 | else |
---|
| 417 | num_tracks = SAP_NTRACKS1; |
---|
| 418 | |
---|
| 419 | /* et de la taille du secteur */ |
---|
| 420 | if (density == 1) |
---|
| 421 | sect_size = SAP_SECTSIZE2; |
---|
| 422 | else |
---|
| 423 | sect_size = SAP_SECTSIZE1; |
---|
| 424 | |
---|
| 425 | for (track=0; track<num_tracks; track++) { |
---|
| 426 | if (verbose) { |
---|
| 427 | printf("\r %scriture piste %d", eacute, track); |
---|
| 428 | fflush(stdout); |
---|
| 429 | } |
---|
| 430 | |
---|
| 431 | for (sect=1; sect<=SAP_NSECTS; sect++) { |
---|
| 432 | sapsector.format = 0; |
---|
| 433 | sapsector.protection = 0; |
---|
| 434 | sapsector.track = track; |
---|
| 435 | sapsector.sector = sect; |
---|
| 436 | |
---|
| 437 | if (sap_ReadSector(sap_file, track, sect, &sapsector) == SAP_ERROR) { |
---|
| 438 | sap_CloseArchive(sap_file); |
---|
| 439 | return 2; |
---|
| 440 | } |
---|
| 441 | else { |
---|
| 442 | memcpy(buffer+(sect-1)*sect_size, sapsector.data, sect_size); |
---|
| 443 | } |
---|
| 444 | } |
---|
| 445 | |
---|
| 446 | /* pour MS-DOS (voir teo/src/dos/ddisk.c) */ |
---|
| 447 | buffer[SAP_NSECTS*sect_size] = 0; |
---|
| 448 | |
---|
| 449 | if (FloppyWriteSector(drive, density, track, 1, SAP_NSECTS, buffer) != 0) { |
---|
| 450 | sap_CloseArchive(sap_file); |
---|
| 451 | return 3; |
---|
| 452 | } |
---|
| 453 | } |
---|
| 454 | |
---|
| 455 | if (verbose) |
---|
| 456 | printf("\n"); |
---|
| 457 | |
---|
| 458 | sap_CloseArchive(sap_file); |
---|
| 459 | return 0; |
---|
| 460 | } |
---|
| 461 | |
---|
| 462 | |
---|
| 463 | |
---|
| 464 | /* get_drive: |
---|
| 465 | * Helper pour obtenir le numéro de lecteur. |
---|
| 466 | */ |
---|
| 467 | static void get_drive(int *drive, int *density) |
---|
| 468 | { |
---|
| 469 | char trash[8]; |
---|
| 470 | char* ret; |
---|
| 471 | |
---|
| 472 | if (fi.num_drives > 1) { |
---|
| 473 | do { |
---|
| 474 | printf(" num%sro du lecteur: ", eacute); |
---|
| 475 | if (!scanf("%d", drive)) |
---|
| 476 | ret=fgets(trash, 7, stdin); |
---|
| 477 | } |
---|
| 478 | while ((*drive<0) || (*drive>3) || (fi.drive_type[*drive]==0)); |
---|
| 479 | } |
---|
| 480 | else { |
---|
| 481 | for (*drive=0; *drive<4; (*drive)++) { |
---|
| 482 | if (fi.drive_type[*drive] > 0) |
---|
| 483 | break; |
---|
| 484 | } |
---|
| 485 | } |
---|
| 486 | |
---|
| 487 | if (fi.fm_support && IS_5_INCHES(*drive)) { |
---|
| 488 | do { |
---|
| 489 | printf(" densit%s (1:simple, 2:double): ", eacute); |
---|
| 490 | if (!scanf("%d", density)) |
---|
| 491 | ret=fgets(trash, 7, stdin); |
---|
| 492 | } |
---|
| 493 | while ((*density<1) || (*density>2)); |
---|
| 494 | } |
---|
| 495 | else |
---|
| 496 | *density = 2; |
---|
| 497 | } |
---|
| 498 | |
---|
| 499 | |
---|
| 500 | |
---|
| 501 | /* interactive_main: |
---|
| 502 | * Point d'entrée du programme interactif. |
---|
| 503 | */ |
---|
| 504 | static void interactive_main(void) |
---|
| 505 | { |
---|
| 506 | int c, ret; |
---|
| 507 | char trash[8]; |
---|
| 508 | int drive, density, format, factor; |
---|
| 509 | char sap_name[FILENAME_LENGTH]; |
---|
| 510 | char* ret2; |
---|
| 511 | |
---|
| 512 | while (1) { |
---|
| 513 | printf("SAP2, syst%sme d'archivage pour disquettes 3\"5 et 5\"25 Thomson\n", egrave); |
---|
| 514 | printf("version "SAP2_VERSION_STR" ("SAP2_PLATFORM_STR") copyright (C) 2000-2003 Eric Botcazou\n"); |
---|
| 515 | printf(" bas%s sur SAP copyright (C) Alexandre Pukall Avril 1998\n\n", eacute); |
---|
| 516 | |
---|
| 517 | if (fi.drive_type[0] > 0) { |
---|
| 518 | printf("Lecteur A: (%s) --> lecteur 0", drive_type_name[fi.drive_type[0]]); |
---|
| 519 | |
---|
| 520 | if (fi.drive_type[1] > 0) |
---|
| 521 | printf(" + lecteur 1\n"); |
---|
| 522 | else |
---|
| 523 | printf("\n"); |
---|
| 524 | } |
---|
| 525 | else { |
---|
| 526 | printf("Lecteur A: (%s)\n", drive_type_name[0]); |
---|
| 527 | } |
---|
| 528 | |
---|
| 529 | if (fi.drive_type[2] > 0) { |
---|
| 530 | printf("Lecteur B: (%s) --> lecteur 2", drive_type_name[fi.drive_type[2]]); |
---|
| 531 | |
---|
| 532 | if (fi.drive_type[3] > 0) |
---|
| 533 | printf(" + lecteur 3\n\n"); |
---|
| 534 | else |
---|
| 535 | printf("\n\n"); |
---|
| 536 | } |
---|
| 537 | else { |
---|
| 538 | printf("Lecteur B: (%s)\n\n", drive_type_name[0]); |
---|
| 539 | } |
---|
| 540 | |
---|
| 541 | printf("Transfert TO-->PC:\n"); |
---|
| 542 | printf(" 1. Visualiser le contenu d'une disquette Thomson\n"); |
---|
| 543 | printf(" 2. Cr%ser une archive SAP vide\n", eacute); |
---|
| 544 | printf(" 3. Archiver une disquette Thomson vers une archive SAP\n"); |
---|
| 545 | printf("Transfert PC-->TO:\n"); |
---|
| 546 | printf(" 4. Visualiser le contenu d'une archive SAP\n"); |
---|
| 547 | printf(" 5. Formater une disquette 3\"5 (720 ko) ou 5\"25 au format Thomson\n"); |
---|
| 548 | printf(" 6. D%ssarchiver une archive SAP vers une disquette Thomson\n", eacute); |
---|
| 549 | printf("Autres commandes:\n"); |
---|
| 550 | printf(" 7. Quitter\n\n"); |
---|
| 551 | |
---|
| 552 | do { |
---|
| 553 | printf("Votre choix: "); |
---|
| 554 | if (!scanf("%d", &c)) |
---|
| 555 | ret2=fgets(trash, 7, stdin); |
---|
| 556 | } |
---|
| 557 | while ((c<1) || (c>7)); |
---|
| 558 | |
---|
| 559 | switch (c) { |
---|
| 560 | |
---|
| 561 | case 1: |
---|
| 562 | printf("Visualisation du contenu d'une disquette:\n"); |
---|
| 563 | get_drive(&drive, &density); |
---|
| 564 | printf("\n"); |
---|
| 565 | |
---|
| 566 | ret = ViewDiskDir(drive, density, PAGE_HEIGHT); |
---|
| 567 | if (ret == 1) |
---|
| 568 | printf("*** Erreur: r%spertoire illisible ***\n", eacute); |
---|
| 569 | |
---|
| 570 | break; |
---|
| 571 | |
---|
| 572 | case 2: |
---|
| 573 | printf("Cr%sation d'une archive vide:\n", eacute); |
---|
| 574 | |
---|
| 575 | printf(" nom de l'archive %s cr%ser (sans extension): ", agrave, eacute); |
---|
| 576 | ret=scanf("%s", sap_name); |
---|
| 577 | strcat(sap_name, ".sap"); |
---|
| 578 | |
---|
| 579 | do { |
---|
| 580 | printf(" format (1:5\"25 SD, 2:5\"25 DD, 3:3\"5 DD): "); |
---|
| 581 | if (!scanf("%d", &format)) |
---|
| 582 | ret2=fgets(trash, 7, stdin); |
---|
| 583 | } |
---|
| 584 | while ((format<1) || (format>3)); |
---|
| 585 | |
---|
| 586 | ret = CreateEmptyArchive(sap_name, (format == 1 ? SAP_FORMAT2 : SAP_FORMAT1), (format == 3 ? SAP_TRK80 : SAP_TRK40)); |
---|
| 587 | if (ret == 1) |
---|
| 588 | printf("*** Erreur: impossible de cr%ser le fichier %s ***\n", eacute, sap_name); |
---|
| 589 | |
---|
| 590 | break; |
---|
| 591 | |
---|
| 592 | case 3: |
---|
| 593 | printf("Archivage d'une disquette:\n"); |
---|
| 594 | |
---|
| 595 | printf(" nom de l'archive %s cr%ser (sans extension): ", agrave, eacute); |
---|
| 596 | ret=scanf("%s", sap_name); |
---|
| 597 | strcat(sap_name, ".sap"); |
---|
| 598 | |
---|
| 599 | get_drive(&drive, &density); |
---|
| 600 | ret = PackArchive(sap_name, drive, density, 1); |
---|
| 601 | if (ret == 1) |
---|
| 602 | printf("*** Erreur: impossible de cr%ser le fichier %s ***\n", eacute, sap_name); |
---|
| 603 | |
---|
| 604 | break; |
---|
| 605 | |
---|
| 606 | case 4: |
---|
| 607 | printf("Visualisation du contenu d'une archive:\n"); |
---|
| 608 | |
---|
| 609 | printf(" nom de l'archive (sans extension): "); |
---|
| 610 | ret=scanf("%s", sap_name); |
---|
| 611 | strcat(sap_name, ".sap"); |
---|
| 612 | |
---|
| 613 | printf("\n"); |
---|
| 614 | |
---|
| 615 | ret = ViewArchiveDir(sap_name, PAGE_HEIGHT); |
---|
| 616 | if (ret == 1) |
---|
| 617 | printf("*** Erreur: impossible d'ouvrir le fichier %s ***\n", sap_name); |
---|
| 618 | else if (ret == 2) |
---|
| 619 | printf("*** Erreur: archive SAP corrompue ***\n"); |
---|
| 620 | |
---|
| 621 | break; |
---|
| 622 | |
---|
| 623 | case 5: |
---|
| 624 | printf("Formatage d'une disquette au format Thomson:\n"); |
---|
| 625 | printf(" Si la disquette est une 3\"5 - 1.44 Mo, occulter l'encoche\n"); |
---|
| 626 | printf(" de droite (recto et verso) avec un morceau de scotch.\n"); |
---|
| 627 | |
---|
| 628 | get_drive(&drive, &density); |
---|
| 629 | |
---|
| 630 | do { |
---|
| 631 | printf(" facteur d'entrelacement ([1..%d], %d recommand%s): ", SAP_NSECTS-1, (SAP_NSECTS-1)/2, eacute); |
---|
| 632 | if (!scanf("%d", &factor)) |
---|
| 633 | ret2=fgets(trash, 7, stdin); |
---|
| 634 | } |
---|
| 635 | while ((factor<1) || (factor>(SAP_NSECTS-1))); |
---|
| 636 | |
---|
| 637 | ret = FormatDisk(drive, density, factor, 1); |
---|
| 638 | if (ret == 1) |
---|
| 639 | printf("\n*** Erreur: impossible de formater la disquette ***\n"); |
---|
| 640 | else if (ret == 2) |
---|
| 641 | printf("*** Erreur: impossible d'%scrire sur la disquette ***\n", eacute); |
---|
| 642 | break; |
---|
| 643 | |
---|
| 644 | case 6: |
---|
| 645 | printf("D%ssarchivage vers une disquette:\n", eacute); |
---|
| 646 | |
---|
| 647 | get_drive(&drive, &density); |
---|
| 648 | |
---|
| 649 | printf(" nom de l'archive (sans extension): "); |
---|
| 650 | ret=scanf("%s", sap_name); |
---|
| 651 | strcat(sap_name, ".sap"); |
---|
| 652 | |
---|
| 653 | ret = UnpackArchive(sap_name, drive, density, 1); |
---|
| 654 | if (ret == 1) |
---|
| 655 | printf("*** Erreur: impossible d'ouvrir le fichier %s ***\n", sap_name); |
---|
| 656 | else if (ret == 2) |
---|
| 657 | printf("*** Erreur: archive SAP corrompue ***\n"); |
---|
| 658 | else if (ret == 3) |
---|
| 659 | printf("\n*** Erreur: impossible d'%scrire sur la disquette ***\n", eacute); |
---|
| 660 | break; |
---|
| 661 | |
---|
| 662 | case 7: |
---|
| 663 | return; |
---|
| 664 | } |
---|
| 665 | |
---|
| 666 | ret2=fgets(trash, 7, stdin); |
---|
| 667 | printf("Appuyer sur <Return>"); |
---|
| 668 | fflush(stdout); |
---|
| 669 | getchar(); |
---|
| 670 | printf("\n"); |
---|
| 671 | } |
---|
| 672 | } |
---|
| 673 | |
---|
| 674 | |
---|
| 675 | #define COMMAND_MAX 8 |
---|
| 676 | |
---|
| 677 | static char *short_command[] = {"-h", "-v", "-d", "-c", "-p", "-t", "-f", "-u"}; |
---|
| 678 | static char *long_command[] = {"--help", "--version", "--dir", "--create", "--pack", "--list", "--format", "--unpack"}; |
---|
| 679 | |
---|
| 680 | |
---|
| 681 | |
---|
| 682 | /* usage: |
---|
| 683 | * Affiche les commandes d'utilisation du programme et quitte. |
---|
| 684 | */ |
---|
| 685 | static void usage(const char prog_name[]) |
---|
| 686 | { |
---|
| 687 | fprintf(stderr, "Usage: %s -h --help | -v --version | -t --list | -p --pack | -u --unpack\n", prog_name); |
---|
| 688 | fprintf(stderr, " -c --create | -d --dir | -f --format\n"); |
---|
| 689 | exit(EXIT_FAILURE); |
---|
| 690 | } |
---|
| 691 | |
---|
| 692 | |
---|
| 693 | |
---|
| 694 | /* main: |
---|
| 695 | * Point d'entrée du programme. |
---|
| 696 | */ |
---|
| 697 | int main(int argc, char *argv[]) |
---|
| 698 | { |
---|
| 699 | int ret = 0; |
---|
| 700 | int i; |
---|
| 701 | |
---|
| 702 | if (argc < 2) { /* no argument? */ |
---|
| 703 | if (FloppyInit(&fi, 1) > 0) { |
---|
| 704 | interactive_main(); |
---|
| 705 | FloppyExit(); |
---|
| 706 | } |
---|
| 707 | else { |
---|
| 708 | ret = 1; |
---|
| 709 | } |
---|
| 710 | } |
---|
| 711 | else { |
---|
| 712 | if (argv[1][0] == '-') { |
---|
| 713 | |
---|
| 714 | switch (argv[1][1]) { |
---|
| 715 | |
---|
| 716 | case '-': /* long commands */ |
---|
| 717 | for (i=0; i<COMMAND_MAX; i++) { |
---|
| 718 | if (strcmp(argv[1], long_command[i]) == 0) { |
---|
| 719 | argv[1] = short_command[i]; |
---|
| 720 | return main(argc, argv); |
---|
| 721 | } |
---|
| 722 | } |
---|
| 723 | |
---|
| 724 | usage(argv[0]); |
---|
| 725 | |
---|
| 726 | case 'h': /* help */ |
---|
| 727 | printf("SAP2 est un syst%sme d'archivage pour disquettes 3\"5 et 5\"25 Thomson. Il permet\n", egrave); |
---|
| 728 | printf("de cr%ser des images de disquettes sous forme d'archive SAP.\n\n", eacute); |
---|
| 729 | printf("Usage:\n"); |
---|
| 730 | printf(" %s (mode interactif)\n", argv[0]); |
---|
| 731 | printf(" %s commande1 archive.sap [lecteur] [densit%s]\n", argv[0], eacute); |
---|
| 732 | printf(" %s commande2 archive.sap [nb pistes] [densit%s]\n", argv[0], eacute); |
---|
| 733 | printf(" %s commande3 lecteur [densit%s] [entrelacement]\n", argv[0], eacute); |
---|
| 734 | printf("o%s la commande1 est prise parmi les suivantes:\n", ugrave); |
---|
| 735 | printf(" -h, --help affiche cette aide\n"); |
---|
| 736 | printf(" -v, --version affiche la version du programme\n"); |
---|
| 737 | printf(" -t, --list affiche la liste des fichiers de l'archive SAP\n"); |
---|
| 738 | printf(" -p, --pack archive une disquette Thomson vers une archive SAP\n"); |
---|
| 739 | printf(" -u, --unpack d%ssarchive une archive SAP vers une disquette Thomson\n", eacute); |
---|
| 740 | printf("et o%s la commande2 est prise parmi les suivantes:\n", ugrave); |
---|
| 741 | printf(" -c, --create cr%se une archive SAP vide\n", eacute); |
---|
| 742 | printf("et o%s la commande3 est prise parmi les suivantes:\n", ugrave); |
---|
| 743 | printf(" -d, --dir affiche le contenu d'une disquette Thomson\n"); |
---|
| 744 | printf(" -f, --format formate une disquette au format Thomson\n"); |
---|
| 745 | break; |
---|
| 746 | |
---|
| 747 | case 'v': /* version */ |
---|
| 748 | printf("SAP2 version "SAP2_VERSION_STR" pour "SAP2_PLATFORM_STR", copyright (C) 2000-2003 Eric Botcazou.\n"); |
---|
| 749 | break; |
---|
| 750 | |
---|
| 751 | case 'd': /* dir */ |
---|
| 752 | if (argc < 3) |
---|
| 753 | usage(argv[0]); |
---|
| 754 | |
---|
| 755 | if (FloppyInit(&fi, 0) > 0) { |
---|
| 756 | ret = ViewDiskDir(atoi(argv[2]), argc > 3 ? atoi(argv[3]) : 2, -1); |
---|
| 757 | FloppyExit(); |
---|
| 758 | } |
---|
| 759 | else { |
---|
| 760 | ret = 1; |
---|
| 761 | } |
---|
| 762 | break; |
---|
| 763 | |
---|
| 764 | case 'c': /* create */ |
---|
| 765 | if (argc < 3) |
---|
| 766 | usage(argv[0]); |
---|
| 767 | |
---|
| 768 | if (argc < 4) { |
---|
| 769 | ret = CreateEmptyArchive(argv[2], SAP_FORMAT1, SAP_TRK80); |
---|
| 770 | } |
---|
| 771 | else if (argc == 4){ |
---|
| 772 | if (atoi(argv[3]) == 40) |
---|
| 773 | ret = CreateEmptyArchive(argv[2], SAP_FORMAT1, SAP_TRK40); |
---|
| 774 | else if (atoi(argv[3]) == 80) |
---|
| 775 | ret = CreateEmptyArchive(argv[2], SAP_FORMAT1, SAP_TRK80); |
---|
| 776 | else |
---|
| 777 | ret = 1; |
---|
| 778 | } |
---|
| 779 | else { |
---|
| 780 | if (atoi(argv[3]) == 40) |
---|
| 781 | ret = CreateEmptyArchive(argv[2], (atoi(argv[4]) == 1 ? SAP_FORMAT2 : SAP_FORMAT1), SAP_TRK40); |
---|
| 782 | else if (atoi(argv[3]) == 80) |
---|
| 783 | ret = CreateEmptyArchive(argv[2], (atoi(argv[4]) == 1 ? SAP_FORMAT2 : SAP_FORMAT1), SAP_TRK80); |
---|
| 784 | else |
---|
| 785 | ret = 1; |
---|
| 786 | } |
---|
| 787 | break; |
---|
| 788 | |
---|
| 789 | case 'p': /* pack */ |
---|
| 790 | if (argc < 4) |
---|
| 791 | usage(argv[0]); |
---|
| 792 | |
---|
| 793 | if (FloppyInit(&fi, 0) > 0) { |
---|
| 794 | ret = PackArchive(argv[2], atoi(argv[3]), argc > 4 ? atoi(argv[4]) : 2, 0); |
---|
| 795 | FloppyExit(); |
---|
| 796 | } |
---|
| 797 | else { |
---|
| 798 | ret = 1; |
---|
| 799 | } |
---|
| 800 | break; |
---|
| 801 | |
---|
| 802 | case 't': /* list */ |
---|
| 803 | if (argc < 3) |
---|
| 804 | usage(argv[0]); |
---|
| 805 | |
---|
| 806 | ret = ViewArchiveDir(argv[2], -1); |
---|
| 807 | break; |
---|
| 808 | |
---|
| 809 | case 'f': /* format */ |
---|
| 810 | if (argc < 3) |
---|
| 811 | usage(argv[0]); |
---|
| 812 | |
---|
| 813 | if (FloppyInit(&fi, 1) > 0) { |
---|
| 814 | if (argc == 3) |
---|
| 815 | ret = FormatDisk(atoi(argv[2]), 2, (SAP_NSECTS-1)/2, 0); |
---|
| 816 | else if (argc == 4) |
---|
| 817 | ret = FormatDisk(atoi(argv[2]), atoi(argv[3]), (SAP_NSECTS-1)/2, 0); |
---|
| 818 | else |
---|
| 819 | ret = FormatDisk(atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), 0); |
---|
| 820 | |
---|
| 821 | FloppyExit(); |
---|
| 822 | } |
---|
| 823 | else { |
---|
| 824 | ret = 1; |
---|
| 825 | } |
---|
| 826 | break; |
---|
| 827 | |
---|
| 828 | case 'u': /* unpack */ |
---|
| 829 | if (argc < 4) |
---|
| 830 | usage(argv[0]); |
---|
| 831 | |
---|
| 832 | if (FloppyInit(&fi, 1) > 0) { |
---|
| 833 | ret = UnpackArchive(argv[2], atoi(argv[3]), argc > 4 ? atoi(argv[4]) : 2, 0); |
---|
| 834 | FloppyExit(); |
---|
| 835 | } |
---|
| 836 | else { |
---|
| 837 | ret = 1; |
---|
| 838 | } |
---|
| 839 | break; |
---|
| 840 | |
---|
| 841 | default: |
---|
| 842 | usage(argv[0]); |
---|
| 843 | } /* end of switch */ |
---|
| 844 | } |
---|
| 845 | else { |
---|
| 846 | usage(argv[0]); |
---|
| 847 | } |
---|
| 848 | } |
---|
| 849 | |
---|
| 850 | return ret; |
---|
| 851 | } |
---|
| 852 | |
---|