#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <ctype.h>
const char * strtera="To";
const char * strgiga="Go";
const char * strmega="Mo";
const char * strkilo="Ko";
const char * stroctets="octets";
const char * strunkwn="inconnu";
#define TERA 1099511627776
#define GIGA 1073741824
#define MEGA 1048576
#define KILO 1024
const long tera = TERA;
const long giga = GIGA;
const long mega = MEGA;
const long kilo = KILO;
long unit=0;
char buffer[4096];
unsigned long size=0;
const char * filename = NULL;
int justdoit = false;
const char* strofunit(const long u)
{ switch (u)
{ case TERA : return strtera;
case GIGA : return strgiga;
case MEGA : return strgiga;
case KILO : return strkilo;
case 1 : return stroctets;
default : return strunkwn;
}
}
void usage(void)
{
fprintf(stderr, "\n");
fprintf(stderr, "usage : zerogen -f filename -s size \n");
fprintf(stderr, " size peut tre specit avec une unit comme '12G' or '125M' \n");
fprintf(stderr, " Si l'unit n'est pas spcifie avec size, elle peut l'etre avec -u (mais pas les deux)\n");
fprintf(stderr, " En l'absence de toute unit, la taille est considre tre en octets.\n");
fprintf(stderr, " La taille ne doit en aucun cas depasser 8To (comportement imprvisible dans ce cas).\n");
fprintf(stderr, " \n");
fprintf(stderr, " zerogen ne modifiera pas les fichiers qui existent dja\n");
fprintf(stderr, " \n");
fprintf(stderr, " exemple : \n");
fprintf(stderr, " zerogen -f disk.img -s 20G\n");
fprintf(stderr, " zerogen -f disk2.img -s 20 -u G\n");
fprintf(stderr, " \n");
}
int getarg(int argc, char* argv[] )
{
int c;
int tmp;
char tmp2;
if (!argc) return false;
while ( (c = getopt(argc, argv, "jS:s:u:f:")) != EOF )
{
switch(c)
{ case 'j' : justdoit=true;
break;
case 's' :
case 'S' : if (size)
{ printf("Erreur : la taille est specifie plusieurs fois\n");
return false;
}
tmp = sscanf(optarg,"%lu%c", &size, &tmp2);
if ( ! tmp ) return false;
if ( tmp == 2 )
switch ( toupper(tmp2) )
{ case 'T' : unit = tera; break;
case 'G' : unit = giga; break;
case 'M' : unit = mega; break;
case 'K' : unit = kilo; break;
case 'O' : unit = 1; break;
}
break;
case 'u' : if (unit)
{ printf("Erreur : Conflit d'units\n");
return false;
}
switch ( toupper(optarg[0]) )
{ case 'T' : unit = tera; break;
case 'G' : unit = giga; break;
case 'M' : unit = mega; break;
case 'K' : unit = kilo; break;
case 'O' : unit = 1; break;
}
break;
case 'f' : filename = optarg;
break;
case '?' : perror("Option inconnue\n");
return false;
}
}
if ( !filename )
{ fprintf(stderr,"fichier non specifie : utilisez l'option -f \"fichier\"\n");
return false;
}
if ( ! size )
{ fprintf(stderr, "taille non spcifie : utiliser l'option -s taille \n");
return false;
}
if ( !unit )
{ fprintf(stderr,"unit non specifie : On considere que la taille specifiee est en octets\n");
unit=1;
}
if ( !unit )
{ fprintf(stderr,"unit non specifie : utilisez l'option -uO -uK -uM -uG -uT pour specifier octets, kilo, mega, giga\n");
return false;
}
return true;
}
int main (int argc, char* argv[])
{ FILE* f;
int w;
assert( sizeof(long) == 8 );
assert( sizeof(size_t) == 8);
memset(buffer, 0, 4096);
if ( ! getarg(argc, argv) )
{ usage();
return 1;
}
f = fopen(filename, "r");
if (f && !justdoit)
{ fclose(f);
fprintf(stderr,"Le fichier existe dj specifiez -j pour passer outre (-j comme just do it)\n");
return 1;
}
if (f && !justdoit) fclose(f);
printf("Cration du fichier [%s] de taille %lu %s\n", filename, size, strofunit(unit));
f = fopen(filename, "w");
assert(f);
fseek(f, (size*unit)-1 , SEEK_SET);
w=fwrite(buffer, 1, 1, f);
assert(w);
fclose (f);
return 0;
}