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