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
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.
13 * Copyright (c) 2018 by Delphix. All rights reserved.
16 #include <sys/types.h>
24 static int alignment
= 0;
27 static char *ifile
= NULL
;
28 static char *ofile
= NULL
;
29 static off_t stride
= 1;
30 static off_t seek
= 0;
31 static int seekbytes
= 0;
32 static int if_o_direct
= 0;
33 static int of_o_direct
= 0;
35 static int skipbytes
= 0;
36 static int entire_file
= 0;
37 static const char *execname
= "stride_dd";
39 static void usage(void);
40 static void parse_options(int argc
, char *argv
[]);
45 (void) fprintf(stderr
,
46 "usage: %s -i inputfile -o outputfile -b blocksize [-c count]\n"
47 " [-s stride] [-k seekblocks] [-K seekbytes]\n"
48 " [-a alignment] [-d if_o_direct] [-D of_o_direct]\n"
49 " [-p skipblocks] [-P skipbytes] [-e entire_file]\n"
51 "Simplified version of dd that supports the stride option.\n"
52 "A stride of n means that for each block written, n - 1 blocks\n"
53 "are skipped in both the input and output file. A stride of 1\n"
54 "means that blocks are read and written consecutively.\n"
55 "All numeric parameters must be integers.\n"
57 " inputfile: File to read from\n"
58 " outputfile: File to write to\n"
59 " blocksize: Size of each block to read/write\n"
60 " count: Number of blocks to read/write (Required"
61 " unless -e is used)\n"
62 " stride: Read/write a block then skip (stride - 1) blocks"
64 " seekblocks: Number of blocks to skip at start of output\n"
65 " seekbytes: Treat seekblocks as byte count\n"
66 " alignment: Alignment passed to posix_memalign() (default"
68 " if_o_direct: Use O_DIRECT with inputfile (default no O_DIRECT)"
70 " of_o_direct: Use O_DIRECT with outputfile (default no "
72 " skipblocks: Number of blocks to skip at start of input "
74 " skipbytes: Treat skipblocks as byte count\n"
75 " entire_file: When used the entire inputfile will be read and"
76 " count will be ignored\n",
82 * posix_memalign() only allows for alignments which are postive, powers of two
83 * and a multiple of sizeof (void *).
86 invalid_alignment(int alignment
)
88 if ((alignment
< 0) || (alignment
& (alignment
- 1)) ||
89 ((alignment
% sizeof (void *)))) {
90 (void) fprintf(stderr
,
91 "Alignment must be a postive, power of two, and multiple "
92 "of sizeof (void *).\n");
99 parse_options(int argc
, char *argv
[])
105 alignment
= sysconf(_SC_PAGE_SIZE
);
108 extern int optind
, optopt
;
110 while ((c
= getopt(argc
, argv
, "a:b:c:deDi:o:s:k:Kp:P")) != -1) {
113 alignment
= atoi(optarg
);
117 bsize
= atoi(optarg
);
121 count
= atoi(optarg
);
145 stride
= atoi(optarg
);
165 (void) fprintf(stderr
,
166 "Option -%c requires an operand\n", optopt
);
172 (void) fprintf(stderr
,
173 "Unrecognized option: -%c\n", optopt
);
183 if (bsize
<= 0 || stride
<= 0 || ifile
== NULL
|| ofile
== NULL
||
184 seek
< 0 || invalid_alignment(alignment
) || skip
< 0) {
185 (void) fprintf(stderr
,
186 "Required parameter(s) missing or invalid.\n");
190 if (count
<= 0 && entire_file
== 0) {
191 (void) fprintf(stderr
,
192 "Required parameter(s) missing or invalid.\n");
198 read_entire_file(int ifd
, int ofd
, void *buf
)
203 c
= read(ifd
, buf
, bsize
);
208 c
= write(ofd
, buf
, bsize
);
216 if (lseek(ifd
, (stride
- 1) * bsize
, SEEK_CUR
) == -1) {
217 perror("input lseek");
220 if (lseek(ofd
, (stride
- 1) * bsize
, SEEK_CUR
) == -1) {
221 perror("output lseek");
229 read_on_count(int ifd
, int ofd
, void *buf
)
234 for (i
= 0; i
< count
; i
++) {
235 c
= read(ifd
, buf
, bsize
);
240 (void) fprintf(stderr
,
241 "%s: unexpected short read, read %d "
242 "bytes, expected %d\n", execname
,
248 c
= write(ofd
, buf
, bsize
);
253 (void) fprintf(stderr
,
254 "%s: unexpected short write, wrote %d "
255 "bytes, expected %d\n", execname
,
262 if (lseek(ifd
, (stride
- 1) * bsize
, SEEK_CUR
) == -1) {
263 perror("input lseek");
266 if (lseek(ofd
, (stride
- 1) * bsize
, SEEK_CUR
) == -1) {
267 perror("output lseek");
275 main(int argc
, char *argv
[])
279 int ifd_flags
= O_RDONLY
;
280 int ofd_flags
= O_WRONLY
| O_CREAT
;
283 parse_options(argc
, argv
);
286 ifd_flags
|= O_DIRECT
;
289 ofd_flags
|= O_DIRECT
;
291 ifd
= open(ifile
, ifd_flags
);
293 (void) fprintf(stderr
, "%s: %s: ", execname
, ifile
);
298 ofd
= open(ofile
, ofd_flags
, 0666);
300 (void) fprintf(stderr
, "%s: %s: ", execname
, ofile
);
306 * We use valloc because some character block devices expect a
307 * page-aligned buffer.
309 int err
= posix_memalign(&buf
, alignment
, bsize
);
311 (void) fprintf(stderr
,
312 "%s: %s\n", execname
, strerror(err
));
317 int skipamt
= skipbytes
== 1 ? skip
: skip
* bsize
;
318 if (lseek(ifd
, skipamt
, SEEK_CUR
) == -1) {
319 perror("input lseek");
325 int seekamt
= seekbytes
== 1 ? seek
: seek
* bsize
;
326 if (lseek(ofd
, seekamt
, SEEK_CUR
) == -1) {
327 perror("output lseek");
332 if (entire_file
== 1)
333 read_entire_file(ifd
, ofd
, buf
);
335 read_on_count(ifd
, ofd
, buf
);