echo: Added echo
[mutos-utils.git] / dd.c
blobff156951846f9de742c7b64a9323e3a084aead18
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>
22 #include <sys/types.h>
23 #include <sys/stat.h>
25 #define VERSION "0.01"
27 int main(int argc, char* argv[])
29 char* input_path = NULL;
30 char* output_path = NULL;
31 uint64_t bs = 512;
32 uint32_t bs_modifier = 1;
33 unsigned int count = 0;
34 unsigned int r_in = 0;
35 unsigned int r_out = 0;
37 // flag parsing
38 int arg = 0;
39 for (arg = 1; arg < argc; arg++)
41 if (strstr(argv[arg], "if=")) {
42 input_path = strstr(argv[arg], "if=") + strlen("if=");
43 } else if (strstr(argv[arg], "of=")) {
44 output_path = strstr(argv[arg], "of=") + strlen("of=");
45 } else if (strstr(argv[arg], "bs=")) {
46 char* bs_value = strstr(argv[arg], "bs=") + strlen("bs=");
47 char bs_unit = bs_value[strlen(bs_value) - 1];
48 // if last character isn't a digit
49 if (!isdigit(bs_unit)) {
50 switch(bs_unit)
52 case 'k':
53 case 'K':
54 bs_modifier = 1024;
55 break;
56 case 'm':
57 case 'M':
58 bs_modifier = 1024 * 1024;
59 break;
60 case 'g':
61 case 'G':
62 bs_modifier = 1024 * 1024 * 1024;
63 break;
64 default:
65 fprintf(stderr, "%s: invalid unit: '%c'\n",
66 argv[0], bs_unit);
67 return 1;
69 printf("%c\n", bs_unit);
70 // delete the unit, leaving just the number
71 bs_value[strlen(bs_value) - 1] = '\0';
74 // validate input
75 for (size_t i = 0; i < strlen(bs_value); i++)
77 if (!isdigit(bs_value[i])) {
78 fprintf(stderr, "%s: invalid number: '%s'\n",
79 argv[0], bs_value);
80 return 1;
84 bs = atoi(bs_value);
85 if (bs == 0) {
86 fprintf(stderr, "%s: invalid number: '%zu'\n",
87 argv[0], bs);
88 return 1;
91 } else if (strstr(argv[arg], "count=")) {
92 char* count_value = strstr(argv[arg], "count=") + strlen("count=");
94 // validate input
95 for (size_t i = 0; i < strlen(count_value); i++)
97 if (!isdigit(count_value[i])) {
98 fprintf(stderr, "%s: invalid number: '%s'\n",
99 argv[0], count_value);
100 return 1;
104 count = atoi(count_value);
105 if (count == 0) {
106 fprintf(stderr, "0+0 records in\n"
107 "0+0 records out\n"
108 "0 bytes (0 B) copied\n");
109 return 0;
111 } else if (strcmp("--help", argv[arg]) == 0 || strcmp("-h", argv[arg]) == 0) {
112 printf("Usage: %s\n", argv[0]);
113 printf("[delim] must be a character and [field] starts at 1.\n"
114 "\n"
115 " -h, --help Print this message.\n"
116 " -v, --version Show version info.\n");
117 return 0;
118 } else if (strcmp("--version", argv[arg]) == 0 || strcmp("-v", argv[arg]) == 0) {
119 printf("dd (mutos) v"VERSION"\n");
120 return 0;
121 } else {
122 // no more flags left
123 break;
127 FILE* input_file = NULL;
128 FILE* output_file = NULL;
130 int rc = 0;
132 if (!input_path || strcmp(input_path, "-") == 0) {
133 input_file = stdin;
134 } else {
135 struct stat input_stat;
136 rc = stat(input_path, &input_stat);
137 if (rc < 0) {
138 fprintf(stderr, "%s: %s: %s\n",
139 argv[0], strerror(errno), input_path);
140 return 1;
142 input_file = fopen(input_path, "r");
145 if (!input_file) {
146 fprintf(stderr, "%s: %s: %s\n",
147 argv[0], strerror(errno), input_path);
148 return 1;
151 if (!output_path) {
152 output_file = stdout;
153 } else {
154 struct stat output_stat;
155 rc = stat(output_path, &output_stat);
156 if (rc < 0 && errno != ENOENT) {
157 fprintf(stderr, "%s: %s: %s\n",
158 argv[0], strerror(errno), input_path);
159 return 1;
161 output_file = fopen(output_path, "w");
164 if (!output_file) {
165 fprintf(stderr, "%s: %s: %s\n",
166 argv[0], strerror(errno), output_path);
167 return 1;
170 int c = '\0';
171 int bytes = 0;
173 c = fgetc(input_file);
174 while (c != EOF)
176 bytes++;
177 if (bytes % (bs*bs_modifier) == 0) {
178 r_in++;
180 fputc(c, output_file);
181 if (bytes % (bs*bs_modifier) == 0) {
182 r_out++;
184 c = fgetc(input_file);
187 fprintf(stderr, "%d+0 records in\n"
188 "%d+0 records out\n"
189 "%d bytes copied\n",
190 r_in, r_out, bytes);
191 return 0;