diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-06-04 07:56:15 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-06-04 07:56:15 +0000 |
commit | 167be6f259825b0e88a4cfc7cd9228c9603fc603 (patch) | |
tree | c173305ec5afd2f63886e210fa18f7b9c69695b8 /usr.sbin/pkg_install/create | |
parent | c8e3d32207db0af93ff3f660ded6b01fac993998 (diff) |
add package tools from FreeBSD
Diffstat (limited to 'usr.sbin/pkg_install/create')
-rw-r--r-- | usr.sbin/pkg_install/create/Makefile | 17 | ||||
-rw-r--r-- | usr.sbin/pkg_install/create/create.h | 46 | ||||
-rw-r--r-- | usr.sbin/pkg_install/create/main.c | 177 | ||||
-rw-r--r-- | usr.sbin/pkg_install/create/perform.c | 286 | ||||
-rw-r--r-- | usr.sbin/pkg_install/create/pkg_create.1 | 381 | ||||
-rw-r--r-- | usr.sbin/pkg_install/create/pl.c | 217 |
6 files changed, 1124 insertions, 0 deletions
diff --git a/usr.sbin/pkg_install/create/Makefile b/usr.sbin/pkg_install/create/Makefile new file mode 100644 index 00000000000..c5029619028 --- /dev/null +++ b/usr.sbin/pkg_install/create/Makefile @@ -0,0 +1,17 @@ +# $OpenBSD: Makefile,v 1.1 1996/06/04 07:56:05 niklas Exp $ +PROG= pkg_create + +CFLAGS+= ${DEBUG} -I${.CURDIR}/../lib + +.if exists(${.CURDIR}/../lib/obj) +LDADD+= -L${.CURDIR}/../lib/obj -linstall +DPADD+= ${.CURDIR}/../lib/obj/libinstall.a +.else +LDADD+= -L${.CURDIR}/../lib -linstall +DPADD+= ${.CURDIR}/../lib/libinstall.a +.endif + + +SRCS= main.c perform.c pl.c + +.include <bsd.prog.mk> diff --git a/usr.sbin/pkg_install/create/create.h b/usr.sbin/pkg_install/create/create.h new file mode 100644 index 00000000000..71c616c673a --- /dev/null +++ b/usr.sbin/pkg_install/create/create.h @@ -0,0 +1,46 @@ +/* $OpenBSD: create.h,v 1.1 1996/06/04 07:56:05 niklas Exp $ */ + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Include and define various things wanted by the create command. + * + */ + +#ifndef _INST_CREATE_H_INCLUDE +#define _INST_CREATE_H_INCLUDE + +extern char *Prefix; +extern char *Comment; +extern char *Desc; +extern char *Display; +extern char *Install; +extern char *DeInstall; +extern char *Contents; +extern char *Require; +extern char PlayPen[]; +extern char *ExcludeFrom; +extern char *Mtree; +extern char *Pkgdeps; +extern int Dereference; +extern int PlistOnly; + +void check_list(char *, Package *); +void usage(const char *, const char *, ...); +int pkg_perform(char **); +void copy_plist(char *, Package *); + +#endif /* _INST_CREATE_H_INCLUDE */ diff --git a/usr.sbin/pkg_install/create/main.c b/usr.sbin/pkg_install/create/main.c new file mode 100644 index 00000000000..19498a8e66c --- /dev/null +++ b/usr.sbin/pkg_install/create/main.c @@ -0,0 +1,177 @@ +# $OpenBSD: main.c,v 1.1 1996/06/04 07:56:05 niklas Exp $ +#ifndef lint +static const char *rcsid = "$OpenBSD: main.c,v 1.1 1996/06/04 07:56:05 niklas Exp $"; +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the create module. + * + */ + +#include "lib.h" +#include "create.h" + +static char Options[] = "YNOhvf:p:P:c:d:i:k:r:t:X:D:m:"; + +char *Prefix = NULL; +char *Comment = NULL; +char *Desc = NULL; +char *Display = NULL; +char *Install = NULL; +char *DeInstall = NULL; +char *Contents = NULL; +char *Require = NULL; +char PlayPen[FILENAME_MAX]; +char *ExcludeFrom = NULL; +char *Mtree = NULL; +char *Pkgdeps = NULL; +int Dereference = 0; +int PlistOnly = 0; + +int +main(int argc, char **argv) +{ + int ch; + char **pkgs, **start; + char *prog_name = argv[0]; + + pkgs = start = argv; + while ((ch = getopt(argc, argv, Options)) != EOF) + switch(ch) { + case 'v': + Verbose = TRUE; + break; + + case 'N': + AutoAnswer = NO; + break; + + case 'Y': + AutoAnswer = YES; + break; + + case 'O': + PlistOnly = YES; + break; + + case 'p': + Prefix = optarg; + break; + + case 'f': + Contents = optarg; + break; + + case 'c': + Comment = optarg; + break; + + case 'd': + Desc = optarg; + break; + + case 'i': + Install = optarg; + break; + + case 'k': + DeInstall = optarg; + break; + + case 'r': + Require = optarg; + break; + + case 't': + strcpy(PlayPen, optarg); + break; + + case 'X': + ExcludeFrom = optarg; + break; + + case 'h': + Dereference = 1; + break; + + case 'D': + Display = optarg; + break; + + case 'm': + Mtree = optarg; + break; + + case 'P': + Pkgdeps = optarg; + break; + + case '?': + default: + usage(prog_name, NULL); + break; + } + + argc -= optind; + argv += optind; + + /* Get all the remaining package names, if any */ + while (*argv) + *pkgs++ = *argv++; + + /* If no packages, yelp */ + if (pkgs == start) + usage(prog_name, "Missing package name"); + *pkgs = NULL; + if (start[1]) + usage(prog_name, "Only one package name allowed\n\t('%s' extraneous)", + start[1]); + if (!pkg_perform(start)) { + if (Verbose) + fprintf(stderr, "Package creation failed.\n"); + return 1; + } + else + return 0; +} + +void +usage(const char *name, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + if (fmt) { + fprintf(stderr, "%s: ", name); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n\n"); + } + va_end(args); + fprintf(stderr, "Usage: %s [args] pkg\n\n", name); + fprintf(stderr, "Where args are one or more of:\n\n"); + + fprintf(stderr, "-c [-]file Get one-line comment from file (-or arg)\n"); + fprintf(stderr, "-d [-]file Get description from file (-or arg)\n"); + fprintf(stderr, "-f file get list of files from file (- for stdin)\n"); + fprintf(stderr, "-h follow symbolic links\n"); + fprintf(stderr, "-i script install script\n"); + fprintf(stderr, "-k script de-install script\n"); + fprintf(stderr, "-D file install notice\n"); + fprintf(stderr, "-m file mtree spec for directories\n"); + fprintf(stderr, "-P pkgs set package dependency list to pkgs\n"); + fprintf(stderr, "-p prefix install prefix will be arg\n"); + fprintf(stderr, "-r script pre/post requirements script\n"); + fprintf(stderr, "-t temp use temp as template for mktemp()\n"); + fprintf(stderr, "-X file exclude files listed in file\n"); + fprintf(stderr, "-v verbose\n"); + fprintf(stderr, "-Y assume `yes' answer to all questions\n"); + fprintf(stderr, "-N assume `no' answer to all questions\n"); + fprintf(stderr, "-O print a revised packing list and exit\n"); + exit(1); +} diff --git a/usr.sbin/pkg_install/create/perform.c b/usr.sbin/pkg_install/create/perform.c new file mode 100644 index 00000000000..f1b703299a2 --- /dev/null +++ b/usr.sbin/pkg_install/create/perform.c @@ -0,0 +1,286 @@ +# $OpenBSD: perform.c,v 1.1 1996/06/04 07:56:05 niklas Exp $ +#ifndef lint +static const char *rcsid = "$OpenBSD: perform.c,v 1.1 1996/06/04 07:56:05 niklas Exp $"; +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * This is the main body of the create module. + * + */ + +#include "lib.h" +#include "create.h" + +#include <errno.h> +#include <signal.h> +#include <sys/syslimits.h> +#include <unistd.h> + +static void sanity_check(void); +static void make_dist(char *, char *, char *, Package *); + +static char *home; + +int +pkg_perform(char **pkgs) +{ + char *pkg = *pkgs; /* Only one arg to create */ + char *cp; + FILE *pkg_in, *fp; + Package plist; + char *suffix; /* What we tack on to the end of the finished package */ + + /* Preliminary setup */ + sanity_check(); + if (Verbose && !PlistOnly) + printf("Creating package %s\n", pkg); + get_dash_string(&Comment); + get_dash_string(&Desc); + if (!strcmp(Contents, "-")) + pkg_in = stdin; + else { + pkg_in = fopen(Contents, "r"); + if (!pkg_in) + barf("Unable to open contents file '%s' for input.", Contents); + } + plist.head = plist.tail = NULL; + + /* Break the package name into base and desired suffix (if any) */ + if ((cp = rindex(pkg, '.')) != NULL) { + suffix = cp + 1; + *cp = '\0'; + } + else + suffix = "tgz"; + + /* Stick the dependencies, if any, at the top */ + if (Pkgdeps) { + if (Verbose && !PlistOnly) + printf("Registering depends:"); + while (Pkgdeps) { + cp = strsep(&Pkgdeps, " \t\n"); + if (*cp) { + add_plist(&plist, PLIST_PKGDEP, cp); + if (Verbose && !PlistOnly) + printf(" %s", cp); + } + } + if (Verbose && !PlistOnly) + printf(".\n"); + } + /* Slurp in the packing list */ + read_plist(&plist, pkg_in); + + /* Prefix should override the packing list */ + if (Prefix) { + delete_plist(&plist, FALSE, PLIST_CWD, NULL); + add_plist_top(&plist, PLIST_CWD, Prefix); + } + /* + * Run down the list and see if we've named it, if not stick in a name + * at the top. + */ + if (find_plist(&plist, PLIST_NAME) == NULL) + add_plist_top(&plist, PLIST_NAME, basename_of(pkg)); + + /* + * We're just here for to dump out a revised plist for the FreeBSD ports + * hack. It's not a real create in progress. + */ + if (PlistOnly) { + write_plist(&plist, stdout); + exit(0); + } + + /* Make a directory to stomp around in */ + home = make_playpen(PlayPen, 0); + signal(SIGINT, cleanup); + signal(SIGHUP, cleanup); + + /* Make first "real contents" pass over it */ + check_list(home, &plist); + (void) umask(022); /* make sure gen'ed directories, files don't have + group or other write bits. */ + /* copy_plist(home, &plist); */ + /* mark_plist(&plist); */ + + /* Now put the release specific items in */ + add_plist(&plist, PLIST_CWD, "."); + write_file(COMMENT_FNAME, Comment); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, COMMENT_FNAME); + write_file(DESC_FNAME, Desc); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, DESC_FNAME); + + if (Install) { + copy_file(home, Install, INSTALL_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, INSTALL_FNAME); + } + if (DeInstall) { + copy_file(home, DeInstall, DEINSTALL_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME); + } + if (Require) { + copy_file(home, Require, REQUIRE_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, REQUIRE_FNAME); + } + if (Display) { + copy_file(home, Display, DISPLAY_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, DISPLAY_FNAME); + add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME); + } + if (Mtree) { + copy_file(home, Mtree, MTREE_FNAME); + add_plist(&plist, PLIST_IGNORE, NULL); + add_plist(&plist, PLIST_FILE, MTREE_FNAME); + add_plist(&plist, PLIST_MTREE, MTREE_FNAME); + } + + /* Run through the list again, picking up extra "local" items */ + /* check_list(".", &plist); */ + /* copy_plist(".", &plist); */ + /* mark_plist(&plist); */ + + /* Finally, write out the packing list */ + fp = fopen(CONTENTS_FNAME, "w"); + if (!fp) + barf("Can't open file %s for writing.", CONTENTS_FNAME); + write_plist(&plist, fp); + if (fclose(fp)) + barf("Error while closing %s.", CONTENTS_FNAME); + + /* And stick it into a tar ball */ + make_dist(home, pkg, suffix, &plist); + + /* Cleanup */ + free(Comment); + free(Desc); + free_plist(&plist); + cleanup(0); + return TRUE; /* Success */ +} + +static void +make_dist(char *home, char *pkg, char *suffix, Package *plist) +{ + char tball[FILENAME_MAX]; + PackingList p; + int ret, max, len; + char *args[50]; /* Much more than enough. */ + int nargs = 0; + int pipefds[2]; + FILE *totar; + pid_t pid; + + args[nargs++] = "tar"; /* argv[0] */ + + if (*pkg == '/') + snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suffix); + else + snprintf(tball, FILENAME_MAX, "%s/%s.%s", home, pkg, suffix); + + args[nargs++] = "-c"; + args[nargs++] = "-f"; + args[nargs++] = tball; + if (index(suffix, 'z')) /* Compress/gzip? */ + args[nargs++] = "-z"; + if (Dereference) + args[nargs++] = "-h"; + if (ExcludeFrom) { + args[nargs++] = "-X"; + args[nargs++] = ExcludeFrom; + } + args[nargs++] = "-T"; /* Take filenames from file instead of args. */ + args[nargs++] = "-"; /* Use stdin for the file. */ + args[nargs] = NULL; + + if (Verbose) + printf("Creating gzip'd tar ball in '%s'\n", tball); + + /* Set up a pipe for passing the filenames, and fork off a tar process. */ + if (pipe(pipefds) == -1) + barf("Cannot create pipe: %s", strerror(errno)); + if ((pid = fork()) == -1) + barf("Cannot fork process for tar: %s", strerror(errno)); + if (pid == 0) { /* The child */ + dup2(pipefds[0], 0); + close(pipefds[0]); + close(pipefds[1]); + execv("/usr/bin/tar", args); + barf("Failed to execute tar command: %s", strerror(errno)); + } + + /* Meanwhile, back in the parent process ... */ + close(pipefds[0]); + if ((totar = fdopen(pipefds[1], "w")) == NULL) + barf("fdopen failed: %s", strerror(errno)); + + fprintf(totar, "%s\n", CONTENTS_FNAME); + fprintf(totar, "%s\n", COMMENT_FNAME); + fprintf(totar, "%s\n", DESC_FNAME); + + if (Install) + fprintf(totar, "%s\n", INSTALL_FNAME); + if (DeInstall) + fprintf(totar, "%s\n", DEINSTALL_FNAME); + if (Require) + fprintf(totar, "%s\n", REQUIRE_FNAME); + if (Display) + fprintf(totar, "%s\n", DISPLAY_FNAME); + if (Mtree) + fprintf(totar, "%s\n", MTREE_FNAME); + + for (p = plist->head; p; p = p->next) { + if (p->type == PLIST_FILE) + fprintf(totar, "%s\n", p->name); + else if (p->type == PLIST_CWD || p->type == PLIST_SRC) + fprintf(totar, "-C\n%s\n", p->name); + else if (p->type == PLIST_IGNORE) + p = p->next; + } + + fclose(totar); + wait(&ret); + /* assume either signal or bad exit is enough for us */ + if (ret) + barf("tar command failed with code %d", ret); +} + +static void +sanity_check() +{ + if (!Comment) + barf("Required package comment string is missing (-c comment)."); + if (!Desc) + barf("Required package description string is missing (-d desc)."); + if (!Contents) + barf("Required package contents list is missing (-f [-]file)."); +} + + +/* Clean up those things that would otherwise hang around */ +void +cleanup(int sig) +{ + leave_playpen(home); +} diff --git a/usr.sbin/pkg_install/create/pkg_create.1 b/usr.sbin/pkg_install/create/pkg_create.1 new file mode 100644 index 00000000000..3715efdf0ad --- /dev/null +++ b/usr.sbin/pkg_install/create/pkg_create.1 @@ -0,0 +1,381 @@ +.\" $OpenBSD: pkg_create.1,v 1.1 1996/06/04 07:56:06 niklas Exp $ +.\" +.\" FreeBSD install - a package for the installation and maintainance +.\" of non-core utilities. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" Jordan K. Hubbard +.\" +.\" +.\" @(#)pkg_create.1 +.\" +.\" hacked up by John Kohl for NetBSD--fixed a few bugs, extended keywords, +.\" added dependency tracking, etc. +.\" +.\" [jkh] Took John's changes back and made some additional extensions for +.\" better integration with FreeBSD's new ports collection. +.\" +.Dd April 21, 1995 +.Dt pkg_create 1 +.Os FreeBSD 2.0 +.Sh NAME +.Nm pkg_create +.Nd a utility for creating software package distributions. +.Sh SYNOPSIS +.Nm +.Op Fl YNOhv +.Op Fl P Ar pkgs +.Op Fl p Ar prefix +.Op Fl f Ar contents +.Op Fl i Ar iscript +.Op Fl k Ar dscript +.Op Fl r Ar rscript +.Op Fl t Ar template +.Op Fl X Ar excludefile +.Op Fl D Ar displayfile +.Op Fl m Ar mtreefile +.Fl d Ar description +.Fl f Ar packlist +.Ar pkg-name +.Sh DESCRIPTION +The +.Nm +command is used to create packages that will subsequently be fed to +one of the package extraction/info utilities. The input description +and command line arguments for the creation of a package are not +really meant to be human-generated, though it is easy enough to +do so. It is more expected that you will use a front-end tool for +the job rather than muddling through it yourself. Nonetheless, a short +description of the input syntax is included in this document. +.Sh OPTIONS +The following command line options are supported. +.Bl -tag -width indent +.It Fl f Ar packinglist +Fetch ``packing list'' for package from the file +.Ar packinglist +or +.Cm stdin +if +.Ar packinglist +is a +.Cm - +(dash). +.Em "Mandatory." +.It Fl c Ar [-]desc +Fetch package ``one line description'' from file +.Ar desc +or, if preceded by +.Cm - , +the argument itself. This string should also +give some idea of which version of the product (if any) the package +represents. +.Em "Mandatory." +.It Fl d Ar [-]desc +Fetch long description for package from file +.Ar desc +or, if preceded by +.Cm - , +the argument itself. +.Em "Mandatory." +.It Fl Y +Assume a default answer of `Yes' for any questions asked. +.Em "Optional." +.It Fl N +Assume a default answer of `No' for any questions asked. +.It Fl O +Go into a `packing list Only' mode. This is a custom hack for the +.Em "FreeBSD Ports Collection" +and is used to do `fake pkg_add' operations when a port is installed. +In such cases, it is necessary to know what the final, adjusted packing +list will look like. +.Em "Optional." +.It Fl v +Turns on verbose output. +.Em "Optional." +.It Fl h +Forces tar to follow symbolic links, so that the files they point to +are dumped, rather than the links themselves. +.It Fl i Ar iscript +Sets +.Ar iscript +to be the install procedure for the package. This can be any +executable program (or shell script). It will be invoked automatically +when the package is later installed. +.Em "Optional." +.It Fl P Ar pkgs +Sets the initial package dependency list to +.Ar pkgs. +This is assumed to be a whitespace separated list of package names +and is meant as a convenient shorthand for specifying multiple +.Cm @pkgdep +directives in the packing list (see PACKING LIST DETAILS section below). +.Em "Optional." +.It Fl p Ar prefix +Sets +.Ar prefix +as the initial directory ``base'' to start from in selecting files for +the package. +.Em "Optional." +.It Fl k Ar dscript +Sets +.Ar dscript +to be the de-install procedure for the package. This can be any +executable program (or shell script). It will be invoked automatically +when the package is later (if ever) de-installed. +.Em "Optional." +.It Fl r Ar rscript +Sets +.Ar rscript +to be the ``requirements'' procedure for the package. This can be any +executable program (or shell script). It will be invoked automatically +at installation/deinstallation time to determine whether or not +installation/deinstallation should proceed. +.Em "Optional." +.It Fl t Ar template +Use +.Ar template +as the input to +.Xr mktemp 3 . +By default, this is the string +.Pa /tmp/instmp.XXXXXX , +but it may be necessary to override it in the situation where +space in your +.Pa /tmp +directory is limited. Be sure to leave some number of `X' characters +for +.Xr mktemp 3 + to fill in with a unique ID. +.Em "Optional." +.It Fl X Ar excludefile +Pass +.Ar excludefile +as a +.Fl exclude-from +argument to +.Cm tar +when creating final package. See +.Cm tar +man page (or run +.Cm tar +with +.Fl -help +flag) for further information on using this flag. +.It Fl D Ar displayfile +Display the file (using +.Xr more 1 ) +after installing the package. Useful for things like +legal notices on almost-free software, etc. +.It Fl m Ar mtreefile +Run +.Xr mtree 8 +with input from mtreefile before the package is installed. +Mtree is invoked as +.Cm mtree +.Fl u +.Fl f +.Ar mtreefile +.Fl d +.Fl e +.Fl p +.Pa prefix , +where +.Pa prefix +is the name of the first directory named by a +.Cm @cwd +directive. +.El +.Pp +.Sh PACKING LIST DETAILS +The ``packing list'' format (see +.Fl f ) +is fairly simple, being +nothing more than a single column of filenames to include in the +package. However, since absolute pathnames are generally a bad idea +for a package that could be installed potentially anywhere, there is +another method of specifying where things are supposed to go +and, optionally, what ownership and mode information they should be +installed with. This is done by imbeding specialized command sequences +in the packing list. Briefly described, these sequences are: +.Bl -tag -width indent -compact +.It Cm @cwd Ar directory +Sets the internal directory pointer to point to +.Ar directory . +All subsequent filenames will be assumed relative to this directory. +Note: +.Cm @cd +is also an alias for this command. +.It Cm @srcdir Ar directory +Sets the internal directory pointer for _creation only_ to +.Ar directory . +That is to say that it overrides +.Cm @cwd +for package creation but not extraction. +.It Cm @exec Ar command +Execute +.Ar command +as part of the unpacking process. If +.Ar command +contains a any of the following sequences somewhere in it, they will +be expanded inline. For the following examples, assume that +.Cm @cwd +is set to +.Pa /usr/local +and the last extracted file was +.Pa bin/emacs . +.Bl -tag -width indent -compact +.It Cm "%F" +Expands to the last filename extracted (as specified), in the example case +.Pa bin/emacs +.It Cm "%D" +Expands to the current directory prefix, as set with +.Cm @cwd , +in the example case +.Pa /usr/local . +.It Cm "%B" +Expands to the ``basename'' of the fully qualified filename, that +is the current directory prefix, plus the last filespec, minus +the trailing filename. In the example case, that would be +.Pa /usr/local/bin . +.It Cm "%f" +Expands to the ``filename'' part of the fully qualified name, or +the converse of +.Cm %B , +being in the example case, +.Pa emacs . +.El +.It Cm @unexec Ar command +Execute +.Ar command +as part of the deinstallation process. Expansion of special +.Cm % +sequences is the same as for +.Cm @exec . +This command is not executed during the package add, as +.Cm @exec +is, but rather when the package is deleted. This is useful +for deleting links and other ancillary files that were created +as a result of adding the package, but not directly known to +the package's table of contents (and hence not automatically +removable). The advantage of using +.Cm @unexec +over a deinstallation script is that you can use the ``special +sequence expansion'' to get at files regardless of where they've +been potentially redirected (see +.Fl p ) +.It Cm @mode Ar mode +Sets default permission for all subsequently extracted files to +.Ar mode . +Format is the same as that used by the +.Cm chmod +command (well, considering that it's later handed off to it, that's +no surprise). Use without an arg to set back to default (extraction) +permissions. +.It Cm @owner Ar user +Sets default ownership for all subsequently extracted files to +.Ar user . +Use without an arg to set back to default (extraction) +ownership. +.It Cm @group Ar group +Sets default group ownership for all subsequently extracted files to +.Ar group . +Use without an arg to set back to default (extraction) +group ownership. +.It Cm @comment Ar string +Imbed a comment in the packing list. Useful in +trying to document some particularly hairy sequence that +may trip someone up later. +.It Cm @ignore +Used internally to tell extraction to ignore the next file (don't +copy it anywhere), as it's used for some special purpose. +.It Cm @ignore_inst +Similar to +.Cm @ignore , +but the ignoring of the next file is delayed one evaluation cycle. This +makes it possible to use this directive in the +.Ar packinglist +file, so you can pack a +specialized datafile in with a distribution for your install script (or +something) yet have the installer ignore it. +.It Cm @name Ar name +Sets the name of the package. This is mandatory and is usually +put at the top. This name is potentially different than the name of +the file it came in, and is used when keeping track of the package +for later deinstallation. Note that +.Nm +will derive this field from the package name and add it automatically +if none is given. +.It Cm @dirrm Ar name +Declare directory +.Pa name +to be deleted at deinstall time. By default, directories created by a +package installation are not deleted when the package is deinstalled; +this provides an explicit directory cleanup method. This directive +should appear at the end of the package list. If more than one +.Cm @dirrm +directives are used, the directories are removed in the order specified. +The +.Pa name +directory will not be removed unless it is empty. +.It Cm @mtree Ar name +Declare +.Pa name +as an +.Xr mtree 8 +input file to be used at install time (see +.Fl m +above). Only the first +.Cm @mtree +directive is honored. +.It Cm @display Ar name +Declare +.Pa name +as the file to be displayed at install time (see +.Fl D +above). +.It Cm @pkgdep Ar pkgname +Declares a dependency on the +.Ar pkgname +package. The +.Ar pkgname +package must be installed before this package may be +installed, and this package must be deinstalled before the +.Ar pkgname +package is deinstalled. Multiple +.Cm @pkgdep +directives may be used if hte package depends on multiple other packages. +.El +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_delete 1 , +.Xr pkg_info 1 , +.Xr sysconf 3 . +.Sh HISTORY +The +.Nm +command first appeared in FreeBSD. +.Sh AUTHORS +.Bl -tag -width indent -compact +.It "Jordan Hubbard" +most of the work +.It "John Kohl" +refined it for NetBSD +.El +.Sh BUGS +Hard links between files in a distribution must be bracketed by +.Cm @cwd +directives in order to be preserved as hard links when the package is +extracted. They additionally must not end up being split between +.Cm tar +invocations due to exec argument-space limitations (this depends on the +value returned by +.Fn sysconf _SC_ARG_MAX ) . +.Pp +Sure to be others. diff --git a/usr.sbin/pkg_install/create/pl.c b/usr.sbin/pkg_install/create/pl.c new file mode 100644 index 00000000000..39101035274 --- /dev/null +++ b/usr.sbin/pkg_install/create/pl.c @@ -0,0 +1,217 @@ +# $OpenBSD: pl.c,v 1.1 1996/06/04 07:56:06 niklas Exp $ +#ifndef lint +static const char *rcsid = "$OpenBSD: pl.c,v 1.1 1996/06/04 07:56:06 niklas Exp $"; +#endif + +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * Routines for dealing with the packing list. + * + */ + +#include "lib.h" +#include "create.h" +#include <errno.h> + +/* Check a list for files that require preconversion */ +void +check_list(char *home, Package *pkg) +{ + char cmd[FILENAME_MAX]; + char name[FILENAME_MAX]; + char *where = home; + char *there = NULL; + PackingList p = pkg->head; + + while (p) { + if (p->type == PLIST_CWD) + where = p->name; + else if (p->type == PLIST_IGNORE) + p = p->next; + else if (p->type == PLIST_SRC) { + there = p->name; + } + else if (p->type == PLIST_FILE) { + cmd[0] = '\0'; + sprintf(name, "%s/%s", there ? there : where, p->name); + + if (*cmd) { + if (Verbose) + printf("Uncompressing-> %s\n", cmd); + if (system(cmd)) + barf("%s failed!", cmd); + nuke_suffix(p->name); + } + } + p = p->next; + } +} + +static int +trylink(const char *from, const char *to) +{ + if (link(from, to) == 0) + return 0; + if (errno == ENOENT) { + /* try making the container directory */ + char *cp = strrchr(to, '/'); + if (cp) + vsystem("mkdir -p %.*s", cp - to, + to); + return link(from, to); + } + return -1; +} + +#define STARTSTRING "tar cf -" +#define TOOBIG(str) strlen(str) + 6 + strlen(home) + where_count > maxargs +#define PUSHOUT() /* push out string */ \ + if (where_count > sizeof(STARTSTRING)-1) { \ + strcat(where_args, "|tar xpf -"); \ + if (system(where_args)) \ + barf("can't invoke tar pipeline"); \ + memset(where_args, 0, maxargs); \ + last_chdir = NULL; \ + strcpy(where_args, STARTSTRING); \ + where_count = sizeof(STARTSTRING)-1; \ + } + +/* + * Copy unmarked files in packing list to playpen - marked files + * have already been copied in an earlier pass through the list. + */ +void +copy_plist(char *home, Package *plist) +{ + PackingList p = plist->head; + char *where = home; + char *there = NULL, *mythere; + char *where_args, *last_chdir, *root = "/"; + int maxargs, where_count = 0, add_count; + struct stat stb; + dev_t curdir; + + maxargs = sysconf(_SC_ARG_MAX); + maxargs -= 64; /* some slop for the tar cmd text, + and sh -c */ + where_args = malloc(maxargs); + if (!where_args) + barf("can't get argument list space"); + + memset(where_args, 0, maxargs); + strcpy(where_args, STARTSTRING); + where_count = sizeof(STARTSTRING)-1; + last_chdir = 0; + + if (stat(".", &stb) == 0) + curdir = stb.st_dev; + else + curdir = (dev_t) -1; /* It's ok if this is a valid dev_t; + this is just a hint for an + optimization. */ + + while (p) { + if (p->type == PLIST_CWD) + where = p->name; + else if (p->type == PLIST_SRC) + there = p->name; + else if (p->type == PLIST_IGNORE) + p = p->next; + else if (p->type == PLIST_FILE && !p->marked) { + char fn[FILENAME_MAX]; + + + /* First, look for it in the "home" dir */ + sprintf(fn, "%s/%s", home, p->name); + if (fexists(fn)) { + if (lstat(fn, &stb) == 0 && stb.st_dev == curdir && + S_ISREG(stb.st_mode)) { + /* if we can link it to the playpen, that avoids a copy + and saves time. */ + if (p->name[0] != '/') { + /* don't link abspn stuff--it doesn't come from + local dir! */ + if (trylink(fn, p->name) == 0) { + p = p->next; + continue; + } + } + } + if (TOOBIG(fn)) { + PUSHOUT(); + } + if (p->name[0] == '/') { + add_count = snprintf(&where_args[where_count], + maxargs - where_count, + " %s %s", + last_chdir == root ? "" : "-C /", + p->name); + last_chdir = root; + } else { + add_count = snprintf(&where_args[where_count], + maxargs - where_count, + " %s%s %s", + last_chdir == home ? "" : "-C ", + last_chdir == home ? "" : home, + p->name); + last_chdir = home; + } + if (add_count > maxargs - where_count) + barf("oops, miscounted strings!"); + where_count += add_count; + } + /* + * Otherwise, try along the actual extraction path.. + */ + else { + if (p->name[0] == '/') + mythere = root; + else mythere = there; + sprintf(fn, "%s/%s", mythere ? mythere : where, p->name); + if (lstat(fn, &stb) == 0 && stb.st_dev == curdir && + S_ISREG(stb.st_mode)) { + /* if we can link it to the playpen, that avoids a copy + and saves time. */ + if (trylink(fn, p->name) == 0) { + p = p->next; + continue; + } + } + if (TOOBIG(p->name)) { + PUSHOUT(); + } + if (last_chdir == (mythere ? mythere : where)) + add_count = snprintf(&where_args[where_count], + maxargs - where_count, + " %s", p->name); + else + add_count = snprintf(&where_args[where_count], + maxargs - where_count, + " -C %s %s", + mythere ? mythere : where, + p->name); + if (add_count > maxargs - where_count) + barf("oops, miscounted strings!"); + where_count += add_count; + last_chdir = (mythere ? mythere : where); + } + } + p = p->next; + } + PUSHOUT(); + free(where_args); +} |