/* * Zeroer (for usage see "man zero"). * This software is licensed under the GNU * public license. See LICENSE for details. * */ #include #include #include #include /* 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 */ 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 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; }