/*
* Zeroer (for usage see "man zero").
* This software is licensed under the GNU
* public license. See LICENSE for details.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <popt.h>
/* use a 10 MB buffer by default (can be changed by -b option*/
long buffersize=10485760;
const char *filename;
poptContext optCtx;
/* option table; for details, see <man popt> */
static struct poptOption commandOptions[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{"buffersize", 'b', POPT_ARG_LONG, &buffersize, 'b', NULL, NULL},
POPT_AUTOHELP /* Pre-implement '-?', '--help', '--usage' */
POPT_TABLEEND /* Needed to mark end of this structure */
};
/* escape with system error message */
void errExit(char *message) {
perror(message);
poptFreeContext(optCtx);
exit(EXIT_FAILURE);
}
/*
* This function writes the zero-filled memory blocks
* to the destination file. If the file system is going
* to be full, the write size is reduced, so that smaller
* blocks in the unallocated disk sector space can still
* be overwritten.
*/
void blockWriteLoop(FILE *f, char *pBuf) {
int writeSize=buffersize;
int loopCount=0;
while(writeSize > 0) {
printf(
"\nSTATS: loopCount=%d, writeSize=%d ",
++loopCount,
writeSize
);
fwrite((void *)pBuf, (size_t)sizeof(char), writeSize, f);
if (ferror(f)) {
printf("write_error, reducing writeSize");
writeSize=writeSize/2;
clearerr(f);
}
}
}
/*
* The <filename> argument specifies the name of a
* file to be created. This will be the file in which
* the zero's are written to.
*/
void initBlockWriter(const char *filename) {
FILE *f=NULL;
char *pBuf=NULL;
f=fopen(filename, "wb");
if (f == NULL) {
errExit("\nCould not open destfile");
}
pBuf=(char *)malloc((size_t)(sizeof(char) * buffersize));
if (pBuf == NULL) {
errExit("\nCould not allocate memory");
}
memset((void *)pBuf, 0, (size_t)(sizeof(char) * buffersize));
blockWriteLoop(f, pBuf);
free((void *)pBuf);
fclose(f);
}
/*
* In the main function, command-line arguments
* are parsed and each switchoption's value is
* implicitly stored in the corresponding global
* variable as specified in the commandOptions
* array.
*/
int main(int argc, char *argv[]) {
int opt;
/* acquire popt context */
optCtx=poptGetContext(
NULL,
argc,
(const char **)argv,
commandOptions,
0
);
/*
* The syntax for additional non-switchoption
* parameters. this is glued together with the
* automatically popt-generated options syntax
* list.
*/
poptSetOtherOptionHelp(optCtx, "filename");
/* if no argument has been specified at all...*/
if (argc < 2) {
poptPrintUsage(optCtx, stderr, 0);
poptFreeContext(optCtx);
exit(EXIT_FAILURE);
}
/* parse switched options */
while ((opt = poptGetNextOpt(optCtx)) >= 0) {
switch (opt) {
case 'b':
fprintf(stderr, "buffersize set to %d\n", (int)buffersize);
break;
}
}
/* parse filename (non-switchoption-parameter) */
filename=poptGetArg(optCtx);
if (filename == NULL) {
fprintf(stderr, "no filename specified\n");
poptPrintUsage(optCtx, stderr, 0);
poptFreeContext(optCtx);
exit(EXIT_FAILURE);
}
/* if a switchoption is malformed, i.e. wrong type */
if (opt < -1) {
fprintf(
stderr,
"%s: %s\n",
poptBadOption(optCtx, POPT_BADOPTION_NOALIAS),
poptStrerror(opt)
);
poptPrintUsage(optCtx, stderr, 0);
poptFreeContext(optCtx);
exit(EXIT_FAILURE);
}
/* run application */
initBlockWriter(filename);
/* release popt context */
poptFreeContext(optCtx);
return EXIT_SUCCESS;
}
syntax highlighted by Code2HTML, v. 0.9.1