#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#define MKFILE_WBUF ((size_t)(1048576))
#define MKFILE_FLAG (O_WRONLY | O_CREAT | O_TRUNC)
#define MKFILE_MODE (S_IRUSR | S_IWUSR | S_ISVTX)
static char buf[MKFILE_WBUF];
static int nofill = 0;
static int verbose = 0;
static void
usage()
{
fprintf(stderr,
"Usage: mkfile [-nv] <size>[e|p|t|g|m|k|b] <filename> ...\n");
}
static unsigned long long
getsize(char *s)
{
int sh;
unsigned long long length;
char *suffix;
length = strtoull(s, &suffix, 10);
sh = 0;
switch (tolower(*suffix)) {
case 'e':
sh = 60;
break;
case 'p':
sh = 50;
break;
case 't':
sh = 40;
break;
case 'g':
sh = 30;
break;
case 'm':
sh = 20;
break;
case 'k':
sh = 10;
break;
case 'b':
sh = 9;
break;
case '\0':
break;
default:
errno = EINVAL;
return 0;
}
if (sh) {
unsigned long long l;
l = length;
length <<= sh;
if ((length >> sh) != l) {
errno = ERANGE;
return 0;
}
}
return length;
}
static int
create_file(char *f, unsigned long long s)
{
int fd;
size_t w;
ssize_t ws;
if (verbose) {
fprintf(stdout, "%s %llu bytes\n", f, s);
fflush(stdout);
}
if ((fd = open(f, MKFILE_FLAG, MKFILE_MODE)) < 0) {
return -1;
}
if ((lseek(fd, (off_t)(s - 1LL), SEEK_SET) == (off_t)-1) ||
(write(fd, buf, (size_t)1) == (ssize_t)-1)) {
return -1;
}
if (!nofill) {
if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
return -1;
}
while (s) {
w = (s > MKFILE_WBUF) ? MKFILE_WBUF : s;
if ((ws = write(fd, buf, w)) == (ssize_t)-1) {
return -1;
}
s -= ws;
}
}
close(fd);
return 0;
}
int
main(int argc, char *argv[])
{
unsigned long long fsize;
int ch;
if (argc < 3) {
usage();
return EXIT_FAILURE;
}
while ((ch = getopt(argc, argv, "nv")) != -1) {
switch (ch) {
case 'n':
nofill = 1;
break;
case 'v':
verbose = 1;
break;
default:
usage();
return EXIT_FAILURE;
}
}
argc -= optind;
argv += optind;
if ((fsize = getsize(*argv)) == 0) {
perror(*argv);
return EXIT_FAILURE;
}
bzero(buf, MKFILE_WBUF);
while (++argv, --argc) {
if (create_file(*argv, fsize) == -1) {
perror(*argv);
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}