Fix FreeBSD build.
[haiku.git] / src / tools / create_image.cpp
blobcec280e19a0ec1d072e597d8f8b6a76cffa87ae7
1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2007, Marcus Overhagen. All Rights Reserved.
4 * Distributed under the terms of the MIT License.
5 */
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <getopt.h>
10 #include <limits.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
18 #define EXIT_FAILURE 1
21 static void
22 print_usage(bool error)
24 printf("\n");
25 printf("create_image\n");
26 printf("\n");
27 printf("usage: create_image -i <imagesize> [-c] [-f] <file>\n");
28 printf(" -i, --imagesize size of raw partition image file\n");
29 printf(" -f, --file the raw partition image file\n");
30 printf(" -c, --clear-image set the image content to zero\n");
31 exit(error ? EXIT_FAILURE : 0);
35 int
36 main(int argc, char *argv[])
38 off_t imageSize = 0;
39 const char *file = NULL;
40 bool clearImage = false;
42 while (1) {
43 int c;
44 static struct option long_options[] = {
45 {"file", required_argument, 0, 'f'},
46 {"clear-image", no_argument, 0, 'c'},
47 {"help", no_argument, 0, 'h'},
48 {"imagesize", required_argument, 0, 'i'},
49 {0, 0, 0, 0}
52 opterr = 0; /* don't print errors */
53 c = getopt_long(argc, argv, "+hi:cf:", long_options, NULL);
54 if (c == -1)
55 break;
57 switch (c) {
58 case 'h':
59 print_usage(false);
60 break;
62 case 'i':
63 imageSize = strtoull(optarg, NULL, 10);
64 if (strchr(optarg, 'G') || strchr(optarg, 'g'))
65 imageSize *= 1024 * 1024 * 1024;
66 else if (strchr(optarg, 'M') || strchr(optarg, 'm'))
67 imageSize *= 1024 * 1024;
68 else if (strchr(optarg, 'K') || strchr(optarg, 'k'))
69 imageSize *= 1024;
70 break;
72 case 'f':
73 file = optarg;
74 break;
76 case 'c':
77 clearImage = true;
78 break;
80 default:
81 print_usage(true);
85 if (file == NULL && optind == argc - 1)
86 file = argv[optind];
88 if (!imageSize || !file)
89 print_usage(true);
91 if (imageSize < 0) {
92 fprintf(stderr, "Error: invalid image size\n");
93 exit(EXIT_FAILURE);
96 if (imageSize % 512) {
97 fprintf(stderr, "Error: image size must be a multiple of 512 bytes\n");
98 exit(EXIT_FAILURE);
101 int fd = open(file, O_RDWR | O_CREAT, 0666);
102 if (fd < 0) {
103 fprintf(stderr, "Error: couldn't open file %s (%s)\n", file,
104 strerror(errno));
105 exit(EXIT_FAILURE);
108 struct stat st;
109 if (fstat(fd, &st) < 0) {
110 fprintf(stderr, "Error: stat()ing file %s failed (%s)\n", file,
111 strerror(errno));
112 exit(EXIT_FAILURE);
115 if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) {
116 fprintf(stderr, "Error: type of file %s not supported\n", file);
117 exit(EXIT_FAILURE);
120 if (S_ISREG(st.st_mode)) {
121 // regular file -- use ftruncate() to resize it
122 if ((clearImage && ftruncate(fd, 0) != 0)
123 || ftruncate(fd, imageSize) != 0) {
124 fprintf(stderr, "Error: resizing file %s failed (%s)\n", file,
125 strerror(errno));
126 exit(EXIT_FAILURE);
128 } else {
129 // some kind of device -- clear it manually, if we have to
130 if (clearImage) {
131 char buffer[1024 * 1024];
132 memset(buffer, 0, sizeof(buffer));
134 off_t totalWritten = 0;
135 ssize_t written;
136 while ((written = write(fd, buffer, sizeof(buffer))) > 0)
137 totalWritten += written;
139 // Only fail, if an error occurs and we haven't written anything at
140 // all yet.
141 // TODO: We should probably first determine the size of the device
142 // and try to write only that much.
143 if (totalWritten == 0 && written < 0) {
144 fprintf(stderr, "Error: writing to device file %s failed "
145 "(%s)\n", file, strerror(errno));
146 exit(EXIT_FAILURE);
151 close(fd);
152 return 0;