2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: bio.c /main/3 1995/11/01 16:58:37 rswiston $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS PROPRIETARY SOURCE CODE LICENSED BY *
31 * Copyright (c) 1995 AT&T Corp. *
32 * All Rights Reserved *
34 * This software is licensed by AT&T Corp. *
35 * under the terms and conditions of the license in *
36 * http://www.research.att.com/orgs/ssr/book/reuse *
38 * This software was created by the *
39 * Software Engineering Research Department *
40 * AT&T Bell Laboratories *
42 * For further information contact *
43 * gsf@research.att.com *
45 ***************************************************************/
47 /* : : generated by proto : : */
49 #if !defined(__PROTO__)
50 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
51 #if defined(__cplusplus)
52 #define __MANGLE__ "C"
57 #define __PROTO__(x) x
59 #define __PARAM__(n,o) n
60 #if !defined(__STDC__) && !defined(__cplusplus)
61 #if !defined(c_plusplus)
72 #define __PROTO__(x) ()
73 #define __OTORP__(x) x
74 #define __PARAM__(n,o) o
82 #if defined(__cplusplus) || defined(c_plusplus)
83 #define __VARARG__ ...
87 #if defined(__STDARG__)
88 #define __VA_START__(p,a) va_start(p,a)
90 #define __VA_START__(p,a) va_start(p)
95 #include "FEATURE/mtio"
101 #if defined(MTIOBSF) && !defined(MTBSF)
102 #define MTBSF MTIOBSF
104 #if defined(MTIOBSR) && !defined(MTBSR)
105 #define MTBSR MTIOBSR
107 #if defined(MTIOEOM) && !defined(MTEOM)
108 #define MTEOM MTIOEOM
110 #if defined(MTIOFSF) && !defined(MTFSF)
111 #define MTFSF MTIOFSF
113 #if defined(MTIOWEOF) && !defined(MTWEOF)
114 #define MTWEOF MTIOWEOF
116 #if !defined(MTBSF) || !defined(MTBSR) || !defined(MTWEOF) || defined(__hppa)/*hppa-compiler-signal-10*/
124 * -o blok=i input is BLOK file
125 * -o blok=o output file is BLOK file
129 blokread __PARAM__((register Archive_t* ap, char* buf, int n), (ap, buf, n)) __OTORP__(register Archive_t* ap; char* buf; int n;){
136 if (!ap->io.blokflag)
140 if ((i = read(ap->io.fd, buf, ap->io.blok ? 4 : n)) < 4 || !strneq(buf, "\002\014\017\013", 4))
142 if (ap->io.blok) error(3, "%s: input archive is not a BLOK file", ap->name);
145 if (i > 4 && lseek(ap->io.fd, 4L, SEEK_SET) != 4L)
146 error(3, "%s: cannot seek on input archive BLOK file -- use -o blok=i", ap->name);
154 if ((i = read(ap->io.fd, &c, 1)) < 1)
155 return(i < 0 && ++eof == 1 ? 0 : -1);
162 error(2, "%s: blokread buffer overflow (%d>%d)", ap->name, j, n);
163 if ((i = read(ap->io.fd, buf, j)) != j)
164 error(2, "%s: blokread blocking error", ap->name);
168 else i = read(ap->io.fd, buf, n);
173 blokwrite __PARAM__((register Archive_t* ap, char* buf, int n), (ap, buf, n)) __OTORP__(register Archive_t* ap; char* buf; int n;){
182 if (!ap->io.blokflag)
191 if (j = (n >> 21) & 0177)
196 if ((j = (n >> 14) & 0177) || i)
201 if ((j = (n >> 7) & 0177) || i)
208 if ((i = write(ap->io.fd, blk, j)) != j)
209 error(ERROR_SYSTEM|3, "%s: blokwrite count write error (%d!=%d)", ap->name, i, j);
211 else if ((i = write(ap->io.fd, buf, n)) != n)
212 error(ERROR_SYSTEM|3, "%s: blokwrite data write error (%d!=%d", ap->name, i, n);
214 else i = write(ap->io.fd, buf, n);
218 #define read(f,b,n) blokread(f,b,n)
219 #define write(f,b,n) blokwrite(f,b,n)
224 * initialize buffered io
228 binit __PARAM__((register Archive_t* ap), (ap)) __OTORP__(register Archive_t* ap;){
232 ap->delta->hdr = ap->delta->hdrbuf;
233 n = 2 * state.buffersize;
234 if (!(ap->io.mode & O_WRONLY))
236 else if (!(format[ap->format].flags & OUT))
237 error(3, "%s: archive format not supported on output" , format[ap->format].name);
238 if (!(ap->io.buffer = newof(0, char, n, 0)))
239 error(3, "%s: cannot allocate buffer", ap->name);
240 ap->io.next = ap->io.last = ap->io.buffer;
244 * skip files on tape fd
248 bskip __PARAM__((register Archive_t* ap), (ap)) __OTORP__(register Archive_t* ap;){
250 int skip = ap->io.skip;
263 ap->io.next = ap->io.last = ap->io.buffer + MAXUNREAD;
270 if (skip < 0 && mteom)
274 if (ioctl(ap->io.fd, MTIOCTOP, &mt) >= 0)
276 if (ap->io.mode) ap->io.eof = 1;
287 if (ioctl(ap->io.fd, MTIOCTOP, &mt) >= 0)
294 if (ap->io.mode) ap->io.eof = 1;
301 while ((c = read(ap->io.fd, state.tmp.buffer, state.tmp.buffersize)) > 0);
304 if (ap->io.mode) ap->io.eof = 1;
313 * fill input buffer at ap->io.last
314 * if must!=0 then EOF causes query for next input volume file
318 bfill __PARAM__((register Archive_t* ap, int must), (ap, must)) __OTORP__(register Archive_t* ap; int must;){
321 if (ap->io.eof) return(-1);
322 if (ap->io.skip) ap->io.skip = bskip(ap);
323 while ((c = read(ap->io.fd, ap->io.last, state.buffersize)) <= 0)
325 if (must) newio(ap, c, 0);
332 message((-8, "read(%s,%d): %-.*s%s", ap->name, c, c > 32 ? 32 : c, ap->io.last, c > 32 ? "..." : ""));
339 * buffered char input
340 * at least n chars required, m chars max
341 * if b is 0 then n chars are skipped
342 * if must!=0 then EOF causes query for next input volume file
346 bread __PARAM__((register Archive_t* ap, __V_* ab, register long n, long m, int must), (ap, ab, n, m, must)) __OTORP__(register Archive_t* ap; __V_* ab; register long n; long m; int must;){
347 register char* b = (char*)ab;
351 if (ap->io.eof) return(-1);
352 if (m <= 0) return(0);
356 if (!b) b = state.tmp.buffer;
357 while ((c = read(ap->io.fd, b, m)) <= 0)
359 if (must) newio(ap, c, 0);
360 else if (ap->io.empty)
367 if (c < 0) ap->io.eof = 1;
372 if (ob) message((-7, "bread(%s,%d@%ld):", ap->name, c, ap->io.count));
379 if (must && c < n) return(-1);
383 ap->memsum = memsum(b, c, ap->memsum);
384 ap->old.memsum = omemsum(b, c, ap->old.memsum);
387 if (ob) message((-7, "bread(%s,%d@%ld): %-.*s%s", ap->name, c, ap->io.count, c > 32 ? 32 : c, ob, c > 32 ? "..." : ""));
397 if (n > (c = ap->io.last - ap->io.next))
403 ap->memsum = memsum(ap->io.next, c, ap->memsum);
404 ap->old.memsum = omemsum(ap->io.next, c, ap->old.memsum);
406 if (ob) memcpy(b, ap->io.next, c);
411 ap->io.next = ap->io.last = ap->io.buffer + MAXUNREAD;
412 if (!ob && ap->sum <= 0)
414 if (!ap->io.seekcheck)
418 ap->io.seekcheck = 1;
419 if (lseek(ap->io.fd, 0L, SEEK_CUR) == (ap->io.count + ap->io.last - ap->io.next) && fstat(ap->io.fd, &st) != -1 && st.st_size > 0)
422 if (ap->io.seekable && (c = n / BUFFERSIZE) && lseek(ap->io.fd, (long)(c *= BUFFERSIZE), SEEK_CUR) != -1)
427 message((-7, "bread(%s) skip(%d@%ld) [%ld]", ap->name, c, ap->io.count));
430 if (bfill(ap, must) < 0)
432 if (ob && (c = (b - ob)))
444 ap->memsum = memsum(ap->io.next, n, ap->memsum);
445 ap->old.memsum = omemsum(ap->io.next, n, ap->old.memsum);
447 if (ob) memcpy(b, ap->io.next, n);
454 message((-7, "bread(%s,%d@%ld): %-.*s%s", ap->name, n, ap->io.count, n > 32 ? 32 : n, ob, n > 32 ? "..." : ""));
464 * pushback for next bread()
468 bunread __PARAM__((register Archive_t* ap, __V_* ab, register int n), (ap, ab, n)) __OTORP__(register Archive_t* ap; __V_* ab; register int n;){
469 register char* b = (char*)ab;
473 if ((ap->io.next -= n) < ap->io.buffer + MAXUNREAD)
475 if (ap->io.next < ap->io.buffer)
476 error(PANIC, "bunread(%s,%d): too much pushback", ap->name, n);
477 memcpy(ap->io.next, b, n);
479 message((-7, "bunread(%s,%d@%ld): %-.*s%s", ap->name, n, ap->io.count, n > 32 ? 32 : n, b, n > 32 ? "..." : ""));
483 * bread() n chars and return a pointer to the char buffer
487 bget __PARAM__((register Archive_t* ap, register int n), (ap, n)) __OTORP__(register Archive_t* ap; register int n;){
493 while (ap->io.next > ap->io.last)
495 if (ap->io.last > ap->io.buffer + MAXUNREAD + state.buffersize)
502 m = roundof(k, IOALIGN) - k;
504 if (m) message((-8, "bget(%s) buffer alignment offset=%d", ap->name, m));
506 b = ap->io.next = ap->io.buffer + MAXUNREAD + m;
511 message((-8, "bget(%s) overlapping memcpy n=%d k=%d m=%d", ap->name, n, k, m));
521 if (bfill(ap, 1) < 0) return(0);
525 ap->memsum = memsum(s, n, ap->memsum);
526 ap->old.memsum = omemsum(s, n, ap->old.memsum);
528 message((-7, "bget(%s,%d@%ld): %-.*s%s", ap->name, n, ap->io.count, n > 32 ? 32 : n, s, n > 32 ? "..." : ""));
533 * back up input to bsave()'d position and prime output buffer
537 backup __PARAM__((register Archive_t* ap), (ap)) __OTORP__(register Archive_t* ap;){
551 if (!(ioctl(ap->io.fd, MTIOCTOP, &mt))) return;
555 m = ap->io.next - (ap->io.buffer + MAXUNREAD);
556 if ((n = ap->io.count - m) > state.backup.count)
558 message((-1, "backup(%s): reread %ld", ap->name, n + m));
559 m = state.backup.last - (state.backup.buffer + MAXUNREAD);
560 if (lseek(ap->io.fd, -(n + m), SEEK_CUR) == -1L)
565 if (ioctl(ap->io.fd, MTIOCTOP, &mt)) break;
570 if (read(ap->io.fd, ap->io.buffer + MAXUNREAD, m) != m) break;
572 else m = ap->io.last - (ap->io.buffer + MAXUNREAD);
573 message((-1, "backup(%s): %ld", ap->name, m));
574 if ((m = lseek(ap->io.fd, -m, SEEK_CUR)) == -1L)
579 if (ioctl(ap->io.fd, MTIOCTOP, &mt)) break;
584 if (state.backup.next < state.backup.last)
585 bwrite(ap, ap->io.buffer + MAXUNREAD, state.backup.next - (state.backup.buffer + MAXUNREAD));
588 error(3, "%s: cannot position %s archive for append", ap->name, format[ap->format].name);
592 * flush buffered input
596 bflushin __PARAM__((register Archive_t* ap), (ap)) __OTORP__(register Archive_t* ap;){
597 ap->io.count += ap->io.last - ap->io.next;
598 ap->io.next = ap->io.last = ap->io.buffer + MAXUNREAD;
601 while (read(ap->io.fd, state.tmp.buffer, state.buffersize) > 0);
607 * rudimentary buffered seek -- force re-read
611 bseek __PARAM__((register Archive_t* ap, off_t pos, int op), (ap, pos, op)) __OTORP__(register Archive_t* ap; off_t pos; int op;){
612 ap->io.next = ap->io.last = ap->io.buffer + MAXUNREAD;
613 if ((pos = lseek(ap->io.fd, pos, op)) >= 0)
617 ap->io.count = pos - ap->io.offset;
623 * flush buffered output
627 bflushout __PARAM__((register Archive_t* ap), (ap)) __OTORP__(register Archive_t* ap;){
631 if (n = ap->io.next - ap->io.buffer)
633 ap->io.next = ap->io.buffer;
634 while ((c = write(ap->io.fd, ap->io.next, n)) != n)
636 if (c <= 0) newio(ap, c, n);
643 ap->io.next = ap->io.buffer;
652 bwrite __PARAM__((register Archive_t* ap, __V_* ab, register int n), (ap, ab, n)) __OTORP__(register Archive_t* ap; __V_* ab; register int n;){
653 register char* b = (char*)ab;
657 ap->memsum = memsum(b, n, ap->memsum);
659 ap->io.skip = bskip(ap);
660 if (state.maxout && ap->io.count >= state.maxout)
669 if (n > 0) message((-7, "bwrite(%s,%d@%ld): %-.*s...", ap->name, n, ap->io.count + n, n > 32 ? 32 : n, b));
670 else message((-7, "bwrite(%s,%d@%ld):", ap->name, n, ap->io.count + n));
672 while ((c = write(ap->io.fd, b, n)) != n)
682 if (ioctl(ap->io.fd, MTIOCTOP, &mt) >= 0) break;
685 error(3, "%s: cannot write tape EOF marks", ap->name);
687 if (c <= 0) newio(ap, c, n);
688 else if ((n -= c) > 0) b += c;
695 if (n > 0) message((-7, "bwrite(%s,%d@%ld): %-.*s...", ap->name, n, ap->io.count + n, n > 32 ? 32 : n, b));
696 else message((-7, "bwrite(%s,%d@%ld):", ap->name, n, ap->io.count + n));
700 if ((c = ap->io.buffer + state.blocksize - ap->io.next) <= n)
704 memcpy(ap->io.next, b, c);
708 ap->io.next = ap->io.buffer;
709 while ((c = write(ap->io.fd, ap->io.next, state.blocksize)) != state.blocksize)
711 if (c <= 0) newio(ap, c, n);
714 memcpy(state.tmp.buffer, ap->io.buffer + c, state.blocksize - c);
715 memcpy(ap->io.buffer, state.tmp.buffer, state.blocksize - c);
716 ap->io.next = ap->io.buffer + state.blocksize - c;
720 message((-8, "write(%s,%d): %-.32s...", ap->name, c, ap->io.buffer));
724 memcpy(ap->io.next, b, n);
733 * bwrite() n chars that have been placed in ap->io.next
737 bput __PARAM__((register Archive_t* ap, register int n), (ap, n)) __OTORP__(register Archive_t* ap; register int n;){
739 message((-7, "bput(%s,%d@%ld): %-.*s%s", ap->name, n, ap->io.count, n > 32 ? 32 : n, ap->io.next, n > 32 ? "..." : ""));
741 ap->memsum = memsum(ap->io.next, n, ap->memsum);
742 if ((ap->io.next += n) > ap->io.buffer + state.blocksize)
744 n = (ap->io.next - ap->io.buffer) - state.blocksize;
748 * flush out the buffer and slide over the remains
752 bwrite(ap, ap->io.next = ap->io.buffer + state.blocksize, n);
764 * find path name in /dev for <dev.st->st_dev,dev.st->st_ino>
769 devpath __PARAM__((register Ftw_t* ftw), (ftw)) __OTORP__(register Ftw_t* ftw;){
770 if (ftw->info == FTW_F && ftw->statb.st_dev == dev.st->st_dev && ftw->statb.st_ino == dev.st->st_ino)
772 message((-1, "device name is %s", ftw->path));
773 dev.path = strdup(ftw->path);
780 * initilize tty file pointers for interactive prompting
784 interactive __PARAM__((void), ()){
790 if (!(state.rtty = sfopen(NiL, "/dev/tty", "r")) || !(state.wtty = sfopen(NiL, "/dev/tty", "w")))
791 error(ERROR_SYSTEM|3, "cannot prompt for interactive input");
792 sfsetbuf(state.rtty, NiL, 0);
793 sfsetbuf(state.wtty, NiL, 0);
794 if (fd >= 0) close(fd);
799 * check for new input or output stream
800 * c is the io count causing the newio()
801 * n is the pending buffered io count
805 newio __PARAM__((register Archive_t* ap, int c, int n), (ap, c, n)) __OTORP__(register Archive_t* ap; int c; int n;){
823 ap->io.offset += ap->io.count - n;
825 z = ap->io.offset + ap->io.count;
826 if (ap->io.blocked && state.record.file) switch (ap->format)
832 putlabels(ap, state.record.file, "EOV");
842 z = ap->io.offset + ap->io.count;
844 if (fstat(ap->io.fd, &st) < 0)
845 error(ERROR_SYSTEM|3, "%s: cannot stat %s", ap->name, io);
846 st.st_mode = modex(st.st_mode);
847 switch (X_ITYPE(st.st_mode))
854 if (ap->io.mode) switch (c < 0 ? errno : 0)
866 error(ERROR_SYSTEM|3, "%s: %s %s error -- cannot recover", ap->name, io, rw);
872 switch (c < 0 ? errno : 0)
877 error(1, "%s: end of %s medium", ap->name, io);
880 error(ERROR_SYSTEM|1, "%s: %s %s error", ap->name, io, rw);
883 if (total == z) error(1, "%s: no %s on part %d", ap->name, io, ap->part--);
885 if (!file && ap->name != definput && ap->name != defoutput)
889 ftwalk("/dev", devpath, 0, NiL);
893 if (file && ap->name != definput && ap->name != defoutput && strmatch(ap->name, "*.+([0-9])") && (s = strrchr(ap->name, '.')) && ((c = strtol(++s, NiL, 10)) == ap->part || c == (ap->part - 1)))
895 if (ap->part == 1 && (!(ap->name = strdup(ap->name)) || !(s = strrchr(ap->name, '.'))))
896 error(3, "out of space");
909 if ((ap->io.fd = open(ap->name, ap->io.mode, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) >= 0)
912 error(1, "continuing %s %d %s on %s", ap->part == ap->volume + 1 ? "volume" : "part", ap->part, io, ap->name);
916 error(ERROR_SYSTEM|1, "%s: cannot %s", ap->name, rw);
918 if (file || ap->name == definput || ap->name == defoutput)
923 sfputc(state.wtty, '\007');
924 sfprintf(state.wtty, "Enter part %d %s %s name: ", ap->part + 1, io, file ? file : "device");
925 if (!(s = sfgetr(state.rtty, '\n', 1)))
927 sfputc(state.wtty, '\n');
933 if ((ap->io.fd = open(s, ap->io.mode, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) >= 0) break;
934 error(ERROR_SYSTEM|1, "%s: cannot open", s);
937 ap->name = strdup(s);
944 sfputc(state.wtty, '\007');
945 sfprintf(state.wtty, eomprompt, ap->part + 1);
946 if (!(s = sfgetr(state.rtty, '\n', 1)))
948 sfputc(state.wtty, '\n');
957 if (last) free(last);
961 if (!s) error(1, "no previous command");
962 else if (n = system(s)) error(1, "exit status %d", n);
966 file = *s ? s : ap->name;
967 if ((ap->io.fd = open(file, ap->io.mode)) >= 0) break;
968 file = strtape(file, &t);
969 if (!*t && (ap->io.fd = open(file, ap->io.mode)) >= 0) break;
970 error(ERROR_SYSTEM|1, "cannot %s %s", rw, *s ? s : ap->name);
973 if (ap->name != file) ap->name = strdup(file);
980 putlabels(ap, state.record.file, "HDR");