bio.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1987-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Bell Laboratories
*
* pax block io support
*/
#include "pax.h"
#if _sys_mtio
#include <ast_tty.h>
#if _sys_ioctl
#endif
#endif
#ifdef MTIOCTOP
#endif
#endif
#endif
#endif
#endif
#if !defined(MTBSF) || !defined(MTBSR) || !defined(MTWEOF) || defined(__hppa)/*hppa-compiler-signal-10*/
#endif
#endif
#define CVT(a,b,c,m,t) \
do \
{ \
if (c) \
{ \
case 1: \
else \
{ \
break; \
} \
case 2: \
ccmapstr(m, b, c); \
break; \
} \
if ((a)->swapio) \
} while (0)
/*
* return 1 if b is text data in f charset
*/
static const unsigned char ascii_text[] =
{
0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
static int
{
register unsigned char* e;
register int c;
if (n > 256)
n = 256;
e = b + n;
while (b < e)
{
c = *b++;
if (!ascii_text[c])
return 0;
}
return 1;
}
#if 0 && DEBUG
/*
* --blok=i input is BLOK file
* --blok=o output file is BLOK file
*/
static int
{
register int i;
register int j;
char c;
{
{
return i;
}
}
{
j = 0;
do
{
{
if (!i)
return 0;
{
return 0;
}
return -1;
}
j <<= 7;
j |= c & 0177;
} while (c & 0200);
if (j > 0)
{
if (j > n)
}
else
i = 0;
}
else
return i;
}
static int
{
register char* s;
register int i;
register int j;
char blk[9];
{
s = blk;
{
*s++ = 002;
*s++ = 014;
*s++ = 017;
*s++ = 013;
}
i = 0;
if (j = (n >> 21) & 0177)
{
*s++ = j | 0200;
i = 1;
}
if ((j = (n >> 14) & 0177) || i)
{
*s++ = j | 0200;
i = 1;
}
if ((j = (n >> 7) & 0177) || i)
{
*s++ = j | 0200;
i = 1;
}
*s++ = n & 0177;
j = s - blk;
if (n <= 0)
i = n;
}
else
return i;
}
#endif
#if 0
static ssize_t
{
static int count = 1;
if (!count)
{
return -1;
}
count--;
return write(f, b, n);
}
#endif
static char*
{
char* s;
s = sfprints("<%p,%d,%d,%I*d,%d,%d>", io->buffer, io->unread, io->fill, sizeof(io->count), io->count, io->next - (io->buffer + io->unread), io->last - (io->buffer + io->unread));
}
/*
* initialize buffered io
*/
void
{
unsigned long n;
unsigned long u;
return;
u = MAXUNREAD;
else
u = 0;
}
/*
* skip files on tape fd
*/
int
{
long c;
#ifdef MTIOCTOP
#ifdef MTEOM
int mteom = 1;
#endif
#ifdef MTFSF
int mtfsf = 1;
#endif
#endif
{
}
while (skip)
{
#ifdef MTIOCTOP
#ifdef MTEOM
{
{
break;
}
mteom = 0;
}
#endif
#ifdef MTFSF
if (mtfsf)
{
{
skip--;
continue;
}
{
break;
}
mtfsf = 0;
}
#endif
#endif
if (c < 0)
{
break;
}
skip--;
}
return 0;
}
/*
* fill input buffer at ap->io->last
* if must!=0 then EOF causes query for next input volume file
*/
static int
{
register int c;
return -1;
{
if (must)
else
{
return -1;
}
}
return 0;
}
/*
* sum and convert a bread()/bget() chunk
*/
static void
{
{
else
{
}
}
if (o)
{
if (t != f)
memcpy(t, f, n);
}
}
/*
* buffered char input
* at least n chars required, m chars max
* if b is 0 then n chars are skipped
* if must!=0 then EOF causes query for next input volume file
*/
{
register char* s = (char*)ob;
register ssize_t c;
char* b;
register off_t r;
register off_t z;
return -1;
if (ob)
if (m <= 0)
m = n;
b = s;
r = m;
{
if (!s)
{
if (must)
{
return -1;
}
else
{
if (c < 0)
else
break;
}
}
s += c;
r -= c;
}
else
for (;;)
{
{
if (c > 0)
{
if (ob)
s += c;
r -= c;
}
if (!ob && ap->sum <= 0 && ap->io->seekable && (z = r / BUFFERSIZE) && lseek(ap->io->fd, z *= BUFFERSIZE, SEEK_CUR) >= 0)
{
s += z;
r -= z;
}
break;
}
else
{
s += r;
r = 0;
break;
}
}
if (r < n)
{
if (ob && r)
{
return 0;
}
return -1;
}
#if DEBUG
if (ob)
message((-7, "bread(%s,%I*d@%I*d) %s: %s", ap->name, sizeof(r), r, sizeof(ap->io->count), ap->io->count, bstatus(ap->io), show(b, r)));
else
message((-7, "bread(%s) skip(%I*d@%I*d) %s", ap->name, sizeof(r), r, sizeof(ap->io->count), ap->io->count, bstatus(ap->io)));
#endif
return r;
}
/*
* pushback for next bread()
*/
void
{
{
if (b)
}
message((-7, "bunread(%s,%d@%I*d) %s: %s", ap->name, n, sizeof(ap->io->count), ap->io->count, bstatus(ap->io), show(ap->io->next, n)));
}
/*
* O_RDONLY bread() n chars and return a pointer to the char buffer
* O_WRONLY return output buffer pointer and available size
*/
char*
{
register char* b;
char* t;
size_t i;
size_t j;
size_t m;
int must;
{
if (p)
}
if (n < 0)
{
n = -n;
must = 0;
}
else if (n > 0)
must = 1;
else
{
{
n = 0;
}
if (p)
*p = n;
}
{
message((-8, "bget(%s,%I*d,%d): reallocate %u=>%d", ap->name, sizeof(n), n, must, ap->io->buffersize, m));
{
}
}
if (p)
*p = n;
{
{
if (m = b - t)
{
while (i > m)
{
message((-8, "bget(%s,%I*d,%d) overlapping memcpy n=%I*d i=%d m=%d next=%p last=%p", ap->name, sizeof(n), n, must, sizeof(n), n, i, m, ap->io->next + n, ap->io->last));
memcpy(t, b, m);
t += m;
b += m;
i -= m;
}
memcpy(t, b, i);
}
}
return 0;
}
message((-7, "bget(%s,%I*d@%I*d,%d): %s", ap->name, sizeof(n), n, sizeof(ap->io->count), ap->io->count, must, show(b, n)));
return b;
}
#ifndef bsave
/*
* save current position for possible backup()
*/
void
{
}
#endif
/*
* back up input to bsave()'d position and prime output buffer
*/
void
{
register off_t n;
register off_t m;
#ifdef MTIOCTOP
#endif
else
{
{
/*
* same buffer window
*/
{
#ifdef MTIOCTOP
goto bad;
#else
goto bad;
#endif
}
}
else
}
return;
bad:
}
/*
* flush buffered input
*/
void
{
{
}
}
/*
* buffered seek
*/
{
off_t l;
off_t u;
if (hard)
{
return -1;
}
else
{
{
return -1;
{
}
}
return -1;
{
}
}
if ((u = lseek(ap->io->fd, ap->io->offset + pos, op)) < 0 && (op != SEEK_SET || (u = pos - ap->io->count) < 0 || u > 0 && bread(ap, NiL, u, u, 1) != u || !(u += ap->io->count + ap->io->offset)))
return -1;
}
/*
* flush buffered output
*/
void
{
register int n;
register int c;
{
{
if (c <= 0)
else
{
n -= c;
}
}
}
}
/*
* buffered output
*/
void
{
register char* b = (char*)ab;
register long c;
long an;
{
}
{
}
{
#if DEBUG
if (n > 0)
message((-7, "bwrite(%s,%I*d@%I*d): %s", ap->name, sizeof(n), n, sizeof(ap->io->count), ap->io->count + n, show(b, n)));
else
message((-7, "bwrite(%s,%I*d@%I*d):", ap->name, sizeof(n), n, sizeof(ap->io->count), ap->io->count + n));
#endif
{
if (n <= 0)
{
#ifdef MTIOCTOP
{
break;
}
#endif
}
if (c <= 0)
else if ((n -= c) > 0)
b += c;
else
break;
}
}
else
{
#if DEBUG
if (n > 0)
message((-7, "bwrite(%s,%I*d@%I*d): %s", ap->name, sizeof(n), n, sizeof(ap->io->count), ap->io->count + n, show(b, n)));
else
message((-7, "bwrite(%s,%I*d@%I*d):", ap->name, sizeof(n), n, sizeof(ap->io->count), ap->io->count + n));
#endif
for (;;)
{
{
if (c)
{
n -= c;
b += c;
}
{
if (c <= 0)
else
{
break;
}
}
}
else
{
break;
}
}
}
}
/*
* bwrite() n chars that have been placed in the
* buffer returned by a previous bget()
*/
void
{
message((-7, "bput(%s,%I*d@%I*d): %s", ap->name, sizeof(n), n, sizeof(ap->io->count), ap->io->count, show(ap->io->next, n)));
{
/*
* flush out the buffer and slide over the remains
*/
}
}
/*
* return recommended io block size for fd
* 0 returned for no recommendation
*/
long
{
#ifdef MTIOCGETBLKINFO
#else
return 0;
#endif
}
static struct
{
char* path;
} dev;
/*
* called by ftwalk()
*/
static int
{
if (ftw->info == FTW_F && ftw->statb.st_rdev == dev.st->st_rdev && S_ISCHR(ftw->statb.st_mode) == S_ISCHR(dev.st->st_mode))
{
return 1;
}
return 0;
}
/*
* initilize tty file pointers for interactive prompting
*/
void
interactive(void)
{
int fd;
{
if (fd >= 0)
}
}
/*
* check for new input or output stream
* c is the io count causing the newio()
* n is the pending buffered io count
*/
void
{
register char* s;
register char* rw;
char* file;
char* io;
char* t;
off_t z;
int i;
{
rw = "write";
io = "output";
return;
}
else
{
rw = "read";
io = "input";
}
{
case X_IFBLK:
case X_IFCHR:
file = 0;
break;
default:
switch (c < 0 ? errno : 0)
{
case 0:
#ifdef EFBIG
case EFBIG:
#endif
#ifdef EDQUOT
case EDQUOT:
#endif
file = "file";
break;
default:
break;
}
else
file = "file";
break;
}
switch (c < 0 ? errno : 0)
{
case 0:
case ENOSPC:
case ENXIO:
break;
default:
break;
}
else
{
}
file = 0;
if (file && ap->name != definput && ap->name != defoutput && strmatch(ap->name, "*.+([0-9])") && (s = strrchr(ap->name, '.')) && (int)strtol(++s, NiL, 10) == ap->part)
{
/*
* the parts will be ap->name in sequence
* the first part realloc the name with
* enough sequence space
*/
{
nospace();
}
if ((ap->io->fd = open(ap->name, ap->io->mode|O_BINARY, st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))) >= 0)
goto nextpart;
}
file = 0;
{
for (;;)
{
interactive();
{
finish(2);
}
if (*s)
{
if (!file)
break;
if ((ap->io->fd = open(s, ap->io->mode|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) >= 0)
break;
}
}
}
if (!file)
{
for (;;)
{
{
nospace();
nospace();
}
else
{
interactive();
if (eomprompt)
}
if (!s)
finish(2);
if (*s == '!')
{
static char* last;
if (*++s)
{
if (last)
}
else
s = last;
if (!s)
else if (n = system(s))
}
{
if ((ap->io->fd = open(file, ap->io->mode|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) >= 0)
break;
{
if (!*t && (ap->io->fd = open(file, ap->io->mode|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) >= 0)
break;
}
}
else
}
if (cp)
if (pp)
error(1, "continuing %s %d %s on %s", ap->part == ap->volume + 1 ? "volume" : "part", ap->part, io, ap->name);
}
else
}