Second round:
1. Make paths work correctly. 2. Make pkg_add generally more robust in the face of failure. 3. Make the depend messages come out on stderr or stdout, but not both interspersed! :-)
This commit is contained in:
parent
07a6a76523
commit
c63844d550
@ -4,5 +4,5 @@ for each individual command.
|
||||
|
||||
This code was written by Jordan Hubbard for FreeBSD, snatched and
|
||||
mildly reshaped by John Kohl in NetBSD and the changes taken back into
|
||||
FreeBSD again by Jordan. Whee! :-)
|
||||
|
||||
FreeBSD again by Jordan, who then proceeded to add another couple
|
||||
of dozen features on top. Whee! :-)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef lint
|
||||
static const char *rcsid = "$Id: perform.c,v 1.17 1995/04/19 14:54:25 jkh Exp $";
|
||||
static const char *rcsid = "$Id: perform.c,v 1.18 1995/04/22 07:40:54 jkh Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -58,7 +58,8 @@ pkg_do(char *pkg)
|
||||
{
|
||||
char pkg_fullname[FILENAME_MAX];
|
||||
char home[FILENAME_MAX];
|
||||
char *tmp;
|
||||
char extract_contents[FILENAME_MAX];
|
||||
char *where_to, *tmp;
|
||||
FILE *cfile;
|
||||
int code = 0;
|
||||
PackingList p;
|
||||
@ -91,6 +92,57 @@ pkg_do(char *pkg)
|
||||
whinge("Can't find package '%s'.", pkg_fullname);
|
||||
return 1;
|
||||
}
|
||||
Home = make_playpen(PlayPen, 0);
|
||||
sprintf(extract_contents, "--fast-read %s", CONTENTS_FNAME);
|
||||
if (unpack(pkg_fullname, extract_contents)) {
|
||||
whinge("Unable to extract table of contents file from `%s' - not a package?.", pkg_fullname);
|
||||
goto bomb;
|
||||
}
|
||||
cfile = fopen(CONTENTS_FNAME, "r");
|
||||
if (!cfile) {
|
||||
whinge("Unable to open table of contents file `%s' - not a package?", CONTENTS_FNAME);
|
||||
goto bomb;
|
||||
}
|
||||
read_plist(&Plist, cfile);
|
||||
fclose(cfile);
|
||||
|
||||
/*
|
||||
* If we have a prefix, delete the first one we see and add this
|
||||
* one in place of it.
|
||||
*/
|
||||
if (Prefix) {
|
||||
delete_plist(&Plist, FALSE, PLIST_CWD, NULL);
|
||||
add_plist_top(&Plist, PLIST_CWD, Prefix);
|
||||
}
|
||||
|
||||
/* Extract directly rather than moving? Oh goodie! */
|
||||
if (find_plist_option(&Plist, "extract-in-place")) {
|
||||
if (Verbose)
|
||||
printf("Doing in-place extraction for %s\n", pkg_fullname);
|
||||
p = find_plist(&Plist, PLIST_CWD);
|
||||
if (p) {
|
||||
if (!isdir(p->name) && !NoInstall) {
|
||||
if (Verbose)
|
||||
printf("Desired prefix of %s does not exist, creating..\n", p->name);
|
||||
vsystem("mkdir -p %s", p->name);
|
||||
if (chdir(p->name)) {
|
||||
whinge("Unable to change directory to `%s' - no permission?", p->name);
|
||||
perror("chdir");
|
||||
leave_playpen();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
where_to = p->name;
|
||||
}
|
||||
else {
|
||||
whinge("No prefix specified in `%s' - this is a bad package!",
|
||||
pkg_fullname);
|
||||
leave_playpen();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
where_to = PlayPen;
|
||||
/*
|
||||
* Apply a crude heuristic to see how much space the package will
|
||||
* take up once it's unpacked. I've noticed that most packages
|
||||
@ -100,33 +152,43 @@ pkg_do(char *pkg)
|
||||
whinge("Can't stat package file '%s'.", pkg_fullname);
|
||||
return 1;
|
||||
}
|
||||
sb.st_size *= 4;
|
||||
Home = make_playpen(PlayPen, sb.st_size);
|
||||
|
||||
if (min_free(where_to) < sb.st_size * 4) {
|
||||
whinge("Projected size of %d exceeds free space in %s.",
|
||||
sb.st_size * 4, where_to);
|
||||
whinge("Not extracting %s, sorry!", pkg_fullname);
|
||||
goto bomb;
|
||||
}
|
||||
|
||||
/* If this is a direct extract and we didn't want it, stop now */
|
||||
if (where_to != PlayPen && NoInstall)
|
||||
goto success;
|
||||
|
||||
setenv(PKG_PREFIX_VNAME,
|
||||
(p = find_plist(&Plist, PLIST_CWD)) ? p->name : NULL, 1);
|
||||
/* Protect against old packages with bogus @name fields */
|
||||
PkgName = (p = find_plist(&Plist, PLIST_NAME)) ? p->name : "anonymous";
|
||||
|
||||
/* See if we're already registered */
|
||||
sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
|
||||
basename_of(PkgName));
|
||||
if (isdir(LogDir)) {
|
||||
char tmp[FILENAME_MAX];
|
||||
|
||||
whinge("Package `%s' already recorded as installed.\n", PkgName);
|
||||
code = 1;
|
||||
goto success; /* close enough for government work */
|
||||
}
|
||||
|
||||
/* Finally unpack the whole mess */
|
||||
if (unpack(pkg_fullname, NULL)) {
|
||||
leave_playpen();
|
||||
return 1;
|
||||
whinge("Unable to extract `%s'!", pkg_fullname);
|
||||
goto bomb;
|
||||
}
|
||||
|
||||
if (sanity_check(pkg_fullname)) {
|
||||
leave_playpen();
|
||||
return 1;
|
||||
}
|
||||
if (sanity_check(pkg_fullname))
|
||||
goto bomb;
|
||||
|
||||
cfile = fopen(CONTENTS_FNAME, "r");
|
||||
if (!cfile) {
|
||||
whinge("Unable to open %s file.", CONTENTS_FNAME);
|
||||
goto fail;
|
||||
}
|
||||
read_plist(&Plist, cfile);
|
||||
fclose(cfile);
|
||||
if (Prefix) {
|
||||
/*
|
||||
* If we have a prefix, delete the first one we see and add this
|
||||
* one in place of it.
|
||||
*/
|
||||
delete_plist(&Plist, FALSE, PLIST_CWD, NULL);
|
||||
add_plist_top(&Plist, PLIST_CWD, Prefix);
|
||||
}
|
||||
/* If we're running in MASTER mode, just output the plist and return */
|
||||
if (AddMode == MASTER) {
|
||||
printf("%s\n", where_playpen());
|
||||
@ -134,28 +196,28 @@ pkg_do(char *pkg)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
setenv(PKG_PREFIX_VNAME,
|
||||
(p = find_plist(&Plist, PLIST_CWD)) ? p->name : NULL, 1);
|
||||
/* Protect against old packages with bogus @name fields */
|
||||
PkgName = (p = find_plist(&Plist, PLIST_NAME)) ? p->name : "anonymous";
|
||||
sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
|
||||
basename_of(PkgName));
|
||||
if (isdir(LogDir)) {
|
||||
whinge("Package `%s' already recorded as installed.\n", PkgName);
|
||||
code = 1;
|
||||
goto success; /* close enough for government work */
|
||||
}
|
||||
for (p = Plist.head; p ; p = p->next) {
|
||||
if (p->type != PLIST_PKGDEP)
|
||||
continue;
|
||||
if (Verbose)
|
||||
printf("Package `%s' depends on `%s'", PkgName, p->name);
|
||||
if (!Fake && vsystem("pkg_info -e %s", p->name)) {
|
||||
char tmp[120];
|
||||
char *cp, tmp[FILENAME_MAX], path[FILENAME_MAX*2];
|
||||
|
||||
if (Verbose)
|
||||
printf(" which is not currently loaded");
|
||||
sprintf(tmp, "%s/%s.tgz", Home, p->name);
|
||||
cp = getenv("PKG_PATH");
|
||||
if (!cp)
|
||||
cp = Home;
|
||||
strcpy(path, cp);
|
||||
cp = path;
|
||||
while (cp) {
|
||||
char *cp2 = strsep(&cp, ":");
|
||||
|
||||
sprintf(tmp, "%s/%s.tgz", cp2 ? cp2 : cp, p->name);
|
||||
if (fexists(tmp))
|
||||
break;
|
||||
}
|
||||
if (fexists(tmp)) {
|
||||
if (Verbose)
|
||||
printf(" but was found - loading:\n");
|
||||
@ -169,7 +231,7 @@ pkg_do(char *pkg)
|
||||
printf("\t`%s' loaded successfully.\n", p->name);
|
||||
}
|
||||
else {
|
||||
whinge("and was not found%s.", p->name,
|
||||
printf("and was not found%s.\n",
|
||||
Force ? " (proceeding anyway)" : "");
|
||||
if (!Force)
|
||||
code++;
|
||||
@ -201,6 +263,7 @@ pkg_do(char *pkg)
|
||||
printf("Running install with PRE-INSTALL for %s..\n", PkgName);
|
||||
if (!Fake && vsystem("./%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) {
|
||||
whinge("Install script returned error status.");
|
||||
unlink(INSTALL_FNAME);
|
||||
code = 1;
|
||||
goto success; /* nothing to uninstall yet */
|
||||
}
|
||||
@ -217,18 +280,22 @@ pkg_do(char *pkg)
|
||||
if (vsystem("/usr/sbin/mtree -u -f %s -d -e -p %s",
|
||||
MTREE_FNAME, p ? p->name : "/")) {
|
||||
perror("error in the execution of mtree");
|
||||
unlink(MTREE_FNAME);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
unlink(MTREE_FNAME);
|
||||
}
|
||||
if (!NoInstall && fexists(INSTALL_FNAME)) {
|
||||
if (Verbose)
|
||||
printf("Running install with POST-INSTALL for %s..\n", PkgName);
|
||||
if (!Fake && vsystem("./%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) {
|
||||
whinge("Install script returned error status.");
|
||||
unlink(INSTALL_FNAME);
|
||||
code = 1;
|
||||
goto fail;
|
||||
}
|
||||
unlink(INSTALL_FNAME);
|
||||
}
|
||||
if (!NoRecord && !Fake) {
|
||||
char contents[FILENAME_MAX];
|
||||
@ -257,9 +324,9 @@ pkg_do(char *pkg)
|
||||
/* Make sure pkg_info can read the entry */
|
||||
vsystem("chmod a+rx %s", LogDir);
|
||||
if (fexists(DEINSTALL_FNAME))
|
||||
copy_file(".", DEINSTALL_FNAME, LogDir);
|
||||
move_file(".", DEINSTALL_FNAME, LogDir);
|
||||
if (fexists(REQUIRE_FNAME))
|
||||
copy_file(".", REQUIRE_FNAME, LogDir);
|
||||
move_file(".", REQUIRE_FNAME, LogDir);
|
||||
sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME);
|
||||
cfile = fopen(contents, "w");
|
||||
if (!cfile) {
|
||||
@ -269,10 +336,10 @@ pkg_do(char *pkg)
|
||||
}
|
||||
write_plist(&Plist, cfile);
|
||||
fclose(cfile);
|
||||
copy_file(".", DESC_FNAME, LogDir);
|
||||
copy_file(".", COMMENT_FNAME, LogDir);
|
||||
move_file(".", DESC_FNAME, LogDir);
|
||||
move_file(".", COMMENT_FNAME, LogDir);
|
||||
if (fexists(DISPLAY_FNAME))
|
||||
copy_file(".", DISPLAY_FNAME, LogDir);
|
||||
move_file(".", DISPLAY_FNAME, LogDir);
|
||||
for (p = Plist.head; p ; p = p->next) {
|
||||
if (p->type != PLIST_PKGDEP)
|
||||
continue;
|
||||
@ -312,6 +379,10 @@ pkg_do(char *pkg)
|
||||
|
||||
goto success;
|
||||
|
||||
bomb:
|
||||
code = 1;
|
||||
goto success;
|
||||
|
||||
fail:
|
||||
/* Nuke the whole (installed) show, XXX but don't clean directories */
|
||||
if (!Fake)
|
||||
|
@ -92,17 +92,18 @@ Sets
|
||||
.Ar prefix
|
||||
as the directory in which to extract files from a package.
|
||||
If a package has set its default directory, it will be overridden
|
||||
by this flag. Note that only the first directory default will
|
||||
be replaced, since
|
||||
by this flag. Note that only the first
|
||||
.Cm @cwd
|
||||
directive will be replaced, since
|
||||
.Nm
|
||||
has no way of knowing which directory settings are relative and
|
||||
which are absolute. It is rare, in any case, that more than one
|
||||
directory transition is made, but when such is the case then you
|
||||
may wish to look into the use of
|
||||
which are absolute. It is rare, in any case, to see more than one
|
||||
directory transition made, but when such is the case you
|
||||
may then wish to look into the use of the
|
||||
.Cm MASTER
|
||||
and
|
||||
.Cm SLAVE
|
||||
mode (see the
|
||||
modes (see the
|
||||
.Fl M
|
||||
and
|
||||
.Fl S
|
||||
@ -166,27 +167,40 @@ and the contents then acted on as normal.
|
||||
.El
|
||||
.Sh TECHNICAL DETAILS
|
||||
.Nm
|
||||
is fairly simple. It simply extracts the requested packages into
|
||||
a ``staging area'' directory and then performs the following steps:
|
||||
is fairly simple. It extracts each packages' "packing list"
|
||||
into a special staging directory in /tmp (or $PKG_TMPDIR), parses it,
|
||||
then runs through the following sequence to fully extract the contents:
|
||||
.Bl -enum -indent indent
|
||||
.It
|
||||
It checks whether the package is already recorded as installed; if so,
|
||||
the installation terminates.
|
||||
Check if the package is already recorded as installed. If so,
|
||||
terminate installation.
|
||||
.It
|
||||
It checks whether all the package dependencies (from
|
||||
Scan all the package dependencies (from
|
||||
.Cm @pkgdep
|
||||
directives, see
|
||||
.Xr pkg_create 8 )
|
||||
are met; if not, the missing dependencies are printed and the
|
||||
installation terminates.
|
||||
and make sure each one is met. If not, print the missing dependencies and
|
||||
terminate the installation.
|
||||
.It
|
||||
Search for any
|
||||
.Cm @option
|
||||
directives which control how the package is added to the system.
|
||||
At the time of this writing, the only currently implemented option is
|
||||
.Cm @option extract-in-place
|
||||
which will cause the package to be extracted direcly into its
|
||||
prefix directory without moving through a staging area in /tmp.
|
||||
.It
|
||||
If
|
||||
.Cm @option extract-in-place
|
||||
is enabled, the package is now extracted directly into its
|
||||
final location, otherwise it is extracted into the staging area.
|
||||
.It
|
||||
If the package contains a
|
||||
.Ar require
|
||||
file (see
|
||||
.Xr pkg_create 8 ),
|
||||
then this is executed first as
|
||||
then execute it with the following arguments:
|
||||
.Bd -filled -offset indent -compact
|
||||
.Cm require
|
||||
.Ar <pkg-name>
|
||||
.Ar INSTALL
|
||||
.Ed
|
||||
@ -194,13 +208,12 @@ where
|
||||
.Ar <pkg-name>
|
||||
is the name of the package in question and
|
||||
.Ar INSTALL
|
||||
is a keyword denoting that this is an installation requirements check.
|
||||
is simply a keyword denoting that this is an installation requirements check.
|
||||
.It
|
||||
If an
|
||||
.Ar install
|
||||
script exists for the package, it is then executed as
|
||||
script exists for the package, it is then executed with the following arguments:
|
||||
.Bd -filled -offset indent -compact
|
||||
.Cm install
|
||||
.Ar <pkg-name>
|
||||
.Ar PRE-INSTALL
|
||||
.Ed
|
||||
@ -210,9 +223,11 @@ is the name of the package in question and
|
||||
.Ar PRE-INSTALL
|
||||
is a keyword denoting that this is the preinstallation phase.
|
||||
.It
|
||||
Using the packing list (the
|
||||
If
|
||||
.Cm @option extract-in-place
|
||||
is not used, then the packing list (this is the
|
||||
.Pa +CONTENTS
|
||||
file) as a guide, files are then moved (or copied, as necessary) from
|
||||
file) is now used as a guide for moving (or copying, as necessary) files from
|
||||
the staging area into their final locations.
|
||||
.It
|
||||
If the package contains an
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef lint
|
||||
static const char *rcsid = "$Id: perform.c,v 1.18 1995/04/22 00:59:33 jkh Exp $";
|
||||
static const char *rcsid = "$Id: perform.c,v 1.19 1995/04/22 01:20:13 jkh Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -174,6 +174,15 @@ pkg_perform(char **pkgs)
|
||||
return TRUE; /* Success */
|
||||
}
|
||||
|
||||
/*
|
||||
* This is evil. It is the command executed inline on tar's command line
|
||||
* to presort file arguments in such a way as to put the all-important
|
||||
* +* files at the front. I'm sure there's a way of doing this that's
|
||||
* a hundred times more efficient, but I'm in a hurry right now and I don't
|
||||
* have the time to think more about it.. -jkh
|
||||
*/
|
||||
#define SORTED_NAMES "`find . | sed -e 's/^\\.\\///' -e '/^\\.$/D' | sort`"
|
||||
|
||||
static void
|
||||
make_dist(char *home, char *pkg, char *suffix, Package *plist)
|
||||
{
|
||||
@ -194,9 +203,10 @@ make_dist(char *home, char *pkg, char *suffix, Package *plist)
|
||||
printf("Creating gzip'd tar ball in '%s'\n", tball);
|
||||
strcat(args, "cf");
|
||||
if (ExcludeFrom)
|
||||
ret = vsystem("tar %sX %s %s .", args, tball, ExcludeFrom);
|
||||
ret = vsystem("tar %sX %s %s %s", args, tball, ExcludeFrom,
|
||||
SORTED_NAMES);
|
||||
else
|
||||
ret = vsystem("tar %s %s .", args, tball);
|
||||
ret = vsystem("tar %s %s %s", args, tball, SORTED_NAMES);
|
||||
if (ret)
|
||||
barf("tar command failed with code %d", ret);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user