/*
|
/*
|
* ar.c -- archiver
|
* ar.c -- archiver
|
*/
|
*/
|
|
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
#include <signal.h>
|
#include <signal.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <sys/stat.h>
|
#include <sys/stat.h>
|
#include <fcntl.h>
|
#include <fcntl.h>
|
#include <time.h>
|
#include <time.h>
|
|
|
#include "endian.h"
|
#include "endian.h"
|
#include "ranlib.h"
|
#include "ranlib.h"
|
#include "../include/ar.h"
|
#include "../include/ar.h"
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
#define BUFSIZE 512
|
#define BUFSIZE 512
|
|
|
#define SKIP 0x01
|
#define SKIP 0x01
|
#define IODD 0x02
|
#define IODD 0x02
|
#define OODD 0x04
|
#define OODD 0x04
|
#define HEAD 0x08
|
#define HEAD 0x08
|
|
|
|
|
char *com = "drqtpmx";
|
char *com = "drqtpmx";
|
char *opt = "vuabcls";
|
char *opt = "vuabcls";
|
|
|
int signums[] = { SIGHUP, SIGINT, SIGQUIT, 0 };
|
int signums[] = { SIGHUP, SIGINT, SIGQUIT, 0 };
|
|
|
void (*comfun)(void);
|
void (*comfun)(void);
|
int flg[26];
|
int flg[26];
|
|
|
char *arnam;
|
char *arnam;
|
int af;
|
int af;
|
|
|
char **namv;
|
char **namv;
|
int namc;
|
int namc;
|
|
|
int baState;
|
int baState;
|
char *posName;
|
char *posName;
|
|
|
char tmp0nam[20];
|
char tmp0nam[20];
|
char tmp1nam[20];
|
char tmp1nam[20];
|
char tmp2nam[20];
|
char tmp2nam[20];
|
char *tf0nam;
|
char *tf0nam;
|
char *tf1nam;
|
char *tf1nam;
|
char *tf2nam;
|
char *tf2nam;
|
int tf0;
|
int tf0;
|
int tf1;
|
int tf1;
|
int tf2;
|
int tf2;
|
int qf;
|
int qf;
|
|
|
char *file;
|
char *file;
|
char name[MAX_NAME];
|
char name[MAX_NAME];
|
|
|
struct stat stbuf;
|
struct stat stbuf;
|
ArHeader arbuf;
|
ArHeader arbuf;
|
unsigned char buf[BUFSIZE];
|
unsigned char buf[BUFSIZE];
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
#define IFMT 070000
|
#define IFMT 070000
|
#define SUID 004000
|
#define SUID 004000
|
#define SGID 002000
|
#define SGID 002000
|
#define STXT 001000
|
#define STXT 001000
|
#define ROWN 000400
|
#define ROWN 000400
|
#define WOWN 000200
|
#define WOWN 000200
|
#define XOWN 000100
|
#define XOWN 000100
|
#define RGRP 000040
|
#define RGRP 000040
|
#define WGRP 000020
|
#define WGRP 000020
|
#define XGRP 000010
|
#define XGRP 000010
|
#define ROTH 000004
|
#define ROTH 000004
|
#define WOTH 000002
|
#define WOTH 000002
|
#define XOTH 000001
|
#define XOTH 000001
|
|
|
|
|
int m1[] = { 1, ROWN, 'r', '-' };
|
int m1[] = { 1, ROWN, 'r', '-' };
|
int m2[] = { 1, WOWN, 'w', '-' };
|
int m2[] = { 1, WOWN, 'w', '-' };
|
int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
|
int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
|
int m4[] = { 1, RGRP, 'r', '-' };
|
int m4[] = { 1, RGRP, 'r', '-' };
|
int m5[] = { 1, WGRP, 'w', '-' };
|
int m5[] = { 1, WGRP, 'w', '-' };
|
int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
|
int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
|
int m7[] = { 1, ROTH, 'r', '-' };
|
int m7[] = { 1, ROTH, 'r', '-' };
|
int m8[] = { 1, WOTH, 'w', '-' };
|
int m8[] = { 1, WOTH, 'w', '-' };
|
int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
|
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 };
|
|
|
|
|
void selectChar(int *pairp) {
|
void selectChar(int *pairp) {
|
int *ap;
|
int *ap;
|
int n;
|
int n;
|
|
|
ap = pairp;
|
ap = pairp;
|
n = *ap++;
|
n = *ap++;
|
while (--n >= 0 && (arbuf.mode & *ap++) == 0) {
|
while (--n >= 0 && (arbuf.mode & *ap++) == 0) {
|
ap++;
|
ap++;
|
}
|
}
|
putchar(*ap);
|
putchar(*ap);
|
}
|
}
|
|
|
|
|
void printMode(void) {
|
void printMode(void) {
|
int **mp;
|
int **mp;
|
|
|
for (mp = &m[0]; mp < &m[9]; mp++) {
|
for (mp = &m[0]; mp < &m[9]; mp++) {
|
selectChar(*mp);
|
selectChar(*mp);
|
}
|
}
|
}
|
}
|
|
|
|
|
void showAttributes(void) {
|
void showAttributes(void) {
|
char *cp;
|
char *cp;
|
|
|
printMode();
|
printMode();
|
printf("%4d/%4d", arbuf.uid, arbuf.gid);
|
printf("%4d/%4d", arbuf.uid, arbuf.gid);
|
printf("%8ld", arbuf.size);
|
printf("%8d", arbuf.size);
|
cp = ctime(&arbuf.date);
|
cp = ctime(&arbuf.date);
|
printf(" %-12.12s %-4.4s ", cp + 4, cp + 20);
|
printf(" %-12.12s %-4.4s ", cp + 4, cp + 20);
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void mesg(int c) {
|
void mesg(int c) {
|
if (flg['v' - 'a']) {
|
if (flg['v' - 'a']) {
|
printf("%c - %s\n", c, file);
|
printf("%c - %s\n", c, file);
|
}
|
}
|
}
|
}
|
|
|
|
|
char *trim(char *s) {
|
char *trim(char *s) {
|
char *p1;
|
char *p1;
|
char *p2;
|
char *p2;
|
|
|
for (p1 = s; *p1 != '\0'; p1++) ;
|
for (p1 = s; *p1 != '\0'; p1++) ;
|
while (p1 > s) {
|
while (p1 > s) {
|
if (*--p1 != '/') {
|
if (*--p1 != '/') {
|
break;
|
break;
|
}
|
}
|
*p1 = '\0';
|
*p1 = '\0';
|
}
|
}
|
p2 = s;
|
p2 = s;
|
for (p1 = s; *p1 != '\0'; p1++) {
|
for (p1 = s; *p1 != '\0'; p1++) {
|
if (*p1 == '/') {
|
if (*p1 == '/') {
|
p2 = p1 + 1;
|
p2 = p1 + 1;
|
}
|
}
|
}
|
}
|
return p2;
|
return p2;
|
}
|
}
|
|
|
|
|
int notFound(void) {
|
int notFound(void) {
|
int n;
|
int n;
|
int i;
|
int i;
|
|
|
n = 0;
|
n = 0;
|
for (i = 0; i < namc; i++) {
|
for (i = 0; i < namc; i++) {
|
if (namv[i] != NULL) {
|
if (namv[i] != NULL) {
|
fprintf(stderr, "ar: %s not found\n", namv[i]);
|
fprintf(stderr, "ar: %s not found\n", namv[i]);
|
n++;
|
n++;
|
}
|
}
|
}
|
}
|
return n;
|
return n;
|
}
|
}
|
|
|
|
|
int moreFiles(void) {
|
int moreFiles(void) {
|
int n;
|
int n;
|
int i;
|
int i;
|
|
|
n = 0;
|
n = 0;
|
for (i = 0; i < namc; i++) {
|
for (i = 0; i < namc; i++) {
|
if (namv[i] != NULL) {
|
if (namv[i] != NULL) {
|
n++;
|
n++;
|
}
|
}
|
}
|
}
|
return n;
|
return n;
|
}
|
}
|
|
|
|
|
void unlinkTempFiles(void) {
|
void unlinkTempFiles(void) {
|
if (tf0nam != NULL) {
|
if (tf0nam != NULL) {
|
unlink(tf0nam);
|
unlink(tf0nam);
|
}
|
}
|
if (tf1nam != NULL) {
|
if (tf1nam != NULL) {
|
unlink(tf1nam);
|
unlink(tf1nam);
|
}
|
}
|
if (tf2nam != NULL) {
|
if (tf2nam != NULL) {
|
unlink(tf2nam);
|
unlink(tf2nam);
|
}
|
}
|
}
|
}
|
|
|
|
|
void done(int c) {
|
void done(int c) {
|
unlinkTempFiles();
|
unlinkTempFiles();
|
exit(c);
|
exit(c);
|
}
|
}
|
|
|
|
|
void sigDone(int signum) {
|
void sigDone(int signum) {
|
done(100);
|
done(100);
|
}
|
}
|
|
|
|
|
void noArchive(void) {
|
void noArchive(void) {
|
fprintf(stderr, "ar: %s does not exist\n", arnam);
|
fprintf(stderr, "ar: %s does not exist\n", arnam);
|
done(1);
|
done(1);
|
}
|
}
|
|
|
|
|
void writeError(void) {
|
void writeError(void) {
|
perror("ar write error");
|
perror("ar write error");
|
done(1);
|
done(1);
|
}
|
}
|
|
|
|
|
void phaseError(void) {
|
void phaseError(void) {
|
fprintf(stderr, "ar: phase error on %s\n", file);
|
fprintf(stderr, "ar: phase error on %s\n", file);
|
}
|
}
|
|
|
|
|
int stats(void) {
|
int stats(void) {
|
int f;
|
int f;
|
|
|
f = open(file, O_RDONLY);
|
f = open(file, O_RDONLY);
|
if (f < 0) {
|
if (f < 0) {
|
return f;
|
return f;
|
}
|
}
|
if (fstat(f, &stbuf) < 0) {
|
if (fstat(f, &stbuf) < 0) {
|
close(f);
|
close(f);
|
return -1;
|
return -1;
|
}
|
}
|
return f;
|
return f;
|
}
|
}
|
|
|
|
|
int match(void) {
|
int match(void) {
|
int i;
|
int i;
|
|
|
for (i = 0; i < namc; i++) {
|
for (i = 0; i < namc; i++) {
|
if (namv[i] == NULL) {
|
if (namv[i] == NULL) {
|
continue;
|
continue;
|
}
|
}
|
if (strcmp(trim(namv[i]), file) == 0) {
|
if (strcmp(trim(namv[i]), file) == 0) {
|
file = namv[i];
|
file = namv[i];
|
namv[i] = NULL;
|
namv[i] = NULL;
|
return 1;
|
return 1;
|
}
|
}
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
void baMatch(void) {
|
void baMatch(void) {
|
int f;
|
int f;
|
|
|
if (baState == 1) {
|
if (baState == 1) {
|
if (strcmp(file, posName) != 0) {
|
if (strcmp(file, posName) != 0) {
|
return;
|
return;
|
}
|
}
|
baState = 2;
|
baState = 2;
|
if (flg['a' - 'a']) {
|
if (flg['a' - 'a']) {
|
return;
|
return;
|
}
|
}
|
}
|
}
|
if (baState == 2) {
|
if (baState == 2) {
|
baState = 0;
|
baState = 0;
|
tf1nam = mktemp(tmp1nam);
|
tf1nam = mktemp(tmp1nam);
|
close(creat(tf1nam, 0600));
|
close(creat(tf1nam, 0600));
|
f = open(tf1nam, O_RDWR);
|
f = open(tf1nam, O_RDWR);
|
if (f < 0) {
|
if (f < 0) {
|
fprintf(stderr, "ar: cannot create second temp file\n");
|
fprintf(stderr, "ar: cannot create second temp file\n");
|
return;
|
return;
|
}
|
}
|
tf1 = tf0;
|
tf1 = tf0;
|
tf0 = f;
|
tf0 = f;
|
}
|
}
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void init(void) {
|
void init(void) {
|
unsigned int mbuf;
|
unsigned int mbuf;
|
|
|
write4ToEco((unsigned char *) &mbuf, AR_MAGIC);
|
write4ToEco((unsigned char *) &mbuf, AR_MAGIC);
|
tf0nam = mktemp(tmp0nam);
|
tf0nam = mktemp(tmp0nam);
|
close(creat(tf0nam, 0600));
|
close(creat(tf0nam, 0600));
|
tf0 = open(tf0nam, O_RDWR);
|
tf0 = open(tf0nam, O_RDWR);
|
if (tf0 < 0) {
|
if (tf0 < 0) {
|
fprintf(stderr, "ar: cannot create temp file\n");
|
fprintf(stderr, "ar: cannot create temp file\n");
|
done(1);
|
done(1);
|
}
|
}
|
if (write(tf0, &mbuf, sizeof(mbuf)) != sizeof(mbuf)) {
|
if (write(tf0, &mbuf, sizeof(mbuf)) != sizeof(mbuf)) {
|
writeError();
|
writeError();
|
}
|
}
|
}
|
}
|
|
|
|
|
int getArchive(void) {
|
int getArchive(void) {
|
unsigned int mbuf;
|
unsigned int mbuf;
|
|
|
af = open(arnam, O_RDONLY);
|
af = open(arnam, O_RDONLY);
|
if (af < 0) {
|
if (af < 0) {
|
return 1;
|
return 1;
|
}
|
}
|
if (read(af, &mbuf, sizeof(mbuf)) != sizeof(mbuf) ||
|
if (read(af, &mbuf, sizeof(mbuf)) != sizeof(mbuf) ||
|
read4FromEco((unsigned char *) &mbuf) != AR_MAGIC) {
|
read4FromEco((unsigned char *) &mbuf) != AR_MAGIC) {
|
fprintf(stderr, "ar: %s not in archive format\n", arnam);
|
fprintf(stderr, "ar: %s not in archive format\n", arnam);
|
done(1);
|
done(1);
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
void getQuick(void) {
|
void getQuick(void) {
|
unsigned int mbuf;
|
unsigned int mbuf;
|
|
|
qf = open(arnam, O_RDWR);
|
qf = open(arnam, O_RDWR);
|
if (qf < 0) {
|
if (qf < 0) {
|
if (!flg['c' - 'a']) {
|
if (!flg['c' - 'a']) {
|
fprintf(stderr, "ar: creating %s\n", arnam);
|
fprintf(stderr, "ar: creating %s\n", arnam);
|
}
|
}
|
close(creat(arnam, 0666));
|
close(creat(arnam, 0666));
|
qf = open(arnam, O_RDWR);
|
qf = open(arnam, O_RDWR);
|
if (qf < 0) {
|
if (qf < 0) {
|
fprintf(stderr, "ar: cannot create %s\n", arnam);
|
fprintf(stderr, "ar: cannot create %s\n", arnam);
|
done(1);
|
done(1);
|
}
|
}
|
write4ToEco((unsigned char *) &mbuf, AR_MAGIC);
|
write4ToEco((unsigned char *) &mbuf, AR_MAGIC);
|
if (write(qf, &mbuf, sizeof(mbuf)) != sizeof(mbuf)) {
|
if (write(qf, &mbuf, sizeof(mbuf)) != sizeof(mbuf)) {
|
writeError();
|
writeError();
|
}
|
}
|
} else
|
} else
|
if (read(qf, &mbuf, sizeof(mbuf)) != sizeof(mbuf) ||
|
if (read(qf, &mbuf, sizeof(mbuf)) != sizeof(mbuf) ||
|
read4FromEco((unsigned char *) &mbuf) != AR_MAGIC) {
|
read4FromEco((unsigned char *) &mbuf) != AR_MAGIC) {
|
fprintf(stderr, "ar: %s not in archive format\n", arnam);
|
fprintf(stderr, "ar: %s not in archive format\n", arnam);
|
done(1);
|
done(1);
|
}
|
}
|
}
|
}
|
|
|
|
|
int getMember(void) {
|
int getMember(void) {
|
int i;
|
int i;
|
|
|
i = read(af, &arbuf, sizeof(arbuf));
|
i = read(af, &arbuf, sizeof(arbuf));
|
if (i != sizeof(arbuf)) {
|
if (i != sizeof(arbuf)) {
|
if (tf1nam != NULL) {
|
if (tf1nam != NULL) {
|
i = tf0;
|
i = tf0;
|
tf0 = tf1;
|
tf0 = tf1;
|
tf1 = i;
|
tf1 = i;
|
}
|
}
|
return 1;
|
return 1;
|
}
|
}
|
conv4FromEcoToNative((unsigned char *) &arbuf.date);
|
conv4FromEcoToNative((unsigned char *) &arbuf.date);
|
conv4FromEcoToNative((unsigned char *) &arbuf.uid);
|
conv4FromEcoToNative((unsigned char *) &arbuf.uid);
|
conv4FromEcoToNative((unsigned char *) &arbuf.gid);
|
conv4FromEcoToNative((unsigned char *) &arbuf.gid);
|
conv4FromEcoToNative((unsigned char *) &arbuf.mode);
|
conv4FromEcoToNative((unsigned char *) &arbuf.mode);
|
conv4FromEcoToNative((unsigned char *) &arbuf.size);
|
conv4FromEcoToNative((unsigned char *) &arbuf.size);
|
for (i = 0; i < MAX_NAME; i++) {
|
for (i = 0; i < MAX_NAME; i++) {
|
name[i] = arbuf.name[i];
|
name[i] = arbuf.name[i];
|
}
|
}
|
file = name;
|
file = name;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|
void copyFile(int fi, int fo, int flags) {
|
void copyFile(int fi, int fo, int flags) {
|
int pe;
|
int pe;
|
int icount, ocount;
|
int icount, ocount;
|
int pad;
|
int pad;
|
|
|
if (flags & HEAD) {
|
if (flags & HEAD) {
|
conv4FromNativeToEco((unsigned char *) &arbuf.date);
|
conv4FromNativeToEco((unsigned char *) &arbuf.date);
|
conv4FromNativeToEco((unsigned char *) &arbuf.uid);
|
conv4FromNativeToEco((unsigned char *) &arbuf.uid);
|
conv4FromNativeToEco((unsigned char *) &arbuf.gid);
|
conv4FromNativeToEco((unsigned char *) &arbuf.gid);
|
conv4FromNativeToEco((unsigned char *) &arbuf.mode);
|
conv4FromNativeToEco((unsigned char *) &arbuf.mode);
|
conv4FromNativeToEco((unsigned char *) &arbuf.size);
|
conv4FromNativeToEco((unsigned char *) &arbuf.size);
|
if (write(fo, &arbuf, sizeof(arbuf)) != sizeof(arbuf)) {
|
if (write(fo, &arbuf, sizeof(arbuf)) != sizeof(arbuf)) {
|
writeError();
|
writeError();
|
}
|
}
|
conv4FromEcoToNative((unsigned char *) &arbuf.date);
|
conv4FromEcoToNative((unsigned char *) &arbuf.date);
|
conv4FromEcoToNative((unsigned char *) &arbuf.uid);
|
conv4FromEcoToNative((unsigned char *) &arbuf.uid);
|
conv4FromEcoToNative((unsigned char *) &arbuf.gid);
|
conv4FromEcoToNative((unsigned char *) &arbuf.gid);
|
conv4FromEcoToNative((unsigned char *) &arbuf.mode);
|
conv4FromEcoToNative((unsigned char *) &arbuf.mode);
|
conv4FromEcoToNative((unsigned char *) &arbuf.size);
|
conv4FromEcoToNative((unsigned char *) &arbuf.size);
|
}
|
}
|
pe = 0;
|
pe = 0;
|
while (arbuf.size > 0) {
|
while (arbuf.size > 0) {
|
icount = ocount = BUFSIZE;
|
icount = ocount = BUFSIZE;
|
if (arbuf.size < icount) {
|
if (arbuf.size < icount) {
|
icount = ocount = arbuf.size;
|
icount = ocount = arbuf.size;
|
pad = -icount & 0x03;
|
pad = -icount & 0x03;
|
if (flags & IODD) {
|
if (flags & IODD) {
|
icount += pad;
|
icount += pad;
|
}
|
}
|
if (flags & OODD) {
|
if (flags & OODD) {
|
ocount += pad;
|
ocount += pad;
|
}
|
}
|
}
|
}
|
if (read(fi, buf, icount) != icount) {
|
if (read(fi, buf, icount) != icount) {
|
pe++;
|
pe++;
|
}
|
}
|
if ((flags & SKIP) == 0) {
|
if ((flags & SKIP) == 0) {
|
if (write(fo, buf, ocount) != ocount) {
|
if (write(fo, buf, ocount) != ocount) {
|
writeError();
|
writeError();
|
}
|
}
|
}
|
}
|
arbuf.size -= BUFSIZE;
|
arbuf.size -= BUFSIZE;
|
}
|
}
|
if (pe != 0) {
|
if (pe != 0) {
|
phaseError();
|
phaseError();
|
}
|
}
|
}
|
}
|
|
|
|
|
void moveFile(int f) {
|
void moveFile(int f) {
|
char *cp;
|
char *cp;
|
int i;
|
int i;
|
|
|
cp = trim(file);
|
cp = trim(file);
|
for (i = 0; i < MAX_NAME; i++) {
|
for (i = 0; i < MAX_NAME; i++) {
|
if ((arbuf.name[i] = *cp) != '\0') {
|
if ((arbuf.name[i] = *cp) != '\0') {
|
cp++;
|
cp++;
|
}
|
}
|
}
|
}
|
arbuf.size = stbuf.st_size;
|
arbuf.size = stbuf.st_size;
|
arbuf.date = stbuf.st_mtime;
|
arbuf.date = stbuf.st_mtime;
|
arbuf.uid = stbuf.st_uid;
|
arbuf.uid = stbuf.st_uid;
|
arbuf.gid = stbuf.st_gid;
|
arbuf.gid = stbuf.st_gid;
|
arbuf.mode = stbuf.st_mode;
|
arbuf.mode = stbuf.st_mode;
|
copyFile(f, tf0, OODD | HEAD);
|
copyFile(f, tf0, OODD | HEAD);
|
close(f);
|
close(f);
|
}
|
}
|
|
|
|
|
void install(void) {
|
void install(void) {
|
int i;
|
int i;
|
|
|
for (i = 0; signums[i] != 0; i++) {
|
for (i = 0; signums[i] != 0; i++) {
|
signal(signums[i], SIG_IGN);
|
signal(signums[i], SIG_IGN);
|
}
|
}
|
if (af < 0) {
|
if (af < 0) {
|
if (!flg['c' - 'a']) {
|
if (!flg['c' - 'a']) {
|
fprintf(stderr, "ar: creating %s\n", arnam);
|
fprintf(stderr, "ar: creating %s\n", arnam);
|
}
|
}
|
}
|
}
|
close(af);
|
close(af);
|
af = creat(arnam, 0666);
|
af = creat(arnam, 0666);
|
if (af < 0) {
|
if (af < 0) {
|
fprintf(stderr, "ar: cannot create %s\n", arnam);
|
fprintf(stderr, "ar: cannot create %s\n", arnam);
|
done(1);
|
done(1);
|
}
|
}
|
if (tf0nam != NULL) {
|
if (tf0nam != NULL) {
|
lseek(tf0, 0, SEEK_SET);
|
lseek(tf0, 0, SEEK_SET);
|
while ((i = read(tf0, buf, BUFSIZE)) > 0) {
|
while ((i = read(tf0, buf, BUFSIZE)) > 0) {
|
if (write(af, buf, i) != i) {
|
if (write(af, buf, i) != i) {
|
writeError();
|
writeError();
|
}
|
}
|
}
|
}
|
}
|
}
|
if (tf2nam != NULL) {
|
if (tf2nam != NULL) {
|
lseek(tf2, 0, SEEK_SET);
|
lseek(tf2, 0, SEEK_SET);
|
while ((i = read(tf2, buf, BUFSIZE)) > 0) {
|
while ((i = read(tf2, buf, BUFSIZE)) > 0) {
|
if (write(af, buf, i) != i) {
|
if (write(af, buf, i) != i) {
|
writeError();
|
writeError();
|
}
|
}
|
}
|
}
|
}
|
}
|
if (tf1nam != NULL) {
|
if (tf1nam != NULL) {
|
lseek(tf1, 0, SEEK_SET);
|
lseek(tf1, 0, SEEK_SET);
|
while ((i = read(tf1, buf, BUFSIZE)) > 0) {
|
while ((i = read(tf1, buf, BUFSIZE)) > 0) {
|
if (write(af, buf, i) != i) {
|
if (write(af, buf, i) != i) {
|
writeError();
|
writeError();
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
void cleanup(void) {
|
void cleanup(void) {
|
int i;
|
int i;
|
int f;
|
int f;
|
|
|
for (i = 0; i < namc; i++) {
|
for (i = 0; i < namc; i++) {
|
file = namv[i];
|
file = namv[i];
|
if (file == NULL) {
|
if (file == NULL) {
|
continue;
|
continue;
|
}
|
}
|
namv[i] = NULL;
|
namv[i] = NULL;
|
mesg('a');
|
mesg('a');
|
f = stats();
|
f = stats();
|
if (f < 0) {
|
if (f < 0) {
|
fprintf(stderr, "ar: cannot open %s\n", file);
|
fprintf(stderr, "ar: cannot open %s\n", file);
|
continue;
|
continue;
|
}
|
}
|
moveFile(f);
|
moveFile(f);
|
}
|
}
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void dCmd(void) {
|
void dCmd(void) {
|
init();
|
init();
|
if (getArchive()) {
|
if (getArchive()) {
|
noArchive();
|
noArchive();
|
}
|
}
|
while (!getMember()) {
|
while (!getMember()) {
|
if (match()) {
|
if (match()) {
|
mesg('d');
|
mesg('d');
|
copyFile(af, -1, IODD | SKIP);
|
copyFile(af, -1, IODD | SKIP);
|
continue;
|
continue;
|
}
|
}
|
mesg('c');
|
mesg('c');
|
copyFile(af, tf0, IODD | OODD | HEAD);
|
copyFile(af, tf0, IODD | OODD | HEAD);
|
}
|
}
|
install();
|
install();
|
}
|
}
|
|
|
|
|
void rCmd(void) {
|
void rCmd(void) {
|
int f;
|
int f;
|
|
|
init();
|
init();
|
getArchive();
|
getArchive();
|
while (!getMember()) {
|
while (!getMember()) {
|
baMatch();
|
baMatch();
|
if (namc == 0 || match()) {
|
if (namc == 0 || match()) {
|
f = stats();
|
f = stats();
|
if (f < 0) {
|
if (f < 0) {
|
if (namc != 0) {
|
if (namc != 0) {
|
fprintf(stderr, "ar: cannot open %s\n", file);
|
fprintf(stderr, "ar: cannot open %s\n", file);
|
}
|
}
|
goto cp;
|
goto cp;
|
}
|
}
|
if (flg['u' - 'a']) {
|
if (flg['u' - 'a']) {
|
if (stbuf.st_mtime <= arbuf.date) {
|
if (stbuf.st_mtime <= arbuf.date) {
|
close(f);
|
close(f);
|
goto cp;
|
goto cp;
|
}
|
}
|
}
|
}
|
mesg('r');
|
mesg('r');
|
copyFile(af, -1, IODD | SKIP);
|
copyFile(af, -1, IODD | SKIP);
|
moveFile(f);
|
moveFile(f);
|
continue;
|
continue;
|
}
|
}
|
cp:
|
cp:
|
mesg('c');
|
mesg('c');
|
copyFile(af, tf0, IODD | OODD | HEAD);
|
copyFile(af, tf0, IODD | OODD | HEAD);
|
}
|
}
|
cleanup();
|
cleanup();
|
install();
|
install();
|
}
|
}
|
|
|
|
|
void qCmd(void) {
|
void qCmd(void) {
|
int i;
|
int i;
|
int f;
|
int f;
|
|
|
if (flg['a' - 'a'] || flg['b' - 'a']) {
|
if (flg['a' - 'a'] || flg['b' - 'a']) {
|
fprintf(stderr, "ar: [ab] not allowed with -q\n");
|
fprintf(stderr, "ar: [ab] not allowed with -q\n");
|
done(1);
|
done(1);
|
}
|
}
|
getQuick();
|
getQuick();
|
for (i = 0; signums[i] != 0; i++) {
|
for (i = 0; signums[i] != 0; i++) {
|
signal(signums[i], SIG_IGN);
|
signal(signums[i], SIG_IGN);
|
}
|
}
|
lseek(qf, 0, SEEK_END);
|
lseek(qf, 0, SEEK_END);
|
for (i = 0; i < namc; i++) {
|
for (i = 0; i < namc; i++) {
|
file = namv[i];
|
file = namv[i];
|
if (file == NULL) {
|
if (file == NULL) {
|
continue;
|
continue;
|
}
|
}
|
namv[i] = NULL;
|
namv[i] = NULL;
|
mesg('q');
|
mesg('q');
|
f = stats();
|
f = stats();
|
if (f < 0) {
|
if (f < 0) {
|
fprintf(stderr, "ar: cannot open %s\n", file);
|
fprintf(stderr, "ar: cannot open %s\n", file);
|
continue;
|
continue;
|
}
|
}
|
tf0 = qf;
|
tf0 = qf;
|
moveFile(f);
|
moveFile(f);
|
qf = tf0;
|
qf = tf0;
|
}
|
}
|
}
|
}
|
|
|
|
|
void tCmd(void) {
|
void tCmd(void) {
|
if (getArchive()) {
|
if (getArchive()) {
|
noArchive();
|
noArchive();
|
}
|
}
|
while (!getMember()) {
|
while (!getMember()) {
|
if (namc == 0 || match()) {
|
if (namc == 0 || match()) {
|
if (flg['v' - 'a']) {
|
if (flg['v' - 'a']) {
|
showAttributes();
|
showAttributes();
|
}
|
}
|
printf("%s\n", trim(file));
|
printf("%s\n", trim(file));
|
}
|
}
|
copyFile(af, -1, IODD | SKIP);
|
copyFile(af, -1, IODD | SKIP);
|
}
|
}
|
}
|
}
|
|
|
|
|
void pCmd(void) {
|
void pCmd(void) {
|
if (getArchive()) {
|
if (getArchive()) {
|
noArchive();
|
noArchive();
|
}
|
}
|
while (!getMember()) {
|
while (!getMember()) {
|
if (namc == 0 || match()) {
|
if (namc == 0 || match()) {
|
if (flg['v' - 'a']) {
|
if (flg['v' - 'a']) {
|
printf("\n<%s>\n\n", file);
|
printf("\n<%s>\n\n", file);
|
fflush(stdout);
|
fflush(stdout);
|
}
|
}
|
copyFile(af, 1, IODD);
|
copyFile(af, 1, IODD);
|
continue;
|
continue;
|
}
|
}
|
copyFile(af, -1, IODD | SKIP);
|
copyFile(af, -1, IODD | SKIP);
|
}
|
}
|
}
|
}
|
|
|
|
|
void mCmd(void) {
|
void mCmd(void) {
|
init();
|
init();
|
if (getArchive()) {
|
if (getArchive()) {
|
noArchive();
|
noArchive();
|
}
|
}
|
tf2nam = mktemp(tmp2nam);
|
tf2nam = mktemp(tmp2nam);
|
close(creat(tf2nam, 0600));
|
close(creat(tf2nam, 0600));
|
tf2 = open(tf2nam, O_RDWR);
|
tf2 = open(tf2nam, O_RDWR);
|
if (tf2 < 0) {
|
if (tf2 < 0) {
|
fprintf(stderr, "ar: cannot create third temp file\n");
|
fprintf(stderr, "ar: cannot create third temp file\n");
|
done(1);
|
done(1);
|
}
|
}
|
while (!getMember()) {
|
while (!getMember()) {
|
baMatch();
|
baMatch();
|
if (match()) {
|
if (match()) {
|
mesg('m');
|
mesg('m');
|
copyFile(af, tf2, IODD | OODD | HEAD);
|
copyFile(af, tf2, IODD | OODD | HEAD);
|
continue;
|
continue;
|
}
|
}
|
mesg('c');
|
mesg('c');
|
copyFile(af, tf0, IODD | OODD | HEAD);
|
copyFile(af, tf0, IODD | OODD | HEAD);
|
}
|
}
|
install();
|
install();
|
}
|
}
|
|
|
|
|
void xCmd(void) {
|
void xCmd(void) {
|
int f;
|
int f;
|
|
|
if (getArchive()) {
|
if (getArchive()) {
|
noArchive();
|
noArchive();
|
}
|
}
|
while (!getMember()) {
|
while (!getMember()) {
|
if (namc == 0 || match()) {
|
if (namc == 0 || match()) {
|
f = creat(file, arbuf.mode & 0777);
|
f = creat(file, arbuf.mode & 0777);
|
if (f < 0) {
|
if (f < 0) {
|
fprintf(stderr, "ar: cannot create %s\n", file);
|
fprintf(stderr, "ar: cannot create %s\n", file);
|
goto sk;
|
goto sk;
|
}
|
}
|
mesg('x');
|
mesg('x');
|
copyFile(af, f, IODD);
|
copyFile(af, f, IODD);
|
close(f);
|
close(f);
|
continue;
|
continue;
|
}
|
}
|
sk:
|
sk:
|
mesg('c');
|
mesg('c');
|
copyFile(af, -1, IODD | SKIP);
|
copyFile(af, -1, IODD | SKIP);
|
if (namc > 0 && !moreFiles()) {
|
if (namc > 0 && !moreFiles()) {
|
done(0);
|
done(0);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
/* specialized r command for updating symbols */
|
/* specialized r command for updating symbols */
|
|
|
|
|
int exec_rCmd(int create, char *args[]) {
|
int exec_rCmd(int create, char *args[]) {
|
int i;
|
int i;
|
int res;
|
int res;
|
|
|
/* reset all global variables */
|
/* reset all global variables */
|
comfun = NULL;
|
comfun = NULL;
|
for (i = 0; i < 26; i++) {
|
for (i = 0; i < 26; i++) {
|
flg[i] = 0;
|
flg[i] = 0;
|
}
|
}
|
arnam = NULL;
|
arnam = NULL;
|
af = 0;
|
af = 0;
|
namv = NULL;
|
namv = NULL;
|
namc = 0;
|
namc = 0;
|
baState = 0;
|
baState = 0;
|
posName = NULL;
|
posName = NULL;
|
for (i = 0; i < 20; i++) {
|
for (i = 0; i < 20; i++) {
|
tmp0nam[i] = '\0';
|
tmp0nam[i] = '\0';
|
tmp1nam[i] = '\0';
|
tmp1nam[i] = '\0';
|
tmp2nam[i] = '\0';
|
tmp2nam[i] = '\0';
|
}
|
}
|
tf0nam = NULL;
|
tf0nam = NULL;
|
tf1nam = NULL;
|
tf1nam = NULL;
|
tf2nam = NULL;
|
tf2nam = NULL;
|
tf0 = 0;
|
tf0 = 0;
|
tf1 = 0;
|
tf1 = 0;
|
tf2 = 0;
|
tf2 = 0;
|
qf = 0;
|
qf = 0;
|
file = NULL;
|
file = NULL;
|
for (i = 0; i < MAX_NAME; i++) {
|
for (i = 0; i < MAX_NAME; i++) {
|
name[i] = '\0';
|
name[i] = '\0';
|
}
|
}
|
/* prepare arguments, call r command, cleanup */
|
/* prepare arguments, call r command, cleanup */
|
comfun = rCmd;
|
comfun = rCmd;
|
flg['l' - 'a'] = 1;
|
flg['l' - 'a'] = 1;
|
strcpy(tmp0nam, "v0XXXXXX");
|
strcpy(tmp0nam, "v0XXXXXX");
|
strcpy(tmp1nam, "v1XXXXXX");
|
strcpy(tmp1nam, "v1XXXXXX");
|
strcpy(tmp2nam, "v2XXXXXX");
|
strcpy(tmp2nam, "v2XXXXXX");
|
if (create) {
|
if (create) {
|
/* ar -rlb firstName archive TEMP_NAME */
|
/* ar -rlb firstName archive TEMP_NAME */
|
flg['b' - 'a'] = 1;
|
flg['b' - 'a'] = 1;
|
baState = 1;
|
baState = 1;
|
posName = trim(args[0]);
|
posName = trim(args[0]);
|
arnam = args[1];
|
arnam = args[1];
|
namv = &args[2];
|
namv = &args[2];
|
namc = 1;
|
namc = 1;
|
} else {
|
} else {
|
/* ar -rl archive TEMP_NAME */
|
/* ar -rl archive TEMP_NAME */
|
arnam = args[0];
|
arnam = args[0];
|
namv = &args[1];
|
namv = &args[1];
|
namc = 1;
|
namc = 1;
|
}
|
}
|
(*comfun)();
|
(*comfun)();
|
res = notFound();
|
res = notFound();
|
unlinkTempFiles();
|
unlinkTempFiles();
|
return res;
|
return res;
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void usage(void) {
|
void usage(void) {
|
printf("usage: ar -[%s][%s] archive files ...\n", com, opt);
|
printf("usage: ar -[%s][%s] archive files ...\n", com, opt);
|
done(1);
|
done(1);
|
}
|
}
|
|
|
|
|
void setcom(void (*fun)(void)) {
|
void setcom(void (*fun)(void)) {
|
if (comfun != NULL) {
|
if (comfun != NULL) {
|
fprintf(stderr, "ar: only one of [%s] allowed\n", com);
|
fprintf(stderr, "ar: only one of [%s] allowed\n", com);
|
done(1);
|
done(1);
|
}
|
}
|
comfun = fun;
|
comfun = fun;
|
}
|
}
|
|
|
|
|
int cmdCanChangeSymbols(void) {
|
int cmdCanChangeSymbols(void) {
|
return comfun == dCmd ||
|
return comfun == dCmd ||
|
comfun == rCmd ||
|
comfun == rCmd ||
|
comfun == mCmd;
|
comfun == mCmd;
|
}
|
}
|
|
|
|
|
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
int i;
|
int i;
|
char *cp;
|
char *cp;
|
int res;
|
int res;
|
|
|
for (i = 0; signums[i] != 0; i++) {
|
for (i = 0; signums[i] != 0; i++) {
|
if (signal(signums[i], SIG_IGN) != SIG_IGN) {
|
if (signal(signums[i], SIG_IGN) != SIG_IGN) {
|
signal(signums[i], sigDone);
|
signal(signums[i], sigDone);
|
}
|
}
|
}
|
}
|
strcpy(tmp0nam, "/tmp/v0XXXXXX");
|
strcpy(tmp0nam, "/tmp/v0XXXXXX");
|
strcpy(tmp1nam, "/tmp/v1XXXXXX");
|
strcpy(tmp1nam, "/tmp/v1XXXXXX");
|
strcpy(tmp2nam, "/tmp/v2XXXXXX");
|
strcpy(tmp2nam, "/tmp/v2XXXXXX");
|
if (argc < 3 || *argv[1] != '-') {
|
if (argc < 3 || *argv[1] != '-') {
|
usage();
|
usage();
|
}
|
}
|
for (cp = argv[1] + 1; *cp != '\0'; cp++) {
|
for (cp = argv[1] + 1; *cp != '\0'; cp++) {
|
switch (*cp) {
|
switch (*cp) {
|
case 'd':
|
case 'd':
|
setcom(dCmd);
|
setcom(dCmd);
|
break;
|
break;
|
case 'r':
|
case 'r':
|
setcom(rCmd);
|
setcom(rCmd);
|
break;
|
break;
|
case 'q':
|
case 'q':
|
setcom(qCmd);
|
setcom(qCmd);
|
break;
|
break;
|
case 't':
|
case 't':
|
setcom(tCmd);
|
setcom(tCmd);
|
break;
|
break;
|
case 'p':
|
case 'p':
|
setcom(pCmd);
|
setcom(pCmd);
|
break;
|
break;
|
case 'm':
|
case 'm':
|
setcom(mCmd);
|
setcom(mCmd);
|
break;
|
break;
|
case 'x':
|
case 'x':
|
setcom(xCmd);
|
setcom(xCmd);
|
break;
|
break;
|
case 'v':
|
case 'v':
|
case 'u':
|
case 'u':
|
case 'a':
|
case 'a':
|
case 'b':
|
case 'b':
|
case 'c':
|
case 'c':
|
case 'l':
|
case 'l':
|
case 's':
|
case 's':
|
flg[*cp - 'a'] = 1;
|
flg[*cp - 'a'] = 1;
|
break;
|
break;
|
default:
|
default:
|
fprintf(stderr, "ar: bad option '%c'\n", *cp);
|
fprintf(stderr, "ar: bad option '%c'\n", *cp);
|
done(1);
|
done(1);
|
}
|
}
|
}
|
}
|
if (flg['l' - 'a']) {
|
if (flg['l' - 'a']) {
|
strcpy(tmp0nam, "v0XXXXXX");
|
strcpy(tmp0nam, "v0XXXXXX");
|
strcpy(tmp1nam, "v1XXXXXX");
|
strcpy(tmp1nam, "v1XXXXXX");
|
strcpy(tmp2nam, "v2XXXXXX");
|
strcpy(tmp2nam, "v2XXXXXX");
|
}
|
}
|
if (flg['a' - 'a'] || flg['b' - 'a']) {
|
if (flg['a' - 'a'] || flg['b' - 'a']) {
|
baState = 1;
|
baState = 1;
|
posName = trim(argv[2]);
|
posName = trim(argv[2]);
|
argv++;
|
argv++;
|
argc--;
|
argc--;
|
if (argc < 3) {
|
if (argc < 3) {
|
usage();
|
usage();
|
}
|
}
|
}
|
}
|
arnam = argv[2];
|
arnam = argv[2];
|
namv = argv + 3;
|
namv = argv + 3;
|
namc = argc - 3;
|
namc = argc - 3;
|
if (comfun == NULL && !flg['s' - 'a']) {
|
if (comfun == NULL && !flg['s' - 'a']) {
|
fprintf(stderr, "ar: one of [%ss] must be specified\n", com);
|
fprintf(stderr, "ar: one of [%ss] must be specified\n", com);
|
done(1);
|
done(1);
|
}
|
}
|
res = 0;
|
res = 0;
|
if (comfun != NULL) {
|
if (comfun != NULL) {
|
(*comfun)();
|
(*comfun)();
|
res = notFound();
|
res = notFound();
|
unlinkTempFiles();
|
unlinkTempFiles();
|
if (res != 0) {
|
if (res != 0) {
|
return res;
|
return res;
|
}
|
}
|
}
|
}
|
if (flg['s' - 'a'] ||
|
if (flg['s' - 'a'] ||
|
(cmdCanChangeSymbols() && hasSymbols(arnam))) {
|
(cmdCanChangeSymbols() && hasSymbols(arnam))) {
|
res = updateSymbols(arnam, flg['v' - 'a']);
|
res = updateSymbols(arnam, flg['v' - 'a']);
|
}
|
}
|
return res;
|
return res;
|
}
|
}
|
|
|