#include <stdio.h>
#ifdef hpux
#define SYSTEM5 1
#endif
#define BYTE unsigned char
#define WORD unsigned short 
#define LONG long 
#define FAST register
#define VOID int
#define BOOL int
#define COUNT int 
#define GLOBAL
#define IMPORT extern
#define LOCAL static
#define YES 1
#define NO 0
#define QUIT_SHUTDOWN 1 
#define PATHSIZE 80 
#ifndef NULL
#define NULL 0
#endif
#define BU_FNSZ 72 
#define BU_MAXRSZ 256 
#define BU_VERSZ 4 
#define BU_MAXBUCK 1024 
#define BU_HDRSZ 154 
#define CKPT_OKAY 0 
#define CKPT_INITIATE 1 
struct DIR {
LONG syn_next; 
LONG dfirst; 
LONG dlast; 
WORD fdate; 
WORD ftime; 
LONG fsize; 
WORD ddate; 
WORD dtime; 
BYTE dattr; 
BYTE fname[BU_FNSZ]; 
};
struct HDR {
BYTE version[BU_VERSZ]; 
WORD recsize; 
WORD buckets; 
BYTE hrec_count; 
WORD hblocking; 
LONG free_first; 
LONG free_last; 
LONG file_last; 
WORD bu_date; 
WORD bu_time; 
BYTE c_status; 
BYTE c_dupname; 
LONG c_prior; 
LONG c_current; 
LONG c_bucket; 
LONG c_nfirst; 
LONG c_newdir; 
LONG c_odfirst; 
LONG c_odlast; 
struct DIR c_dir; 
};
LONG htab[BU_MAXBUCK] = {0}; 
BYTE bu_rec[BU_MAXRSZ] = {0}; 
BYTE bu_rec2[BU_MAXRSZ] = {0}; 
BYTE *bu_ptr = {0}; 
LONG bu_link = {0}; 
GLOBAL struct DIR dir = {0}; 
GLOBAL struct HDR hdr = {0}; 
LONG prior = {0}; 
LONG current = {0}; 
LONG bucket = {0}; 
GLOBAL WORD ferrno = {0}; 
GLOBAL char *ferrtx = {0}; 
long file_size();
BYTE Bread();
BYTE bgchar();
WORD bgword();
LONG bglink();
LONG bglong();
GLOBAL LONG host_rec_len = 0;
#define NOON 0x6000 
#define ONE_PM 0x7000 
#define PC_FILE_SPEC_SIZE 81
#define BACKUP_FILE_NAME_SIZE 81
char backup_file_name[BACKUP_FILE_NAME_SIZE] = "BACKUP";
char pc_file_spec[PC_FILE_SPEC_SIZE] = "\\*.*";
char display_buf[78];
char display_init1[] = {"     Size =          Create/Mod =   -  -      :   "};
char display_init2[] = {"  Backup =   -  -      :   "};
int sub_search = NO;
int name_only = NO;
VOID main(ac, av)
int ac;
char **av;
{
BOOL more;
int i, j;
parse_parms(ac, av);
if (!Binit(backup_file_name, NO))
printf("UNABLE TO OPEN BACKUP FILE - '%s'\n",backup_file_name);
else
if (!Bopenf(pc_file_spec, sub_search))
printf("NO PC FILES FOUND FOR - %s %s\n",pc_file_spec,
((sub_search)? "/s": ""));
else
{
for (i = 0; (display_init1[i] != 0); i++)
display_buf[i] = display_init1[i];
for (j = 0; (display_init2[j] != 0); j++)
{
display_buf[i] = display_init2[j];
i++;
}
display_buf[77] = NULL;
do
display_file_info();
while (more = Bopenn());
}
}
VOID parse_parms(argc, argv)
int argc;
char **argv;
{
char *argp;
int i;
if (argc < 2)
return;
parse_10:
argp = *++argv;
if (*argp != '\\')
goto parse_20;
for (i = 0; *argp != 0; ++argp)
{
if ((*argp >= 97) && (*argp <= 122))
pc_file_spec[i] = (*argp - 32);
else
pc_file_spec[i] = *argp;
i = i + 1;
}
pc_file_spec[i] = '\000';
argp = *++argv;
parse_20:
if (argp == 0)
return;
if (*argp == '/')
goto parse_30;
for (i = 0; *argp != 0; ++argp)
{
backup_file_name[i] = *argp;
i = i + 1;
}
backup_file_name[i] = '\000';
argp = *++argv;
parse_30:
if (argp == 0)
return;
if (*argp != '/')
{
argp = *++argv;
goto parse_30;
}
++argp;
if ((*argp == 'S') || (*argp == 's'))
sub_search = YES;
if ((*argp == 'N') || (*argp == 'n'))
name_only = YES;
goto parse_30;
}
VOID display_file_info()
{
int i;
char ch;
printf("%s\n", dir.fname);
if (!name_only)
{
convert_size(dir.fsize, &display_buf[12]);
convert_word(((dir.ddate >> 5) & 0x000F), &display_buf[34], YES);
convert_word((dir.ddate & 0x001F), &display_buf[37], NO);
convert_word(((dir.ddate >> 9) + 80), &display_buf[40], NO);
if (dir.dtime >= NOON)
{
display_buf[49] = 'p';
if (dir.dtime >= ONE_PM)
dir.dtime = (dir.dtime - NOON);
}
else
{
display_buf[49] = 'a';
}
convert_word((dir.dtime >> 11), &display_buf[44], YES);
convert_word(((dir.dtime >> 5) & 0x003F), &display_buf[47], NO);
convert_word(((dir.fdate >> 5) & 0x000F), &display_buf[61], YES);
convert_word((dir.fdate & 0x001F), &display_buf[64], NO);
convert_word(((dir.fdate >> 9) + 80), &display_buf[67], NO);
if (dir.ftime >= NOON)
{
display_buf[76] = 'p';
if (dir.ftime >= ONE_PM)
dir.ftime = (dir.ftime - NOON);
}
else
{
display_buf[76] = 'a';
}
convert_word((dir.ftime >> 11), &display_buf[71], YES);
convert_word(((dir.ftime >> 5) & 0x003F), &display_buf[74], NO);
printf("%s\n", display_buf);
}
}
VOID convert_size(lg, dest_ptr)
LONG lg;
char *dest_ptr;
{
int i;
char *ptr;
LONG l;
for (ptr = dest_ptr; ptr < (dest_ptr + 7); ptr++)
*ptr = ' ';
for (l = 1000000; l >= 10; l = l / 10)
{
if ((lg / l % 10) != 0)
break;
}
for (; l >= 1; l = l / 10)
*dest_ptr++ = ((lg / l % 10) | 0x30);
}
VOID convert_word(wd, dest_ptr, suppress_leading_zero)
WORD wd;
char *dest_ptr;
BOOL suppress_leading_zero;
{
*dest_ptr = (((wd / 10 % 10) | 0x30) & 0x3F);
if (suppress_leading_zero && (*dest_ptr == 0x30))
*dest_ptr = 0x20;
*++dest_ptr = (wd % 10) | 0x30;
}
VOID shutdown(errcode, errtext)
WORD errcode;
BYTE *errtext;
{
quit(QUIT_SHUTDOWN);
}
VOID quit(i)
{
exit(i);
}
#ifdef SYSTEM5
#include <fcntl.h>
#endif
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
extern int errno; 
static int u_fd = -1; 
static int u_eof = NO; 
VOID file_open(fn)
char *fn; 
{
u_eof = NO;
u_fd = fl_open(fn, 0); 
}
int file_read(buf, blen)
char *buf; 
int blen; 
{
int i;
if (u_eof)
return(0);
if ((i = fl_read(u_fd, buf, blen)) != blen)
u_eof = YES;
return(i);
}
int file_close()
{
return(fl_close(u_fd));
}
long file_size(fn)
char *fn; 
{
struct stat sbuf;
if (stat(fn, &sbuf) == -1)
{
ferrno = errno;
ferrtx = "stat() failed";
#ifdef ENOTDIR
if (errno == ENOTDIR)
ferrtx = "a component of the path prefix is not a directory.";
#endif
#ifdef ENOENT
if (errno == ENOENT)
return(-1L);
#endif
#ifdef EACCES
if (errno == EACCES)
ferrtx = "read permission is denied for the specified file.";
#endif
return(-2L);
}
return(sbuf.st_size);
}
static int RF_rsize = 0;
static int RF_fd = 0;
VOID RF_open(nm, rsize)
char *nm;
int rsize;
{
RF_rsize = rsize;
RF_fd = fl_open(nm, 2);
}
VOID RF_read(buf, rnum)
char *buf;
LONG rnum;
{
RF_position(rnum);
if (fl_read(RF_fd, buf, RF_rsize) != RF_rsize)
shutdown(-45, "Invalid backup file record.");
}
int RF_close()
{
return(fl_close(RF_fd));
}
VOID RF_position(rnum)
LONG rnum; 
{
long rval;
long lseek();
if ((rval = lseek(RF_fd, rnum * RF_rsize, 0)) == -1L)
{
ferrno = errno;
ferrtx = "lseek failed.";
#ifdef EBADF
if (errno == EBADF)
ferrtx = "lseek: invalid file handle.";
#endif
#ifdef EINVAL
if (errno == EINVAL)
ferrtx = "lseek: invalid origin or offset.";
#endif
shutdown(ferrno, ferrtx);
}
}
int fl_open(fn, open_flag)
char *fn;
int open_flag;
{
int r_value;
#ifdef SYSTEM5
if (open_flag = 0) 
open_flag = O_RDONLY;
else 
open_flag = O_RDWR;
#endif
if ((r_value = open(fn, open_flag)) == -1)
{
ferrno = errno;
ferrtx = "open failed; file not found or inaccessible.";
#ifdef ENOTDIR
if (errno == ENOTDIR)
ferrtx = "a component of the path prefix is not a directory.";
#endif
#ifdef ENOENT
if (errno == ENOENT)
ferrtx = "the specified file does not exist.";
#endif
#ifdef EACCES
if (errno == EACCES)
ferrtx = "read permission is denied for the specified file.";
#endif
shutdown(ferrno, ferrtx);
}
return(r_value);
}
int fl_close(fd)
int fd;
{
if (close(fd) == -1)
{
ferrno = errno;
ferrtx = "close failed.";
#ifdef EBADF
if (errno == EBADF)
ferrtx = "close: bad file handle.";
#endif
return(-1);
}
else
return(0);
}
int fl_read(fd, buf, blen)
int fd;
char *buf; 
int blen; 
{
int i, progress;
progress = 0;
for (i = 1; (i >= 1) && blen; buf += i, blen -= i, progress += i)
i = read(fd, buf, blen);
if (i == -1)
shutdown(errno, "read failed.");
return(progress);
}
BOOL Binit(fname, create_it, rec_size, ibuckets)
char *fname;
BOOL create_it;
int rec_size, ibuckets;
{
int i;
if (file_size(fname) < BU_HDRSZ)
return(NO);
file_open(fname);
file_read(bu_rec, BU_HDRSZ); 
hdr_read();
if (file_close() == -1)
shutdown(ferrno, ferrtx);
RF_open(fname, hdr.recsize);
if (hdr.c_status != CKPT_INITIATE)
for (i = 1; i <= hdr.hrec_count; ++i)
hash_read((LONG) i);
if (hdr.c_status != CKPT_OKAY)
return(NO);
return(YES);
}
BOOL Bopenf(path, subdirs_ok)
char *path;
BOOL subdirs_ok;
{
if (Bcompile(path, subdirs_ok)) 
{
if (!Bposition((WORD) 0, YES)) 
return(NO);
while (!Bmatch(dir.fname))
{
if (!Badvance(YES)) 
return(NO);
}
return(YES);
}
else
return(Blookup(path));
}
BOOL Bopenn()
{
while (Badvance(YES))
{
if (Bmatch(dir.fname))
return(YES);
}
return(NO);
}
BYTE Bread()
{
return(bgchar());
}
BOOL Badvance(keep_going)
BOOL keep_going;
{
prior = current;
current = dir.syn_next;
if (current > 0L)
{
dir_read(current);
return(YES);
}
if (!keep_going)
return(NO);
return(Bposition((WORD) bucket+1, YES));
}
WORD Bhash(name)
char *name;
{
WORD hash_value;
int i;
hash_value = 0;
while (*name)
hash_value += *name++;
return(hash_value % hdr.buckets);
}
BOOL Blookup(name)
char *name;
{
int rval;
if (!Bposition(Bhash(name), NO))
return(NO);
while ((rval = strncmp(name, dir.fname, BU_FNSZ)) > 0) 
{
if (!Badvance(NO))
return(NO);
}
return(rval == 0);
}
BOOL Bposition(hash_value, keep_going)
WORD hash_value;
BOOL keep_going;
{
prior = 0; 
current = 0;
for (bucket = hash_value; bucket < hdr.buckets; ++bucket)
{
current = htab[bucket];
if (current > 0L)
{
dir_read(current);
return(YES);
}
if (!keep_going)
return(NO);
}
return(NO);
}
#define SD_CHAR '\\' 
#define AUTOSIZE 300
#define SUBDIR '\001'
#define FCHAR 'C'
#define FDOT 'D'
#define FANY 'A'
#define FSUBDIR 'S'
#define FSUCCEED 'Y'
#define FFAIL 'F'
LOCAL BYTE autotab[AUTOSIZE+1] = {0};
LOCAL BYTE *autoix = NULL;
LOCAL add_chr(c)
BYTE c;
{
if (autoix >= autotab + AUTOSIZE)
shutdown(-35, "Internal error.");
*autoix++ = c;
}
BOOL Bcompile(pname, subs_ok)
FAST BYTE *pname;
BOOL subs_ok;
{
FAST BYTE *p, *q, *r;
COUNT i;
BOOL wild = NO;
BYTE buf[PATHSIZE+2];
if ((i = strlen(pname)) > PATHSIZE || i < 1)
shutdown(-46, "Internal error.");
if (subs_ok)
{
for (p = q = pname; *p; ++p)
if (*p == SD_CHAR)
q = p + 1;
for (p = buf; pname < q;)
*p++ = *pname++;
*p++ = SUBDIR;
while (*p++ = *pname++)
;
pname = buf;
}
for (autoix = autotab; *pname; ++pname)
switch (*pname)
{
case '*':
for (i = 0; i < 8; ++i)
add_chr(FANY);
while (*pname != '.' && *pname != SD_CHAR && *pname)
++pname;
--pname;
wild = YES;
break;
case '?':
add_chr(FANY);
wild = YES;
break;
case SUBDIR:
add_chr(FSUBDIR);
wild = YES;
break;
case '.':
add_chr(FDOT);
break;
default:
add_chr(FCHAR);
add_chr(*pname);
}
if (wild)
{
add_chr(FCHAR);
add_chr(NULL);
add_chr(FSUCCEED);
return(YES);
}
else
{
autoix = autotab;
add_chr(FFAIL);
return(NO);
}
}
BOOL Bmatch(s)
FAST BYTE *s;
{
FAST BYTE *p, *q;
for (p = autotab; ;)
switch (*p++)
{
case FCHAR:
if (*p++ != *s++)
return(NO);
break;
case FDOT:
if (*s == '.')
++s;
else if (*s)
return(NO);
break;
case FSUBDIR:
for (q = s; *q; ++q)
if (*q == SD_CHAR)
s = q + 1;
break;
case FANY:
if (*s == SD_CHAR)
return(NO);
if (*s && *s != '.')
++s;
break;
case FSUCCEED:
return(YES);
default: 
return(NO);
}
}
BYTE bgchar()
{
if ((bu_ptr - bu_rec) >= hdr.recsize)
{
RF_read(bu_rec, bu_link);
bu_link = bglink();
}
return(*bu_ptr++);
}
VOID bgstr(s, c)
BYTE *s;
int c;
{
while (c--)
*s++ = bgchar();
}
WORD bgword()
{
BYTE c;
c = bgchar();
return( (c<<8) + (bgchar() & 0xff));
}
LONG bglong()
{
WORD w;
w = bgword();
return( (((LONG) w) << 16) + (bgword() & 0xffff));
}
LONG bglink()
{
bu_ptr = bu_rec;
return(bglong());
}
VOID hdr_read()
{
bu_ptr = bu_rec;
hdr.recsize = BU_HDRSZ; 
bgstr(hdr.version, BU_VERSZ);
hdr.recsize = bgword();
hdr.buckets = bgword();
hdr.hrec_count = bgchar();
hdr.hblocking = bgword();
hdr.free_first = bglong();
hdr.free_last = bglong();
hdr.file_last = bglong();
hdr.bu_date = bgword();
hdr.bu_time = bgword();
hdr.c_status = bgchar();
hdr.c_dupname = bgchar();
hdr.c_prior = bglong();
hdr.c_current = bglong();
hdr.c_bucket = bglong();
hdr.c_nfirst = bglong();
hdr.c_newdir = bglong();
hdr.c_odfirst = bglong();
hdr.c_odlast = bglong();
hdr.c_dir.syn_next = bglong();
hdr.c_dir.dfirst = bglong();
hdr.c_dir.dlast = bglong();
hdr.c_dir.fdate = bgword();
hdr.c_dir.ftime = bgword();
hdr.c_dir.fsize = bglong();
hdr.c_dir.ddate = bgword();
hdr.c_dir.dtime = bgword();
hdr.c_dir.dattr = bgchar();
bgstr(hdr.c_dir.fname, BU_FNSZ);
}
VOID hash_read(r)
LONG r; 
{
FAST int offset, i;
RF_read(bu_rec, r);
offset = (r-1) * hdr.hblocking;
bu_ptr = bu_rec;
for (i = 0; i < hdr.hblocking; ++i)
if (offset < hdr.buckets)
htab[offset++] = bglong();
}
VOID dir_read(r)
LONG r;
{
RF_read(bu_rec, r);
dir.syn_next = bglink();
dir.dfirst = bglong();
dir.dlast = bglong();
dir.fdate = bgword();
dir.ftime = bgword();
dir.fsize = bglong();
dir.ddate = bgword();
dir.dtime = bgword();
dir.dattr = bgchar();
bgstr(dir.fname, BU_FNSZ);
bu_ptr = bu_rec + hdr.recsize + 1; 
bu_link = dir.dfirst; 
}
