1
0
mirror of https://github.com/golang/go synced 2024-11-22 02:24:41 -07:00

gopack: add P flag to remove prefix from filename information

R=r, r2
CC=golang-dev
https://golang.org/cl/4307047
This commit is contained in:
Russ Cox 2011-03-30 22:19:02 -04:00
parent b66b22cdd4
commit 3d2e57a312
2 changed files with 161 additions and 13 deletions

View File

@ -41,6 +41,7 @@
#include <libc.h> #include <libc.h>
#include <bio.h> #include <bio.h>
#include <mach.h> #include <mach.h>
#include "../../libmach/obj.h"
#include <ar.h> #include <ar.h>
#undef select #undef select
@ -123,6 +124,7 @@ int gflag;
int oflag; int oflag;
int uflag; int uflag;
int vflag; int vflag;
int Pflag; /* remove leading file prefix */
int Sflag; /* force mark Go package as safe */ int Sflag; /* force mark Go package as safe */
int errors; int errors;
@ -141,6 +143,7 @@ char poname[ARNAMESIZE+1]; /* name of pivot member */
char *file; /* current file or member being worked on */ char *file; /* current file or member being worked on */
Biobuf bout; Biobuf bout;
Biobuf bar; Biobuf bar;
char *prefix;
void arcopy(Biobuf*, Arfile*, Armember*); void arcopy(Biobuf*, Arfile*, Armember*);
int arcreate(char*); int arcreate(char*);
@ -149,7 +152,7 @@ void arinsert(Arfile*, Armember*);
void *armalloc(int); void *armalloc(int);
char *arstrdup(char*); char *arstrdup(char*);
void armove(Biobuf*, Arfile*, Armember*); void armove(Biobuf*, Arfile*, Armember*);
void arread(Biobuf*, Armember*, int); void arread(Biobuf*, Armember*);
void arstream(int, Arfile*); void arstream(int, Arfile*);
int arwrite(int, Armember*); int arwrite(int, Armember*);
int bamatch(char*, char*); int bamatch(char*, char*);
@ -179,6 +182,7 @@ void trim(char*, char*, int);
void usage(void); void usage(void);
void wrerr(void); void wrerr(void);
void wrsym(Biobuf*, long, Arsymref*); void wrsym(Biobuf*, long, Arsymref*);
int arread_cutprefix(Biobuf*, Armember*);
void rcmd(char*, int, char**); /* command processing */ void rcmd(char*, int, char**); /* command processing */
void dcmd(char*, int, char**); void dcmd(char*, int, char**);
@ -220,6 +224,7 @@ main(int argc, char *argv[])
case 'v': vflag = 1; break; case 'v': vflag = 1; break;
case 'x': setcom(xcmd); break; case 'x': setcom(xcmd); break;
case 'S': Sflag = 1; break; case 'S': Sflag = 1; break;
case 'P': Pflag = 1; break;
default: default:
fprint(2, "gopack: bad option `%c'\n", *cp); fprint(2, "gopack: bad option `%c'\n", *cp);
exits("error"); exits("error");
@ -236,6 +241,15 @@ main(int argc, char *argv[])
if(argc < 3) if(argc < 3)
usage(); usage();
} }
if(Pflag) {
if(argc < 4) {
fprint(2, "gopack: P flag requires prefix argument\n");
usage();
}
prefix = argv[2];
argv++;
argc--;
}
if(comfun == 0) { if(comfun == 0) {
if(uflag == 0) { if(uflag == 0) {
fprint(2, "gopack: one of [%s] must be specified\n", man); fprint(2, "gopack: one of [%s] must be specified\n", man);
@ -313,7 +327,16 @@ rcmd(char *arname, int count, char **files)
skip(&bar, bp->size); skip(&bar, bp->size);
continue; continue;
} }
if (count && !match(count, files)) { /*
* the plan 9 ar treats count == 0 as equivalent
* to listing all the archive's files on the command line:
* it will try to open every file name in the archive
* and copy that file into the archive if it exists.
* for go we disable that behavior, because we use
* r with no files to make changes to the archive itself,
* using the S or P flags.
*/
if (!match(count, files)) {
scanobj(&bar, ap, bp->size); scanobj(&bar, ap, bp->size);
arcopy(&bar, ap, bp); arcopy(&bar, ap, bp);
continue; continue;
@ -972,7 +995,7 @@ phaseerr(int offset)
void void
usage(void) usage(void)
{ {
fprint(2, "usage: gopack [%s][%s] archive files ...\n", opt, man); fprint(2, "usage: gopack [%s][%s][P prefix] archive files ...\n", opt, man);
exits("error"); exits("error");
} }
@ -1012,12 +1035,14 @@ armove(Biobuf *b, Arfile *ap, Armember *bp)
{ {
char *cp; char *cp;
Dir *d; Dir *d;
vlong n;
d = dirfstat(Bfildes(b)); d = dirfstat(Bfildes(b));
if (d == nil) { if (d == nil) {
fprint(2, "gopack: cannot stat %s\n", file); fprint(2, "gopack: cannot stat %s\n", file);
return; return;
} }
trim(file, bp->hdr.name, sizeof(bp->hdr.name)); trim(file, bp->hdr.name, sizeof(bp->hdr.name));
for (cp = strchr(bp->hdr.name, 0); /* blank pad on right */ for (cp = strchr(bp->hdr.name, 0); /* blank pad on right */
cp < bp->hdr.name+sizeof(bp->hdr.name); cp++) cp < bp->hdr.name+sizeof(bp->hdr.name); cp++)
@ -1029,12 +1054,13 @@ armove(Biobuf *b, Arfile *ap, Armember *bp)
sprint(bp->hdr.size, "%-10lld", d->length); sprint(bp->hdr.size, "%-10lld", d->length);
strncpy(bp->hdr.fmag, ARFMAG, 2); strncpy(bp->hdr.fmag, ARFMAG, 2);
bp->size = d->length; bp->size = d->length;
arread(b, bp, bp->size); arread(b, bp);
if (d->length&0x01) n = bp->size;
d->length++; if (n&1)
n++;
if (ap) { if (ap) {
arinsert(ap, bp); arinsert(ap, bp);
ap->size += d->length+SAR_HDR; ap->size += n+SAR_HDR;
} }
free(d); free(d);
} }
@ -1047,10 +1073,10 @@ arcopy(Biobuf *b, Arfile *ap, Armember *bp)
{ {
long n; long n;
arread(b, bp);
n = bp->size; n = bp->size;
if (n & 01) if (n & 01)
n++; n++;
arread(b, bp, n);
if (ap) { if (ap) {
arinsert(ap, bp); arinsert(ap, bp);
ap->size += n+SAR_HDR; ap->size += n+SAR_HDR;
@ -1316,7 +1342,8 @@ longt(Armember *bp)
Bprint(&bout, "%7ld", bp->size); Bprint(&bout, "%7ld", bp->size);
date = bp->date; date = bp->date;
cp = ctime(&date); cp = ctime(&date);
Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+24); /* using unix ctime, not plan 9 time, so cp+20 for year, not cp+24 */
Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+20);
} }
int m1[] = { 1, ROWN, 'r', '-' }; int m1[] = { 1, ROWN, 'r', '-' };
@ -1378,17 +1405,29 @@ newmember(void) /* allocate a member buffer */
} }
void void
arread(Biobuf *b, Armember *bp, int n) /* read an image into a member buffer */ arread(Biobuf *b, Armember *bp) /* read an image into a member buffer */
{ {
int i; int i;
vlong off;
bp->member = armalloc(n); bp->member = armalloc(bp->size);
i = Bread(b, bp->member, n);
// If P flag is set, let arread_cutprefix try.
// If it succeeds, we're done. If not, fall back
// to a direct copy.
off = Boffset(b);
if(Pflag && arread_cutprefix(b, bp))
return;
Bseek(b, off, 0);
i = Bread(b, bp->member, bp->size);
if (i < 0) { if (i < 0) {
free(bp->member); free(bp->member);
bp->member = 0; bp->member = 0;
rderr(); rderr();
} }
if(bp->size&1)
Bgetc(b);
} }
/* /*
@ -1551,3 +1590,109 @@ arstrdup(char *s)
} }
/*
* Parts of libmach we're not supposed
* to look at but need for arread_cutprefix.
*/
extern int _read5(Biobuf*, Prog*);
extern int _read6(Biobuf*, Prog*);
extern int _read8(Biobuf*, Prog*);
int (*reader[256])(Biobuf*, Prog*) = {
[ObjArm] = _read5,
[ObjAmd64] = _read6,
[Obj386] = _read8,
};
/*
* copy b into bp->member but rewrite object
* during copy to drop prefix from all file names.
* return 1 if b was recognized as an object file
* and copied successfully, 0 otherwise.
*/
int
arread_cutprefix(Biobuf *b, Armember *bp)
{
vlong offset, o, end;
int n, t;
int (*rd)(Biobuf*, Prog*);
char *w, *inprefix;
Prog p;
offset = Boffset(b);
end = offset + bp->size;
t = objtype(b, nil);
if(t < 0)
return 0;
if((rd = reader[t]) == nil)
return 0;
// copy header
w = bp->member;
n = Boffset(b) - offset;
Bseek(b, -n, 1);
if(Bread(b, w, n) != n)
return 0;
offset += n;
w += n;
// read object file one pseudo-instruction at a time,
// eliding the file name instructions that refer to
// the prefix.
memset(&p, 0, sizeof p);
inprefix = nil;
while(Boffset(b) < end && rd(b, &p)) {
if(p.kind == aName && p.type == UNKNOWN && p.sym == 1 && p.id[0] == '<') {
// part of a file path.
// we'll keep continuing (skipping the copy)
// around the loop until either we get to a
// name piece that should be kept or we see
// the whole prefix.
if(inprefix == nil && prefix[0] == '/' && p.id[1] == '/' && p.id[2] == '\0') {
// leading /
inprefix = prefix+1;
} else if(inprefix != nil) {
// handle subsequent elements
n = strlen(p.id+1);
if(strncmp(p.id+1, inprefix, n) == 0 && (inprefix[n] == '/' || inprefix[n] == '\0')) {
inprefix += n;
if(inprefix[0] == '/')
inprefix++;
}
}
if(inprefix && inprefix[0] == '\0') {
// reached end of prefix.
// if we another path element follows,
// nudge the offset to skip over the prefix we saw.
// if not, leave offset alone, to emit the whole name.
// additional name elements will not be skipped
// because inprefix is now nil and we won't see another
// leading / in this name.
inprefix = nil;
o = Boffset(b);
if(o < end && rd(b, &p) && p.kind == aName && p.type == UNKNOWN && p.sym == 1 && p.id[0] == '<') {
print("skip %lld-%lld\n", offset, o);
offset = o;
}
}
}
// copy instructions
if(!inprefix) {
n = Boffset(b) - offset;
Bseek(b, -n, 1);
if(Bread(b, w, n) != n)
return 0;
offset += n;
w += n;
}
}
bp->size = w - (char*)bp->member;
sprint(bp->hdr.size, "%-10lld", (vlong)bp->size);
strncpy(bp->hdr.fmag, ARFMAG, 2);
Bseek(b, end, 0);
if(Boffset(b)&1)
Bgetc(b);
return 1;
}

View File

@ -12,12 +12,15 @@ It adds a special Go-specific section __.PKGDEF that collects all the
Go type information from the files in the archive; that section is Go type information from the files in the archive; that section is
used by the compiler when importing the package during compilation. used by the compiler when importing the package during compilation.
Usage: gopack [uvnbailogS][mrxtdpq] archive files ... Usage: gopack [uvnbailogS][mrxtdpq][P prefix] archive files ...
The new option 'g' causes gopack to maintain the __.PKGDEF section The new option 'g' causes gopack to maintain the __.PKGDEF section
as files are added to the archive. as files are added to the archive.
The new option 'S' forces gopack to mark the archive as safe. The new option 'S' forces gopack to mark the archive as safe.
The new option 'P' causes gopack to remove the given prefix
from file names in the line number information in object files
that are already stored in or added to the archive.
*/ */
package documentation package documentation