Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

790 lines
20 KiB

  1. /* $Source: /u/mark/src/pax/RCS/buffer.c,v $
  2. *
  3. * $Revision: 1.2 $
  4. *
  5. * buffer.c - Buffer management functions
  6. *
  7. * DESCRIPTION
  8. *
  9. * These functions handle buffer manipulations for the archiving
  10. * formats. Functions are provided to get memory for buffers,
  11. * flush buffers, read and write buffers and de-allocate buffers.
  12. * Several housekeeping functions are provided as well to get some
  13. * information about how full buffers are, etc.
  14. *
  15. * AUTHOR
  16. *
  17. * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  18. *
  19. * Sponsored by The USENIX Association for public distribution.
  20. *
  21. * Copyright (c) 1989 Mark H. Colburn.
  22. * All rights reserved.
  23. *
  24. * Redistribution and use in source and binary forms are permitted
  25. * provided that the above copyright notice is duplicated in all such
  26. * forms and that any documentation, advertising materials, and other
  27. * materials related to such distribution and use acknowledge that the
  28. * software was developed * by Mark H. Colburn and sponsored by The
  29. * USENIX Association.
  30. *
  31. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  32. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  33. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  34. *
  35. * $Log: buffer.c,v $
  36. * Revision 1.2 89/02/12 10:04:02 mark
  37. * 1.2 release fixes
  38. *
  39. * Revision 1.1 88/12/23 18:02:01 mark
  40. * Initial revision
  41. *
  42. */
  43. #ifndef lint
  44. static char *ident = "$Id: buffer.c,v 1.2 89/02/12 10:04:02 mark Exp $";
  45. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  46. #endif /* ! lint */
  47. /* Headers */
  48. #include "pax.h"
  49. /* Function Prototypes */
  50. static int ar_write(int, char *, uint);
  51. static void buf_pad(OFFSET);
  52. static int indata(int, OFFSET, char *);
  53. static void outflush(void);
  54. static void buf_use(uint);
  55. static int buf_in_avail(char **, uint *);
  56. static uint buf_out_avail(char **);
  57. /* inentry - install a single archive entry
  58. *
  59. * DESCRIPTION
  60. *
  61. * Inentry reads an archive entry from the archive file and writes it
  62. * out the the named file. If we are in PASS mode during archive
  63. * processing, the pass() function is called, otherwise we will
  64. * extract from the archive file.
  65. *
  66. * Inentry actaully calls indata to process the actual data to the
  67. * file.
  68. *
  69. * PARAMETERS
  70. *
  71. * char *name - name of the file to extract from the archive
  72. * Stat *asb - stat block of the file to be extracted from the
  73. * archive.
  74. *
  75. * RETURNS
  76. *
  77. * Returns zero if successful, -1 otherwise.
  78. */
  79. int inentry(char *name, Stat *asb)
  80. {
  81. Link *linkp;
  82. int ifd;
  83. int ofd;
  84. #ifdef _POSIX_SOURCE /* Xn */
  85. struct utimbuf tstamp; /* Xn */
  86. #else /* Xn */
  87. time_t tstamp[2];
  88. #endif /* Xn */
  89. #ifdef DF_TRACE_DEBUG
  90. printf("DF_TRACE_DEBUG: int inentry() in buffer.c\n");
  91. #endif
  92. if ((ofd = openout(name, asb, linkp = linkfrom(name, asb), 0)) > 0) {
  93. if (asb->sb_size || linkp == (Link *)NULL || linkp->l_size == 0) {
  94. close(indata(ofd, asb->sb_size, name));
  95. } else if ((ifd = open(linkp->l_path->p_name, O_RDONLY)) < 0) {
  96. warn(linkp->l_path->p_name, strerror(errno)); /* Xn */
  97. } else {
  98. passdata(linkp->l_path->p_name, ifd, name, ofd);
  99. close(ifd);
  100. close(ofd);
  101. }
  102. } else {
  103. return (buf_skip((OFFSET) asb->sb_size) >= 0);
  104. }
  105. #ifdef _POSIX_SOURCE
  106. tstamp.actime = (!f_pass && f_access_time) ? asb->sb_atime : time((time_t *) 0); /* Xn */
  107. tstamp.modtime = f_mtime ? asb->sb_mtime : time((time_t *) 0); /* Xn */
  108. (void) utime(name, &tstamp); /* Xn */
  109. #else
  110. tstamp[0] = (!f_pass && f_access_time) ? asb->sb_atime : time((time_t *) 0);
  111. tstamp[1] = f_mtime ? asb->sb_mtime : time((time_t *) 0);
  112. (void) utime(name, tstamp); /* Xn */
  113. #endif
  114. return (0);
  115. }
  116. /* outdata - write archive data
  117. *
  118. * DESCRIPTION
  119. *
  120. * Outdata transfers data from the named file to the archive buffer.
  121. * It knows about the file padding which is required by tar, but no
  122. * by cpio. Outdata continues after file read errors, padding with
  123. * null characters if neccessary. Closes the input file descriptor
  124. * when finished.
  125. *
  126. * PARAMETERS
  127. *
  128. * int fd - file descriptor of file to read data from
  129. * char *name - name of file
  130. * OFFSET size - size of the file
  131. *
  132. */
  133. void outdata(int fd, char *name, OFFSET size)
  134. {
  135. uint chunk, remaining;
  136. int got;
  137. int oops;
  138. uint avail;
  139. int pad;
  140. char *buf;
  141. remaining = size < 0 ? 0 : (uint)size;
  142. oops = got = 0;
  143. #ifdef DF_TRACE_DEBUG
  144. printf("DF_TRACE_DEBUG: void outdata() in buffer.c\n");
  145. #endif
  146. if (pad = (remaining % BLOCKSIZE)) {
  147. pad = (BLOCKSIZE - pad);
  148. }
  149. while (remaining) {
  150. avail = buf_out_avail(&buf);
  151. //printf("avail X%dX, size X%dX\n", avail, size);
  152. remaining -= (chunk = remaining < avail ? remaining : avail);
  153. //printf("chunk X%dX", chunk);
  154. memset(buf, 0, chunk);
  155. if (oops == 0 && (got = read(fd, buf, (unsigned int) chunk)) < 0 && errno != 12) {
  156. oops = -1;
  157. //puts("b warn outdata");
  158. //printf("size X%dX\n", sizeof(buf));
  159. //printf("oops X%dX got X%dX fd X%dX buf X%sX errno X%dX X%dX\n", oops, got, fd, buf, errno, chunk);
  160. warn(name, strerror(errno)); /* Xn */
  161. //puts("a warn outdata");
  162. got = 0;
  163. }
  164. if (got == -1 && errno == 12)
  165. got = 0;
  166. if (got < 0)
  167. got = 0;
  168. if ((uint)got < chunk) {
  169. if (oops == 0) {
  170. oops = -1;
  171. }
  172. warn(name, "Early EOF");
  173. while ((uint)got < chunk) {
  174. buf[got++] = '\0';
  175. }
  176. }
  177. buf_use(chunk);
  178. }
  179. close(fd);
  180. if (ar_format == TAR) {
  181. buf_pad((OFFSET) pad);
  182. }
  183. }
  184. /* write_eot - write the end of archive record(s)
  185. *
  186. * DESCRIPTION
  187. *
  188. * Write out an End-Of-Tape record. We actually zero at least one
  189. * record, through the end of the block. Old tar writes garbage after
  190. * two zeroed records -- and PDtar used to.
  191. */
  192. void write_eot(void)
  193. {
  194. OFFSET pad;
  195. char header[M_STRLEN + H_STRLEN + 1];
  196. #ifdef DF_TRACE_DEBUG
  197. printf("DF_TRACE_DEBUG: void write_eot() in buffer.c\n");
  198. #endif
  199. if (ar_format == TAR) {
  200. /* write out two zero blocks for trailer */
  201. pad = 2 * BLOCKSIZE;
  202. } else {
  203. if (pad = (total + M_STRLEN + H_STRLEN + TRAILZ) % BLOCKSIZE) {
  204. pad = BLOCKSIZE - pad;
  205. }
  206. strcpy(header, M_ASCII);
  207. sprintf(header + M_STRLEN, H_PRINT, 0, 0,
  208. #if 0 /* NIST-PCTS */
  209. 0, 0, 0, 1, 0, (time_t) 0, TRAILZ, pad);
  210. #else /* NIST-PCTS */
  211. 0, 0, 0, 1, 0, (time_t) 0, TRAILZ, (OFFSET) 0); /* NIST-PCTS */
  212. #endif /* NIST-PCTS */
  213. outwrite(header, M_STRLEN + H_STRLEN);
  214. outwrite(TRAILER, TRAILZ);
  215. }
  216. buf_pad((OFFSET) pad);
  217. outflush();
  218. }
  219. /* outwrite - write archive data
  220. *
  221. * DESCRIPTION
  222. *
  223. * Writes out data in the archive buffer to the archive file. The
  224. * buffer index and the total byte count are incremented by the number
  225. * of data bytes written.
  226. *
  227. * PARAMETERS
  228. *
  229. * char *idx - pointer to data to write
  230. * uint len - length of the data to write
  231. */
  232. void outwrite(char *idx, uint len)
  233. {
  234. uint have;
  235. uint want;
  236. char *endx;
  237. endx = idx + len;
  238. #ifdef DF_TRACE_DEBUG
  239. printf("DF_TRACE_DEBUG: void outwrite() in buffer.c\n");
  240. #endif
  241. while (want = (uint)(endx - idx)) {
  242. if (bufend - bufidx < 0) {
  243. fatal("Buffer overflow in out_write\n"); /* Xn */
  244. }
  245. //puts("b outflush");
  246. if ((have = (uint)(bufend - bufidx)) == 0) {
  247. outflush();
  248. //puts("a outflush");
  249. }
  250. if (have > want) {
  251. have = want;
  252. }
  253. memcpy(bufidx, idx, (int) have);
  254. //puts("a memcpy outwrite");
  255. bufidx += have;
  256. idx += have;
  257. total += have;
  258. }
  259. }
  260. /* passdata - copy data to one file
  261. *
  262. * DESCRIPTION
  263. *
  264. * Copies a file from one place to another. Doesn't believe in input
  265. * file descriptor zero (see description of kludge in openin() comments).
  266. * Closes the provided output file descriptor.
  267. *
  268. * PARAMETERS
  269. *
  270. * char *from - input file name (old file)
  271. * int ifd - input file descriptor
  272. * char *to - output file name (new file)
  273. * int ofd - output file descriptor
  274. */
  275. void passdata(char *from, int ifd, char *to, int ofd)
  276. {
  277. int got;
  278. int sparse;
  279. char block[BUFSIZ];
  280. #ifdef DF_TRACE_DEBUG
  281. printf("DF_TRACE_DEBUG: void passdata() in buffer.c\n");
  282. #endif
  283. if (ifd) {
  284. lseek(ifd, (OFFSET) 0, SEEK_SET); /* Xn */
  285. sparse = 0;
  286. while ((got = read(ifd, block, sizeof(block))) > 0
  287. && (sparse = ar_write(ofd, block, (uint) got)) >= 0) {
  288. total += got;
  289. }
  290. if (got) {
  291. warn(got < 0 ? from : to, strerror(errno)); /* Xn */
  292. } else if (sparse > 0
  293. && (lseek(ofd, (OFFSET)(-sparse), SEEK_CUR) < 0 /* Xn */
  294. || write(ofd, block, (uint) sparse) != sparse)) {
  295. warn(to, strerror(errno)); /* Xn */
  296. }
  297. }
  298. close(ofd);
  299. }
  300. /* buf_allocate - get space for the I/O buffer
  301. *
  302. * DESCRIPTION
  303. *
  304. * buf_allocate allocates an I/O buffer using malloc. The resulting
  305. * buffer is used for all data buffering throughout the program.
  306. * Buf_allocate must be called prior to any use of the buffer or any
  307. * of the buffering calls.
  308. *
  309. * PARAMETERS
  310. *
  311. * int size - size of the I/O buffer to request
  312. *
  313. * ERRORS
  314. *
  315. * If an invalid size is given for a buffer or if a buffer of the
  316. * required size cannot be allocated, then the function prints out an
  317. * error message and returns a non-zero exit status to the calling
  318. * process, terminating the program.
  319. *
  320. */
  321. void buf_allocate(OFFSET size)
  322. {
  323. #ifdef DF_TRACE_DEBUG
  324. printf("DF_TRACE_DEBUG: void buf_allocate() in buffer.c\n");
  325. #endif
  326. if (size <= 0) {
  327. fatal("invalid value for blocksize");
  328. }
  329. if ((bufstart = malloc((unsigned) size)) == (char *)NULL) {
  330. fatal("Cannot allocate I/O buffer");
  331. }
  332. bufend = bufidx = bufstart;
  333. bufend += size;
  334. }
  335. /* buf_skip - skip input archive data
  336. *
  337. * DESCRIPTION
  338. *
  339. * Buf_skip skips past archive data. It is used when the length of
  340. * the archive data is known, and we do not wish to process the data.
  341. *
  342. * PARAMETERS
  343. *
  344. * OFFSET len - number of bytes to skip
  345. *
  346. * RETURNS
  347. *
  348. * Returns zero under normal circumstances, -1 if unreadable data is
  349. * encountered.
  350. */
  351. int buf_skip(OFFSET len)
  352. {
  353. uint chunk, remaining;
  354. int corrupt = 0;
  355. remaining = len < 0 ? 0 : (uint)len;
  356. #ifdef DF_TRACE_DEBUG
  357. printf("DF_TRACE_DEBUG: int buf_skip() in buffer.c\n");
  358. #endif
  359. while (remaining) {
  360. if (bufend - bufidx < 0) {
  361. fatal("Buffer overflow in buf_skip\n"); /* Xn */
  362. }
  363. while ((chunk = (uint)(bufend - bufidx)) == 0) {
  364. corrupt |= ar_read();
  365. }
  366. if (chunk > remaining) {
  367. chunk = remaining;
  368. }
  369. bufidx += chunk;
  370. remaining -= chunk;
  371. total += chunk;
  372. }
  373. return (corrupt);
  374. }
  375. /* buf_read - read a given number of characters from the input archive
  376. *
  377. * DESCRIPTION
  378. *
  379. * Reads len number of characters from the input archive and
  380. * stores them in the buffer pointed at by dst.
  381. *
  382. * PARAMETERS
  383. *
  384. * char *dst - pointer to buffer to store data into
  385. * uint len - length of data to read
  386. *
  387. * RETURNS
  388. *
  389. * Returns zero with valid data, -1 if unreadable portions were
  390. * replaced by null characters.
  391. */
  392. int buf_read(char *dst, uint len)
  393. {
  394. int have;
  395. int want;
  396. int corrupt = 0;
  397. char *endx = dst + len;
  398. #ifdef DF_TRACE_DEBUG
  399. printf("DF_TRACE_DEBUG: int buf_read() in buffer.c\n");
  400. #endif
  401. while (want = (int)(endx - dst)) {
  402. if (bufend - bufidx < 0) {
  403. fatal("Buffer overflow in buf_read\n"); /* Xn */
  404. }
  405. while ((have = (int)(bufend - bufidx)) == 0) {
  406. have = 0;
  407. corrupt |= ar_read();
  408. }
  409. if (have > want) {
  410. have = want;
  411. }
  412. memcpy(dst, bufidx, have);
  413. bufidx += have;
  414. dst += have;
  415. total += have;
  416. }
  417. return (corrupt);
  418. }
  419. /* indata - install data from an archive
  420. *
  421. * DESCRIPTION
  422. *
  423. * Indata writes size bytes of data from the archive buffer to the output
  424. * file specified by fd. The filename which is being written, pointed
  425. * to by name is provided only for diagnostics.
  426. *
  427. * PARAMETERS
  428. *
  429. * int fd - output file descriptor
  430. * OFFSET size - number of bytes to write to output file
  431. * char *name - name of file which corresponds to fd
  432. *
  433. * RETURNS
  434. *
  435. * Returns given file descriptor.
  436. */
  437. static int indata(int fd, OFFSET size, char *name)
  438. {
  439. uint chunk, remaining;
  440. char *oops;
  441. int sparse;
  442. int corrupt;
  443. char *buf;
  444. uint avail;
  445. remaining = size < 0 ? 0 : (uint)size;
  446. corrupt = sparse = 0;
  447. #ifdef DF_TRACE_DEBUG
  448. printf("DF_TRACE_DEBUG: static int indata() in buffer.c\n");
  449. #endif
  450. oops = (char *)NULL;
  451. while (remaining) {
  452. corrupt |= buf_in_avail(&buf, &avail);
  453. remaining -= (chunk = remaining < avail ? remaining : avail);
  454. if (oops == (char *)NULL && (sparse = ar_write(fd, buf, chunk)) < 0) {
  455. oops = strerror(errno); /* Xn */
  456. }
  457. buf_use(chunk);
  458. }
  459. if (corrupt) {
  460. warn(name, "Corrupt archive data");
  461. }
  462. if (oops) {
  463. warn(name, oops);
  464. } else if (sparse > 0 && (lseek(fd, (OFFSET) - 1, SEEK_CUR) < 0 /* Xn */
  465. || write(fd, "", 1) != 1)) {
  466. warn(name, strerror(errno)); /* Xn */
  467. }
  468. return (fd);
  469. }
  470. /* outflush - flush the output buffer
  471. *
  472. * DESCRIPTION
  473. *
  474. * The output buffer is written, if there is anything in it, to the
  475. * archive file.
  476. */
  477. void outflush(void)
  478. {
  479. char *buf;
  480. int got;
  481. uint len;
  482. #ifdef DF_TRACE_DEBUG
  483. printf("DF_TRACE_DEBUG: void outflush() in buffer.c\n");
  484. #endif
  485. /* if (bufidx - buf > 0) */
  486. for (buf = bufstart; len = (uint)(bufidx - buf);) {
  487. #ifdef _POSIX_SOURCE /* 7/3/90-JPB */
  488. if ((got = write(archivefd, buf, MIN(len, blocksize))) > 0)
  489. buf += got;
  490. if (got <= 0 || got != (int)(MIN(len, blocksize)))
  491. next(AR_WRITE);
  492. #else
  493. if ((got = write(archivefd, buf, MIN(len, blocksize))) > 0) {
  494. buf += got;
  495. } else if (got <= 0) {
  496. next(AR_WRITE);
  497. }
  498. #endif
  499. }
  500. bufend = (bufidx = bufstart) + blocksize;
  501. }
  502. /* ar_read - fill the archive buffer
  503. *
  504. * DESCRIPTION
  505. *
  506. * Remembers mid-buffer read failures and reports them the next time
  507. * through. Replaces unreadable data with null characters. Resets
  508. * the buffer pointers as appropriate.
  509. *
  510. * RETURNS
  511. *
  512. * Returns zero with valid data, -1 otherwise.
  513. */
  514. int ar_read(void)
  515. {
  516. int got;
  517. static int failed = 0; /* Xn */
  518. bufend = bufidx = bufstart;
  519. /*
  520. #ifdef DF_TRACE_DEBUG
  521. printf("DF_TRACE_DEBUG: int ar_read() in buffer.c\n");
  522. #endif
  523. */
  524. if (!failed) {
  525. if (areof) {
  526. if (total == 0) {
  527. fatal("No input");
  528. } else {
  529. next(AR_READ);
  530. }
  531. }
  532. while (!failed && !areof && (uint)(bufstart + blocksize - bufend) >= blocksize) {
  533. if ((got = read(archivefd, bufend, (unsigned int) blocksize)) > 0) {
  534. bufend += got;
  535. #ifdef _POSIX_SOURCE /* 7/3/90-JPB */
  536. if ((uint)got != blocksize)
  537. ++areof;
  538. #endif
  539. } else if (got < 0) {
  540. failed = -1;
  541. warnarch(strerror(errno), (OFFSET) 0 - (bufend - bufidx)); /* Xn */
  542. } else {
  543. ++areof;
  544. }
  545. }
  546. }
  547. if (failed && bufend == bufstart) {
  548. failed = 0;
  549. for (got = 0; (uint)got < blocksize; ++got) {
  550. *bufend++ = '\0';
  551. }
  552. return (-1);
  553. }
  554. return (0);
  555. }
  556. /* ar_write - write a filesystem block
  557. *
  558. * DESCRIPTION
  559. *
  560. * Writes len bytes of data data from the specified buffer to the
  561. * specified file. Seeks past sparse blocks.
  562. *
  563. * PARAMETERS
  564. *
  565. * int fd - file to write to
  566. * char *buf - buffer to get data from
  567. * uint len - number of bytes to transfer
  568. *
  569. * RETURNS
  570. *
  571. * Returns 0 if the block was written, the given length for a sparse
  572. * block or -1 if unsuccessful.
  573. */
  574. int ar_write(int fd, char *buf, uint len)
  575. {
  576. char *bidx;
  577. char *bend;
  578. #ifdef DF_TRACE_DEBUG
  579. printf("DF_TRACE_DEBUG: int ar_write() in buffer.c\n");
  580. #endif
  581. bend = (bidx = buf) + len;
  582. while (bidx < bend) {
  583. if (*bidx++) {
  584. return (write(fd, buf, len) == (ssize_t)(len ? 0 : -1));
  585. }
  586. }
  587. return (lseek(fd, (OFFSET) len, SEEK_CUR) < 0 ? -1 : len); /* Xn */
  588. }
  589. /* buf_pad - pad the archive buffer
  590. *
  591. * DESCRIPTION
  592. *
  593. * Buf_pad writes len zero bytes to the archive buffer in order to
  594. * pad it.
  595. *
  596. * PARAMETERS
  597. *
  598. * OFFSET pad - number of zero bytes to pad
  599. *
  600. */
  601. static void buf_pad(OFFSET pad)
  602. {
  603. int idx;
  604. int have;
  605. #ifdef DF_TRACE_DEBUG
  606. printf("DF_TRACE_DEBUG: static void buf_pad() in buffer.c\n");
  607. #endif
  608. while (pad) {
  609. if ((have = (int)(bufend - bufidx)) > pad) {
  610. have = pad;
  611. }
  612. for (idx = 0; idx < have; ++idx) {
  613. *bufidx++ = '\0';
  614. }
  615. total += have;
  616. pad -= have;
  617. if (bufend - bufidx == 0) {
  618. outflush();
  619. }
  620. }
  621. }
  622. /* buf_use - allocate buffer space
  623. *
  624. * DESCRIPTION
  625. *
  626. * Buf_use marks space in the buffer as being used; advancing both the
  627. * buffer index (bufidx) and the total byte count (total).
  628. *
  629. * PARAMETERS
  630. *
  631. * uint len - Amount of space to allocate in the buffer
  632. */
  633. static void buf_use(uint len)
  634. {
  635. bufidx += len;
  636. total += len;
  637. }
  638. /* buf_in_avail - index available input data within the buffer
  639. *
  640. * DESCRIPTION
  641. *
  642. * Buf_in_avail fills the archive buffer, and points the bufp
  643. * parameter at the start of the data. The lenp parameter is
  644. * modified to contain the number of bytes which were read.
  645. *
  646. * PARAMETERS
  647. *
  648. * char **bufp - pointer to the buffer to read data into
  649. * uint *lenp - pointer to the number of bytes which were read
  650. * (returned to the caller)
  651. *
  652. * RETURNS
  653. *
  654. * Stores a pointer to the data and its length in given locations.
  655. * Returns zero with valid data, -1 if unreadable portions were
  656. * replaced with nulls.
  657. *
  658. * ERRORS
  659. *
  660. * If an error occurs in ar_read, the error code is returned to the
  661. * calling function.
  662. *
  663. */
  664. #ifdef DF_TRACE_DEBUG
  665. printf("DF_TRACE_DEBUG: static void buf_use() in buffer.c\n");
  666. #endif
  667. static int buf_in_avail(char **bufp, uint *lenp)
  668. {
  669. uint have;
  670. int corrupt = 0;
  671. #ifdef DF_TRACE_DEBUG
  672. printf("DF_TRACE_DEBUG: static int buf_in_avail() in buffer.c\n");
  673. #endif
  674. while ((have = (uint)(bufend - bufidx)) == 0) {
  675. corrupt |= ar_read();
  676. }
  677. *bufp = bufidx;
  678. *lenp = have;
  679. return (corrupt);
  680. }
  681. /* buf_out_avail - index buffer space for archive output
  682. *
  683. * DESCRIPTION
  684. *
  685. * Stores a buffer pointer at a given location. Returns the number
  686. * of bytes available.
  687. *
  688. * PARAMETERS
  689. *
  690. * char **bufp - pointer to the buffer which is to be stored
  691. *
  692. * RETURNS
  693. *
  694. * The number of bytes which are available in the buffer.
  695. *
  696. */
  697. static uint buf_out_avail(char **bufp)
  698. {
  699. int have;
  700. #ifdef DF_TRACE_DEBUG
  701. printf("DF_TRACE_DEBUG: static uint buf_out_avail() in buffer.c\n");
  702. #endif
  703. //printf("bufend X%dX bufidx X%dX\n", bufend, bufidx);
  704. if (bufend - bufidx < 0) {
  705. //puts("buf_out_avail fata");
  706. fatal("Buffer overflow in buf_out_avail\n"); /* Xn */
  707. }
  708. if ((have = (int)(bufend - bufidx)) == 0) {
  709. outflush();
  710. }
  711. *bufp = bufidx;
  712. //printf("buf_out_avail rets X%dX\n", have);
  713. return (have);
  714. }