Adding upstream version 6.02~pre8+dfsg.
[syslinux-debian/hramrach.git] / com32 / modules / cptime.c
blob0f5ffe61bbb5dd9e87a07c950753cb38f7636ec9
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)
22 * -v Verbose output
23 * -q Quiet output
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
29 * Hisory:
30 * 1.4 Use fread() rather than read(); use CLK_TCK when available.
31 * 1.3 Added -v/-q; rework some argument processing.
32 * 1.2 Added -n
33 * 1.1 Added -l and -b switches; more flexible command line processing
34 * 1.0 First release
38 * ToDos:
39 * - Refine timing to be more precise. Low priority.
40 * - Add -o for offset. Wishlist.
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <unistd.h>
48 #include <sys/times.h>
49 #include <consoles.h>
50 #include <minmax.h>
51 #include <limits.h>
52 #include <string.h>
53 #include <stdint.h>
54 #include <console.h>
56 #ifdef __COM32__
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 */
64 # define TPS_T float
65 # ifdef CLK_TCK
66 static inline TPS_T get_tps(void) { return CLK_TCK; }
67 # else
68 static inline TPS_T get_tps(void) { return 18.2; }
69 # endif
71 #else /* __COM32__ */
73 # define BUFSZ_DEF (size_t)16384
74 /* Need to check what might be a "best" buffer/fetch block size here */
76 # define TPS_T long
77 static inline TPS_T get_tps(void) { return sysconf(_SC_CLK_TCK); }
79 #endif /* __COM32__ */
81 #ifndef SSIZE_MAX
82 # define SSIZE_MAX PTRDIFF_MAX
83 #endif
84 /* typedef ptrdiff_t ssize_t; */
85 #define BUFSZ_MAX (size_t)SSIZE_MAX
86 /* ssize_t 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))
92 #define TYPE_MAX(t) \
93 ((t) (! TYPE_SIGNED (t) \
94 ? (t) -1 \
95 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
97 #ifndef OFF_T_MAX
98 # define OFF_T_MAX TYPE_MAX(off_t)
99 #endif
100 /* Can't be SIZE_MAX or SSIZE_MAX as Syslinux/COM32 is unsigned while Linux
101 * is signed.
104 #define LEN_MAX OFF_T_MAX
105 /* 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)
110 size_t dr;
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)
118 TPS_T tps;
119 if (do_verbose > 2)
120 printf("Enter print_cp_result_long()\n");
121 tps = get_tps();
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)
131 if (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)
142 // int fd;
143 int rv = 0;
144 int i = 0;
145 FILE *f;
146 size_t bufsz, bcnt = 0;
147 int numrd;
148 struct tms tm;
149 clock_t bc, ec;
150 char buf[ibufsz + 1];
152 buf[0] = 0;
153 if (do_verbose)
154 printf("Trying file '%s'\n", fn);
155 errno = 0;
156 // fd = open(fn, O_RDONLY);
157 f = fopen(fn, "r");
158 // if (fd == -1) {
159 if (!f) {
160 switch (errno) {
161 case ENOENT :
162 printf("File '%s' does not exist\n", fn);
163 break;
164 case EBADF:
165 printf("File '%s': Bad File Descriptor\n", fn);
166 break;
167 default :
168 printf("Error '%d' opening file '%s'\n", errno, fn);
170 rv = 1;
171 } else {
172 if (do_verbose)
173 printf("File '%s' opened\n", fn);
174 bufsz = time_copy_bufsz(ibufsz, bcnt, maxlen);
175 bc = times(&tm);
176 // numrd = read(fd, buf, bufsz);
177 // numrd = fread(buf, bufsz, 1, f);
178 numrd = fread(buf, 1, bufsz, f);
179 i++;
180 if (numrd > 0)
181 bcnt = numrd;
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);
187 i++;
188 if (numrd >= 0)
189 // bcnt = bcnt + numrd;
190 bcnt += numrd;
192 ec = times(&tm);
193 // close(fd);
194 fclose(f);
195 if (do_verbose)
196 printf("File '%s' closed\n", fn);
197 if (numrd < 0) {
198 switch (errno) {
199 case EIO :
200 printf("IO Error at %zu B reading file '%s'\n", bcnt, fn);
201 break;
202 case EINVAL :
203 printf("Invalid Mode at %zu B reading file '%s'\n", bcnt, fn);
204 break;
205 default :
206 printf("Error '%d' at %zu B reading file '%s'\n", errno, bcnt, fn);
208 rv = 2;
210 if (bcnt > 0) {
211 if (bufsz == 0)
212 printf("maxed out on maxln\n");
213 if (do_simple)
214 print_cp_result_simple(fn, bcnt, bc, ec, ibufsz, do_verbose);
215 else
216 print_cp_result_long(fn, bcnt, bc, ec, ibufsz, do_verbose);
218 if (do_verbose)
219 printf(" numrd %d bcnt %d bufsz %d i %d\n", numrd, bcnt, bufsz, i);
221 return rv;
222 } /* int time_copy(char *fn, char do_simple, int bufsz, off_t maxlen) */
224 int main(int argc, char *argv[])
226 int i;
227 char do_simple = 0, do_pbuf = 0, do_plen = 0, do_verbose = 0;
228 char *arg;
229 size_t tbufsz, bufsz = min((BUFSZ_DEF), (BUFSZ_MAX));
230 off_t tmaxlen, maxlen = LEN_MAX;
231 int numfl = 0;
232 console_ansi_std();
233 // openconsole(&dev_stdcon_r, &dev_stdcon_w);
234 for (i = 1; i < argc; i++) {
235 if (argv[i][0] == '-') {
236 arg = argv[i] + 1;
237 if (strcmp(arg, "b") == 0) {
238 i++;
239 if (i < argc) {
240 tbufsz = atoi(argv[i]);
241 if (tbufsz > 0)
242 bufsz = min(max((BUFSZ_MIN), tbufsz), (BUFSZ_MAX));
243 do_pbuf = 1;
245 } else if (strcmp(arg, "n") == 0) {
246 i++;
247 if (i < argc) {
248 tmaxlen = atoi(argv[i]);
249 if (tmaxlen > 0)
250 maxlen = min(max((LEN_MIN), tmaxlen), (LEN_MAX));
251 do_plen = 1;
253 } else if (strcmp(arg, "s") == 0)
254 do_simple = 1;
255 else if (strcmp(arg, "l") == 0)
256 do_simple = 0;
257 else if (strcmp(arg, "v") == 0)
258 do_verbose = 1;
259 else if (strcmp(arg, "q") == 0)
260 do_verbose = 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] == '-') {
269 arg = argv[i] + 1;
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);
274 numfl++;
276 } else {
277 time_copy(argv[i], do_simple, do_verbose, bufsz, maxlen);
278 numfl++;
281 if (numfl == 0)
282 fprintf(stderr, "%s: Please specify a file\n", argv[0]);
283 return 0;
284 } /* int main(int argc, char *argv[]) */