[net.sources] public domain portable archiver

mark@cbosgd.UUCP (Mark Horton) (07/17/84)

Enclosed is a pair of programs to pack and unpack in the portable
archive format.  For chicken-and-egg reasons, they are in shell
archive format.

echo x - Makefile
cat >Makefile <<'!Funky!Stuff!'

par:	arwrite.o main.o
	cc -o par main.o arwrite.o
unpar:	unpar.o
	cc -o unpar unpar.o
clean:
	rm par unpar *.o
!Funky!Stuff!
echo x - README
cat >README <<'!Funky!Stuff!'
These programs pack and unpack files in the portable archive format.
This format is compatible with the ar command on 4BSD and System V
release 2.  These programs are available for use by anyone without
fee or license.

The par program packs into portable archive format.  The files to
write are named on the command line, the resulting archive is
written on stdout:
	par file1 file2 ... filen > files.a

The unpar program unpacks from stdin and writes the named files
out directly:
	unpar < files.a
!Funky!Stuff!
echo x - arwrite.c
cat >arwrite.c <<'!Funky!Stuff!'
/*
 *		COPYRIGHT (c) HEWLETT-PACKARD COMPANY, 1984
 *
 *	Permission is granted for unlimited modification, use, and
 *	distribution except that this software may not be sold for
 *	profit.  No warranty is implied or expressed.
 *
 *Author:
 *	Paul Bame, HEWLETT-PACKARD LOGIC SYSTEMS DIVISION - Colorado Springs
 *	{ ihnp4!hpfcla | hplabs | harpo!hp-pcd }!hp-lsd!paul
 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#define ARFMAG "`\n"
#define ARMAG "!<arch>\n"

int
arwrite(filename,stream)
char *filename;
FILE *stream;
/*
 *	Write the file denoted by 'filename' to 'stream' in portable ar format.
 *	Any stream positioning is assumed to already be done.
 *
 *	arwrite() normally returns 0 but returns -1 in case of errors.  errno
 *	may be inspected to determine the cause of the error.
 *
 *	If necessary, the stream is padded with \n's to match the even boundary
 *	condition.
 */
{
	struct stat statbuf;
	FILE *instream;
	long i;

	/* stat() the file to get the stuff for the header */
	if( stat(filename,&statbuf) < 0 )
	{
		/* error! */
		return(-1);
	}

	/* Open file for reading */
	if( (instream = fopen(filename,"r")) == NULL )
	{
		/* error! */
		return(-1);
	}

	/* Now write the header */
	/* This information gleaned from ar(4) in V.2 */
	fprintf(stream,
		"%-16s%-12ld%-6d%-6d%-8o%-10ld%2s",
		filename,
		statbuf.st_mtime,
		statbuf.st_uid,
		statbuf.st_gid,
		statbuf.st_mode,
		statbuf.st_size,
		ARFMAG
		);

	/* And copy the file */
	/*   Note that there is no error recovery here! */
	for( i = 0 ; i < statbuf.st_size ; i++ )
	{
		fputc(fgetc(instream),stream);
	}

	/* and close */
	close(instream);

	/* and pad output stream */
	if( (ftell(stream) & 0x1) != 0 )
	{
		/* if offset is odd, pad with a nuline */
		fputc('\n',stream);
	}
	return(0);
}

arhdwrite(stream)
FILE *stream;
/*
 *	Write the archive header onto 'stream'
 */
{
	fprintf(stream,"%s",ARMAG);
}
!Funky!Stuff!
echo x - main.c
cat >main.c <<'!Funky!Stuff!'
/*
 *		COPYRIGHT (c) HEWLETT-PACKARD COMPANY, 1984
 *
 *	Permission is granted for unlimited modification, use, and
 *	distribution except that this software may not be sold for
 *	profit.  No warranty is implied or expressed.
 *
 *Author:
 *	Paul Bame, HEWLETT-PACKARD LOGIC SYSTEMS DIVISION - Colorado Springs
 *	{ ihnp4!hpfcla | hplabs | harpo!hp-pcd }!hp-lsd!paul
 */
#include <stdio.h>

extern	int	arwrite();
extern		arhdwrite();

main(argc,argv)
int argc;
char *argv[];
/*
 *	Write the named files (in argv) to stdout in portable ar format.
 */
{
	int i;

	if( argc < 2 )
	{
		fprintf(stderr,"Usage: %s file1 [file...]\n",argv[0]);
		exit(1);
	}

	/* Write the header */
	arhdwrite(stdout);

	/* and the files */
	for( i = 1 ; i < argc ; i++ )
	{
		if( arwrite(argv[i],stdout) < 0 )
		{
			perror(argv[i]);
			exit(1);
		}
	}
	exit(0);
}
!Funky!Stuff!
echo x - sample
cat >sample <<'!Funky!Stuff!'
!<arch>
foo             458764309   12    0     100666  29        `
Sun Jul 15 14:31:49 EDT 1984

bar             458764313   12    0     100666  189       `
sarge    ttya    Jul 13 10:02
jgs      ttys1   Jul 15 10:45
mark     ttyp0   Jul 15 14:07	(cbosgd)
mark     ttyp1   Jul 13 09:36
mark     ttyp2   Jul 13 09:36
mark     ttyp3   Jul 13 16:57


!Funky!Stuff!
echo x - unpar.c
cat >unpar.c <<'!Funky!Stuff!'
/* unpack portable archives - written by Bill Welch */
#include <stdio.h>
#include <sys/types.h>

char buf[512];
main()
{
	char name[80];
	struct utimbuf {
		time_t actime;
		time_t modtime;
	} times;
	long mtime;
	int uid, gid, mode;
	long len, i;
	FILE *fp;

	while(gets(buf) != NULL){
		if (buf[strlen(buf) - 1] == '`') {
			printf("%s\n", buf);
			sscanf(buf, "%s %ld %d %d %o %ld", name,&mtime,&uid,&gid,
					&mode, &len);
			printf("%s %ld\n", name, len);
			fp = fopen(name, "w");
			for (i=0; i<len; i++) putc(getchar(), fp);
			fclose(fp);
			times.actime = times.modtime = mtime;
			/* If you don't have utime, just remove next 4 lines */
			if( utime(name,&times) < 0 )
			{
				perror("Can't modify date");
			}
			if( chmod(name,mode) < 0 )
			{
				perror("Can't modify mode");
			}
		}
	}
}
!Funky!Stuff!