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