diff options
| author | Thomas Ulmer <thomasmulmer02@gmail.com> | 2026-03-02 20:03:16 -0800 |
|---|---|---|
| committer | Thomas Ulmer <thomasmulmer02@gmail.com> | 2026-03-02 20:03:16 -0800 |
| commit | 8b9a895e4425462787aba1b9b0b55495880fe707 (patch) | |
| tree | 5c6faa3afd20729b86def89762e33606a001f3b8 /src/vi/ex-070224/exrecover.c | |
| parent | 8e8d7917d5742c7ce42b46681c7c4430a51da505 (diff) | |
move vi to separate repo
Diffstat (limited to 'src/vi/ex-070224/exrecover.c')
| -rw-r--r-- | src/vi/ex-070224/exrecover.c | 906 |
1 files changed, 0 insertions, 906 deletions
diff --git a/src/vi/ex-070224/exrecover.c b/src/vi/ex-070224/exrecover.c deleted file mode 100644 index e2fa677..0000000 --- a/src/vi/ex-070224/exrecover.c +++ /dev/null @@ -1,906 +0,0 @@ -/* - * This code contains changes by - * Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved. - * - * Conditions 1, 2, and 4 and the no-warranty notice below apply - * to these changes. - * - * - * Copyright (c) 1980, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * Redistributions of source code and documentation must retain the - * above copyright notice, this list of conditions and the following - * disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed or owned by Caldera - * International, Inc. - * Neither the name of Caldera International, Inc. nor the names of - * other contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA - * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE - * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef __GNUC__ -#define UNUSED __attribute__ ((unused)) -#else -#define UNUSED -#endif - -#ifndef lint -#ifdef DOSCCS -char *copyright = -"@(#) Copyright (c) 1980 Regents of the University of California.\n\ - All rights reserved.\n"; -#endif -static char sccsid[] UNUSED = "@(#)exrecover.c 1.23 (gritter) 12/25/06"; -#endif - -/* from exrecover.c 7.9.2 (2.11BSD) 1996/10/26 */ - -#include <stdarg.h> -#ifdef notdef /* GR */ -#include <stdio.h> /* mjm: BUFSIZ: stdio = 512, VMUNIX = 1024 */ -#undef BUFSIZ /* mjm: BUFSIZ different */ -#undef EOF /* mjm: EOF and NULL effectively the same */ -#undef NULL -#else -#define xstderr (int*)0 -typedef int xFILE; -extern void perror(const char *); -extern int vsprintf(char *, const char *, va_list); -#endif - -#define var - -#include "ex.h" -#include "ex_temp.h" -#include "ex_tty.h" -#include "brk_shim.h" -#include <dirent.h> -#include <time.h> - -#ifndef MAXNAMLEN -#ifdef FNSIZE -#define MAXNAMLEN FNSIZE -#else -#ifdef NAME_MAX -#define MAXNAMLEN NAME_MAX -#else -#define MAXNAMLEN 255 -#endif -#endif -#endif - -#define TMP "/var/tmp" - -#ifdef LANGMSG -nl_catd catd; -#endif - -char xstr[1]; /* make loader happy */ -int tfile = -1; /* ditto */ - -/* - * - * This program searches through the specified directory and then - * the directory /usr/preserve looking for an instance of the specified - * file from a crashed editor or a crashed system. - * If this file is found, it is unscrambled and written to - * the standard output. - * - * If this program terminates without a "broken pipe" diagnostic - * (i.e. the editor doesn't die right away) then the buffer we are - * writing from is removed when we finish. This is potentially a mistake - * as there is not enough handshaking to guarantee that the file has actually - * been recovered, but should suffice for most cases. - */ - -/* - * Here we save the information about files, when - * you ask us what files we have saved for you. - * We buffer file name, number of lines, and the time - * at which the file was saved. - */ -struct svfile { - char sf_name[FNSIZE + 1]; - int sf_lines; - char sf_entry[MAXNAMLEN + 1]; - time_t sf_time; -}; - -#define ignorl(a) a - -/* - * This directory definition also appears (obviously) in expreserve.c. - * Change both if you change either. - */ -#ifdef notdef -char mydir[] = "/usr/preserve"; -#else -char mydir[] = "/var/lib/ex"; -#endif - -/* - * Limit on the number of printed entries - * when an, e.g. ``ex -r'' command is given. - */ -#define NENTRY 50 - -char nb[BUFSIZ]; -int vercnt; /* Count number of versions of file found */ - -extern void error(char *, ...); -extern void listfiles(char *); -extern void enter(struct svfile *, char *, int); -extern int qucmp(struct svfile *, struct svfile *); -extern void findtmp(char *); -extern void searchdir(char *); -extern int yeah(char *); -extern int preserve(void); -extern void scrapbad(void); -extern void putfile(int); -extern void wrerror(void); -extern void clrstats(void); -extern void getline(line); -extern char *getblock(line, int); -extern void blkio(bloc, char *, ssize_t (*)(int, void *, size_t)); -extern void syserror(void); -extern void xvfprintf(xFILE *, char *, va_list); -extern void xfprintf(xFILE *, char *, ...); - -int -main(int argc, char *argv[]) -{ - register char *cp; - register int b, i; - - /* - * Initialize the built-in memory allocator. - */ -#ifdef VMUNIX - poolsbrk(0); -#endif - linebuf = calloc(LBSIZE = BUFSIZ<4096?4096:BUFSIZ, sizeof *linebuf); - genbuf = calloc(MAXBSIZE, sizeof *genbuf); -#ifdef LANGMSG - setlocale(LC_MESSAGES, ""); - catd = catopen(CATNAME, NL_CAT_LOCALE); -#endif - - /* - * Initialize as though the editor had just started. - */ - fendcore = (line *) shim_sbrk(0); - dot = zero = dol = fendcore; - one = zero + 1; - endcore = fendcore - 2; - iblock = oblock = -1; - - /* - * If given only a -r argument, then list the saved files. - */ - if (argc == 2 && strcmp(argv[1], "-r") == 0) { - listfiles(mydir); - listfiles(TMP); - exit(0); - } - if (argc != 3) - error(catgets(catd, 2, 1, - " Wrong number of arguments to exrecover"), 0); - - strcpy(file, argv[2]); - - /* - * Search for this file. - */ - findtmp(argv[1]); - - /* - * Got (one of the versions of) it, write it back to the editor. - */ - cp = ctime(&H.Time); - cp[19] = 0; - xfprintf(xstderr, catgets(catd, 2, 2, " [Dated: %s"), cp); - xfprintf(xstderr, vercnt > 1 ? catgets(catd, 2, 3, - ", newest of %d saved]") - : catgets(catd, 2, 4, "]"), vercnt); - H.Flines++; - - /* - * Allocate space for the line pointers from the temp file. - */ - if ((char *) shim_sbrk(H.Flines * sizeof (line)) == (char *) -1) - /* - * Good grief. - */ - error(catgets(catd, 1, 5, " Not enough core for lines"), 0); -#ifdef DEBUG - xfprintf(xstderr, "%d lines\n", H.Flines); -#endif - - /* - * Now go get the blocks of seek pointers which are scattered - * throughout the temp file, reconstructing the incore - * line pointers at point of crash. - */ - b = 0; - while (H.Flines > 0) { - ignorl(lseek(tfile, (off_t) ((blocks[b] & BLKMSK) * BUFSIZ), - SEEK_SET)); - i = H.Flines < BUFSIZ / sizeof (line) ? - H.Flines * sizeof (line) : BUFSIZ; - if (read(tfile, (char *) dot, i) != i) { - perror(nb); - exit(1); - } - dot += i / sizeof (line); - H.Flines -= i / sizeof (line); - b++; - } - dot--; dol = dot; - - /* - * Sigh... due to sandbagging some lines may really not be there. - * Find and discard such. This shouldn't happen much. - */ - scrapbad(); - - /* - * Now if there were any lines in the recovered file - * write them to the standard output. - */ - if (dol > zero) { - addr1 = one; addr2 = dol; io = 1; - putfile(0); - } - - /* - * Trash the saved buffer. - * Hopefully the system won't crash before the editor - * syncs the new recovered buffer; i.e. for an instant here - * you may lose if the system crashes because this file - * is gone, but the editor hasn't completed reading the recovered - * file from the pipe from us to it. - * - * This doesn't work if we are coming from an non-absolute path - * name since we may have chdir'ed but what the hay, noone really - * ever edits with temporaries in "." anyways. - */ - if (nb[0] == '/') - ignore(unlink(nb)); - - /* - * Adieu. - */ - exit(0); -} - -/* - * Print an error message (notably not in error - * message file). If terminal is in RAW mode, then - * we should be writing output for "vi", so don't print - * a newline which would screw up the screen. - */ -/*VARARGS2*/ -void -error(char *str, ...) -{ - va_list ap; - - va_start(ap, str); - xvfprintf(xstderr, str, ap); - va_end(ap); - tcgetattr(2, &tty); - if (tty.c_lflag & ICANON) - xfprintf(xstderr, "\n"); - exit(1); -} - -void -listfiles(char *dirname) -{ - register DIR *dir; - struct dirent *dirent; - int ecount; - register int f; - char *cp; - struct svfile *fp, svbuf[NENTRY]; - - /* - * Open /usr/preserve, and go there to make things quick. - */ - dir = opendir(dirname); - if (dir == NULL) { - perror(dirname); - return; - } - if (chdir(dirname) < 0) { - perror(dirname); - return; - } - xfprintf(xstderr, "%s:\n", dirname); - - /* - * Look at the candidate files in /usr/preserve. - */ - fp = &svbuf[0]; - ecount = 0; - while ((dirent = readdir(dir)) != NULL) { - if (dirent->d_name[0] != 'E') - continue; -#ifdef DEBUG - xfprintf(xstderr, "considering %s\n", dirent->d_name); -#endif - /* - * Name begins with E; open it and - * make sure the uid in the header is our uid. - * If not, then don't bother with this file, it can't - * be ours. - */ - f = open(dirent->d_name, O_RDONLY); - if (f < 0) { -#ifdef DEBUG - xfprintf(xstderr, "open failed\n"); -#endif - continue; - } - if (read(f, (char *) &H, sizeof H) != sizeof H) { -#ifdef DEBUG - xfprintf(xstderr, "culdnt read hedr\n"); -#endif - ignore(close(f)); - continue; - } - ignore(close(f)); - if (getuid() != H.Uid) { -#ifdef DEBUG - xfprintf(xstderr, "uid wrong\n"); -#endif - continue; - } - - /* - * Saved the day! - */ - enter(fp++, dirent->d_name, ecount); - ecount++; -#ifdef DEBUG - xfprintf(xstderr, "entered file %s\n", dirent->d_name); -#endif - } - ignore(closedir(dir)); - - /* - * If any files were saved, then sort them and print - * them out. - */ - if (ecount == 0) { - xfprintf(xstderr, catgets(catd, 2, 6, "No files saved.\n")); - return; - } - qsort(&svbuf[0], ecount, sizeof svbuf[0], (int(*)(const void *, const void *)) qucmp); - for (fp = &svbuf[0]; fp < &svbuf[ecount]; fp++) { - cp = ctime(&fp->sf_time); - cp[10] = 0; - xfprintf(xstderr, catgets(catd, 2, 7, "On %s at "), cp); - cp[16] = 0; - xfprintf(xstderr, &cp[11]); - xfprintf(xstderr, catgets(catd, 2, 8, - " saved %d lines of file \"%s\"\n"), - fp->sf_lines, fp->sf_name); - } -} - -/* - * Enter a new file into the saved file information. - */ -void -enter(struct svfile *fp, char *fname, int count) -{ - register char *cp, *cp2; - register struct svfile *f, *fl; - time_t curtime; - - f = 0; - if (count >= NENTRY) { - /* - * My god, a huge number of saved files. - * Would you work on a system that crashed this - * often? Hope not. So lets trash the oldest - * as the most useless. - * - * (I wonder if this code has ever run?) - */ - fl = fp - count + NENTRY - 1; - curtime = fl->sf_time; - for (f = fl; --f > fp-count; ) - if (f->sf_time < curtime) - curtime = f->sf_time; - for (f = fl; --f > fp-count; ) - if (f->sf_time == curtime) - break; - fp = f; - } - - /* - * Gotcha. - */ - fp->sf_time = H.Time; - fp->sf_lines = H.Flines; - cp2 = fp->sf_name, cp = savedfile; - while (*cp2++ = *cp++); - for (cp2 = fp->sf_entry, cp = fname; *cp && cp-fname < 14;) - *cp2++ = *cp++; - *cp2++ = 0; -} - -/* - * Do the qsort compare to sort the entries first by file name, - * then by modify time. - */ -int -qucmp(struct svfile *p1, struct svfile *p2) -{ - register int t; - - if (t = strcmp(p1->sf_name, p2->sf_name)) - return(t); - if (p1->sf_time > p2->sf_time) - return(-1); - return(p1->sf_time < p2->sf_time); -} - -/* - * Scratch for search. - */ -char bestnb[BUFSIZ]; /* Name of the best one */ -long besttime; /* Time at which the best file was saved */ -int bestfd; /* Keep best file open so it dont vanish */ - -/* - * Look for a file, both in the users directory option value - * (i.e. usually /tmp) and in /usr/preserve. - * Want to find the newest so we search on and on. - */ -void -findtmp(char *dir) -{ - - /* - * No name or file so far. - */ - bestnb[0] = 0; - bestfd = -1; - - /* - * Search /usr/preserve and, if we can get there, /tmp - * (actually the users "directory" option). - */ - searchdir(dir); - if (chdir(mydir) == 0) - searchdir(mydir); - if (bestfd != -1) { - /* - * Gotcha. - * Put the file (which is already open) in the file - * used by the temp file routines, and save its - * name for later unlinking. - */ - tfile = bestfd; - strcpy(nb, bestnb); - ignorl(lseek(tfile, (off_t) 0, SEEK_SET)); - - /* - * Gotta be able to read the header or fall through - * to lossage. - */ - if (read(tfile, (char *) &H, sizeof H) == sizeof H) - return; - } - - /* - * Extreme lossage... - */ - error(catgets(catd, 2, 9, " File not found"), 0); -} - -/* - * Search for the file in directory dirname. - * - * Don't chdir here, because the users directory - * may be ".", and we would move away before we searched it. - * Note that we actually chdir elsewhere (because it is too slow - * to look around in /usr/preserve without chdir'ing there) so we - * can't win, because we don't know the name of '.' and if the path - * name of the file we want to unlink is relative, rather than absolute - * we won't be able to find it again. - */ -void -searchdir(char *dirname) -{ - struct dirent *dirent; - register DIR *dir; - /* char dbuf[BUFSIZ]; */ - - dir = opendir(dirname); - if (dir == NULL) - return; - while ((dirent = readdir(dir)) != NULL) { - if (dirent->d_name[0] != 'E') - continue; - /* - * Got a file in the directory starting with E... - * Save a consed up name for the file to unlink - * later, and check that this is really a file - * we are looking for. - */ - ignore(strcat(strcat(strcpy(nb, dirname), "/"), dirent->d_name)); - if (yeah(nb)) { - /* - * Well, it is the file we are looking for. - * Is it more recent than any version we found before? - */ - if (H.Time > besttime) { - /* - * A winner. - */ - ignore(close(bestfd)); - bestfd = dup(tfile); - besttime = H.Time; - strcpy(bestnb, nb); - } - /* - * Count versions so user can be told there are - * ``yet more pages to be turned''. - */ - vercnt++; - } - ignore(close(tfile)); - } - ignore(closedir(dir)); -} - -/* - * Given a candidate file to be recovered, see - * if its really an editor temporary and of this - * user and the file specified. - */ -int -yeah(char *name) -{ - - tfile = open(name, O_RDWR); - if (tfile < 0) - return (0); - if (read(tfile, (char *) &H, sizeof H) != sizeof H) { -nope: - ignore(close(tfile)); - return (0); - } - if (strcmp(savedfile, file)) - goto nope; - if (getuid() != H.Uid) - goto nope; - /* - * This is old and stupid code, which - * puts a word LOST in the header block, so that lost lines - * can be made to point at it. - */ - ignorl(lseek(tfile, (off_t) (BUFSIZ*HBLKS-8), SEEK_SET)); - ignore(write(tfile, "LOST", 5)); - return (1); -} - -int -preserve(void) -{ - return 0; -} - -/* - * Find the true end of the scratch file, and ``LOSE'' - * lines which point into thin air. This lossage occurs - * due to the sandbagging of i/o which can cause blocks to - * be written in a non-obvious order, different from the order - * in which the editor tried to write them. - * - * Lines which are lost are replaced with the text LOST so - * they are easy to find. We work hard at pretty formatting here - * as lines tend to be lost in blocks. - * - * This only seems to happen on very heavily loaded systems, and - * not very often. - */ -void -scrapbad(void) -{ - register line *ip; - struct stat stbuf; - off_t size, maxt; - bbloc bno, cnt = 0, bad, was; - char bk[BUFSIZ]; - - ignore(fstat(tfile, &stbuf)); - size = stbuf.st_size; - maxt = (size >> SHFT) | (BNDRY-1); - bno = (maxt >> OFFBTS) & BLKMSK; -#ifdef DEBUG - xfprintf(xstderr, "size %ld, maxt %o, bno %d\n", size, maxt, bno); -#endif - - /* - * Look for a null separating two lines in the temp file; - * if last line was split across blocks, then it is lost - * if the last block is. - */ - while (bno > 0) { - ignorl(lseek(tfile, (off_t) (BUFSIZ * (bno & BLKMSK)), - SEEK_SET)); - cnt = read(tfile, (char *) bk, BUFSIZ); - while (cnt > 0) - if (bk[--cnt] == 0) - goto null; - bno--; - } -null: - - /* - * Magically calculate the largest valid pointer in the temp file, - * consing it up from the block number and the count. - */ - maxt = ((bno << OFFBTS) | (cnt >> SHFT)) & ~1; -#ifdef DEBUG - xfprintf(xstderr, "bno %d, cnt %d, maxt %o\n", bno, cnt, maxt); -#endif - - /* - * Now cycle through the line pointers, - * trashing the Lusers. - */ - was = bad = 0; - for (ip = one; ip <= dol; ip++) - if (*ip > maxt) { -#ifdef DEBUG - xfprintf(xstderr, "%d bad, %o > %o\n", ip - zero, *ip, maxt); -#endif - if (was == 0) - was = ip - zero; - *ip = ((HBLKS*BUFSIZ)-8) >> SHFT; - } else if (was) { - if (bad == 0) - xfprintf(xstderr, catgets(catd, 2, 10, - " [Lost line(s):")); - xfprintf(xstderr, catgets(catd, 2, 11, - " %d"), was); - if ((ip - 1) - zero > was) - xfprintf(xstderr, catgets(catd, 2, 12, "-%d"), - (int) ((ip - 1) - zero)); - bad++; - was = 0; - } - if (was != 0) { - if (bad == 0) - xfprintf(xstderr, catgets(catd, 2, 13, - " [Lost line(s):")); - xfprintf(xstderr, catgets(catd, 2, 14, " %d"), was); - if (dol - zero != was) - xfprintf(xstderr, catgets(catd, 2, 15, - "-%d"), (int) (dol - zero)); - bad++; - } - if (bad) - xfprintf(xstderr, catgets(catd, 2, 16, "]")); -} - -int cntch, cntln, cntodd, cntnull; - -/* - * Following routines stolen mercilessly from ex. - */ -void -putfile(int unused) -{ - line *a1; - register char *fp, *lp; - register int nib; - - a1 = addr1; - clrstats(); - cntln = addr2 - a1 + 1; - if (cntln == 0) - return; - nib = BUFSIZ; - fp = genbuf; - do { - getline(*a1++); - lp = linebuf; - for (;;) { - if (--nib < 0) { - nib = fp - genbuf; - if (write(io, genbuf, nib) != nib) - wrerror(); - cntch += nib; - nib = MAXBSIZE - 1 /* 511 */; - fp = genbuf; - } - if ((*fp++ = *lp++) == 0) { - fp[-1] = '\n'; - break; - } - } - } while (a1 <= addr2); - nib = fp - genbuf; - if (write(io, genbuf, nib) != nib) - wrerror(); - cntch += nib; -} - -void -wrerror(void) -{ - - syserror(); -} - -void -clrstats(void) -{ - - ninbuf = 0; - cntch = 0; - cntln = 0; - cntnull = 0; - cntodd = 0; -} - -#define READ 0 -#define WRITE 1 - -void -getline(line tl) -{ - register char *bp, *lp; - register int nl; - - lp = linebuf; - bp = getblock(tl, READ); - nl = nleft; - tl &= ~OFFMSK; - while (*lp++ = *bp++) - if (--nl == 0) { - bp = getblock(tl += INCRMT, READ); - nl = nleft; - } -} - -char * -getblock(line atl, int iof) -{ - register bbloc bno, off; - - bno = (atl >> OFFBTS) & BLKMSK; - off = (atl << SHFT) & LBTMSK; - if (bno >= NMBLKS) - error(catgets(catd, 2, 17, " Tmp file too large")); - nleft = BUFSIZ - off; - if (bno == iblock) { - ichanged |= iof; - return (ibuff + off); - } - if (bno == oblock) - return (obuff + off); - if (iof == READ) { - if (ichanged) - blkio(iblock, ibuff, - (ssize_t(*)(int, void *, size_t))write); - ichanged = 0; - iblock = bno; - blkio(bno, ibuff, (ssize_t(*)(int, void *, size_t))read); - return (ibuff + off); - } - if (oblock >= 0) - blkio(oblock, obuff, (ssize_t(*)(int, void *, size_t))write); - oblock = bno; - return (obuff + off); -} - -void -blkio(bloc b, char *buf, ssize_t (*iofcn)(int, void *, size_t)) -{ - - lseek(tfile, (off_t) ((b & BLKMSK) * BUFSIZ), SEEK_SET); - if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ) - syserror(); -} - -void -syserror(void) -{ - - dirtcnt = 0; - write(2, " ", 1); - error("%s", strerror(errno)); - exit(1); -} - -/* - * Must avoid stdio because expreserve uses sbrk to do memory - * allocation and stdio uses malloc. - */ -/* - * I do not know whether vsprintf() uses malloc() or not. - * So this may be fail, too. - */ -void -xvfprintf(xFILE *fp, char *fmt, va_list ap) -{ - char buf[BUFSIZ]; - - if (fp != xstderr) - return; - vsprintf(buf, fmt, ap); - write(2, buf, strlen(buf)); -} - -void -xfprintf(xFILE *fp, char *fmt, ...) -{ - va_list ap; - - if (fp != xstderr) - return; - va_start(ap, fmt); - xvfprintf(fp, fmt, ap); - va_end(ap); -} |
