1 /* ----------------------------------------------------------------------- *
3 * Copyright 2010-2011 Gene Cumm
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 * Boston MA 02111-1307, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
14 * cptime.c Version 1.4
16 * Timed copy; read entire file then output total time, bytes transferred,
17 * and compute transfer rate.
19 * cptime [-s|-l] [-v|-q] [-b _SIZE_] [-n _LEN_] _FILE_...
20 * -s Change to simple output mode without computing transfer rate
21 * -l Change to long output mode (to allow for overriding previous -s)
24 * -b _SIZE_ use _SIZE_ for transfer size
25 * -n _LEN_ maximum length to fetch
26 * _FILE_... Space delimited list of files to dump
27 * Note: The last instance of -s or -l wins, along with the last use of -b and -n and the winning option will be applied to all operations
30 * 1.4 Use fread() rather than read(); use CLK_TCK when available.
31 * 1.3 Added -v/-q; rework some argument processing.
33 * 1.1 Added -l and -b switches; more flexible command line processing
39 * - Refine timing to be more precise. Low priority.
40 * - Add -o for offset. Wishlist.
48 #include <sys/times.h>
57 # define BUFSZ_DEF (size_t)2048
58 /* What's optimal? Under 4k?
59 * layout.inc: xfer_buf_seg equ 1000h
60 * com32.inc: push dword (1 << 16) ; 64K bounce buffer
62 /* typedef size_t off_t */
66 static inline TPS_T
get_tps(void) { return CLK_TCK
; }
68 static inline TPS_T
get_tps(void) { return 18.2; }
73 # define BUFSZ_DEF (size_t)16384
74 /* Need to check what might be a "best" buffer/fetch block size here */
77 static inline TPS_T
get_tps(void) { return sysconf(_SC_CLK_TCK
); }
79 #endif /* __COM32__ */
82 # define SSIZE_MAX PTRDIFF_MAX
84 /* typedef ptrdiff_t ssize_t; */
85 #define BUFSZ_MAX (size_t)SSIZE_MAX
87 #define BUFSZ_MIN (size_t)1
90 /* Please note: I don't know the origin of these two macros nor their license */
91 #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
93 ((t) (! TYPE_SIGNED (t) \
95 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
98 # define OFF_T_MAX TYPE_MAX(off_t)
100 /* Can't be SIZE_MAX or SSIZE_MAX as Syslinux/COM32 is unsigned while Linux
104 #define LEN_MAX OFF_T_MAX
106 #define LEN_MIN (off_t)0
108 void print_cp_result_tick(size_t bcnt
, clock_t et
, TPS_T tps
, int offs
)
111 /* prevent divide by 0 */
112 dr
= max(bcnt
, (bcnt
* tps
)) / max((clock_t)1, (et
+ offs
));
113 printf(" %+d %zu B/s; %zu KiB/s; %zu MiB/s\n", offs
, dr
, dr
/1024, dr
/1048576);
114 } /* void print_cp_result_tick(size_t bcnt, clock_t et, TPS_T tps, int offs) */
116 void print_cp_result_long(char *fn
, size_t bcnt
, clock_t bc
, clock_t ec
, size_t bufsz
, char do_verbose
)
120 printf("Enter print_cp_result_long()\n");
122 printf(" %zu B in %d ticks from '%s'\n", bcnt
, (int)(ec
- bc
), fn
);
123 printf(" ~%d ticks per second; %zu B block/transfer size\n", (int)tps
, bufsz
);
124 print_cp_result_tick(bcnt
, (ec
- bc
), tps
, 0);
125 print_cp_result_tick(bcnt
, (ec
- bc
), tps
, 1);
126 print_cp_result_tick(bcnt
, (ec
- bc
), tps
, -1);
127 } /* void print_cp_result_long(char *fn, size_t bcnt, clock_t bc, clock_t ec, size_t bufsz) */
129 void print_cp_result_simple(char *fn
, size_t bcnt
, clock_t bc
, clock_t ec
, size_t bufsz
, char do_verbose
)
132 printf(" %zuB %dt %zux '%s'\n", bcnt
, (int)(ec
- bc
), bufsz
, fn
);
133 } /* void print_cp_result_simple(char *fn, int bcnt, clock_t bc, clock_t ec, char do_verbose) */
135 size_t time_copy_bufsz(size_t bufsz
, size_t bcnt
, off_t maxlen
)
137 return min(bufsz
, (maxlen
- bcnt
));
138 } /* size_t time_copy_bufsz(size_t bufsz, size_t bcnt, off_t maxlen) */
140 int time_copy(char *fn
, char do_simple
, char do_verbose
, size_t ibufsz
, off_t maxlen
)
146 size_t bufsz
, bcnt
= 0;
150 char buf
[ibufsz
+ 1];
154 printf("Trying file '%s'\n", fn
);
156 // fd = open(fn, O_RDONLY);
162 printf("File '%s' does not exist\n", fn
);
165 printf("File '%s': Bad File Descriptor\n", fn
);
168 printf("Error '%d' opening file '%s'\n", errno
, fn
);
173 printf("File '%s' opened\n", fn
);
174 bufsz
= time_copy_bufsz(ibufsz
, bcnt
, maxlen
);
176 // numrd = read(fd, buf, bufsz);
177 // numrd = fread(buf, bufsz, 1, f);
178 numrd
= fread(buf
, 1, bufsz
, f
);
182 while ((numrd
> 0) && (bufsz
> 0)) {
183 bufsz
= time_copy_bufsz(bufsz
, bcnt
, maxlen
);
184 // numrd = read(fd, buf, bufsz);
185 // numrd = fread(buf, bufsz, 1, f);
186 numrd
= fread(buf
, 1, bufsz
, f
);
189 // bcnt = bcnt + numrd;
196 printf("File '%s' closed\n", fn
);
200 printf("IO Error at %zu B reading file '%s'\n", bcnt
, fn
);
203 printf("Invalid Mode at %zu B reading file '%s'\n", bcnt
, fn
);
206 printf("Error '%d' at %zu B reading file '%s'\n", errno
, bcnt
, fn
);
212 printf("maxed out on maxln\n");
214 print_cp_result_simple(fn
, bcnt
, bc
, ec
, ibufsz
, do_verbose
);
216 print_cp_result_long(fn
, bcnt
, bc
, ec
, ibufsz
, do_verbose
);
219 printf(" numrd %d bcnt %d bufsz %d i %d\n", numrd
, bcnt
, bufsz
, i
);
222 } /* int time_copy(char *fn, char do_simple, int bufsz, off_t maxlen) */
224 int main(int argc
, char *argv
[])
227 char do_simple
= 0, do_pbuf
= 0, do_plen
= 0, do_verbose
= 0;
229 size_t tbufsz
, bufsz
= min((BUFSZ_DEF
), (BUFSZ_MAX
));
230 off_t tmaxlen
, maxlen
= LEN_MAX
;
233 // openconsole(&dev_stdcon_r, &dev_stdcon_w);
234 for (i
= 1; i
< argc
; i
++) {
235 if (argv
[i
][0] == '-') {
237 if (strcmp(arg
, "b") == 0) {
240 tbufsz
= atoi(argv
[i
]);
242 bufsz
= min(max((BUFSZ_MIN
), tbufsz
), (BUFSZ_MAX
));
245 } else if (strcmp(arg
, "n") == 0) {
248 tmaxlen
= atoi(argv
[i
]);
250 maxlen
= min(max((LEN_MIN
), tmaxlen
), (LEN_MAX
));
253 } else if (strcmp(arg
, "s") == 0)
255 else if (strcmp(arg
, "l") == 0)
257 else if (strcmp(arg
, "v") == 0)
259 else if (strcmp(arg
, "q") == 0)
263 if (do_pbuf
|| do_verbose
)
264 printf("Using bufsz %zu\n", bufsz
);
265 if (do_plen
|| do_verbose
)
266 printf("Using maxlen %zu\n", maxlen
);
267 for (i
= 1; i
< argc
; i
++) {
268 if (argv
[i
][0] == '-') {
270 if ((strcmp(arg
, "b") == 0) || (strcmp(arg
, "n") == 0))
271 i
++; /* Skip next arg */
272 else if (!((strcmp(arg
, "s") == 0) || (strcmp(arg
, "l") == 0) || (strcmp(arg
, "v") == 0) || (strcmp(arg
, "q") == 0))) {
273 time_copy(argv
[i
], do_simple
, do_verbose
, bufsz
, maxlen
);
277 time_copy(argv
[i
], do_simple
, do_verbose
, bufsz
, maxlen
);
282 fprintf(stderr
, "%s: Please specify a file\n", argv
[0]);
284 } /* int main(int argc, char *argv[]) */