home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / unix / sysv386 / 12480 < prev    next >
Encoding:
Text File  |  1992-07-26  |  18.5 KB  |  609 lines

  1. Newsgroups: comp.unix.sysv386
  2. Path: sparky!uunet!cs.utexas.edu!csc.ti.com!tilde.csc.ti.com!m2.dseg.ti.com!ernest!alan
  3. From: alan@ernest.dseg.ti.com (Alan Edmonds)
  4. Subject: ddd (was Re: Getting a tape drive to stream...)
  5. Organization: Texas Instruments, Inc. - Plano, Tx
  6. Date: Mon, 27 Jul 1992 05:29:18 GMT
  7. Message-ID: <Bs18Ku.9H2@ernest.dseg.ti.com>
  8. Keywords: ddd archive
  9. References: <2065@aegis.or.jp> <1992Jul25.223756.15177@stade.co.uk> <2172@aegis.or.jp>
  10. Lines: 597
  11.  
  12. In article <2172@aegis.or.jp> davidg@aegis.or.jp (Dave McLane) writes:
  13. >Some people said they were going to post a buffer program but it's 
  14. >never appeared that I know of.
  15.  
  16. I think you mean ddd.
  17. Ask and ye shall receive...
  18.  
  19. Newsgroups: comp.sources.unix
  20. Subject: v15i084:  Fast, multi-process dd(1) clone
  21. Message-ID: <974@fig.bbn.com>
  22. Date: 6 Jul 88 20:45:07 GMT
  23. Approved: rsalz@uunet.UU.NET
  24.  
  25. Submitted-by: Tapani Lindgren <nispa@cs.hut.fi>
  26. Posting-number: Volume 15, Issue 84
  27. Archive-name: ddd
  28.  
  29. Hi!  I wrote a little utility to speed up dumping to tape.
  30. It is a subset of dd(1), but has a much better throughput.
  31. I call it "ddd" for "Douple-speed DD".
  32. I posted it to eunet.sources about a month ago; a bug and
  33. some portability problems were found, but they are corrected
  34. in this second version.
  35. I planned to add some features and port the thing to Minix,
  36. but I won't have time bofere October, so it seems I've better
  37. post it now, as it is, and let others play with it too.
  38. See man page for details.
  39.  
  40. Tapani Lindgren                              | Email <nispa@cs.hut.fi> or
  41. Helsinki University of Technology            | <nispa@finhutcs.BITNET> or
  42. Laboratory of Information Processing Science | <mcvax!santra!sauna!nispa>
  43.  
  44. ------- CUT HERE ------- OUCH! -------
  45. #! /bin/sh
  46. # This is a shell archive.  Remove anything before this line, then unpack
  47. # it by saving it into a file and typing "sh file".  To overwrite existing
  48. # files, type "sh file -c".  You can also feed this as standard input via
  49. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  50. # will see the following message at the end:
  51. #               "End of shell archive."
  52. # Contents:  README ddd.1 Makefile ddd.c
  53. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  54. if test -f README -a "${1}" != "-c" ; then
  55.   echo shar: Will not over-write existing file \"README\"
  56. else
  57. echo shar: Extracting \"README\" \(506 characters\)
  58. sed "s/^X//" >README <<'END_OF_README'
  59. XDDD     DOUBLE-SPEED DATA DUMPER
  60. X
  61. XDdd is a stripped-down enhanced-throughput multi-process dd(1) clone.
  62. X
  63. XThis is version 2.  It has some bugs fixed.  The code is also cleaner
  64. Xand more portable.  Forget about version 1 and destroy all copies of it.
  65. X(version 1 is the set of files _without_ version numbers...)
  66. X
  67. XSee man page and source for details.
  68. X
  69. XFUTURE PROJECETS:
  70. XImplement skip, files, count and seek opitions,
  71. Xas well as noerror and swab conversions.
  72. XSupport for multivolume files - replace bundle(1).
  73. END_OF_README
  74. if test 506 -ne `wc -c <README`; then
  75.     echo shar: \"README\" unpacked with wrong size!
  76. fi
  77. # end of overwriting check
  78. fi
  79. if test -f ddd.1 -a "${1}" != "-c" ; then
  80.   echo shar: Will not over-write existing file \"ddd.1\"
  81. else
  82. echo shar: Extracting \"ddd.1\" \(2332 characters\)
  83. sed "s/^X//" >ddd.1 <<'END_OF_ddd.1'
  84. X.TH DDD 1L
  85. X.SH NAME
  86. Xddd \- double-speed data dumper
  87. X.SH SYNOPSIS
  88. X.B ddd [option=value] ...
  89. X.SH DESCRIPTION
  90. X.IR Ddd
  91. Xworks almost the same way as dd(1), but it has a much better
  92. Xthroughput, especially when used with slow i/o-devices, such as
  93. Xtape drives.  The improvement is achieved mainly by dividing
  94. Xthe copying process into two processes, one of which reads while
  95. Xthe other one writes and vice versa.  Also all code conversion
  96. Xcapabilities are omitted.  There is no additional overhead copying
  97. Xdata between various conversion buffers.
  98. X
  99. XDdd was inspired by the vast difference in speed between BSD4.2 and
  100. XBSD4.3 dumps - in BSD4.3 dump(8) uses alternating processes to write
  101. Xto raw magnetic tape, thus keeping the tape continuously in motion.
  102. XI wanted to get the same improvement to remote dumps, so this
  103. Xfilter was needed.  Directing all physical I/O through ddd usually
  104. Xincreases the throughput of any pipeline of unix commands
  105. X(if you have enough MIPS and RAM to handle two extra processes).
  106. X.SH OPTIONS
  107. XDdd uses options if, of, ibs and obs exactly as dd(1).  Option bs can
  108. Xalso be used to specify ibs and obs at once.  One option differs slightly
  109. Xin meaning: cbs can be used to specify the size of the internal buffer.
  110. XInput and output processes will swap duties when cbs bytes have been
  111. Xtransferred.  Default values for all sizes are 512 bytes.
  112. XAs with dd(1), letters k (kilobyte), b (block) or w (word) can be
  113. Xappended to size values.
  114. XOther options are not provided.
  115. X.SH HINTS
  116. XFor best performance, block sizes should be rather large.  For magnetic
  117. Xtape, I use obs=100b and cbs=500b or so.  Large block sizes (~100b) are
  118. Xalso effective for network connections.  However, cbs should be small
  119. Xenough for all the data to fit in core, since page faults add
  120. Xoverhead.
  121. X.SH AUTHOR
  122. XTapani Lindgren <nispa@cs.hut.fi>
  123. X.br
  124. XLaboratory of Information Processing Science
  125. X.br
  126. XHelsinki University of Technology
  127. X.br
  128. XFinland
  129. X.SH SEE ALSO
  130. Xdd(1), tar(1), dump(8)
  131. X.SH BUGS
  132. XShould you find one, let me know!
  133. X.SH WARNING
  134. X(Applies to U.S. residents & citizens only)
  135. X.br
  136. XDo not use this program!  Get rid of it as soon as you can!
  137. XIt will probably corrupt all your data, break down your computer
  138. Xand cause severe injury to the operators.
  139. XEven reading the source code may give you a headache.
  140. XI warned you!  I will take no responsibility whatsoever!
  141. END_OF_ddd.1
  142. if test 2332 -ne `wc -c <ddd.1`; then
  143.     echo shar: \"ddd.1\" unpacked with wrong size!
  144. fi
  145. # end of overwriting check
  146. fi
  147. if test -f Makefile -a "${1}" != "-c" ; then
  148.   echo shar: Will not over-write existing file \"Makefile\"
  149. else
  150. echo shar: Extracting \"Makefile\" \(605 characters\)
  151. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  152. X# Makefile for ddd
  153. X
  154. XDEFS = -DBSD
  155. XCFLAGS = -O $(DEFS)
  156. X
  157. XCC = cc
  158. XLINT = lint
  159. XCP = cp
  160. XRM = /bin/rm -f
  161. X
  162. XSRC = ddd.c
  163. XOBJ = ddd.o
  164. XHEAD =
  165. XBIN = ddd
  166. XSHAR = ddd.shar
  167. X
  168. XBINDIR = /usr/local/bin
  169. X
  170. XMAN = ddd.1
  171. XMANDIR = /usr/local/man
  172. X
  173. Xall: $(BIN) lint
  174. X       touch all
  175. X
  176. X$(BIN): $(OBJ) $(HEAD) Makefile
  177. X       $(CC) $(OBJ) -o $(BIN)
  178. X
  179. Xlint: $(SRC) $(HEAD)
  180. X       $(LINT) $(DEFS) $(SRC)
  181. X       touch lint
  182. X
  183. Xinstall: all
  184. X       strip $(BIN)
  185. X       $(CP) $(BIN) $(BINDIR)
  186. X       $(CP) $(MAN) $(MANDIR)
  187. X
  188. Xclean:
  189. X       -$(RM) $(BIN) $(OBJ) all lint a.out core *~ #* $(SHAR)
  190. X
  191. Xshar: lint README $(MAN) Makefile $(HEAD $(SRC)
  192. X       shar README $(MAN) Makefile $(HEAD) $(SRC) > $(SHAR)
  193. END_OF_Makefile
  194. if test 605 -ne `wc -c <Makefile`; then
  195.     echo shar: \"Makefile\" unpacked with wrong size!
  196. fi
  197. # end of overwriting check
  198. fi
  199. if test -f ddd.c -a "${1}" != "-c" ; then
  200.   echo shar: Will not over-write existing file \"ddd.c\"
  201. else
  202. echo shar: Extracting \"ddd.c\" \(10706 characters\)
  203. sed "s/^X//" >ddd.c <<'END_OF_ddd.c'
  204. X/*
  205. X * ddd.c - double dd (version 2)
  206. X *
  207. X * Copyright 1988 Helsinki University of Technology.
  208. X * All rights reserved.
  209. X *
  210. X * Permission granted to distribute, use and modify
  211. X * this code for uncommercial purposes, provided
  212. X * that this copyright notice is not changed.
  213. X *
  214. X * Author: Tapani Lindgren (nispa@cs.hut.fi)
  215. X *
  216. X * Ddd is a dd clone that operates as two processes;
  217. X * one process reads while the other one writes and vice versa.
  218. X * This way the throughput may be up to twice as good as that of dd,
  219. X * especially with slow devices such as tape drives.
  220. X *
  221. X * ***** WARNING ***** (For U.S. residents & citizens only)
  222. X *
  223. X * Do not use this program!  Get rid of it as soon as you can!
  224. X * It will probably corrupt all your data, break down your computer
  225. X * and cause severe injury to the operators.
  226. X * Even reading the source code may give you a headache.
  227. X * I warned you!  I will take no responsibility whatsoever!
  228. X */
  229. X
  230. X/* declarations common to all unix versions */
  231. X#include <stdio.h>     /* for fprintf() and stderr() */
  232. X#include <signal.h>    /* for SIGTERM */
  233. Xextern char *malloc();
  234. X
  235. X/* version dependent declarations */
  236. X
  237. X#ifdef BSD
  238. X#include <sys/wait.h>  /* for union wait */
  239. X#include <sys/file.h>  /* for O_RDONLY and O_WRONLY */
  240. Xextern char *sprintf();
  241. X#endif
  242. X
  243. X#ifdef SYSV
  244. X#include <fcntl.h>     /* for O_RDONLY and O_WRONLY */
  245. Xvoid exit();
  246. Xvoid perror();
  247. X#endif
  248. X
  249. X
  250. X
  251. X/* macros to find min or max of two values */
  252. X#define min(a,b) ((a)<(b)? (a): (b))
  253. X#define max(a,b) ((a)>(b)? (a): (b))
  254. X
  255. X/* inherited file descriptors */
  256. X#define STDIN 0
  257. X#define STDOUT 1
  258. X
  259. X/* boolean values */
  260. X#define FALSE 0
  261. X#define TRUE 1
  262. X
  263. X/* pipes have a read end and a write end */
  264. X#define P_REND 0
  265. X#define P_WEND 1
  266. X
  267. X/* there are two pipes; one for read tokens and one for write tokens */
  268. X#define RTOK_P 0
  269. X#define WTOK_P 1
  270. X
  271. X/* token bytes passed along pipes */
  272. X#define TOK_CONT 0     /* go ahead */
  273. X#define TOK_DONE 1     /* end of data */
  274. X#define TOK_ERROR 2    /* something's wrong, you've better stop now */
  275. X
  276. X/* input/output full/short record counters are in a table;
  277. X indexes defined below */
  278. X#define FULLIN 0
  279. X#define SHORTIN 1
  280. X#define FULLOUT 2
  281. X#define SHORTOUT 3
  282. X
  283. X/* defaults */
  284. X#define DEFBS 512      /* default block size */
  285. X
  286. X/* forward declarations */
  287. Xint doerror();
  288. X
  289. X/* global variables */
  290. Xstatic int
  291. X  ifd, ofd,    /* input/output file descriptors */
  292. X  ibs, obs,    /* input/output block sizes */
  293. X  cbs, /* "conversion" buffer size */
  294. X  pid, /* pid of child (in parent) or 0 (in child) */
  295. X  eof = FALSE, /* have we encountered end-of-file */
  296. X  pipefd[2][2],        /* read/write fd's for 2 pipes */
  297. X  counters[4] = {0, 0, 0, 0},  /* input/output full/short record counters */
  298. X  buflen;      /* count of characters read into buffer */
  299. Xstatic char
  300. X  *buffer;     /* address of buffer */
  301. X
  302. X
  303. Xmain(argc, argv)
  304. Xint argc;
  305. Xchar *argv[];
  306. X{
  307. X  (void) catchsignals();       /* prepare for interrupts etc */
  308. X  (void) setdefaults();        /* set default values for parameters */
  309. X  (void) parsearguments(argc, argv);   /* parse arguments */
  310. X  (void) initbuffer(); /* initialize buffer */
  311. X  (void) inittokens(); /* create one READ and one WRITE token */
  312. X  (void) dofork();     /* 1 will be 2 */
  313. X  while (!eof) {       /* enter main loop */
  314. X    (void) gettoken(RTOK_P);   /* compete for first/next read turn */
  315. X    (void) readbuffer();       /* fill buffer with input */
  316. X    (void) gettoken(WTOK_P);   /* make sure we also get the next write turn */
  317. X    /* now others may read if they wish (and if there's any data left */
  318. X    (void) passtoken(RTOK_P, eof? TOK_DONE: TOK_CONT);
  319. X    (void) writebuffer();      /* ... while we write to output */
  320. X    /* this cycle is done now */
  321. X    if (!eof) (void) passtoken(WTOK_P, TOK_CONT);
  322. X  }    /* end of main loop */
  323. X  (void) passcounters(RTOK_P); /* send record counters to our partner */
  324. X  (void) terminate(0); /* and exit (no errors) */
  325. X  /* NOTREACHED */
  326. X}      /* end of main() */
  327. X
  328. X
  329. Xcatchsignals()
  330. X/* arrange for some signals to be catched, so that statistics can be printed */
  331. X{
  332. X  static int siglist[] = {
  333. X    SIGINT, SIGQUIT, SIGILL, SIGFPE,
  334. X    SIGBUS, SIGSEGV, SIGSYS, SIGPIPE,
  335. X    SIGALRM, SIGTERM, 0
  336. X    };
  337. X  int *sigp;
  338. X
  339. X  for (sigp = siglist; *sigp != 0; sigp++)
  340. X    (void) signal(*sigp, doerror);
  341. X}      /* end of catchsignals() */
  342. X
  343. Xdoerror()
  344. X/* what we do if we get an error or catch a signal */
  345. X{
  346. X  /* send error token to both pipes */
  347. X  (void) passtoken(RTOK_P, TOK_ERROR);
  348. X  (void) passtoken(WTOK_P, TOK_ERROR);
  349. X  /* also send i/o record counters */
  350. X  (void) passcounters(RTOK_P);
  351. X  (void) passcounters(RTOK_P);
  352. X  /* terminate with error status */
  353. X  (void) terminate(1);
  354. X}
  355. X
  356. Xterminate(stat)
  357. Xint stat;
  358. X{
  359. X  /* parent will try to wait for child */
  360. X#ifdef BSD
  361. X  if (pid) (void) wait((union wait *) 0);
  362. X#endif
  363. X#ifdef SYSV
  364. X  if (pid) (void) wait((int *) 0);
  365. X#endif
  366. X
  367. X  exit(stat);
  368. X}
  369. X
  370. Xsetdefaults()
  371. X/* set default values */
  372. X{
  373. X  ifd = STDIN;
  374. X  ofd = STDOUT;
  375. X  ibs = obs = DEFBS;   /* block sizes */
  376. X  cbs = 0;     /* initially; will be set to max(ibs, obs, cbs) */
  377. X}
  378. X
  379. Xparsearguments(argc, argv)
  380. Xint argc;
  381. Xchar *argv[];
  382. X  /* parse arguments */
  383. X{
  384. X  /* constant strings "array" for recognizing options */
  385. X  static struct {
  386. X    char *IF, *OF, *CBS, *IBS, *OBS, *BS, *NOTHING;
  387. X  } consts = {
  388. X    "if=", "of=", "cbs=", "ibs=", "obs=", "bs=", ""
  389. X    };
  390. X  char **constp;       /* const structure pointer */
  391. X
  392. X  for (argc--, argv++; argc > 0; argc--, argv++) {
  393. X    constp = (char **) &consts;
  394. X    while (**constp && strncmp(*argv, *constp, strlen(*constp)))
  395. X      constp++;
  396. X    /* constp now points to one of the pointers in consts structure */
  397. X    *argv += strlen(*constp);  /* skip the constant part of the argument */
  398. X    if (constp == &consts.IF) {        /* open another file for input */
  399. X      ifd = open(*argv, O_RDONLY);
  400. X      if (ifd < 0) perror (*argv);
  401. X    } else if (constp == &consts.OF) {
  402. X      ofd = open(*argv, O_WRONLY | O_CREAT);   /* open file for output */
  403. X      if (ofd < 0) perror (*argv);
  404. X    } else if (constp == &consts.CBS) {        /* set buffer size */
  405. X      cbs = evalopt(*argv);
  406. X    } else if (constp == &consts.IBS) {        /* set input block size */
  407. X      ibs = evalopt(*argv);
  408. X    } else if (constp == &consts.OBS) {        /* set output block size */
  409. X      obs = evalopt(*argv);
  410. X    } else if (constp == &consts.BS) { /* set input and output block sizes */
  411. X      ibs = obs = evalopt(*argv);
  412. X    } else {
  413. X      (void) fprintf(stderr,
  414. X                    "usage: ddd [if=name] [of=name] [bs=n] [ibs=n obs=n]\n");
  415. X      exit(1);
  416. X    }
  417. X  } /* end of for loop */
  418. X} /* end of parsearguments() */
  419. X
  420. Xevalopt(p) /* return numerical value of string */
  421. Xchar *p;
  422. X{
  423. X  int temp = 0;
  424. X
  425. X  for ( ; *p >= '0' && *p <= '9'; p++)
  426. X    temp = temp * 10 + *p - '0';
  427. X  if (temp < 1) {
  428. X    (void) fprintf(stderr, "ddd: illegal size option\n");
  429. X    exit(1);
  430. X  }
  431. X  switch (*p) {
  432. X  case '\0':
  433. X    return(temp);
  434. X  case 'w':
  435. X  case 'W':
  436. X    return(temp << 2); /* 4-byte words */
  437. X  case 'b':
  438. X  case 'B':
  439. X    return(temp << 9); /* 512-byte blocks */
  440. X  case 'k':
  441. X  case 'K':
  442. X    return(temp << 10);        /* kilobytes */
  443. X  default:
  444. X    (void) fprintf(stderr, "ddd: bad size option\n");
  445. X    exit(1);
  446. X  }
  447. X  /* NOTREACHED */
  448. X}      /* end of evalopt() */
  449. X
  450. Xinitbuffer()
  451. X/* initialize buffer */
  452. X{
  453. X  cbs = max(cbs, max(ibs, obs));       /* determine buffer size */
  454. X  if (cbs % ibs || cbs % obs) {
  455. X    (void) fprintf(stderr, "ddd: warning: incompatible block/buffer sizes\n");
  456. X  }
  457. X  buffer = malloc((unsigned) cbs);
  458. X  if (buffer == NULL) {
  459. X    (void) perror("ddd: cannot allocate buffer");
  460. X    exit(1);
  461. X  }
  462. X}      /* end of initbuffer() */
  463. X
  464. Xinittokens()
  465. X/* initialize token passing system with 2 pipes */
  466. X{
  467. X  if(pipe(pipefd[RTOK_P]) < 0 || pipe(pipefd[WTOK_P]) < 0) {
  468. X    (void) perror("ddd: cannot create token pipes");
  469. X    exit(1);
  470. X  }
  471. X  /* create initial tokens */
  472. X  (void) passtoken(RTOK_P, TOK_CONT);
  473. X  (void) passtoken(WTOK_P, TOK_CONT);
  474. X}      /* end of inittokens() */
  475. X
  476. Xpasstoken(pipenum, token)
  477. Xint pipenum;
  478. Xchar token;
  479. X/* pass a token to a pipe */
  480. X{
  481. X  if (write(pipefd[pipenum][P_WEND], &token, 1) < 1) {
  482. X    (void) perror("ddd: cannot write token to pipe");
  483. X    exit(1);
  484. X  }
  485. X}      /* end of passtoken() */
  486. X
  487. Xgettoken(pipenum)
  488. Xint pipenum;
  489. X/* wait to read a token from the pipe; also see if we should stop */
  490. X{
  491. X  char tokenbuf;
  492. X
  493. X  if (read(pipefd[pipenum][P_REND], &tokenbuf, 1) < 1) {
  494. X    (void) perror("ddd: cannot read token from pipe");
  495. X    exit(1);
  496. X  }
  497. X  if (tokenbuf != TOK_CONT) {  /* we did not get what we wanted */
  498. X    (void) getcounters(pipenum);       /* report record counters */
  499. X    terminate(tokenbuf == TOK_DONE);   /* TOK_DONE means no error */
  500. X  }
  501. X}      /* end of gettoken() */
  502. X
  503. Xpasscounters(pipenum)
  504. Xint pipenum;
  505. X/* pass read/write counters to the other process */
  506. X{
  507. X  if (write(pipefd[pipenum][P_WEND], (char *) counters,
  508. X           sizeof(counters)) < sizeof(counters)) {
  509. X    (void) perror("ddd: cannot write counters to pipe");
  510. X    exit(1);
  511. X  }
  512. X}
  513. X
  514. Xgetcounters(pipenum)
  515. Xint pipenum;
  516. X/* report input/output record counts */
  517. X{
  518. X  int hiscounters[4];
  519. X
  520. X  if (read(pipefd[pipenum][P_REND], (char *) hiscounters,
  521. X          sizeof(hiscounters)) < sizeof(hiscounters)) {
  522. X    (void) perror("ddd: cannot read counters from pipe");
  523. X    exit(1);
  524. X  }
  525. X  (void) fprintf(stderr,
  526. X                "%d+%d records in\n%d+%d records out\n",
  527. X                counters[FULLIN] + hiscounters[FULLIN],
  528. X                counters[SHORTIN] + hiscounters[SHORTIN],
  529. X                counters[FULLOUT] + hiscounters[FULLOUT],
  530. X                counters[SHORTOUT] + hiscounters[SHORTOUT]
  531. X                );
  532. X}      /* end of printcounters() */
  533. X
  534. Xdofork()
  535. X/* fork into 2 processes */
  536. X{
  537. X  if ((pid = fork()) < 0) {
  538. X    (void) perror("ddd: warning: cannot fork");
  539. X    /* But continue and do our job anyway, as regular dd */
  540. X  }
  541. X}
  542. X
  543. Xreadbuffer()
  544. X/* read buffer from input */
  545. X{
  546. X  int iolen, ioresult;
  547. X
  548. X  buflen = 0;
  549. X  while (buflen < cbs && !eof) {
  550. X    iolen = min(ibs, cbs - buflen);
  551. X#ifdef BSD
  552. X    ioresult = read(ifd, &buffer[buflen], iolen);
  553. X#endif
  554. X#ifdef SYSV
  555. X    ioresult = read(ifd, &buffer[buflen], (unsigned) iolen);
  556. X#endif
  557. X    if (ioresult == 0) {       /* end of file */
  558. X      eof = TRUE;
  559. X    } else if (ioresult < 0) {
  560. X      (void) perror("ddd: read error");
  561. X      (void) doerror();
  562. X    }
  563. X    buflen += ioresult;        /* update current count of chars in buffer */
  564. X    /* if we got any data, update appropriate input record count */
  565. X    if (ioresult > 0) counters[(ioresult == ibs)? FULLIN: SHORTIN]++;
  566. X  }
  567. X}      /* end of readbuffer() */
  568. X
  569. Xwritebuffer()
  570. X/* writing phase */
  571. X{
  572. X  int ocount, iolen, ioresult;
  573. X
  574. X  ocount = 0;  /* count of chars written */
  575. X  while (ocount < buflen) {
  576. X    iolen = min(obs, buflen - ocount);
  577. X#ifdef BSD
  578. X    ioresult = write(ofd, &buffer[ocount], iolen);
  579. X#endif
  580. X#ifdef SYSV
  581. X    ioresult = write(ofd, &buffer[ocount], (unsigned) iolen);
  582. X#endif
  583. X    if (ioresult < iolen) {
  584. X      perror("ddd: write error");
  585. X      (void) doerror();
  586. X    }
  587. X    ocount += ioresult;
  588. X    /* count output records */
  589. X    counters[(ioresult == obs)? FULLOUT: SHORTOUT]++;
  590. X  }
  591. X}      /* end of writebuffer() */
  592. END_OF_ddd.c
  593. if test 10706 -ne `wc -c <ddd.c`; then
  594.     echo shar: \"ddd.c\" unpacked with wrong size!
  595. fi
  596. # end of overwriting check
  597. fi
  598. echo shar: End of shell archive.
  599. exit 0
  600.  
  601. -- 
  602. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  603.  
  604. -- 
  605. Alan Edmonds                                     Texas Instruments, Inc.
  606. I don't speak for TI; TI doesn't speak for me    M/S 8513
  607. Work phone: (214)575-6427                        6620 Chase Oaks Blvd.
  608. Email: alan@ernest.dseg.ti.com                   Plano, Texas  75023
  609.