/*-
* Copyright (c) 2001-2004
* HATANOU Tomomi. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)mkfile.c 1.3 (HATANOU Tomomi) 2004/01/21";
#endif /* !lint */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#define MKFILE_WBUF (1048576) /* XXX - is 1M an reasonable value? */
/*
* Try settting "sticky bit" for compatibility with SunOS's mkfile(8).
*/
#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");
exit(0);
}
/*
* NOTE: On many *BSD systems, size_t is still 32bit width.
* We use `off_t' instead here.
* This may also be okay for LP64 systems.
*/
static off_t
getsize(s)
char *s;
{
int sft;
off_t length;
char *suffix;
length = (off_t)strtoll(s, &suffix, 10);
sft = 0;
switch (*suffix) {
case 'e':
case 'E': /* exabytes */
sft = 60;
break;
case 'p':
case 'P': /* petabytes */
sft = 50;
break;
case 't':
case 'T': /* terabytes */
sft = 40;
break;
case 'g':
case 'G': /* gigabytes */
sft = 30;
break;
case 'm':
case 'M': /* megabytes */
sft = 20;
break;
case 'k':
case 'K': /* kilobytes */
sft = 10;
break;
case 'b':
case 'B': /* blocks */
sft = 9;
break;
}
if (sft) {
off_t len;
len = length;
length <<= sft;
/* check overflow */
if ((length >> sft) != len) {
printf("Size too large.\n");
exit(0);
}
}
return length;
}
static void
init_buf()
{
bzero(buf, MKFILE_WBUF);
}
static void
create_file(f, s)
char *f;
off_t s;
{
int fd, i;
size_t bk, ix;
if (verbose) {
fprintf(stdout, "%s %qu bytes\n", f, s);
fflush(stdout);
}
if ((fd = open(f, O_WRONLY | O_CREAT | O_TRUNC, MKFILE_MODE)) < 0) {
perror(f);
} else {
lseek(fd, s - (off_t)1, SEEK_SET);
write(fd, buf, (size_t)1);
if (!nofill) {
lseek(fd, (off_t)0, SEEK_SET);
bk = (size_t)(s / (off_t)MKFILE_WBUF);
ix = (size_t)(s % (off_t)MKFILE_WBUF);
for (i = 0; i < bk; i++) {
write(fd, buf, (size_t)MKFILE_WBUF);
}
if (ix) {
write(fd, buf, (size_t)ix);
}
}
close(fd);
}
}
int
main(argc, argv)
int argc;
char **argv;
{
off_t fsize;
char *p;
if (argc < 3) {
usage();
}
argv++;
init_buf();
for (fsize = 0; *argv != NULL; argv++) {
switch (**argv) {
case '-':
for (p = *argv + 1; *p; p++) {
switch (*p) {
case 'n': /* no filling */
nofill = 1;
break;
case 'v': /* verbose */
verbose = 1;
break;
}
}
break;
default:
if (!fsize) {
fsize = getsize(*argv);
} else {
create_file(*argv, fsize);
}
}
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1