blob: 8e71e3be4742dc836cb9820b234ed41728e93cbf [file] [log] [blame]
/* Copyright 2003 Stefan Feuz, Lukas Meyer, Thomas Locher
* Copyright 2004,2006,2007,2009 Alain Knaff.
* This file is part of mtools.
*
* Mtools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Mtools is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Mtools. If not, see <http://www.gnu.org/licenses/>.
*
* Filename:
* mclasserase.c
*
* Original Creation Date:
* 05.III.2003
*
* Copyright:
* GPL
*
* Programmer:
* Stefan Feuz, Lukas Meyer, Thomas Locher
*/
#include "sysincludes.h"
#include "msdos.h"
#include "mtools.h"
#include "vfat.h"
#include "mainloop.h"
#include "fsP.h"
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include "file.h"
#include <unistd.h>
#include <stdio.h>
/**
* Prints the Usage Message to STDOUT<br>
*
* @author stefan feuz<br>
* stefan.feuz@ruag.com
*
* @param n.a.
*
* @returns n.a.
*
*/
static void usage(int ret) NORETURN;
static void usage(int ret)
{
fprintf(stderr, "Mtools version %s, dated %s\n", mversion, mdate);
fprintf(stderr, "Usage: %s [-d] drive:\n", progname);
exit(ret);
}
/**
* Delete all files on a Drive.<br>
*
* @author Lukas Meyer<br>
* lukas.meyer@ruag.com
* @version 0.4, 11.12.2003
*
* @param drive the drive to erase
* @param debug 1: stop after each erase cycle, 0: normal mode
*
* @returns n.a.
*
*/
static void do_mclasserase(char drive,int debug) NORETURN;
static void do_mclasserase(char drive,int debug)
{
struct device dev; /* Device information structure */
union bootsector boot;
int media; /* Just used to enter some in find_device */
char name[EXPAND_BUF];
Stream_t *Stream;
struct label_blk_t *labelBlock;
FILE * fDevice; /* Stores device's file descriptor */
char cCardType[12];
char drivel[3]; /* Stores the drive letter */
int i = 0;
/* FILE *forf; */
char dummy[2]; /* dummy input for debugging purposes.. */
int icount=0;
int iTotalErase = 0;
/* How many times we'll overwrite the media: */
#define CYCLES 3
unsigned char odat[CYCLES]; /* Data for each overwrite procedure */
/* Creating values for overwrite */
odat[0]=0xff;
odat[1]=0x00;
odat[2]=0xff;
if (debug == 1)
printf("cycles: %i, odats: %i,%i,%i\n",CYCLES,odat[0],odat[1],odat[2]);
/* Reading parameters from card. Exit with -1 if failed. */
if(! (Stream = find_device(drive, O_RDONLY, &dev, &boot,
name, &media, 0, NULL)))
exit(1);
FREE(&Stream);
/* Determine the FAT - type */
#if 0
if(WORD(fatlen)) {
labelBlock = &bbelBlock = &boot->ext.old.labelBlock;
} else {
labelBlock = &boot->ext.fat32.labelBlock;
}
#endif
/* we use only FAT12/16 ...*/
labelBlock = &boot.boot.ext.old.labelBlock;
/* store card type */
sprintf(cCardType, "%11.11s", labelBlock->label);
if (debug == 1)
{
printf("Using Device: %s\n",name);
printf("Card-Type detected: %s\n",cCardType);
}
/* Forming cat command to overwrite the medias content. */
sprintf( drivel, "%c:", ch_tolower(drive) );
#if 0
media_sectors = dev.tracks * dev.sectors;
sector_size = WORD(secsiz) * dev.heads;
printf(mcat);
printf("\n%d\n", media_sectors);
printf("%d\n", sector_size);
#endif
/*
* Overwrite device
*/
for( i=0; i < CYCLES; i++){
if (debug==1)
{
printf("Erase Cycle %i, writing data: 0x%2.2x...\n",i+1,odat[i]);
}
fDevice = fopen(name,"ab+");
if (fDevice == 0)
{
perror("Error opening device");
exit(-1);
}
if (debug==1)
{
printf("Open successful...\n");
printf("Flushing device after 32 kBytes of data...\n");
printf("Erasing:");
fflush( stdout );
}
/* iTotalErase = 0; */
/*
* overwrite the whole device
*/
while ((feof(fDevice)==0) && (ferror(fDevice)==0))
{
fputc(odat[i],fDevice);
icount++;
if (icount > (32 * 1024))
{
/* flush device every 32KB of data...*/
fflush( fDevice );
iTotalErase += icount;
if (debug == 1)
{
printf(".");
fflush( stdout );
}
icount=0;
}
}
if (debug==1)
{
printf("\nPress <ENTER> to continue\n");
printf("Press <x> and <ENTER> to abort\n");
if(scanf("%c",dummy) < 1)
printf("Input error\n");
fflush( stdin );
if (strcmp(dummy,"x") == 0)
{
printf("exiting.\n");
exit(0);
}
}
fclose(fDevice);
}
/*
* Format device using shell script
*/
if (debug == 0)
{
/* redirect STDERR and STDOUT to the black hole... */
if (dup2(open("/dev/null", O_WRONLY), STDERR_FILENO) != STDERR_FILENO)
printf("Error with dup2() stdout\n");
if (dup2(open("/dev/null", O_WRONLY), STDOUT_FILENO) != STDOUT_FILENO)
printf("Error with dup2() stdout\n");
}
if (debug == 1)
printf("Calling amuFormat.sh with args: %s,%s\n",cCardType,drivel);
execlp("amuFormat.sh","",cCardType,drivel,NULL);
/* we never come back...(we shouldn't come back ...) */
exit(-1);
}
/**
* Total Erase of Data on a Disk. After using mclasserase there won't
* be ANY bits of old files on the disk.<br>
* </b>
* @author stefan feuz<br>
* thomas locher<br>
* stefan.feuz@ruag.com
* thomas.locher@ruag.com
* @version 0.3, 02.12.2003
*
* @param argc generated automatically by operating systems
* @param **argv1 generated automatically by operating systems
* @param type generated automatically by operating systems
*
* @param -d stop after each erase cycle, for testing purposes
*
* @returns int 0 if all is well done<br>
* int -1 if there is something wrong
*
* @info mclasserase [-p tempFilePath] [-d] drive:
*
*
*/
void mclasserase(int argc, char **argv, int type UNUSEDP) NORETURN;
void mclasserase(int argc, char **argv, int type UNUSEDP)
{
/* declaration of all variables */
int c;
int debug=0;
/* char* tempFilePath=NULL; */
char drive='a';
extern int optind;
destroy_privs();
/* check and read command line arguments */
#ifdef DEBUG
printf("mclasserase: argc = %i\n",argc);
#endif
/* check num of arguments */
if(helpFlag(argc, argv))
usage(0);
if ( (argc != 2) & (argc != 3) & (argc != 4))
{ /* wrong num of arguments */
printf ("mclasserase: wrong num of args\n");
usage(1);
}
else
{ /* correct num of arguments */
while ((c = getopt(argc, argv, "+p:dh")) != EOF)
{
switch (c)
{
case 'd':
printf("=============\n");
printf("Debug Mode...\n");
printf("=============\n");
debug = 1;
break;
case 'p':
printf("option -p not implemented yet\n");
break;
case 'h':
usage(0);
case '?':
usage(1);
default:
break;
}
}
#ifdef DEBUG
printf("mclasserase: optind = %i\n",optind);
/* look for the drive to erase */
printf("mclasserase: searching drive\n");
#endif
for(; optind < argc; optind++)
{
if(!argv[optind][0] || argv[optind][1] != ':')
{
usage(1);
}
drive = ch_toupper(argv[optind][0]);
}
}
#ifdef DEBUG
printf("mclasserase: found drive %c\n", drive);
#endif
/* remove all data on drive, you never come back if drive does
* not exist */
do_mclasserase(drive,debug);
}