shithub: scc

ref: 95e151ee065ec25ae3bab2b8a74a8529e72f5ee8
dir: /ar/main.c/

View raw version
static char sccsid[] = "@(#) ./ar/main.c";

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <stat.h>

#include "../inc/ar.h"
#include "../inc/arg.h"
#include "../inc/scc.h"

char *argv0;

static int bflag, iflag, vflag, cflag, lflag, uflag, aflag;
static int done;
static char *afile, *posname;

static void
cleanup(void)
{
	if (!done)
		remove(afile);
}

static void
usage(void)
{
	fputs("ar [-drqtpmx][posname] [-vuaibcl] [posname] afile name ...\n", stderr);
	exit(1);
}

FILE *
openar(char *afile)
{
	FILE *fp;
	char magic[SARMAG+1];
	struct stat st;

	if ((fp = fopen(afile,"rb")) == NULL) {
		if (!cflag)
			fprintf(stderr, "ar: creating %s\n", afile);
		if ((fopen(afile, "w+b")) == NULL)
			goto file_error;
		fputs(ARMAG, fp);
		fflush(fp);
	} else {
		if (fgets(magic, sizeof(magic), fp) == NULL)
			goto file_error;
		if (!strcmp(magic, ARMAG)) {
			fprintf(stderr,
			        "ar:%s:invalid magic number '%s'\n",
			        afile,
			        magic);
			exit(1);
		}
	}
	if (ferror(fp))
		goto file_error;
	return fp;

file_error:
	perror("ar:opening archive");
	exit(1);
}

static void
archieve(char *fname, FILE *to)
{
	int c;
	size_t n;
	FILE *from;
	char mtime[13];
	struct stat st;

	if (strlen(fname) > 16)
		fprintf(stderr, "ar:%s: too long name\n", fname);
	if (stat(fname, &st) < 0) {
		fprintf(stderr, "ar:error getting '%s' attributes\n", fname);
		exit(1);
	}
	if ((from = fopen(fname, "rb")) == NULL) {
		fprintf(stderr,
		        "ar:opening member '%s':%s\n",
		        fname,
		        strerror(errno));
		exit(1);
	}
	strftime(mtime, sizeof(mtime), "%s", gmtime(&st.st_mtime));
	fprintf(to,
	        "%-16.16s%-12s%-6u%-6u%-8o%-10llu`\n",
	        fname,
	        mtime,
	        st.st_uid,
	        st.st_gid,
	        st.st_mode,
	        st.st_size);
	for (n = 0; (c = getc(from)) != EOF; n++)
		putc(c, to);
	if (n & 1)
		putc('\n', to);
	if (ferror(from)) {
		fprintf(stderr,
		        "ar:reading input '%s':%s\n",
		        fname, strerror(errno));
		exit(1);
	}
	fclose(from);
}

static void
append(FILE *fp, char *list[])
{
	char *fname;

	if (fseek(fp, 0, SEEK_END) == EOF) {
		perror("ar:seeking archive");
		exit(1);
	}
	while ((fname = *list++) != NULL) {
		if (vflag)
			printf("a - %s\n", fname);
		archieve(fname, fp);
	}
}

int
main(int argc, char *argv[])
{
	int key, nkey = 0, pos = 0;
	FILE *fp;

	atexit(cleanup);
	ARGBEGIN {
	case 'd':
		nkey++;
		key = 'd';
		break;
	case 'r':
		key = 'r';
		break;
	case 'q':
		nkey++;
		key = 'q';
		break;
	case 't':
		nkey++;
		key = 't';
		break;
	case 'p':
		nkey++;
		key = 'p';
		break;
	case 'm':
		nkey++;
		key = 'm';
		break;
	case 'x':
		nkey++;
		key = 'x';
		break;

	case 'a':
		aflag = 1;
		pos++;
		posname = EARGF(usage());
		break;
	case 'b':
		bflag = 1;
		pos++;
		posname = EARGF(usage());
		break;
	case 'i':
		iflag = 1;
		pos++;
		posname = EARGF(usage());
		break;
	case 'v':
		vflag = 1;
		break;
	case 'c':
		cflag = 1;
		break;
	case 'l':
		lflag = 1;
		break;
	case 'u':
		uflag = 1;
		break;
	default:
		usage();
	} ARGEND

	if (nkey == 0 || nkey > 1 || pos > 1 || argc == 0)
		usage();
	afile = *argv++;
	fp = openar(afile);

	switch (key) {
	case 'q':
		append(fp, argv);
		break;
	case 'd':
	case 'r':
	case 't':
	case 'p':
	case 'm':
	case 'x':
		/* TODO */
		;
	}

	if (ferror(fp)) {
		perror("ar:error reading archive");
		exit(1);
	}


	/* TODO: check status of stdout */
	done = 1;

	return 0;

}