chmod: Added default case in option parsing
[mutos-utils.git] / dd.c
blob320a210c5bf348f4ffcac3671a687012f197e7b1
1 /*
2 Copyright © 2013 Alastair Stuart
4 This program is open source software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdint.h>
18 #include <ctype.h>
19 #include <stdlib.h>
20 #include <errno.h>
21 #include <inttypes.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
26 #define VERSION "0.01"
28 int main(int argc, char* argv[])
30 char* input_path = NULL;
31 char* output_path = NULL;
32 uint64_t bs = 512;
33 uint32_t bs_modifier = 1;
34 unsigned int count = 0;
35 unsigned int r_in = 0;
36 unsigned int r_out = 0;
38 // flag parsing
39 int arg = 0;
40 for (arg = 1; arg < argc; arg++)
42 if (strstr(argv[arg], "if=")) {
43 input_path = strstr(argv[arg], "if=") + strlen("if=");
44 } else if (strstr(argv[arg], "of=")) {
45 output_path = strstr(argv[arg], "of=") + strlen("of=");
46 } else if (strstr(argv[arg], "bs=")) {
47 char* bs_value = strstr(argv[arg], "bs=") + strlen("bs=");
48 char bs_unit = bs_value[strlen(bs_value) - 1];
49 // if last character isn't a digit
50 if (!isdigit(bs_unit)) {
51 switch(bs_unit)
53 case 'k':
54 case 'K':
55 bs_modifier = 1024;
56 break;
57 case 'm':
58 case 'M':
59 bs_modifier = 1024 * 1024;
60 break;
61 case 'g':
62 case 'G':
63 bs_modifier = 1024 * 1024 * 1024;
64 break;
65 default:
66 fprintf(stderr, "%s: invalid unit: '%c'\n",
67 argv[0], bs_unit);
68 return 1;
70 printf("%c\n", bs_unit);
71 // delete the unit, leaving just the number
72 bs_value[strlen(bs_value) - 1] = '\0';
75 // validate input
76 for (size_t i = 0; i < strlen(bs_value); i++)
78 if (!isdigit(bs_value[i])) {
79 fprintf(stderr, "%s: invalid number: '%s'\n",
80 argv[0], bs_value);
81 return 1;
85 bs = atoi(bs_value);
86 if (bs == 0) {
87 fprintf(stderr, "%s: invalid number: '%"PRIu64"'\n",
88 argv[0], bs);
89 return 1;
92 } else if (strstr(argv[arg], "count=")) {
93 char* count_value = strstr(argv[arg], "count=") + strlen("count=");
95 // validate input
96 for (size_t i = 0; i < strlen(count_value); i++)
98 if (!isdigit(count_value[i])) {
99 fprintf(stderr, "%s: invalid number: '%s'\n",
100 argv[0], count_value);
101 return 1;
105 count = atoi(count_value);
106 if (count == 0) {
107 fprintf(stderr, "0+0 records in\n"
108 "0+0 records out\n"
109 "0 bytes (0 B) copied\n");
110 return 0;
112 } else if (strcmp("--help", argv[arg]) == 0 || strcmp("-h", argv[arg]) == 0) {
113 printf("Usage: %s\n", argv[0]);
114 printf("[delim] must be a character and [field] starts at 1.\n"
115 "\n"
116 " -h, --help Print this message.\n"
117 " -v, --version Show version info.\n");
118 return 0;
119 } else if (strcmp("--version", argv[arg]) == 0 || strcmp("-v", argv[arg]) == 0) {
120 printf("dd (mutos) v"VERSION"\n");
121 return 0;
122 } else {
123 // no more flags left
124 break;
128 FILE* input_file = NULL;
129 FILE* output_file = NULL;
131 int rc = 0;
133 if (!input_path || strcmp(input_path, "-") == 0) {
134 input_file = stdin;
135 } else {
136 struct stat input_stat;
137 rc = stat(input_path, &input_stat);
138 if (rc < 0) {
139 fprintf(stderr, "%s: %s: %s\n",
140 argv[0], strerror(errno), input_path);
141 return 1;
143 input_file = fopen(input_path, "r");
146 if (!input_file) {
147 fprintf(stderr, "%s: %s: %s\n",
148 argv[0], strerror(errno), input_path);
149 return 1;
152 if (!output_path) {
153 output_file = stdout;
154 } else {
155 struct stat output_stat;
156 rc = stat(output_path, &output_stat);
157 if (rc < 0 && errno != ENOENT) {
158 fprintf(stderr, "%s: %s: %s\n",
159 argv[0], strerror(errno), input_path);
160 return 1;
162 output_file = fopen(output_path, "w");
165 if (!output_file) {
166 fprintf(stderr, "%s: %s: %s\n",
167 argv[0], strerror(errno), output_path);
168 return 1;
171 int c = '\0';
172 int bytes = 0;
174 c = fgetc(input_file);
175 while (c != EOF)
177 bytes++;
178 if (bytes % (bs*bs_modifier) == 0) {
179 r_in++;
181 fputc(c, output_file);
182 if (bytes % (bs*bs_modifier) == 0) {
183 r_out++;
185 c = fgetc(input_file);
188 fprintf(stderr, "%d+0 records in\n"
189 "%d+0 records out\n"
190 "%d bytes copied\n",
191 r_in, r_out, bytes);
192 return 0;