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:
parent
b66b22cdd4
commit
3d2e57a312
@ -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;
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user