1 /* DASDCOPY.C (c) Copyright Roger Bowler, 1999-2010 */
2 /* Copy a dasd file to another dasd file */
3
4 /*-------------------------------------------------------------------*/
5 /* This program copies a dasd file to another dasd file. */
6 /* Input file and output file may be compressed or not. */
7 /* Files may be either ckd (or cckd) or fba (or cfba) but */
8 /* file types (ckd/cckd or fba/cfba) may not be mixed. */
9 /* */
10 /* Usage: */
11 /* dasdcopy [-options] ifile [sf=sfile] ofile */
12 /* */
13 /* Refer to the usage section below for details of options. */
14 /* */
15 /* The program may also be invoked by one of the following */
16 /* aliases which override the default output file format: */
17 /* */
18 /* ckd2cckd [-options] ifile ofile */
19 /* cckd2ckd [-options] ifile [sf=sfile] ofile */
20 /* fba2cfba [-options] ifile ofile */
21 /* cfba2fba [-options] ifile [sf=sfile] ofile */
22 /*-------------------------------------------------------------------*/
23
24 #include "hstdinc.h"
25
26 #include "hercules.h"
27 #include "dasdblks.h"
28 #include "devtype.h"
29 #include "opcode.h"
30
31 #define FBA_BLKGRP_SIZE (120 * 512) /* Size of block group */
32 #define FBA_BLKS_PER_GRP 120 /* Blocks per group */
33
34 int syntax (char *);
35 void status (int, int);
36 int nulltrk(BYTE *, int, int, int);
37
38 #define CKD 0x01
39 #define CCKD 0x02
40 #define FBA 0x04
41 #define CFBA 0x08
42 #define CKDMASK 0x03
43 #define FBAMASK 0x0c
44 #define COMPMASK 0x0a
45
46 /*-------------------------------------------------------------------*/
47 /* Copy a dasd file to another dasd file */
48 /*-------------------------------------------------------------------*/
main(int argc,char * argv[])49 int main (int argc, char *argv[])
50 {
51 char *pgm; /* -> Program name */
52 int ckddasd=-1; /* 1=CKD 0=FBA */
53 int rc; /* Return code */
54 int quiet=0; /* 1=Don't display status */
55 int comp=255; /* Compression algorithm */
56 int cyls=-1, blks=-1; /* Size of output file */
57 int lfs=0; /* 1=Create 1 large file */
58 int alt=0; /* 1=Create alt cyls */
59 int r=0; /* 1=Replace output file */
60 int in=0, out=0; /* Input/Output file types */
61 int fd; /* Input file descriptor */
62 char *ifile, *ofile; /* -> Input/Output file names*/
63 char *sfile=NULL; /* -> Input shadow file name */
64 CIFBLK *icif, *ocif; /* -> Input/Output CIFBLK */
65 DEVBLK *idev, *odev; /* -> Input/Output DEVBLK */
66
67 CKDDEV *ckd=NULL; /* -> CKD device table entry */
68 FBADEV *fba=NULL; /* -> FBA device table entry */
69 int i, n, max; /* Loop index, limits */
70 BYTE unitstat; /* Device unit status */
71 char msgbuf[512]; /* Message buffer */
72 size_t fba_bytes_remaining=0; /* FBA bytes to be copied */
73 int nullfmt = CKDDASD_NULLTRK_FMT0; /* Null track format */
74 char pathname[MAX_PATH]; /* file path in host format */
75 char pgmpath[MAX_PATH]; /* prog path in host format */
76
77 INITIALIZE_UTILITY("dasdcopy");
78
79 /* Figure out processing based on the program name */
80 hostpath(pgmpath, argv[0], sizeof(pgmpath));
81 pgm = strrchr (pgmpath, '/');
82 if (pgm) pgm++;
83 else pgm = argv[0];
84 strtok (pgm, ".");
85 if (strcmp(pgm, "ckd2cckd") == 0)
86 {
87 in = CKD;
88 out = CCKD;
89 }
90 else if (strcmp(pgm, "cckd2ckd") == 0)
91 {
92 in = CCKD;
93 out = CKD;
94 }
95 else if (strcmp(pgm, "fba2cfba") == 0)
96 {
97 in = FBA;
98 out = CFBA;
99 }
100 else if (strcmp(pgm, "cfba2fba") == 0)
101 {
102 in = CFBA;
103 out = FBA;
104 }
105
106 /* Process the arguments */
107 for (argc--, argv++ ; argc > 0 ; argc--, argv++)
108 {
109 if (argv[0][0] != '-') break;
110 if (strcmp(argv[0], "-v") == 0)
111 {
112 snprintf (msgbuf, 512, _("Hercules %s copy program "), pgm);
113 display_version (stderr, msgbuf, FALSE);
114 return 0;
115 }
116 else if (strcmp(argv[0], "-h") == 0)
117 {
118 syntax(pgm);
119 return 0;
120 }
121 else if (strcmp(argv[0], "-q") == 0
122 || strcmp(argv[0], "-quiet") == 0)
123 quiet = 1;
124 else if (strcmp(argv[0], "-r") == 0)
125 r = 1;
126 #ifdef CCKD_COMPRESS_ZLIB
127 else if (strcmp(argv[0], "-z") == 0)
128 comp = CCKD_COMPRESS_ZLIB;
129 #endif
130 #ifdef CCKD_COMPRESS_BZIP2
131 else if (strcmp(argv[0], "-bz2") == 0)
132 comp = CCKD_COMPRESS_BZIP2;
133 #endif
134 else if (strcmp(argv[0], "-0") == 0)
135 comp = CCKD_COMPRESS_NONE;
136 else if ((strcmp(argv[0], "-cyl") == 0
137 || strcmp(argv[0], "-cyls") == 0) && cyls < 0)
138 {
139 if (argc < 2 || (cyls = atoi(argv[1])) < 0)
140 return syntax(pgm);
141 argc--; argv++;
142 }
143 else if ((strcmp(argv[0], "-blk") == 0
144 || strcmp(argv[0], "-blks") == 0) && blks < 0)
145 {
146 if (argc < 2 || (blks = atoi(argv[1])) < 0)
147 return syntax(pgm);
148 argc--; argv++;
149 }
150 else if (strcmp(argv[0], "-a") == 0
151 || strcmp(argv[0], "-alt") == 0
152 || strcmp(argv[0], "-alts") == 0)
153 alt = 1;
154 else if (strcmp(argv[0], "-lfs") == 0)
155 lfs = 1;
156 else if (out == 0 && strcmp(argv[0], "-o") == 0)
157 {
158 if (argc < 2 || out != 0) return syntax(pgm);
159 if (strcasecmp(argv[1], "ckd") == 0)
160 out = CKD;
161 else if (strcasecmp(argv[1], "cckd") == 0)
162 out = CCKD;
163 else if (strcasecmp(argv[1], "fba") == 0)
164 out = FBA;
165 else if (strcasecmp(argv[1], "cfba") == 0)
166 out = CFBA;
167 else
168 return syntax(pgm);
169 argc--; argv++;
170 }
171 else
172 return syntax(pgm);
173 }
174
175 /* Get the file names:
176 input-file [sf=shadow-file] output-file */
177 if (argc < 2 || argc > 3) return syntax(pgm);
178 ifile = argv[0];
179 if (argc < 3)
180 ofile = argv[1];
181 else
182 {
183 if (strlen(argv[1]) < 4 || memcmp(argv[1], "sf=", 3))
184 return syntax(pgm);
185 sfile = argv[1];
186 ofile = argv[2];
187 }
188
189 /* If we don't know what the input file is then find out */
190 if (in == 0)
191 {
192 BYTE buf[8];
193 hostpath(pathname, ifile, sizeof(pathname));
194 fd = hopen(pathname, O_RDONLY|O_BINARY);
195 if (fd < 0)
196 {
197 fprintf (stderr, _("HHCDC001E %s: %s open error: %s\n"),
198 pgm, ifile, strerror(errno));
199 return -1;
200 }
201 rc = read (fd, buf, 8);
202 if (rc < 8)
203 {
204 fprintf (stderr, _("HHCDC002E %s: %s read error: %s\n"),
205 pgm, ifile, strerror(errno));
206 return -1;
207 }
208 if (memcmp(buf, "CKD_P370", 8) == 0)
209 in = CKD;
210 else if (memcmp(buf, "CKD_C370", 8) == 0)
211 in = CCKD;
212 else if (memcmp(buf, "FBA_C370", 8) == 0)
213 in = CFBA;
214 else
215 in = FBA;
216 close (fd);
217 }
218
219 /* If we don't know what the output file type is
220 then derive it from the input file type */
221 if (out == 0)
222 {
223 switch (in) {
224 case CKD: if (!lfs) out = CCKD;
225 else out = CKD;
226 break;
227 case CCKD: if (comp == 255) out = CKD;
228 else out = CCKD;
229 break;
230 case FBA: if (!lfs) out = CFBA;
231 else out = FBA;
232 break;
233 case CFBA: if (comp == 255) out = FBA;
234 else out = CFBA;
235 break;
236 }
237 }
238
239 /* Set default compression if out file is to be compressed */
240 if (comp == 255 && (out & COMPMASK))
241 #ifdef CCKD_COMPRESS_ZLIB
242 comp = CCKD_COMPRESS_ZLIB;
243 #else
244 comp = CCKD_COMPRESS_NONE;
245 #endif
246
247 /* Perform sanity checks on the options */
248 if ((in & CKDMASK) && !(out & CKDMASK)) return syntax(pgm);
249 if ((in & FBAMASK) && !(out & FBAMASK)) return syntax(pgm);
250 if (sfile && !(in & COMPMASK)) return syntax(pgm);
251 if (comp != 255 && !(out & COMPMASK)) return syntax(pgm);
252 if (lfs && (out & COMPMASK)) return syntax(pgm);
253 if (cyls >= 0 && !(in & CKDMASK)) return syntax(pgm);
254 if (blks >= 0 && !(in & FBAMASK)) return syntax(pgm);
255 if (!(in & CKDMASK) && alt) return syntax(pgm);
256
257 /* Set the type of processing (ckd or fba) */
258 ckddasd = (in & CKDMASK);
259
260 /* Open the input file */
261 if (ckddasd)
262 icif = open_ckd_image (ifile, sfile, O_RDONLY|O_BINARY, 0);
263 else
264 icif = open_fba_image (ifile, sfile, O_RDONLY|O_BINARY, 0);
265 if (icif == NULL)
266 {
267 fprintf (stderr, _("HHCDC003E %s: %s open failed\n"), pgm, ifile);
268 return -1;
269 }
270 idev = &icif->devblk;
271 if (idev->oslinux) nullfmt = CKDDASD_NULLTRK_FMT2;
272
273 /* Calculate the number of tracks or blocks to copy */
274 if (ckddasd)
275 {
276 if (cyls < 0) cyls = idev->ckdcyls;
277 else if (cyls == 0) cyls = (idev->hnd->used)(idev);
278 ckd = dasd_lookup (DASD_CKDDEV, NULL, idev->devtype, cyls);
279 if (ckd == NULL)
280 {
281 fprintf (stderr, _("HHCDC004E %s: ckd lookup failed for %4.4X "
282 "cyls %d\n"),
283 pgm, idev->devtype, cyls);
284 close_image_file (icif);
285 return -1;
286 }
287 // if (out == CCKD) cyls = ckd->cyls;
288 if (cyls <= ckd->cyls && alt) cyls = ckd->cyls + ckd->altcyls;
289 n = cyls * idev->ckdheads;
290 max = idev->ckdtrks;
291 if (max < n && out == CCKD) n = max;
292 }
293 else
294 {
295 fba_bytes_remaining = idev->fbanumblk * idev->fbablksiz;
296 if (blks < 0) blks = idev->fbanumblk;
297 else if (blks == 0) blks = (idev->hnd->used)(idev);
298 fba = dasd_lookup (DASD_FBADEV, NULL, idev->devtype, blks);
299 if (fba == NULL)
300 {
301 fprintf (stderr, _("HHCDC005E %s: fba lookup failed, blks %d\n"),
302 pgm, blks);
303 close_image_file (icif);
304 return -1;
305 }
306 n = blks;
307 max = idev->fbanumblk;
308 if (max < n && out == CFBA) n = max;
309 n = (n + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP;
310 max = (max + FBA_BLKS_PER_GRP - 1) / FBA_BLKS_PER_GRP;
311 }
312
313 /* Create the output file */
314 if (ckddasd)
315 rc = create_ckd(ofile, idev->devtype, idev->ckdheads,
316 ckd->r1, cyls, "", comp, lfs, 1+r, nullfmt, 0);
317 else
318 rc = create_fba(ofile, idev->devtype, fba->size,
319 blks, "", comp, lfs, 1+r, 0);
320 if (rc < 0)
321 {
322 fprintf (stderr, _("HHCDC006E %s: %s create failed\n"), pgm, ofile);
323 close_image_file (icif);
324 return -1;
325 }
326
327 /* Open the output file */
328 if (ckddasd)
329 ocif = open_ckd_image (ofile, NULL, O_RDWR|O_BINARY, 1);
330 else
331 ocif = open_fba_image (ofile, NULL, O_RDWR|O_BINARY, 1);
332 if (ocif == NULL)
333 {
334 fprintf (stderr, _("HHCDC007E %s: %s open failed\n"), pgm, ofile);
335 close_image_file (icif);
336 return -1;
337 }
338 odev = &ocif->devblk;
339
340 /* Copy the files */
341 #ifdef EXTERNALGUI
342 if (extgui)
343 /* Notify GUI of total #of tracks or blocks being copied... */
344 fprintf (stderr, "TRKS=%d\n", n);
345 else
346 #endif /*EXTERNALGUI*/
347 if (!quiet) printf (" %3d%% %7d of %d", 0, 0, n);
348 for (i = 0; i < n; i++)
349 {
350 /* Read a track or block */
351 if (ckddasd)
352 {
353 if (i < max)
354 rc = (idev->hnd->read)(idev, i, &unitstat);
355 else
356 {
357 memset (idev->buf, 0, idev->ckdtrksz);
358 rc = nulltrk(idev->buf, i, idev->ckdheads, nullfmt);
359 }
360 }
361 else
362 {
363 if (i < max)
364 rc = (idev->hnd->read)(idev, i, &unitstat);
365 else
366 memset (idev->buf, 0, FBA_BLKGRP_SIZE);
367 rc = 0;
368 }
369 if (rc < 0)
370 {
371 fprintf (stderr, _("HHCDC008E %s: %s read error %s %d "
372 "stat=%2.2X, null %s substituted\n"),
373 pgm, ifile, ckddasd ? "track" : "block", i, unitstat,
374 ckddasd ? "track" : "block");
375 if (ckddasd)
376 nulltrk(idev->buf, i, idev->ckdheads, nullfmt);
377 else
378 memset (idev->buf, 0, FBA_BLKGRP_SIZE);
379 if (!quiet)
380 {
381 printf (_(" %3d%% %7d of %d"), 0, 0, n);
382 status (i, n);
383 }
384 }
385
386 /* Write the track or block just read */
387 if (ckddasd)
388 {
389 rc = (odev->hnd->write)(odev, i, 0, idev->buf,
390 idev->ckdtrksz, &unitstat);
391 }
392 else
393 {
394 if (fba_bytes_remaining >= (size_t)idev->buflen)
395 {
396 rc = (odev->hnd->write)(odev, i, 0, idev->buf,
397 idev->buflen, &unitstat);
398 fba_bytes_remaining -= (size_t)idev->buflen;
399 }
400 else
401 {
402 ASSERT(fba_bytes_remaining > 0 && (i+1) >= n);
403 rc = (odev->hnd->write)(odev, i, 0, idev->buf,
404 (int)fba_bytes_remaining, &unitstat);
405 fba_bytes_remaining = 0;
406 }
407 }
408 if (rc < 0)
409 {
410 fprintf (stderr, _("HHCDC009E %s: %s write error %s %d "
411 "stat=%2.2X\n"),
412 pgm, ofile, ckddasd ? "track" : "block", i, unitstat);
413 close_image_file(icif); close_image_file(ocif);
414 return -1;
415 }
416
417 /* Update the status indicator */
418 if (!quiet) status (i+1, n);
419 }
420
421 close_image_file(icif); close_image_file(ocif);
422 if (!quiet) printf (_("\r"));
423 printf (_("HHCDC010I %s successfully completed.\n"), pgm);
424 return 0;
425 }
426
427 /*-------------------------------------------------------------------*/
428 /* Build a null track image */
429 /*-------------------------------------------------------------------*/
nulltrk(BYTE * buf,int trk,int heads,int nullfmt)430 int nulltrk(BYTE *buf, int trk, int heads, int nullfmt)
431 {
432 int i; /* Loop counter */
433 CKDDASD_TRKHDR *trkhdr; /* -> Track header */
434 CKDDASD_RECHDR *rechdr; /* -> Record header */
435 U32 cyl; /* Cylinder number */
436 U32 head; /* Head number */
437 BYTE r; /* Record number */
438 BYTE *pos; /* -> Next position in buffer*/
439 static BYTE eighthexFF[]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
440
441 /* cylinder and head calculations */
442 cyl = trk / heads;
443 head = trk % heads;
444
445 /* Build the track header */
446 trkhdr = (CKDDASD_TRKHDR*)buf;
447 trkhdr->bin = 0;
448 store_hw(&trkhdr->cyl, cyl);
449 store_hw(&trkhdr->head, head);
450 pos = buf + CKDDASD_TRKHDR_SIZE;
451
452 /* Build record zero */
453 r = 0;
454 rechdr = (CKDDASD_RECHDR*)pos;
455 pos += CKDDASD_RECHDR_SIZE;
456 store_hw(&rechdr->cyl, cyl);
457 store_hw(&rechdr->head, head);
458 rechdr->rec = r;
459 rechdr->klen = 0;
460 store_hw(&rechdr->dlen, 8);
461 pos += 8;
462 r++;
463
464 /* Specific null track formatting */
465 if (nullfmt == CKDDASD_NULLTRK_FMT0)
466 {
467 rechdr = (CKDDASD_RECHDR*)pos;
468 pos += CKDDASD_RECHDR_SIZE;
469
470 store_hw(&rechdr->cyl, cyl);
471 store_hw(&rechdr->head, head);
472 rechdr->rec = r;
473 rechdr->klen = 0;
474 store_hw(&rechdr->dlen, 0);
475 r++;
476 }
477 else if (nullfmt == CKDDASD_NULLTRK_FMT2)
478 {
479 for (i = 0; i < 12; i++)
480 {
481 rechdr = (CKDDASD_RECHDR*)pos;
482 pos += CKDDASD_RECHDR_SIZE;
483
484 store_hw(&rechdr->cyl, cyl);
485 store_hw(&rechdr->head, head);
486 rechdr->rec = r;
487 rechdr->klen = 0;
488 store_hw(&rechdr->dlen, 4096);
489 r++;
490
491 pos += 4096;
492 }
493 }
494
495 /* Build the end of track marker */
496 memcpy (pos, eighthexFF, 8);
497 pos += 8;
498
499 return 0;
500 }
501
502 /*-------------------------------------------------------------------*/
503 /* Display command syntax */
504 /*-------------------------------------------------------------------*/
syntax(char * pgm)505 int syntax (char *pgm)
506 {
507 char usage[8192];
508
509 if (strcmp(pgm, "ckd2cckd") == 0)
510 snprintf(usage,8192,_(
511 "usage: ckd2cckd [-options] ifile ofile\n"
512 "\n"
513 " copy a ckd dasd file to a compressed ckd dasd file\n"
514 "\n"
515 " ifile -- input ckd dasd file\n"
516 " ofile -- output compressed ckd dasd file\n"
517 "\n"
518 " options:\n"
519 " -v display program version and quit\n"
520 " -h display this help and quit\n"
521 " -q quiet mode, don't display status\n"
522 " -r replace the output file if it exists\n"
523 "%s"
524 "%s"
525 " -0 don't compress track images\n"
526 " -cyls n size of output file\n"
527 " -a output file will have alt cyls\n"
528 ),
529 #ifdef CCKD_COMPRESS_ZLIB
530 _(
531 " -z compress using zlib [default]\n"
532 ),
533 #else
534 "",
535 #endif
536 #ifdef CCKD_COMPRESS_BZIP2
537 _(
538 " -bz2 compress using bzip2\n"
539 )
540 #else
541 ""
542 #endif
543 );
544 else if (strcmp(pgm, "cckd2ckd") == 0)
545 snprintf(usage,8192,_(
546 "usage: cckd2ckd [-options] ifile [sf=sfile] ofile\n"
547 "\n"
548 " copy a compressed ckd file to a ckd file\n"
549 "\n"
550 " ifile -- input compressed ckd dasd file\n"
551 " sfile -- input compressed ckd shadow file\n"
552 " (optional)\n"
553 " ofile -- output ckd dasd file\n"
554 "\n"
555 " options:\n"
556 " -v display program version and quit\n"
557 " -h display this help and quit\n"
558 " -q quiet mode, don't display status\n"
559 " -r replace the output file if it exists\n"
560 "%s"
561 " -cyls n size of output file\n"
562 " -a output file will have alt cyls\n"
563 ),
564 (sizeof(off_t) > 4) ? _( " -lfs create single large output file\n" ) : ( "" )
565 );
566 else if (strcmp(pgm, "fba2cfba") == 0)
567 snprintf(usage,8192,_(
568 "usage: fba2cfba [-options] ifile ofile\n"
569 "\n"
570 " copy a fba dasd file to a compressed fba dasd file\n"
571 "\n"
572 " ifile -- input fba dasd file\n"
573 " ofile -- output compressed fba dasd file\n"
574 "\n"
575 " options:\n"
576 " -v display program version and quit\n"
577 " -h display this help and quit\n"
578 " -q quiet mode, don't display status\n"
579 " -r replace the output file if it exists\n"
580 "%s"
581 "%s"
582 " -0 don't compress track images\n"
583 " -blks n size of output file\n"
584 ),
585 #ifdef CCKD_COMPRESS_ZLIB
586 _(
587 " -z compress using zlib [default]\n"
588 ),
589 #else
590 "",
591 #endif
592 #ifdef CCKD_COMPRESS_BZIP2
593 _(
594 " -bz2 compress using bzip2\n"
595 )
596 #else
597 ""
598 #endif
599 );
600 else if (strcmp(pgm, "cfba2fba") == 0)
601 snprintf(usage,8192,_(
602 "usage: cfba2fba [-options] ifile [sf=sfile] ofile\n"
603 "\n"
604 " copy a compressed fba file to a fba file\n"
605 "\n"
606 " ifile -- input compressed fba dasd file\n"
607 " sfile -- input compressed fba shadow file\n"
608 " (optional)\n"
609 " ofile -- output fba dasd file\n"
610 "\n"
611 " options:\n"
612 " -v display program version and quit\n"
613 " -h display this help and quit\n"
614 " -q quiet mode, don't display status\n"
615 " -r replace the output file if it exists\n"
616 "%s"
617 " -blks n size of output file\n"
618 ),
619 (sizeof(off_t) > 4) ? _( " -lfs create single large output file\n" ) : ( "" )
620 );
621 else
622 snprintf(usage,8192,_(
623 "usage: %s [-options] ifile [sf=sfile] ofile\n"
624 "\n"
625 " copy a dasd file to another dasd file\n"
626 "\n"
627 " ifile -- input dasd file\n"
628 " sfile -- input shadow file [optional]\n"
629 " ofile -- output dasd file\n"
630 "\n"
631 " options:\n"
632 " -v display program version and quit\n"
633 " -h display this help and quit\n"
634 " -q quiet mode, don't display status\n"
635 " -r replace the output file if it exists\n"
636 "%s"
637 "%s"
638 " -0 don't compress output\n"
639 " -blks n size of output fba file\n"
640 " -cyls n size of output ckd file\n"
641 " -a output ckd file will have alt cyls\n"
642 "%s"
643 " even if it exceeds 2G in size\n"
644 " -o type output file type (CKD, CCKD, FBA, CFBA)\n"
645 ),
646 pgm,
647 #ifdef CCKD_COMPRESS_ZLIB
648 _(
649 " -z compress using zlib [default]\n"
650 ),
651 #else
652 "",
653 #endif
654 #ifdef CCKD_COMPRESS_BZIP2
655 _(
656 " -bz2 compress output using bzip2\n"
657 )
658 #else
659 ""
660 #endif
661 ,(sizeof(off_t) > 4) ? _( " -lfs output ckd file will be a single file\n" ) : ( "" )
662 );
663 printf ("%s", usage);
664 return -1;
665 } /* end function syntax */
666
667 /*-------------------------------------------------------------------*/
668 /* Display progress status */
669 /*-------------------------------------------------------------------*/
status(int i,int n)670 void status (int i, int n)
671 {
672 static char indic[] = "|/-\\";
673
674 #ifdef EXTERNALGUI
675 if (extgui)
676 {
677 if (i % 100) return;
678 fprintf (stderr, "TRK=%d\n", i);
679 return;
680 }
681 #endif /*EXTERNALGUI*/
682 // if (i % 101 != 1) return;
683 printf ("\r%c %3d%% %7d", indic[i%4], (int)((i*100.0)/n), i);
684 } /* end function status */
685