Interdata_v6/usr/source/cmds/arcv.c
/*
* Convert old format archives to new format
*/
char noar[] "No archive file";
char noup[] "Archive file not updated";
char nocreat[] "Can't create archive file";
char badform[] "Bad archive format";
char readio[] "Archive file read i/o error";
char inpio[] "Input file i/o error";
char tmpio[] "Temp file i/o error";
char tfname[] "/tmp/arXXXXXXX";
int magic 0177555; /* magic word to identify archive format file */
int nmagic 0177545; /* magic word for new archive format */
struct { /* old archive file header */
char fname[8];
int mtime[2];
char uid;
char mode;
int size;
} dir;
struct { /* new archive file header */
char nfname[14];
char nuid;
char ngid;
long ndate;
long nsize;
int nmode;
} ndir;
struct { /* buffer for stat() */
int s_dev;
int s_ino;
int s_flags;
char s_nlinks;
char s_uid;
char s_gid;
char s_size0;
int s_size1;
int s_addr[8];
int s_atime[2];
int s_mtime[2];
} stbuf;
char *afname; /* name of archive file */
int afmode; /* protect mode of archive file */
int afdev; /* device on which archive file resides */
int afi, tfi; /* fd for archive & temp files */
int buff[128];
int nerr; /* count of errors */
int vflag; /* 'verbose'*/
int zero; /* zero for padding */
char gid; /* group id of user */
main(argc, argv)
char *argv[];
{
extern dexit();
gid = getgid()&0377;
/* set up interrupt exit */
if ((signal(2, 1)&01) == 0) {
signal(1, &dexit);
signal(2, &dexit);
}
if (argc < 2) {
printf("Usage: arcv file ...\n");
exit(1);
}
while (--argc) {
afname = *++argv;
convert();
}
}
/*
* Convert an archive
*/
convert()
{
mktemp();
if (!getaf())
error(noar);
while (getdir()) {
msg('c');
copyfl();
}
copyback();
}
/*
* Open archive file & check format
*/
getaf()
{
if (stat(afname, &stbuf) < 0) {
afmode = 0666;
afi = -1;
return(0);
}
if ((afi = open(afname, 0)) < 0)
error("Can't open old archive file");
afmode = stbuf.s_flags & 0777;
afdev = stbuf.s_dev;
readaf(sizeof magic);
if (buff[0] != magic)
error(badform);
return(1);
}
/*
* Create temporary file
*/
mktemp()
{
register pid;
register char *p;
/* use process id to create unique name in /tmp directory */
for (p = tfname; *p; p++)
;
pid = getpid();
while (*--p == 'X') {
*p = (pid&7) + '0';
pid =>> 3;
}
/*
* create file & reopen in input/output mode
*/
if ((tfi = creat(tfname, 0600)) < 0)
error("Can't create temp file");
close(tfi);
if ((tfi = open(tfname, 2)) < 0)
error("Can't open temp file???");
/* write 'magic word' archive header */
write(tfi, &nmagic, sizeof nmagic);
}
/*
* Read from archive file, checking for i/o errors
*/
readaf(size)
{
register len;
if ((len = read(afi, buff, size)) == size)
return;
if (size < 0) /* i/o error */
error(readio);
error(badform); /* premature eof */
}
/*
* Read next file header
*/
getdir()
{
register len;
if ((len = read(afi, &dir, sizeof dir)) == sizeof dir)
return(1);
if (len == 0) /* end of file */
return(0);
if (len < 0) /* i/o error */
error(readio);
error(badform); /* premature eof */
}
/*
* Copy a file from the old archive to the temporary file
*/
copyfl()
{
register size;
register i;
/* convert the header to the new format */
for (i=0; i<sizeof(dir.fname); i++)
ndir.nfname[i] = dir.fname[i];
for (; i<sizeof(ndir.nfname); i++)
ndir.nfname[i] = '\0';
ndir.nuid = dir.uid;
ndir.ngid = gid;
ndir.nsize = dir.size;
ndir.nmode = dir.mode|0600;
ndir.ndate = dir.mtime[1];
write(tfi, &ndir, sizeof ndir);
/* copy the file */
for (size = dir.size; size >= 512; size =- 512) {
readaf(512);
write(tfi, buff, 512);
}
if (size) {
readaf(size);
write(tfi, buff, size);
}
/* pad to halfword if necessary */
if (size & 01) {
seek(afi, 1, 1);
write(tfi, &zero, 1);
}
}
/*
* Verbose option -- running commentary
*/
msg(ch)
{
if (vflag)
printf("%c %.8s\n", ch, dir.fname);
}
/*
* All finished -- replace archive with new temporary file
*/
copyback()
{
register fd, len;
/* if any errors have occured, don't update the archive */
if (nerr)
error(noup);
/* create archive file if it didn't exist before */
if (afi < 0) {
if ((fd = creat(afname, afmode)) < 0)
error(nocreat);
fstat(fd, &stbuf);
afdev = stbuf.s_dev;
close(fd);
}
else
close(afi);
/* prevent interrupts while moving back */
signal(1, 1);
signal(2, 1);
/* if temp & archive files on same device, just do a mv */
stat(tfname, &stbuf);
if (stbuf.s_dev == afdev) {
unlink(afname);
if (link(tfname, afname) < 0)
error(nocreat);
unlink(tfname);
chmod(afname, afmode);
return;
}
/* copy temp file to archive file */
if ((fd = creat(afname, afmode)) < 0)
error(nocreat);
seek(tfi, 0, 0);
while ((len = read(tfi, buff, 512)) > 0)
write(fd, buff, len);
if (len < 0)
error(tmpio);
unlink(tfname);
}
/*
* Error exit
*/
error(s)
{
printf("%s\n", s);
dexit();
}
/*
* Delete temp file & exit
*/
dexit()
{
if (tfi)
unlink(tfname);
exit(1);
}