Initial import package mtools: Programs for accessing MS-DOS disks without mounting...
[profile/ivi/mtools.git] / mclasserase.c
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  */
58 static void usage(int ret) NORETURN;
59 static 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  */
79 static void do_mclasserase(char drive,int debug)
80 {
81   struct device dev;            /* Device information structure */
82   union bootsector boot;
83
84   int media;                    /* Just used to enter some in find_device */
85   char name[EXPAND_BUF];
86   Stream_t *Stream;
87   struct label_blk_t *labelBlock;
88   
89   FILE * fDevice;              /* Stores device's file descriptor */
90   
91   char cCardType[12];
92   
93   char drivel[2];               /* Stores the drive letter */
94
95
96   int i = 0;
97
98   /* FILE *forf; */
99
100   char dummy[2];       /* dummy input for debugging purposes.. */
101   int icount=0;
102   int iTotalErase = 0;
103
104   const int cycles = 3;         /* How many times we'll overwrite the media */
105   char odat[cycles];            /* Data for each overwrite procedure */
106
107   /* Creating values for overwrite  */
108   odat[0]=0xff;
109   odat[1]=0x00;
110   odat[2]=0xff;
111   
112
113   if (debug == 1)
114      printf("cycles: %i, odats: %i,%i,%i\n",cycles,odat[0],odat[1],odat[2]);
115   
116   
117
118   /* Reading parameters from card. Exit with -1 if failed. */
119   if(! (Stream = find_device(drive, O_RDONLY, &dev, &boot,
120                                            name, &media, 0, NULL)))
121         exit(1);
122
123   FREE(&Stream);
124
125   /* Determine the FAT - type */
126 #if 0
127   if(WORD(fatlen)) {
128     labelBlock = &bbelBlock = &boot->ext.old.labelBlock;
129   } else {
130     labelBlock = &boot->ext.fat32.labelBlock;
131   }
132 #endif
133
134   /* we use only FAT12/16 ...*/
135   labelBlock = &boot.boot.ext.old.labelBlock;
136    
137   /* store card type */
138   sprintf(cCardType, "%11.11s", labelBlock->label);
139
140   if (debug == 1)
141   {
142      printf("Using Device: %s\n",name);
143      printf("Card-Type detected: %s\n",cCardType);
144   }
145       
146   /* Forming cat command to overwrite the medias content. */
147   sprintf( drivel, "%c:", tolower(drive) );
148
149 #if 0
150   media_sectors = dev.tracks * dev.sectors;
151   sector_size = WORD(secsiz) * dev.heads; 
152   
153
154         printf(mcat);
155         printf("\n%d\n", media_sectors);
156         printf("%d\n", sector_size);
157 #endif
158  
159   /*
160    * Overwrite device
161    */
162   for( i=0; i < cycles; i++){
163
164      if (debug==1)
165      {
166         printf("Erase Cycle %i, writing data: 0x%2.2x...\n",i+1,odat[i]);
167      }
168
169      fDevice = fopen(name,"ab+");
170           
171      if (fDevice == 0)
172      {
173         perror("Error opening device");
174         exit(-1);
175      }
176
177
178      if (debug==1)
179      {
180         printf("Open successful...\n");
181         printf("Flushing device after 32 kBytes of data...\n");
182         printf("Erasing:");
183         fflush( stdout );
184      }
185
186      /* iTotalErase = 0; */
187       
188      /*
189       * overwrite the whole device
190       */
191      while ((feof(fDevice)==0) && (ferror(fDevice)==0))
192      {
193                         
194         fputc(odat[i],fDevice);
195
196         icount++;
197         if (icount > (32 * 1024))
198         {
199            /* flush device every 32KB of data...*/
200            fflush( fDevice );
201            
202            iTotalErase += icount;
203            if (debug == 1)
204            {
205               printf(".");         
206               fflush( stdout );
207            }
208            icount=0;
209         }
210      }
211      
212      if (debug==1)
213      {
214         printf("\nPress <ENTER> to continue\n");
215         printf("Press <x> and <ENTER> to abort\n");
216         
217         if(scanf("%c",dummy) < 1)
218           printf("Input error\n");
219         fflush( stdin );
220         
221         if (strcmp(dummy,"x") == 0)
222         {
223            printf("exiting.\n");
224            exit(0);
225         }
226      }
227      
228      fclose(fDevice);
229
230   }
231
232    
233   /*
234    * Format device using shell script
235    */  
236   if (debug == 0)
237   {
238         /* redirect STDERR and STDOUT to the black hole... */
239         if (dup2(open("/dev/null", O_WRONLY), STDERR_FILENO) != STDERR_FILENO)
240                 printf("Error with dup2() stdout\n");
241         if (dup2(open("/dev/null", O_WRONLY), STDOUT_FILENO) != STDOUT_FILENO)
242                 printf("Error with dup2() stdout\n");
243   }
244                
245   if (debug == 1)
246       printf("Calling amuFormat.sh with args: %s,%s\n",cCardType,drivel);
247         
248   execlp("amuFormat.sh","",cCardType,drivel,NULL);
249
250   /* we never come back...(we shouldn't come back ...) */
251   exit(-1);
252     
253 }
254
255
256 /**
257  * Total Erase of Data on a Disk. After using mclasserase there wont
258  * be ANY bits of old files on the disk.<br>
259  * </b>
260  * @author  stefan feuz<br>
261  *          thomas locher<br>
262  *          stefan.feuz@ruag.com
263  *          thomas.locher@ruag.com
264  * @version 0.3, 02.12.2003
265  *
266  * @param   argc    generated automatically by operating systems
267  * @param   **argv1  generated automatically by operating systems
268  * @param   type    generated automatically by operating systems
269  *
270  * @param   -d      stop after each erase cycle, for testing purposes
271  * 
272  * @returns int     0 if all is well done<br>
273  *          int     -1 if there is something wrong
274  *
275  * @info    mclasserase [-p tempFilePath] [-d] drive:
276  *
277  *
278  */
279 void mclasserase(int argc, char **argv, int type)
280 {
281   /* declaration of all variables */
282   int c;
283   int debug=0;
284   /* char* tempFilePath=NULL; */
285   char drive='a';
286
287   int extern optind;
288
289   destroy_privs();
290
291   /* check and read command line arguments */
292 #ifdef DEBUG
293   printf("mclasserase: argc = %i\n",argc);
294 #endif
295   /* check num of arguments */
296   if(helpFlag(argc, argv))
297     usage(0);
298   if ( (argc != 2) & (argc != 3) & (argc != 4))
299     { /* wrong num of arguments */
300     printf ("mclasserase: wrong num of args\n");
301     usage(1);
302   }
303   else
304   { /* correct num of arguments */
305     while ((c = getopt(argc, argv, "+p:dh")) != EOF)
306     {
307       switch (c)
308       {
309         
310         case 'd':
311            
312            printf("=============\n");
313            printf("Debug Mode...\n");
314            printf("=============\n");
315            debug = 1;
316            break;
317         case 'p':
318            printf("option -p not implemented yet\n"); 
319            break;
320         case 'h':
321           usage(0);
322         case '?':
323            usage(1);
324         default:
325            break;
326        }
327      }
328 #ifdef DEBUG
329      printf("mclasserase: optind = %i\n",optind);
330    /* look for the drive to erase */
331    printf("mclasserase: searching drive\n");
332 #endif
333    for(; optind < argc; optind++)
334    {
335      if(!argv[optind][0] || argv[optind][1] != ':')
336      {
337        usage(1);
338      }
339      drive = toupper(argv[optind][0]);
340    }
341   }
342 #ifdef DEBUG
343   printf("mclasserase: found drive %c\n", drive);
344 #endif 
345   /* remove all data on drive, you never come back if drive does
346    * not exist */
347   
348   do_mclasserase(drive,debug);
349   
350   exit (0);
351 }