~nabijaczleweli/foreports

14c7148c0cfa0da4d3d2fae30c136c5e4d9c89e2 — наб 16 days ago 08def26 trunk
Port ar
4 files changed, 157 insertions(+), 147 deletions(-)

A .gitignore
A LICENCE
M README.md
M ar.c
A .gitignore => .gitignore +3 -0
@@ 0,0 1,3 @@
*
!LICENCE
!*.*

A LICENCE => LICENCE +1 -0
@@ 0,0 1,1 @@
ar.c: original under 4-clause BSD licence following Caldera/SCO Group ancient UNIX release, modifications public domain

M README.md => README.md +6 -5
@@ 1,13 1,14 @@
# foreports
Forward-ports of ancient UNIX programs

## [`ar.c`](ar.c)
## [`ar`](ar.c)
1BSD is primarily distributed as 
```
./s1/cont.a:   old 16-bit-int little-endian archive
./man1/cont.a: old 16-bit-int little-endian archive
s1/cont.a:   old 16-bit-int little-endian archive
man1/cont.a: old 16-bit-int little-endian archive
```
Which neither LLVM nor GNU binutils can read; this is 2BSD ar, ported and working at least R/O.

[original](TODO): tar -xaf https://ftp.okass.net/pub/mirror/minnie.tuhs.org/Distributions/UCB/2bsd.tar.gz misc/ar.c
[original](//git.sr.ht/~nabijaczleweli/foreports/tree/08def261ae73dc292ed344d65ddc45a1787207fd/ar.c): tar -xaf https://ftp.okass.net/pub/mirror/minnie.tuhs.org/Distributions/UCB/2bsd.tar.gz misc/ar.c

Port should work on big-endian hosts, too, but who knows. Uses unaligned reads.
Uses unaligned reads.

M ar.c => ar.c +147 -142
@@ 1,39 1,73 @@
/* 2BSD ar modified to build on a modern system; non-obvious issue: longs are in middle-endian */
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
void setcom(int (*fun)());
void init(void);
void usage(void);
void noar(void);
void notfound(void);
void cleanup(void);
void install(void);
void movefil(int f);
void copyfil(int fi, int fo, int flag);
void bamatch(void);
void phserr(void);
void mesg(char c);
void longt(void);
void pmode(void);
void select_(int *pairp);
int main(int argc, char *argv[]);
int getaf(void);
int stats(void);
int getdir(void);
int match(void);
int equal(const char *s1, const char *s2);
char *trim(char *s);


#define	NARMAG	0177545
struct
struct __attribute__((packed))
{
	char	name[14];
	long	date;
	char	uid;
	char	gid;
	int	mode;
	long	size;
	char	name[14];  // char	name[14];
	unsigned int	date;  // long	date;
	unsigned char	uid;  // char	uid;
	unsigned char	gid;  // char	gid;
	unsigned short	mode;  // int	mode;
	int	size;  // long	size;
} arbuf;
struct
{
	char	minor;
	char	major;
	int	inumber;
	int	flags;
	char	nlinks;
	char	usrid;
	char	grpid;
	char	siz0;
	int	siz1;
	int	addr[8];
	long	adate;
	long	mdate;
} stbuf;

struct stat stbuf;
// {
// 	char	minor;
// 	char	major;
// 	int	inumber;
// 	int	flags;
// 	char	nlinks;
// 	char	usrid;
// 	char	grpid;
// 	char	siz0;
// 	int	siz1;
// 	int	addr[8];
// 	long	adate;
// 	long	mdate;
// } stbuf;

#define	SKIP	1
#define	IODD	2
#define	OODD	4
#define	HEAD	8

char	*man	{ "mrxtdp" };
char	*opt	{ "uvnbai" };
const char	*man	= "mrxtdp";
const char	*opt	= "uvnbai";

long	itol();
int	done();
void	done();
int	rcmd();
int	dcmd();
int	xcmd();


@@ 56,16 90,14 @@ int	tf;
int	tf1;
int	tf2;
int	bastate;
int	buf[256];
unsigned short	buf[256];

main(argc, argv)
char *argv[];
int main(int argc, char *argv[])
{
	register i;
	register char *cp;
	char *cp;

	for(i=1; i<4; i++)
		if((signal(i, 1) & 1) == 0)
	for(int i=1; i<4; i++)
		if(signal(i, SIG_IGN) != SIG_IGN)
			signal(i, done);
	if(argc < 3)
		usage();


@@ 134,10 166,8 @@ char *argv[];
	done();
}

setcom(fun)
int (*fun)();
void setcom(int (*fun)())
{

	if(comfun != 0) {
		printf("only one of [%s] allowed\n", man);
		done();


@@ 145,27 175,25 @@ int (*fun)();
	comfun = fun;
}

rcmd()
int rcmd(void)
{
	register f;

	init();
	if(getaf()) {
		printf("creating %s\n", arnam);
		cleanup();
		return;
		return 0;
	}
	while(!getdir()) {
		bamatch();
		if(namc == 0 || match()) {
			f = stats();
			int f = stats();
			if(f < 0) {
				if(namc)
					printf("cannot open %s\n", file);
				goto cp;
			}
			if(flg['u'-'a'])
				if(stbuf.mdate <= arbuf.date) {
				if(stbuf.st_mtime <= arbuf.date) {
					close(f);
					goto cp;
				}


@@ 179,11 207,11 @@ rcmd()
		copyfil(af, tf, IODD+OODD+HEAD);
	}
	cleanup();
	return 0;
}

dcmd()
int dcmd(void)
{

	init();
	if(getaf())
		noar();


@@ 197,17 225,16 @@ dcmd()
		copyfil(af, tf, IODD+OODD+HEAD);
	}
	install();
	return 0;
}

xcmd()
int xcmd(void)
{
	register f;

	if(getaf())
		noar();
	while(!getdir()) {
		if(namc == 0 || match()) {
			f = creat(file, arbuf.mode & 0777);
			int f = creat(file, arbuf.mode & 0777);
			if(f < 0) {
				printf("%s cannot create\n", file);
				goto sk;


@@ 221,11 248,11 @@ xcmd()
		mesg('c');
		copyfil(af, -1, IODD+SKIP);
	}
	return 0;
}

pcmd()
int pcmd(void)
{

	if(getaf())
		noar();
	while(!getdir()) {


@@ 237,11 264,11 @@ pcmd()
		}
		copyfil(af, -1, IODD+SKIP);
	}
	return 0;
}

mcmd()
int mcmd(void)
{

	init();
	if(getaf())
		noar();


@@ 263,11 290,11 @@ mcmd()
		copyfil(af, tf, IODD+OODD+HEAD);
	}
	install();
	return 0;
}

tcmd()
int tcmd(void)
{

	if(getaf())
		noar();
	while(!getdir()) {


@@ 278,11 305,11 @@ tcmd()
		}
		copyfil(af, -1, IODD+SKIP);
	}
	return 0;
}

init()
void init(void)
{

	tfnam = mktemp("/tmp/vXXXXX");
	close(creat(tfnam, 0600));
	tf = open(tfnam, 2);


@@ 297,9 324,8 @@ init()
	}
}

getaf()
int getaf(void)
{

	af = open(arnam, 0);
	if(af < 0)
		return(1);


@@ 312,51 338,45 @@ getaf()
	return(0);
}

usage()
void usage(void)
{
	printf("usage: ar [%s][%s] archive files ...\n", opt, man);
	done();
}

noar()
void noar(void)
{

	printf("%s does not exist\n", arnam);
	done();
}

done()
void done()
{

	if(tfnam)
		unlink(tfnam);
	if(tf1nam)
		unlink(tf1nam);
	if(tf2nam)
		unlink(tf2nam);
	exit();
	exit(-1);
}

notfound()
void notfound(void)
{
	register i;

	for(i=0; i<namc; i++)
	for(int i=0; i<namc; i++)
		if(namv[i])
			printf("%s not found\n", namv[i]);
}

cleanup()
void cleanup(void)
{
	register i, f;

	for(i=0; i<namc; i++) {
	for(int i=0; i<namc; i++) {
		file = namv[i];
		if(file == 0)
			continue;
		namv[i] = 0;
		mesg('a');
		f = stats();
		int f = stats();
		if(f < 0) {
			printf("%s cannot open\n", file);
			continue;


@@ 366,26 386,26 @@ cleanup()
	install();
}

install()
void install(void)
{
	register i;
	int i;

	for(i=1; i<4; i++)
		signal(i, 1);
		signal(i, SIG_IGN);
	close(af);
	af = creat(arnam, 0644);
	if(af < 0) {
		printf("cannot create %s\n", arnam);
		done();
	}
	seek(tf, 0, 0);
	lseek(tf, 0, 0);
	while((i = read(tf, buf, 512)) > 0)
		if(write(af, buf, i) != i) {
			perror(arnam);
			done();
		}
	if(tf2nam) {
		seek(tf2, 0, 0);
		lseek(tf2, 0, 0);
		while((i = read(tf2, buf, 512)) > 0)
			if(write(af, buf, i) != i) {
				perror(arnam);


@@ 393,7 413,7 @@ install()
			}
	}
	if(tf1nam) {
		seek(tf1, 0, 0);
		lseek(tf1, 0, 0);
		while((i = read(tf1, buf, 512)) > 0)
			if(write(af, buf, i) != i) {
				perror(arnam);


@@ 406,29 426,24 @@ install()
 * insert the file 'file'
 * into the temporary file
 */
movefil(f)
void movefil(int f)
{
	register char *cp;
	register i;

	cp = trim(file);
	for(i=0; i<14; i++)
		if(arbuf.name[i] = *cp)
	char *cp = trim(file);
	for(int i=0; i<14; i++)
		if((arbuf.name[i] = *cp))
			cp++;
	arbuf.size = itol(stbuf.siz0&0377, stbuf.siz1);
	arbuf.date = stbuf.mdate;
	arbuf.uid = stbuf.usrid;
	arbuf.gid = stbuf.grpid;
	arbuf.mode = stbuf.flags;
	arbuf.size = stbuf.st_size;
	arbuf.date = stbuf.st_mtime;
	arbuf.uid = stbuf.st_uid;
	arbuf.gid = stbuf.st_gid;
	arbuf.mode = stbuf.st_mode;
	copyfil(f, tf, OODD+HEAD);
	close(f);
}

stats()
int stats(void)
{
	register f;

	f = open(file, 0);
	int f = open(file, 0);
	if(f < 0)
		return(f);
	if(fstat(f, &stbuf) < 0) {


@@ 442,17 457,16 @@ stats()
 * copy next file
 * size given in arbuf
 */
copyfil(fi, fo, flag)
void copyfil(int fi, int fo, int flag)
{
	register i, o;
	int pe;
	int i, o;

	if((flag & HEAD) && fo >= 0)
		if(write(fo, &arbuf, sizeof arbuf) != sizeof arbuf) {
			perror("write");
			done();
		}
	pe = 0;
	int pe = 0;
	while(arbuf.size > 0) {
		i = o = 512;
		if(arbuf.size < i) {


@@ 471,17 485,15 @@ copyfil(fi, fo, flag)
				perror("write");
				done();
			}
		arbuf.size =- 512;
		arbuf.size -= 512;
	}
	if(pe)
		phserr();
}

getdir()
int getdir(void)
{
	register i;

	i = read(af, &arbuf, sizeof arbuf);
	int i = read(af, &arbuf, sizeof arbuf);
	if(i != sizeof arbuf) {
		if(tf1nam) {
			i = tf;


@@ 490,17 502,17 @@ getdir()
		}
		return(1);
	}
	arbuf.size = ((unsigned int)(*(unsigned short *)&arbuf.size) << 16) | ((unsigned int)(*((unsigned short *)&arbuf.size + 1)));
	arbuf.date = ((unsigned int)(*(unsigned short *)&arbuf.date) << 16) | ((unsigned int)(*((unsigned short *)&arbuf.date + 1)));
	for(i=0; i<14; i++)
		name[i] = arbuf.name[i];
	file = name;
	return(0);
}

match()
int match(void)
{
	register i;

	for(i=0; i<namc; i++) {
	for(int i=0; i<namc; i++) {
		if(namv[i] == 0)
			continue;
		if(equal(trim(namv[i]), file)) {


@@ 512,9 524,9 @@ match()
	return(0);
}

bamatch()
void bamatch(void)
{
	register f;
	int f;

	switch(bastate) {



@@ 539,10 551,9 @@ bamatch()
	}
}

equal(s1, s2)
char *s1, *s2;
int equal(const char *s1, const char *s2)
{
	register char *p1, *p2;
	const char *p1, *p2;

	p1 = s1;
	p2 = s2;


@@ 552,24 563,21 @@ char *s1, *s2;
	return(0);
}

phserr()
void phserr(void)
{

	printf("phase error on %s\n", file);
}

mesg(c)
void mesg(char c)
{

	if(flg['v'-'a'])
		if(c != 'c' || flg['v'-'a'] > 1)
			printf("%c - %s\n", c, file);
}

trim(s)
char *s;
char *trim(char *s)
{
	register char *p1, *p2;
	char *p1, *p2;

	for(p1 = s; *p1; p1++)
		;


@@ 601,40 609,37 @@ char *s;
#define	XOTH	01
#define	STXT	01000

longt()
void longt(void)
{
	register char *cp;
	register t;
	char *cp;

	pmode();
	printf("%3d/%1d", arbuf.uid&0377, arbuf.gid&0377);
	printf("%6s", locv(arbuf.size));
	cp = ctime(&arbuf.date);
	printf("%6d", arbuf.size);
	time_t d = arbuf.date;
	cp = ctime(&d);
	printf(" %-12.12s %-4.4s ", cp+4, cp+20);
}

int	m1[] { 1, ROWN, 'r', '-' };
int	m2[] { 1, WOWN, 'w', '-' };
int	m3[] { 2, SUID, 's', XOWN, 'x', '-' };
int	m4[] { 1, RGRP, 'r', '-' };
int	m5[] { 1, WGRP, 'w', '-' };
int	m6[] { 2, SGID, 's', XGRP, 'x', '-' };
int	m7[] { 1, ROTH, 'r', '-' };
int	m8[] { 1, WOTH, 'w', '-' };
int	m9[] { 2, STXT, 't', XOTH, 'x', '-' };
int	m1[] = { 1, ROWN, 'r', '-' };
int	m2[] = { 1, WOWN, 'w', '-' };
int	m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
int	m4[] = { 1, RGRP, 'r', '-' };
int	m5[] = { 1, WGRP, 'w', '-' };
int	m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
int	m7[] = { 1, ROTH, 'r', '-' };
int	m8[] = { 1, WOTH, 'w', '-' };
int	m9[] = { 2, STXT, 't', XOTH, 'x', '-' };

int	*m[] { m1, m2, m3, m4, m5, m6, m7, m8, m9};
int	*m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};

pmode()
void pmode(void)
{
	register int **mp;

	for (mp = &m[0]; mp < &m[9];)
		select(*mp++);
	for (int **mp = &m[0]; mp < &m[9];)
		select_(*mp++);
}

select(pairp)
int *pairp;
void select_(int *pairp)
{
	register int n, *ap;