mirror of
https://review.haiku-os.org/haiku
synced 2025-02-07 22:35:26 +01:00
at all. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30151 a95241bf-73f2-0310-859d-f6bbb57e9c96
154 lines
3.5 KiB
C++
154 lines
3.5 KiB
C++
/*
|
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
|
* Copyright 2007, Marcus Overhagen. All Rights Reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
#define EXIT_FAILURE 1
|
|
|
|
|
|
static void
|
|
print_usage(bool error)
|
|
{
|
|
printf("\n");
|
|
printf("create_image\n");
|
|
printf("\n");
|
|
printf("usage: create_image -i <imagesize> [-c] [-f] <file>\n");
|
|
printf(" -i, --imagesize size of raw partition image file\n");
|
|
printf(" -f, --file the raw partition image file\n");
|
|
printf(" -c, --clear-image set the image content to zero\n");
|
|
exit(error ? EXIT_FAILURE : 0);
|
|
}
|
|
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
off_t imageSize = 0;
|
|
const char *file = NULL;
|
|
bool clearImage = false;
|
|
|
|
while (1) {
|
|
int c;
|
|
static struct option long_options[] = {
|
|
{"file", required_argument, 0, 'f'},
|
|
{"clear-image", no_argument, 0, 'c'},
|
|
{"help", no_argument, 0, 'h'},
|
|
{"imagesize", required_argument, 0, 'i'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
opterr = 0; /* don't print errors */
|
|
c = getopt_long(argc, argv, "+hi:cf:", long_options, NULL);
|
|
if (c == -1)
|
|
break;
|
|
|
|
switch (c) {
|
|
case 'h':
|
|
print_usage(false);
|
|
break;
|
|
|
|
case 'i':
|
|
imageSize = strtoull(optarg, NULL, 10);
|
|
if (strchr(optarg, 'G') || strchr(optarg, 'g'))
|
|
imageSize *= 1024 * 1024 * 1024;
|
|
else if (strchr(optarg, 'M') || strchr(optarg, 'm'))
|
|
imageSize *= 1024 * 1024;
|
|
else if (strchr(optarg, 'K') || strchr(optarg, 'k'))
|
|
imageSize *= 1024;
|
|
break;
|
|
|
|
case 'f':
|
|
file = optarg;
|
|
break;
|
|
|
|
case 'c':
|
|
clearImage = true;
|
|
break;
|
|
|
|
default:
|
|
print_usage(true);
|
|
}
|
|
}
|
|
|
|
if (file == NULL && optind == argc - 1)
|
|
file = argv[optind];
|
|
|
|
if (!imageSize || !file)
|
|
print_usage(true);
|
|
|
|
if (imageSize < 0) {
|
|
fprintf(stderr, "Error: invalid image size\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (imageSize % 512) {
|
|
fprintf(stderr, "Error: image size must be a multiple of 512 bytes\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int fd = open(file, O_RDWR | O_CREAT, 0666);
|
|
if (fd < 0) {
|
|
fprintf(stderr, "Error: couldn't open file %s (%s)\n", file,
|
|
strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
struct stat st;
|
|
if (fstat(fd, &st) < 0) {
|
|
fprintf(stderr, "Error: stat()ing file %s failed (%s)\n", file,
|
|
strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) {
|
|
fprintf(stderr, "Error: type of file %s not supported\n", file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (S_ISREG(st.st_mode)) {
|
|
// regular file -- use ftruncate() to resize it
|
|
if ((clearImage && ftruncate(fd, 0) != 0)
|
|
|| ftruncate(fd, imageSize) != 0) {
|
|
fprintf(stderr, "Error: resizing file %s failed (%s)\n", file,
|
|
strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} else {
|
|
// some kind of device -- clear it manually, if we have to
|
|
if (clearImage) {
|
|
char buffer[1024 * 1024];
|
|
memset(buffer, 0, sizeof(buffer));
|
|
|
|
off_t totalWritten = 0;
|
|
ssize_t written;
|
|
while ((written = write(fd, buffer, sizeof(buffer))) > 0)
|
|
totalWritten += written;
|
|
|
|
// Only fail, if an error occurs and we haven't written anything at
|
|
// all yet.
|
|
// TODO: We should probably first determine the size of the device
|
|
// and try to write only that much.
|
|
if (totalWritten == 0 && written < 0) {
|
|
fprintf(stderr, "Error: writing to device file %s failed "
|
|
"(%s)\n", file, strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
}
|
|
|
|
close(fd);
|
|
return 0;
|
|
}
|