summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-04-22 13:58:24 +0000
committerjkh <jkh@FreeBSD.org>1995-04-22 13:58:24 +0000
commit631042660156d0f11cb143dc9a3fc9667a5705e2 (patch)
tree0fb33deff621eb7b07f74732bbece46c9f515373 /usr.sbin
parent9f35997ce19bdb55060cf582bd750b9e58794f42 (diff)
downloadFreeBSD-src-631042660156d0f11cb143dc9a3fc9667a5705e2.zip
FreeBSD-src-631042660156d0f11cb143dc9a3fc9667a5705e2.tar.gz
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! :-)
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/pkg_install/README4
-rw-r--r--usr.sbin/pkg_install/add/perform.c159
-rw-r--r--usr.sbin/pkg_install/add/pkg_add.155
-rw-r--r--usr.sbin/pkg_install/create/perform.c16
4 files changed, 165 insertions, 69 deletions
diff --git a/usr.sbin/pkg_install/README b/usr.sbin/pkg_install/README
index dabd52a..a5a517d 100644
--- a/usr.sbin/pkg_install/README
+++ b/usr.sbin/pkg_install/README
@@ -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! :-)
diff --git a/usr.sbin/pkg_install/add/perform.c b/usr.sbin/pkg_install/add/perform.c
index aa5058c..1218c75 100644
--- a/usr.sbin/pkg_install/add/perform.c
+++ b/usr.sbin/pkg_install/add/perform.c
@@ -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 (unpack(pkg_fullname, NULL)) {
- leave_playpen();
- return 1;
- }
- if (sanity_check(pkg_fullname)) {
- leave_playpen();
- return 1;
+ 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;
}
- 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 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)) {
+ whinge("Unable to extract `%s'!", pkg_fullname);
+ goto bomb;
}
+
+ if (sanity_check(pkg_fullname))
+ goto bomb;
+
/* 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)
diff --git a/usr.sbin/pkg_install/add/pkg_add.1 b/usr.sbin/pkg_install/add/pkg_add.1
index 5dba67c..682a1d5 100644
--- a/usr.sbin/pkg_install/add/pkg_add.1
+++ b/usr.sbin/pkg_install/add/pkg_add.1
@@ -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
diff --git a/usr.sbin/pkg_install/create/perform.c b/usr.sbin/pkg_install/create/perform.c
index 54c7fce..951ccce 100644
--- a/usr.sbin/pkg_install/create/perform.c
+++ b/usr.sbin/pkg_install/create/perform.c
@@ -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);
}
OpenPOWER on IntegriCloud