1/* Copyright 2003 Stefan Feuz, Lukas Meyer, Thomas Locher 2 * Copyright 2004,2006,2007,2009 Alain Knaff. 3 * This file is part of mtools. 4 * 5 * Mtools 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 3 of the License, or 8 * (at your option) any later version. 9 * 10 * Mtools 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 Mtools. If not, see <http://www.gnu.org/licenses/>. 17 * 18 * Filename: 19 * mclasserase.c 20 * 21 * Original Creation Date: 22 * 05.III.2003 23 * 24 * Copyright: 25 * GPL 26 * 27 * Programmer: 28 * Stefan Feuz, Lukas Meyer, Thomas Locher 29 */ 30 31#include "sysincludes.h" 32#include "msdos.h" 33#include "mtools.h" 34#include "vfat.h" 35#include "mainloop.h" 36#include "fsP.h" 37 38#ifdef HAVE_GETOPT_H 39#include <getopt.h> 40#endif 41 42#include "file.h" 43 44#include <unistd.h> 45#include <stdio.h> 46 47/** 48 * Prints the Usage Message to STDOUT<br> 49 * 50 * @author stefan feuz<br> 51 * stefan.feuz@ruag.com 52 * 53 * @param n.a. 54 * 55 * @returns n.a. 56 * 57 */ 58static void usage(int ret) NORETURN; 59static void usage(int ret) 60{ 61 fprintf(stderr, "Mtools version %s, dated %s\n", mversion, mdate); 62 fprintf(stderr, "Usage: %s [-d] drive:\n", progname); 63 exit(ret); 64} 65 66/** 67 * Delete all files on a Drive.<br> 68 * 69 * @author Lukas Meyer<br> 70 * lukas.meyer@ruag.com 71 * @version 0.4, 11.12.2003 72 * 73 * @param drive the drive to erase 74 * @param debug 1: stop after each erase cycle, 0: normal mode 75 * 76 * @returns n.a. 77 * 78 */ 79static void do_mclasserase(char drive,int debug) 80{ 81 struct device dev; /* Device information structure */ 82 unsigned char boot0[MAX_BOOT]; 83/* Bootsector information structure 84 has to be here. some compilers don't do preprocessor statements if 85 they're not in first row. 86*/ 87 struct bootsector *boot = (struct bootsector *) boot0; 88 int media; /* Just used to enter some in find_device */ 89 char name[EXPAND_BUF]; 90 Stream_t *Stream; 91 struct label_blk_t *labelBlock; 92 93 FILE * fDevice; /* Stores device's file descriptor */ 94 95 char cCardType[12]; 96 97 char drivel[2]; /* Stores the drive letter */ 98 99 100 int i = 0; 101 102 /* FILE *forf; */ 103 104 char dummy[2]; /* dummy input for debugging purposes.. */ 105 int icount=0; 106 int iTotalErase = 0; 107 108 const int cycles = 3; /* How many times we'll overwrite the media */ 109 char odat[cycles]; /* Data for each overwrite procedure */ 110 111 /* Creating values for overwrite */ 112 odat[0]=0xff; 113 odat[1]=0x00; 114 odat[2]=0xff; 115 116 117 if (debug == 1) 118 printf("cycles: %i, odats: %i,%i,%i\n",cycles,odat[0],odat[1],odat[2]); 119 120 121 122 /* Reading parameters from card. Exit with -1 if failed. */ 123 if(! (Stream = find_device(drive, O_RDONLY, &dev, boot, 124 name, &media, 0, NULL))) 125 exit(1); 126 127 FREE(&Stream); 128 129 /* Determine the FAT - type */ 130#if 0 131 if(WORD(fatlen)) { 132 labelBlock = &bbelBlock = &boot->ext.old.labelBlock; 133 } else { 134 labelBlock = &boot->ext.fat32.labelBlock; 135 } 136#endif 137 138 /* we use only FAT12/16 ...*/ 139 labelBlock = &boot->ext.old.labelBlock; 140 141 /* store card type */ 142 sprintf(cCardType, "%11.11s", labelBlock->label); 143 144 if (debug == 1) 145 { 146 printf("Using Device: %s\n",name); 147 printf("Card-Type detected: %s\n",cCardType); 148 } 149 150 /* Forming cat command to overwrite the medias content. */ 151 sprintf( drivel, "%c:", tolower(drive) ); 152 153#if 0 154 media_sectors = dev.tracks * dev.sectors; 155 sector_size = WORD(secsiz) * dev.heads; 156 157 158 printf(mcat); 159 printf("\n%d\n", media_sectors); 160 printf("%d\n", sector_size); 161#endif 162 163 /* 164 * Overwrite device 165 */ 166 for( i=0; i < cycles; i++){ 167 168 if (debug==1) 169 { 170 printf("Erase Cycle %i, writing data: 0x%2.2x...\n",i+1,odat[i]); 171 } 172 173 fDevice = fopen(name,"ab+"); 174 175 if (fDevice == 0) 176 { 177 perror("Error opening device"); 178 exit(-1); 179 } 180 181 182 if (debug==1) 183 { 184 printf("Open successful...\n"); 185 printf("Flushing device after 32 kBytes of data...\n"); 186 printf("Erasing:"); 187 fflush( stdout ); 188 } 189 190 /* iTotalErase = 0; */ 191 192 /* 193 * overwrite the whole device 194 */ 195 while ((feof(fDevice)==0) && (ferror(fDevice)==0)) 196 { 197 198 fputc(odat[i],fDevice); 199 200 icount++; 201 if (icount > (32 * 1024)) 202 { 203 /* flush device every 32KB of data...*/ 204 fflush( fDevice ); 205 206 iTotalErase += icount; 207 if (debug == 1) 208 { 209 printf("."); 210 fflush( stdout ); 211 } 212 icount=0; 213 } 214 } 215 216 if (debug==1) 217 { 218 printf("\nPress <ENTER> to continue\n"); 219 printf("Press <x> and <ENTER> to abort\n"); 220 221 scanf("%c",dummy); 222 fflush( stdin ); 223 224 if (strcmp(dummy,"x") == 0) 225 { 226 printf("exiting.\n"); 227 exit(0); 228 } 229 } 230 231 fclose(fDevice); 232 233 } 234 235 236 /* 237 * Format device using shell script 238 */ 239 if (debug == 0) 240 { 241 /* redirect STDERR and STDOUT to the black hole... */ 242 if (dup2(open("/dev/null", O_WRONLY), STDERR_FILENO) != STDERR_FILENO) 243 printf("Error with dup2() stdout\n"); 244 if (dup2(open("/dev/null", O_WRONLY), STDOUT_FILENO) != STDOUT_FILENO) 245 printf("Error with dup2() stdout\n"); 246 } 247 248 if (debug == 1) 249 printf("Calling amuFormat.sh with args: %s,%s\n",cCardType,drivel); 250 251 execlp("amuFormat.sh","",cCardType,drivel,NULL); 252 253 /* we never come back...(we shouldn't come back ...) */ 254 exit(-1); 255 256} 257 258 259/** 260 * Total Erase of Data on a Disk. After using mclasserase there wont 261 * be ANY bits of old files on the disk.<br> 262 * </b> 263 * @author stefan feuz<br> 264 * thomas locher<br> 265 * stefan.feuz@ruag.com 266 * thomas.locher@ruag.com 267 * @version 0.3, 02.12.2003 268 * 269 * @param argc generated automatically by operating systems 270 * @param **argv1 generated automatically by operating systems 271 * @param type generated automatically by operating systems 272 * 273 * @param -d stop after each erase cycle, for testing purposes 274 * 275 * @returns int 0 if all is well done<br> 276 * int -1 if there is something wrong 277 * 278 * @info mclasserase [-p tempFilePath] [-d] drive: 279 * 280 * 281 */ 282void mclasserase(int argc, char **argv, int type) 283{ 284 /* declaration of all variables */ 285 int c; 286 int debug=0; 287 /* char* tempFilePath=NULL; */ 288 char drive='a'; 289 290 int extern optind; 291 292 destroy_privs(); 293 294 /* check and read command line arguments */ 295#ifdef DEBUG 296 printf("mclasserase: argc = %i\n",argc); 297#endif 298 /* check num of arguments */ 299 if(helpFlag(argc, argv)) 300 usage(0); 301 if ( (argc != 2) & (argc != 3) & (argc != 4)) 302 { /* wrong num of arguments */ 303 printf ("mclasserase: wrong num of args\n"); 304 usage(1); 305 } 306 else 307 { /* correct num of arguments */ 308 while ((c = getopt(argc, argv, "+p:dh")) != EOF) 309 { 310 switch (c) 311 { 312 313 case 'd': 314 315 printf("=============\n"); 316 printf("Debug Mode...\n"); 317 printf("=============\n"); 318 debug = 1; 319 break; 320 case 'p': 321 printf("option -p not implemented yet\n"); 322 break; 323 case 'h': 324 usage(0); 325 case '?': 326 usage(1); 327 default: 328 break; 329 } 330 } 331#ifdef DEBUG 332 printf("mclasserase: optind = %i\n",optind); 333 /* look for the drive to erase */ 334 printf("mclasserase: searching drive\n"); 335#endif 336 for(; optind < argc; optind++) 337 { 338 if(!argv[optind][0] || argv[optind][1] != ':') 339 { 340 usage(1); 341 } 342 drive = toupper(argv[optind][0]); 343 } 344 } 345#ifdef DEBUG 346 printf("mclasserase: found drive %c\n", drive); 347#endif 348 /* remove all data on drive, you never come back if drive does 349 * not exist */ 350 351 do_mclasserase(drive,debug); 352 353 exit (0); 354} 355