Made staging area configurable rather than assuming /tmp (-t)
Made pkg_add -n less bitchy. Made -p in pkg_add override "default" package location in pkg_create. Added concept of "slave" and "master" modes, allowing many different things to be done to packing lists on the fly. This is really something for front-end drivers to use, but also something for the more expert user. rename()'ing files before trying to copy them, thus saving considerable time when targets and staging area are on same filesystem.
This commit is contained in:
parent
14cb3fbecd
commit
368b3399cd
@ -23,6 +23,8 @@
|
||||
#ifndef _INST_ADD_H_INCLUDE
|
||||
#define _INST_ADD_H_INCLUDE
|
||||
|
||||
typedef enum { NORMAL, MASTER, SLAVE } add_mode_t;
|
||||
|
||||
extern char *Prefix;
|
||||
extern Boolean NoInstall;
|
||||
extern Boolean NoRecord;
|
||||
@ -31,6 +33,8 @@ extern char *Owner;
|
||||
extern char *Group;
|
||||
extern char *Directory;
|
||||
extern char *PkgName;
|
||||
extern char *PlayPen;
|
||||
extern add_mode_t AddMode;
|
||||
|
||||
int make_hierarchy(char *);
|
||||
void extract_plist(char *, Package *);
|
||||
|
@ -52,7 +52,12 @@ extract_plist(char *home, Package *pkg)
|
||||
if (Verbose)
|
||||
printf("extract: %s/%s\n", Directory, p->name);
|
||||
if (!Fake) {
|
||||
copy_hierarchy(Directory, p->name, TRUE);
|
||||
char try[FILENAME_MAX];
|
||||
|
||||
/* first try to rename it into place */
|
||||
sprintf(try, "%s/%s", Directory, p->name);
|
||||
if (rename(p->name, try) == FAIL)
|
||||
copy_hierarchy(Directory, p->name, TRUE);
|
||||
apply_perms(Directory, p->name);
|
||||
}
|
||||
break;
|
||||
|
@ -26,7 +26,7 @@ static char *rcsid = "$Id: main.c,v 1.6 1993/09/04 05:06:28 jkh Exp $";
|
||||
#include "lib.h"
|
||||
#include "add.h"
|
||||
|
||||
static char Options[] = "hvIRnp:";
|
||||
static char Options[] = "hvIRnp:SM";
|
||||
|
||||
char *Prefix = NULL;
|
||||
Boolean NoInstall = FALSE;
|
||||
@ -37,6 +37,8 @@ char *Owner = NULL;
|
||||
char *Group = NULL;
|
||||
char *PkgName = NULL;
|
||||
char *Directory = NULL;
|
||||
char *PlayPen = NULL;
|
||||
add_mode_t AddMode = NORMAL;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
@ -69,6 +71,18 @@ main(int argc, char **argv)
|
||||
Verbose = TRUE;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
PlayPen = optarg;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
AddMode = SLAVE;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
AddMode = MASTER;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
@ -84,9 +98,13 @@ main(int argc, char **argv)
|
||||
*pkgs++ = *argv++;
|
||||
|
||||
/* If no packages, yelp */
|
||||
if (pkgs == start)
|
||||
usage(prog_name, "Missing package name(s)");
|
||||
*pkgs = NULL;
|
||||
if (pkgs == start && AddMode != SLAVE)
|
||||
usage(prog_name, "Missing package name(s)");
|
||||
else if (start[1] && AddMode == MASTER)
|
||||
usage(prog_name, "Only one package name may be specified with master mode");
|
||||
else if (pkgs != start && AddMode == SLAVE)
|
||||
whinge("Package names ignored in slave mode.");
|
||||
if ((err = pkg_perform(start)) != NULL) {
|
||||
if (Verbose)
|
||||
fprintf(stderr, "%d package addition(s) failed.\n", err);
|
||||
@ -115,5 +133,8 @@ usage(const char *name, const char *fmt, ...)
|
||||
fprintf(stderr, "-I don't execute pkg install script, if any\n");
|
||||
fprintf(stderr, "-R don't record installation (can't delete!)\n");
|
||||
fprintf(stderr, "-n don't actually install, just show steps\n");
|
||||
fprintf(stderr, "-t temp use temp as template for mktemp()\n");
|
||||
fprintf(stderr, "-S run in SLAVE mode\n");
|
||||
fprintf(stderr, "-M run in MASTER mode\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -41,8 +41,12 @@ pkg_perform(char **pkgs)
|
||||
signal(SIGINT, cleanup);
|
||||
signal(SIGHUP, cleanup);
|
||||
|
||||
for (i = 0; pkgs[i]; i++)
|
||||
err_cnt += pkg_do(pkgs[i]);
|
||||
if (AddMode == SLAVE)
|
||||
err_cnt = pkg_do(NULL);
|
||||
else {
|
||||
for (i = 0; pkgs[i]; i++)
|
||||
err_cnt += pkg_do(pkgs[i]);
|
||||
}
|
||||
return err_cnt;
|
||||
}
|
||||
|
||||
@ -61,40 +65,65 @@ pkg_do(char *pkg)
|
||||
if (Plist.head)
|
||||
free_plist(&Plist);
|
||||
LogDir[0] = '\0';
|
||||
home = make_playpen();
|
||||
if (pkg[0] == '/') /* full pathname? */
|
||||
strcpy(pkg_fullname, pkg);
|
||||
else
|
||||
sprintf(pkg_fullname, "%s/%s", home, pkg);
|
||||
if (!fexists(pkg_fullname)) {
|
||||
whinge("Can't open package '%s'.", pkg_fullname);
|
||||
return 1;
|
||||
if (AddMode == SLAVE) {
|
||||
char tmp_dir[FILENAME_MAX];
|
||||
|
||||
fgets(tmp_dir, FILENAME_MAX, stdin);
|
||||
tmp_dir[strlen(tmp_dir) - 1] = '\0'; /* pesky newline! */
|
||||
if (chdir(tmp_dir) == FAIL) {
|
||||
whinge("pkg_add in SLAVE mode can't chdir to %s.", tmp_dir);
|
||||
return 1;
|
||||
}
|
||||
read_plist(&Plist, stdin);
|
||||
}
|
||||
else {
|
||||
home = make_playpen(PlayPen);
|
||||
if (pkg[0] == '/') /* full pathname? */
|
||||
strcpy(pkg_fullname, pkg);
|
||||
else
|
||||
sprintf(pkg_fullname, "%s/%s", home, pkg);
|
||||
if (!fexists(pkg_fullname)) {
|
||||
whinge("Can't open package '%s'.", pkg_fullname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unpack(pkg_fullname, NULL))
|
||||
return 1;
|
||||
if (unpack(pkg_fullname, NULL))
|
||||
return 1;
|
||||
|
||||
if (sanity_check(pkg_fullname))
|
||||
return 1;
|
||||
if (sanity_check(pkg_fullname))
|
||||
return 1;
|
||||
|
||||
cfile = fopen(CONTENTS_FNAME, "r");
|
||||
if (!cfile) {
|
||||
whinge("Unable to open %s file.", CONTENTS_FNAME);
|
||||
goto fail;
|
||||
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);
|
||||
}
|
||||
/* Just to be safe - overridden if package has made a choice */
|
||||
else
|
||||
add_plist_top(&Plist, PLIST_CWD, home);
|
||||
/* If we're running in MASTER mode, just output the plist and return */
|
||||
if (AddMode == MASTER) {
|
||||
printf("%s\n", where_playpen());
|
||||
write_plist(&Plist, stdout);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* If we have a prefix, add it now */
|
||||
if (Prefix)
|
||||
add_plist(&Plist, PLIST_CWD, Prefix);
|
||||
else
|
||||
add_plist(&Plist, PLIST_CWD, home);
|
||||
read_plist(&Plist, cfile);
|
||||
fclose(cfile);
|
||||
PkgName = find_name(&Plist);
|
||||
if (fexists(REQUIRE_FNAME)) {
|
||||
vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */
|
||||
if (Verbose)
|
||||
printf("Running requirements file first for %s..\n", PkgName);
|
||||
if (vsystem("%s %s INSTALL", REQUIRE_FNAME, PkgName)) {
|
||||
if (!Fake && vsystem("%s %s INSTALL", REQUIRE_FNAME, PkgName)) {
|
||||
whinge("Package %s fails requirements - not installed.",
|
||||
pkg_fullname);
|
||||
goto fail;
|
||||
@ -104,7 +133,7 @@ pkg_do(char *pkg)
|
||||
vsystem("chmod +x %s", INSTALL_FNAME); /* make sure */
|
||||
if (Verbose)
|
||||
printf("Running install with PRE-INSTALL for %s..\n", PkgName);
|
||||
if (vsystem("%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) {
|
||||
if (!Fake && vsystem("%s %s PRE-INSTALL", INSTALL_FNAME, PkgName)) {
|
||||
whinge("Install script returned error status.");
|
||||
goto fail;
|
||||
}
|
||||
@ -113,12 +142,15 @@ pkg_do(char *pkg)
|
||||
if (!NoInstall && fexists(INSTALL_FNAME)) {
|
||||
if (Verbose)
|
||||
printf("Running install with POST-INSTALL for %s..\n", PkgName);
|
||||
if (vsystem("%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) {
|
||||
if (!Fake && vsystem("%s %s POST-INSTALL", INSTALL_FNAME, PkgName)) {
|
||||
whinge("Install script returned error status.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (!NoRecord && !Fake) {
|
||||
char contents[FILENAME_MAX];
|
||||
FILE *cfile;
|
||||
|
||||
if (getuid() != 0)
|
||||
whinge("Not running as root - trying to record install anyway.");
|
||||
if (!PkgName) {
|
||||
@ -140,7 +172,15 @@ pkg_do(char *pkg)
|
||||
copy_file(".", DEINSTALL_FNAME, LogDir);
|
||||
if (fexists(REQUIRE_FNAME))
|
||||
copy_file(".", REQUIRE_FNAME, LogDir);
|
||||
copy_file(".", CONTENTS_FNAME, LogDir);
|
||||
sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME);
|
||||
cfile = fopen(contents, "w");
|
||||
if (!cfile) {
|
||||
whinge("Can't open new contents file '%s'! Can't register pkg.",
|
||||
contents);
|
||||
goto success; /* can't log, but still keep pkg */
|
||||
}
|
||||
write_plist(&Plist, cfile);
|
||||
fclose(cfile);
|
||||
copy_file(".", DESC_FNAME, LogDir);
|
||||
copy_file(".", COMMENT_FNAME, LogDir);
|
||||
if (Verbose)
|
||||
@ -194,6 +234,8 @@ find_name(Package *pkg)
|
||||
void
|
||||
cleanup(int signo)
|
||||
{
|
||||
if (signo)
|
||||
printf("Signal %d received, cleaning up..\n", signo);
|
||||
if (Plist.head) {
|
||||
if (!Fake)
|
||||
delete_package(FALSE, &Plist);
|
||||
|
@ -60,15 +60,77 @@ you know what you are doing!
|
||||
.BI "\-p\ " prefix
|
||||
Sets
|
||||
.I prefix
|
||||
as the directory in which to extract files from any packages
|
||||
which do not explicitly set theirs.
|
||||
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
|
||||
.B pkg_add
|
||||
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
|
||||
.B MASTER
|
||||
and
|
||||
.B SLAVE
|
||||
mode (see
|
||||
.B \-M
|
||||
and
|
||||
.B \-S
|
||||
options).
|
||||
.B "Optional."
|
||||
.TP
|
||||
.BI "\-t\ " template
|
||||
Use
|
||||
.I template
|
||||
as the input to mktemp(3). By default, this is the string
|
||||
.B /tmp/instmp.XXXXXX
|
||||
, but it may be necessary to override it in the situation where
|
||||
space in your
|
||||
.B /tmp
|
||||
directory is limited. Be sure to leave some number of `X' characters
|
||||
for mktemp(3) to fill in with a unique ID.
|
||||
.B "Optional."
|
||||
.TP
|
||||
.B \-M
|
||||
Run in
|
||||
.B MASTER
|
||||
mode. This is a very specialized mode for running
|
||||
.B pkg_add
|
||||
and is meant to be run in conjunction with
|
||||
.B SLAVE
|
||||
mode. When run in this mode,
|
||||
.B pkg_add
|
||||
does no work beyond extracting the package into a temporary staging
|
||||
area (see
|
||||
.B \-t
|
||||
option), reading in the packing list, and then dumping it (prefaced by
|
||||
the current staging area) to stdout where it may be filtered by a
|
||||
program such as
|
||||
.B sed(1).
|
||||
When used in conjunction with
|
||||
.B SLAVE
|
||||
mode, it allows you to make radical changes to the package structure
|
||||
before acting on its contents.
|
||||
.TP
|
||||
.B \-S
|
||||
Run in
|
||||
.B SLAVE
|
||||
mode. This is a very specialized mode for running
|
||||
.B pkg_add
|
||||
and is meant to be run in conjunction with
|
||||
.B MASTER
|
||||
mode. When run in this mode,
|
||||
.B pkg_add
|
||||
expects the release contents to be already extracted and waiting
|
||||
in the staging area, the location of which is read as a string
|
||||
from stdin. The complete packing list is also read from stdin,
|
||||
and the contents then acted on as normal.
|
||||
.PP
|
||||
.SH "TECHNICAL DETAILS"
|
||||
.B
|
||||
pkg_add
|
||||
is fairly simple. It simply extracts the requested packages into
|
||||
the current working directory and then performs the following steps:
|
||||
a "staging area" directory and then performs the following steps:
|
||||
.PP
|
||||
If the package contains a
|
||||
.B require
|
||||
@ -95,8 +157,8 @@ Where
|
||||
is the name of the package in question and
|
||||
.I PRE-INSTALL
|
||||
is a keyword denoting that this is the "pre installation" pass.
|
||||
Files are then copied from the packing list into their new homes, as expected,
|
||||
and the
|
||||
Using the packing list as a guide, files are then moved (or copied,
|
||||
as necessary) from the staging area into their new homes and the
|
||||
.B install
|
||||
script is then executed a second time with the flags
|
||||
.PP
|
||||
@ -113,6 +175,7 @@ to any
|
||||
script the package might have, is copied into /var/pkg/<pkg-name>
|
||||
for subsequent possible use by
|
||||
.B pkg-delete.
|
||||
Finally, the staging area is deleted and the program terminates.
|
||||
.PP
|
||||
.SH BUGS
|
||||
Sure to be some.
|
||||
|
Loading…
Reference in New Issue
Block a user