1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright (c) 2018 by Delphix. All rights reserved.
14 */
15
16 #include <sys/types.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 static int bsize = 0;
25 static int count = 0;
26 static char *ifile = NULL;
27 static char *ofile = NULL;
28 static off_t stride = 0;
29 static off_t seek = 0;
30 static const char *execname = "stride_dd";
31
32 static void usage(void);
33 static void parse_options(int argc, char *argv[]);
34
35 static void
36 usage(void)
37 {
38 (void) fprintf(stderr,
39 "usage: %s -i inputfile -o outputfile -b blocksize -c count \n"
40 " -s stride [ -k seekblocks]\n"
41 "\n"
42 "Simplified version of dd that supports the stride option.\n"
43 "A stride of n means that for each block written, n - 1 blocks\n"
44 "are skipped in both the input and output file. A stride of 1\n"
45 "means that blocks are read and written consecutively.\n"
46 "All numeric parameters must be integers.\n"
47 "\n"
48 " inputfile: File to read from\n"
49 " outputfile: File to write to\n"
50 " blocksize: Size of each block to read/write\n"
51 " count: Number of blocks to read/write\n"
52 " stride: Read/write a block then skip (stride - 1) blocks\n"
53 " seekblocks: Number of blocks to skip at start of output\n",
54 execname);
55 (void) exit(1);
56 }
57
58 static void
59 parse_options(int argc, char *argv[])
60 {
61 int c;
62 int errflag = 0;
63
64 execname = argv[0];
65
66 extern char *optarg;
67 extern int optind, optopt;
68
69 while ((c = getopt(argc, argv, ":b:c:i:o:s:k:")) != -1) {
70 switch (c) {
71 case 'b':
72 bsize = atoi(optarg);
73 break;
74
75 case 'c':
76 count = atoi(optarg);
77 break;
78
79 case 'i':
80 ifile = optarg;
81 break;
82
83 case 'o':
84 ofile = optarg;
85 break;
86
87 case 's':
88 stride = atoi(optarg);
89 break;
90
91 case 'k':
92 seek = atoi(optarg);
93 break;
94
95 case ':':
96 (void) fprintf(stderr,
97 "Option -%c requires an operand\n", optopt);
98 errflag++;
99 break;
100
101 case '?':
102 default:
103 (void) fprintf(stderr,
104 "Unrecognized option: -%c\n", optopt);
105 errflag++;
106 break;
107 }
108
109 if (errflag) {
110 (void) usage();
111 }
112 }
113
114 if (bsize <= 0 || count <= 0 || stride <= 0 || ifile == NULL ||
115 ofile == NULL || seek < 0) {
116 (void) fprintf(stderr,
117 "Required parameter(s) missing or invalid.\n");
118 (void) usage();
119 }
120 }
121
122 int
123 main(int argc, char *argv[])
124 {
125 int i;
126 int ifd;
127 int ofd;
128 void *buf;
129 int c;
130
131 parse_options(argc, argv);
132
133 ifd = open(ifile, O_RDONLY);
134 if (ifd == -1) {
135 (void) fprintf(stderr, "%s: %s: ", execname, ifile);
136 perror("open");
137 exit(2);
138 }
139
140 ofd = open(ofile, O_WRONLY | O_CREAT, 0666);
141 if (ofd == -1) {
142 (void) fprintf(stderr, "%s: %s: ", execname, ofile);
143 perror("open");
144 exit(2);
145 }
146
147 /*
148 * We use valloc because some character block devices expect a
149 * page-aligned buffer.
150 */
151 int err = posix_memalign(&buf, 4096, bsize);
152 if (err != 0) {
153 (void) fprintf(stderr,
154 "%s: %s\n", execname, strerror(err));
155 exit(2);
156 }
157
158 if (seek > 0) {
159 if (lseek(ofd, seek * bsize, SEEK_CUR) == -1) {
160 perror("output lseek");
161 exit(2);
162 }
163 }
164
165 for (i = 0; i < count; i++) {
166 c = read(ifd, buf, bsize);
167 if (c != bsize) {
168
169 perror("read");
170 exit(2);
171 }
172 if (c != bsize) {
173 if (c < 0) {
174 perror("read");
175 } else {
176 (void) fprintf(stderr,
177 "%s: unexpected short read, read %d "
178 "bytes, expected %d\n", execname,
179 c, bsize);
180 }
181 exit(2);
182 }
183
184 c = write(ofd, buf, bsize);
185 if (c != bsize) {
186 if (c < 0) {
187 perror("write");
188 } else {
189 (void) fprintf(stderr,
190 "%s: unexpected short write, wrote %d "
191 "bytes, expected %d\n", execname,
192 c, bsize);
193 }
194 exit(2);
195 }
196
197 if (stride > 1) {
198 if (lseek(ifd, (stride - 1) * bsize, SEEK_CUR) == -1) {
199 perror("input lseek");
200 exit(2);
201 }
202 if (lseek(ofd, (stride - 1) * bsize, SEEK_CUR) == -1) {
203 perror("output lseek");
204 exit(2);
205 }
206 }
207 }
208 free(buf);
209
210 (void) close(ofd);
211 (void) close(ifd);
212
213 return (0);
214 }
Cache object: 1a469b29bdd3f8e4dfb41310290ae13d
|