Пример #1
0
static int
check_package_conflict(const char *pkgname, void *v)
{
    struct package_conflict *conflict = v;
    package_t pkg;
    plist_t *p;
    FILE *f;
    int rv;

    if (conflict->skip_pkgname != NULL &&
            strcmp(conflict->skip_pkgname, pkgname) == 0)
        return 0;

    rv = 0;

    f = fopen_contents(pkgname, "r");
    read_plist(&pkg, f);
    (void)fclose(f);

    for (p = pkg.head; p; p = p->next) {
        if (p->type != PLIST_PKGCFL)
            continue;

        if (pkg_match(p->name, conflict->pkgname) == 1) {
            *(conflict->conflicting_pkgname) = xstrdup(pkgname);
            *(conflict->conflicting_pattern) = xstrdup(p->name);
            rv = 1 /* nonzero, stop iterating */;
            break;
        }
    }

    free_plist(&pkg);
    return rv;
}
Пример #2
0
static int
add_depends_of(const char *pkgname, void *cookie)
{
    FILE *fp;
    plist_t *p;
    package_t plist;
    char *path;

    path = pkgdb_pkg_file(pkgname, CONTENTS_FNAME);
    if ((fp = fopen(path, "r")) == NULL)
        errx(EXIT_FAILURE, "Cannot read %s of package %s",
             CONTENTS_FNAME, pkgname);
    free(path);
    read_plist(&plist, fp);
    fclose(fp);

    for (p = plist.head; p; p = p->next) {
        if (p->type == PLIST_PKGDEP)
            add_required_by(p->name, pkgname);
    }

    free_plist(&plist);

    return 0;
}
Пример #3
0
static int
create_from_installed(const char *ipkg, const char *pkg, const char *suf)
{
    FILE *fp;
    Package plist;
    char homedir[MAXPATHLEN], log_dir[FILENAME_MAX];

    snprintf(log_dir, sizeof(log_dir), "%s/%s", LOG_DIR, ipkg);
    if (!fexists(log_dir)) {
	warnx("can't find package '%s' installed!", ipkg);
	return FALSE;
    }
    getcwd(homedir, sizeof(homedir));
    if (chdir(log_dir) == FAIL) {
	warnx("can't change directory to '%s'!", log_dir);
	return FALSE;
    }
    /* Suck in the contents list */
    plist.head = plist.tail = NULL;
    fp = fopen(CONTENTS_FNAME, "r");
    if (!fp) {
	warnx("unable to open %s file", CONTENTS_FNAME);
	return FALSE;
    }
    read_plist(&plist, fp);
    fclose(fp);

    Install = isfile(INSTALL_FNAME) ? (char *)INSTALL_FNAME : NULL;
    PostInstall = isfile(POST_INSTALL_FNAME) ?
	(char *)POST_INSTALL_FNAME : NULL;
    DeInstall = isfile(DEINSTALL_FNAME) ? (char *)DEINSTALL_FNAME : NULL;
    PostDeInstall = isfile(POST_DEINSTALL_FNAME) ?
	(char *)POST_DEINSTALL_FNAME : NULL;
    Require = isfile(REQUIRE_FNAME) ? (char *)REQUIRE_FNAME : NULL;
    Display = isfile(DISPLAY_FNAME) ? (char *)DISPLAY_FNAME : NULL;
    Mtree = isfile(MTREE_FNAME) ?  (char *)MTREE_FNAME : NULL;

    make_dist(homedir, pkg, suf, &plist);

    free_plist(&plist);
    if (chdir(homedir) == FAIL) {
	warnx("can't change directory to '%s'!", homedir);
	return FALSE;
    }
    return TRUE;
}
Пример #4
0
static int
create_from_installed_recursive(const char *pkg, const char *suf)
{
    FILE *fp;
    Package plist;
    PackingList p;
    char tmp[PATH_MAX];
    int rval;

    if (!create_from_installed(InstalledPkg, pkg, suf))
	return FALSE;
    snprintf(tmp, sizeof(tmp), "%s/%s/%s", LOG_DIR, InstalledPkg, CONTENTS_FNAME);
    if (!fexists(tmp)) {
	warnx("can't find package '%s' installed!", InstalledPkg);
	return FALSE;
    }
    /* Suck in the contents list */
    plist.head = plist.tail = NULL;
    fp = fopen(tmp, "r");
    if (!fp) {
	warnx("unable to open %s file", tmp);
	return FALSE;
    }
    read_plist(&plist, fp);
    fclose(fp);
    rval = TRUE;
    for (p = plist.head; p ; p = p->next) {
	if (p->type != PLIST_PKGDEP)
	    continue;
	if (Verbose)
	    printf("Creating package %s\n", p->name);
	if (!create_from_installed(p->name, p->name, suf)) {
	    rval = FALSE;
	    break;
	}
    }
    free_plist(&plist);
    return rval;
}
Пример #5
0
/*
 * add1pkg(<pkg>)
 *	adds the files listed in the +CONTENTS of <pkg> into the
 *	pkgdb.byfile.db database file in the current package dbdir.  It
 *	returns the number of files added to the database file.
 */
static int
add_pkg(const char *pkgdir, void *vp)
{
    FILE	       *f;
    plist_t	       *p;
    package_t	Plist;
    char 	       *contents;
    char *PkgName, *dirp;
    char 		file[MaxPathSize];
    struct pkgdb_count *count;

    if (!pkgdb_open(ReadWrite))
        err(EXIT_FAILURE, "cannot open pkgdb");

    count = vp;
    ++count->packages;

    contents = pkgdb_pkg_file(pkgdir, CONTENTS_FNAME);
    if ((f = fopen(contents, "r")) == NULL)
        errx(EXIT_FAILURE, "%s: can't open `%s'", pkgdir, CONTENTS_FNAME);
    free(contents);

    read_plist(&Plist, f);
    if ((p = find_plist(&Plist, PLIST_NAME)) == NULL) {
        errx(EXIT_FAILURE, "Package `%s' has no @name, aborting.", pkgdir);
    }

    PkgName = p->name;
    dirp = NULL;
    for (p = Plist.head; p; p = p->next) {
        switch(p->type) {
        case PLIST_FILE:
            if (dirp == NULL) {
                errx(EXIT_FAILURE, "@cwd not yet found, please send-pr!");
            }
            (void) snprintf(file, sizeof(file), "%s/%s", dirp, p->name);
            if (!(isfile(file) || islinktodir(file))) {
                if (isbrokenlink(file)) {
                    warnx("%s: Symlink `%s' exists and is in %s but target does not exist!",
                          PkgName, file, CONTENTS_FNAME);
                } else {
                    warnx("%s: File `%s' is in %s but not on filesystem!",
                          PkgName, file, CONTENTS_FNAME);
                }
            } else {
                pkgdb_store(file, PkgName);
                ++count->files;
            }
            break;
        case PLIST_PKGDIR:
            add_pkgdir(PkgName, dirp, p->name);
            ++count->directories;
            break;
        case PLIST_CWD:
            if (strcmp(p->name, ".") != 0)
                dirp = p->name;
            else
                dirp = pkgdb_pkg_dir(pkgdir);
            break;
        case PLIST_IGNORE:
            p = p->next;
            break;
        case PLIST_SHOW_ALL:
        case PLIST_SRC:
        case PLIST_CMD:
        case PLIST_CHMOD:
        case PLIST_CHOWN:
        case PLIST_CHGRP:
        case PLIST_COMMENT:
        case PLIST_NAME:
        case PLIST_UNEXEC:
        case PLIST_DISPLAY:
        case PLIST_PKGDEP:
        case PLIST_DIR_RM:
        case PLIST_OPTION:
        case PLIST_PKGCFL:
        case PLIST_BLDDEP:
            break;
        }
    }
    free_plist(&Plist);
    fclose(f);
    pkgdb_close();

    return 0;
}
Пример #6
0
/*
 * Assumes CWD is in /var/db/pkg/<pkg>!
 */
static void 
check1pkg(const char *pkgdir, int *filecnt, int *pkgcnt)
{
	FILE   *f;
	plist_t *p;
	package_t Plist;
	char   *PkgName, *dirp = NULL, *md5file;
	char    file[MaxPathSize];
	char   *content;

	content = pkgdb_pkg_file(pkgdir, CONTENTS_FNAME);
	f = fopen(content, "r");
	if (f == NULL)
		err(EXIT_FAILURE, "can't open %s", content);
	free(content);

	read_plist(&Plist, f);
	p = find_plist(&Plist, PLIST_NAME);
	if (p == NULL)
		errx(EXIT_FAILURE, "Package %s has no @name, aborting.",
		    pkgdir);
	PkgName = p->name;
	for (p = Plist.head; p; p = p->next) {
		switch (p->type) {
		case PLIST_FILE:
			if (dirp == NULL) {
				warnx("dirp not initialized, please send-pr!");
				abort();
			}
			
			(void) snprintf(file, sizeof(file), "%s/%s", dirp, p->name);

			if (isfile(file) || islinktodir(file)) {
				if (p->next && p->next->type == PLIST_COMMENT) {
					if (strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) {
						if ((md5file = MD5File(file, NULL)) != NULL) {
							/* Mismatch? */
							if (strcmp(md5file, p->next->name + ChecksumHeaderLen) != 0)
								printf("%s fails MD5 checksum\n", file);

							free(md5file);
						}
					} else if (strncmp(p->next->name, SYMLINK_HEADER, SymlinkHeaderLen) == 0) {
						char	buf[MaxPathSize + SymlinkHeaderLen];
						int	cc;

						(void) strlcpy(buf, SYMLINK_HEADER, sizeof(buf));
						if ((cc = readlink(file, &buf[SymlinkHeaderLen],
							  sizeof(buf) - SymlinkHeaderLen - 1)) < 0) {
							warnx("can't readlink `%s'", file);
						} else {
							buf[SymlinkHeaderLen + cc] = 0x0;
							if (strcmp(buf, p->next->name) != 0) {
								printf("symlink (%s) is not same as recorded value, %s: %s\n",
								    file, buf, p->next->name);
							}
						}
					}
				}
				
				(*filecnt)++;
			} else if (isbrokenlink(file)) {
				warnx("%s: Symlink `%s' exists and is in %s but target does not exist!", PkgName, file, CONTENTS_FNAME);
			} else {
				warnx("%s: File `%s' is in %s but not on filesystem!", PkgName, file, CONTENTS_FNAME);
			}
			break;
		case PLIST_CWD:
			if (strcmp(p->name, ".") != 0)
				dirp = p->name;
			else
				dirp = pkgdb_pkg_dir(pkgdir);
			break;
		case PLIST_IGNORE:
			p = p->next;
			break;
		case PLIST_SHOW_ALL:
		case PLIST_SRC:
		case PLIST_CMD:
		case PLIST_CHMOD:
		case PLIST_CHOWN:
		case PLIST_CHGRP:
		case PLIST_COMMENT:
		case PLIST_NAME:
		case PLIST_UNEXEC:
		case PLIST_DISPLAY:
		case PLIST_PKGDEP:
		case PLIST_DIR_RM:
		case PLIST_OPTION:
		case PLIST_PKGCFL:
		case PLIST_BLDDEP:
		case PLIST_PKGDIR:
			break;
		}
	}
	free_plist(&Plist);
	fclose(f);
	(*pkgcnt)++;
}
Пример #7
0
/*
 * This is seriously ugly code following.  Written very fast!
 * [And subsequently made even worse..  Sigh!  This code was just born
 * to be hacked, I guess.. :) -jkh]
 */
static int
pkg_do(char *pkg)
{
    Package Plist;
    char pkg_fullname[FILENAME_MAX];
    char playpen[FILENAME_MAX];
    char extract_contents[FILENAME_MAX];
    char *extract;
    const char *where_to;
    FILE *cfile;
    int code;
    PackingList p;
    struct stat sb;
    int inPlace, conflictsfound, errcode;
    /* support for separate pre/post install scripts */
    int new_m = 0;
    char pre_script[FILENAME_MAX] = INSTALL_FNAME;
    char post_script[FILENAME_MAX];
    char pre_arg[FILENAME_MAX], post_arg[FILENAME_MAX];
    char *conflict[2];
    char **matched;
    int fd;

    conflictsfound = 0;
    code = 0;
    zapLogDir = 0;
    LogDir[0] = '\0';
    strcpy(playpen, FirstPen);
    inPlace = 0;

    memset(&Plist, '\0', sizeof(Plist));

    /* Are we coming in for a second pass, everything already extracted? */
    if (!pkg) {
	fgets(playpen, FILENAME_MAX, stdin);
	playpen[strlen(playpen) - 1] = '\0'; /* pesky newline! */
	if (chdir(playpen) == FAIL) {
	    warnx("pkg_add in SLAVE mode can't chdir to %s", playpen);
	    return 1;
	}
	read_plist(&Plist, stdin);
	where_to = playpen;
    }
    /* Nope - do it now */
    else {
	/* Is it an ftp://foo.bar.baz/file.t[bg]z specification? */
	if (isURL(pkg)) {
	    if (!(where_to = fileGetURL(NULL, pkg, KeepPackage))) {
		warnx("unable to fetch '%s' by URL", pkg);
		return 1;
	    }
	    strcpy(pkg_fullname, pkg);
	    cfile = fopen(CONTENTS_FNAME, "r");
	    if (!cfile) {
		warnx(
		"unable to open table of contents file '%s' - not a package?",
		CONTENTS_FNAME);
		goto bomb;
	    }
	    read_plist(&Plist, cfile);
	    fclose(cfile);
	}
	else {
	    strcpy(pkg_fullname, pkg);		/*
						 * Copy for sanity's sake,
						 * could remove pkg_fullname
						 */
	    if (strcmp(pkg, "-")) {
		if (stat(pkg_fullname, &sb) == FAIL) {
		    warnx("can't stat package file '%s'", pkg_fullname);
		    goto bomb;
		}
		sprintf(extract_contents, "--fast-read %s", CONTENTS_FNAME);
		extract = extract_contents;
	    }
	    else {
		extract = NULL;
		sb.st_size = 100000;	/* Make up a plausible average size */
	    }
	    if (!(where_to = make_playpen(playpen, sb.st_size * 4)))
		errx(1, "unable to make playpen for %lld bytes", (long long)sb.st_size * 4);
	    /* Since we can call ourselves recursively, keep notes on where we came from */
	    if (!getenv("_TOP"))
		setenv("_TOP", where_to, 1);
	    if (unpack(pkg_fullname, extract)) {
		warnx(
	"unable to extract table of contents file from '%s' - not a package?",
		pkg_fullname);
		goto bomb;
	    }
	    cfile = fopen(CONTENTS_FNAME, "r");
	    if (!cfile) {
		warnx(
	"unable to open table of contents file '%s' - not a package?",
		CONTENTS_FNAME);
		goto bomb;
	    }
	    read_plist(&Plist, cfile);
	    fclose(cfile);

	    /* 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) && !Fake) {
			if (Verbose)
			    printf("Desired prefix of %s does not exist, creating..\n", p->name);
			vsystem("/bin/mkdir -p %s", p->name);
			if (chdir(p->name) == -1) {
			    warn("unable to change directory to '%s'", p->name);
			    goto bomb;
			}
		    }
		    where_to = p->name;
		    inPlace = 1;
		}
		else {
		    warnx(
		"no prefix specified in '%s' - this is a bad package!",
			pkg_fullname);
		    goto bomb;
		}
	    }

	    /*
	     * Apply a crude heuristic to see how much space the package will
	     * take up once it's unpacked.  I've noticed that most packages
	     * compress an average of 75%, so multiply by 4 for good measure.
	     */

	    if (!extract && !inPlace && min_free(playpen) < sb.st_size * 4) {
		warnx("projected size of %lld exceeds available free space.\n"
"Please set your PKG_TMPDIR variable to point to a location with more\n"
		       "free space and try again", (long long)sb.st_size * 4);
		warnx("not extracting %s\ninto %s, sorry!",
			pkg_fullname, where_to);
		goto bomb;
	    }

	    /* If this is a direct extract and we didn't want it, stop now */
	    if (inPlace && Fake)
		goto success;

	    /* Finally unpack the whole mess.  If extract is null we
	       already + did so so don't bother doing it again. */
	    if (extract && unpack(pkg_fullname, NULL)) {
		warnx("unable to extract '%s'!", pkg_fullname);
		goto bomb;
	    }
	}

	/* Check for sanity and dependencies */
	if (sanity_check(pkg))
	    goto bomb;

	/* 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 0;
	}
    }

    /*
     * 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);
    }

    setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1);
    /* Protect against old packages with bogus @name and origin fields */
    if (Plist.name == NULL)
	Plist.name = "anonymous";
    if (Plist.origin == NULL)
	Plist.origin = "anonymous/anonymous";

    /*
     * See if we're already registered either with the same name (the same
     * version) or some other version with the same origin.
     */
    if ((isinstalledpkg(Plist.name) > 0 ||
         matchbyorigin(Plist.origin, NULL) != NULL) && !Force) {
	warnx("package '%s' or its older version already installed%s",
	      Plist.name, FailOnAlreadyInstalled ? "" : " (ignored)");
	code = FailOnAlreadyInstalled != FALSE;
	goto success;	/* close enough for government work */
    }

    /* Now check the packing list for conflicts */
    if (!IgnoreDeps){
    for (p = Plist.head; p != NULL; p = p->next) {
	if (p->type == PLIST_CONFLICTS) {
	    int i;
	    conflict[0] = strdup(p->name);
	    conflict[1] = NULL;
	    matched = matchinstalled(MATCH_GLOB, conflict, &errcode);
	    free(conflict[0]);
	    if (errcode == 0 && matched != NULL)
		for (i = 0; matched[i] != NULL; i++)
		    if (isinstalledpkg(matched[i]) > 0) {
			warnx("package '%s' conflicts with %s", Plist.name,
				matched[i]);
			conflictsfound = 1;
		    }

	    continue;
	}
    }
    if(conflictsfound) {
	if(!Force) {
	    warnx("please use pkg_delete first to remove conflicting package(s) or -f to force installation");
	    code = 1;
	    goto bomb;
	} else
	    warnx("-f specified; proceeding anyway");
    }

#if ENSURE_THAT_ALL_REQUIREMENTS_ARE_MET
    /*
     * Before attempting to do the slave mode bit, ensure that we've
     * downloaded & processed everything we need.
     * It's possible that we haven't already installed all of our
     * dependencies if the dependency list was misgenerated due to
     * other dynamic dependencies or if a dependency was added to a
     * package without all REQUIRED_BY packages being regenerated.
     */
    for (p = pkg ? Plist.head : NULL; p; p = p->next) {
	const char *ext;
	char *deporigin;

	if (p->type != PLIST_PKGDEP)
	    continue;
	deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL;

	if (isinstalledpkg(p->name) <= 0 &&
	    !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) {
	    char subpkg[FILENAME_MAX], *sep;

	    strlcpy(subpkg, pkg, sizeof subpkg);
	    if ((sep = strrchr(subpkg, '/')) != NULL) {
		*sep = '\0';
		if ((sep = strrchr(subpkg, '/')) != NULL) {
		    *sep = '\0';
		    strlcat(subpkg, "/All/", sizeof subpkg);
		    strlcat(subpkg, p->name, sizeof subpkg);
		    if ((ext = strrchr(pkg, '.')) == NULL) {
			if (getenv("PACKAGESUFFIX"))
			  ext = getenv("PACKAGESUFFIX");
			else
			  ext = ".tbz";
		    }
		    strlcat(subpkg, ext, sizeof subpkg);
		    pkg_do(subpkg);
		}
	    }
	}
    }
#endif

    /* Now check the packing list for dependencies */
    for (p = Plist.head; p ; p = p->next) {
	char *deporigin;

	if (p->type != PLIST_PKGDEP)
	    continue;
	deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL;
	if (Verbose) {
	    printf("Package '%s' depends on '%s'", Plist.name, p->name);
	    if (deporigin != NULL)
		printf(" with '%s' origin", deporigin);
	    printf(".\n");
	}
	if (isinstalledpkg(p->name) <= 0 &&
	    !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) {
	    char path[FILENAME_MAX];
	    const char *cp = NULL;

	    if (!Fake) {
		char prefixArg[2 + MAXPATHLEN]; /* "-P" + Prefix */
		if (PrefixRecursive) {
		    strlcpy(prefixArg, "-P", sizeof(prefixArg));
		    strlcat(prefixArg, Prefix, sizeof(prefixArg));
		}
		if (!isURL(pkg) && !getenv("PKG_ADD_BASE")) {
		    const char *ext;

		    ext = strrchr(pkg_fullname, '.');
		    if (ext == NULL) {
			if (getenv("PACKAGESUFFIX")) {
			  ext = getenv("PACKAGESUFFIX");
			} else {
			  ext = ".tbz";
			}
		    }
		    snprintf(path, FILENAME_MAX, "%s/%s%s", getenv("_TOP"), p->name, ext);
		    if (fexists(path))
			cp = path;
		    else
			cp = fileFindByPath(pkg, p->name);
		    if (cp) {
			if (Verbose)
			    printf("Loading it from %s.\n", cp);
			if (vsystem("%s %s %s '%s'", PkgAddCmd, Verbose ? "-v " : "", PrefixRecursive ? prefixArg : "", cp)) {
			    warnx("autoload of dependency '%s' failed%s",
				cp, Force ? " (proceeding anyway)" : "!");
			    if (!Force)
				++code;
			}
		    }
		    else {
			warnx("could not find package %s %s",
			      p->name, Force ? " (proceeding anyway)" : "!");
			if (!Force)
			    ++code;
		    }
		}
		else if ((cp = fileGetURL(pkg, p->name, KeepPackage)) != NULL) {
		    if (Verbose)
			printf("Finished loading %s via a URL\n", p->name);
		    if (!fexists("+CONTENTS")) {
			warnx("autoloaded package %s has no +CONTENTS file?",
				p->name);
			if (!Force)
			    ++code;
		    }
		    else if (vsystem("(pwd; /bin/cat +CONTENTS) | %s %s %s %s -S", PkgAddCmd, Verbose ? "-v" : "", PrefixRecursive ? prefixArg : "", KeepPackage ? "-K" : "")) {
			warnx("pkg_add of dependency '%s' failed%s",
				p->name, Force ? " (proceeding anyway)" : "!");
			if (!Force)
			    ++code;
		    }
		    else if (Verbose)
			printf("\t'%s' loaded successfully.\n", p->name);
		    /* Nuke the temporary playpen */
		    leave_playpen();
		}
	    }
	    else {
		if (Verbose)
		    printf("and was not found%s.\n", Force ? " (proceeding anyway)" : "");
		else
		    printf("Package dependency %s for %s not found%s\n", p->name, pkg,
			   Force ? " (proceeding anyway)" : "!");
		if (!Force)
		    ++code;
	    }
	}
	else if (Verbose)
	    printf(" - already installed.\n");
    }
    } /* if (!IgnoreDeps) */

    if (code != 0)
	goto bomb;

    /* Look for the requirements file */
    if ((fd = open(REQUIRE_FNAME, O_RDWR)) != -1) {
	fstat(fd, &sb);
	fchmod(fd, sb.st_mode | S_IXALL);	/* be sure, chmod a+x */
	close(fd);
	if (Verbose)
	    printf("Running requirements file first for %s..\n", Plist.name);
	if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, Plist.name)) {
	    warnx("package %s fails requirements %s", pkg_fullname,
		   Force ? "installing anyway" : "- not installed");
	    if (!Force) {
		code = 1;
		goto success;	/* close enough for government work */
	    }
	}
    }

    /*
     * Test whether to use the old method of passing tokens to installation
     * scripts, and set appropriate variables..
     */

    if (fexists(POST_INSTALL_FNAME)) {
	new_m = 1;
	sprintf(post_script, "%s", POST_INSTALL_FNAME);
	pre_arg[0] = '\0';
	post_arg[0] = '\0';
    } else {
	if (fexists(INSTALL_FNAME)) {
	    sprintf(post_script, "%s", INSTALL_FNAME);
	    sprintf(pre_arg, "PRE-INSTALL");
	    sprintf(post_arg, "POST-INSTALL");
	}
    }

    /* If we're really installing, and have an installation file, run it */
    if (!NoInstall && (fd = open(pre_script, O_RDWR)) != -1) {
	fstat(fd, &sb);
	fchmod(fd, sb.st_mode | S_IXALL);	/* be sure, chmod a+x */
	close(fd);
	if (Verbose)
	    printf("Running pre-install for %s..\n", Plist.name);
	if (!Fake && vsystem("./%s %s %s", pre_script, Plist.name, pre_arg)) {
	    warnx("install script returned error status");
	    unlink(pre_script);
	    code = 1;
	    goto success;		/* nothing to uninstall yet */
	}
    }

    /* Now finally extract the entire show if we're not going direct */
    if (!inPlace && !Fake)
	extract_plist(".", &Plist);

    if (!Fake && fexists(MTREE_FNAME)) {
	if (Verbose)
	    printf("Running mtree for %s..\n", Plist.name);
	p = find_plist(&Plist, PLIST_CWD);
	if (Verbose)
	    printf("mtree -U -f %s -d -e -p %s >%s\n", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL);
	if (!Fake) {
	    if (vsystem("/usr/sbin/mtree -U -f %s -d -e -p %s >%s", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL))
		warnx("mtree returned a non-zero status - continuing");
	}
    }

    /* Run the installation script one last time? */
    if (!NoInstall && (fd = open(post_script, O_RDWR)) != -1) {
	fstat(fd, &sb);
	fchmod(fd, sb.st_mode | S_IXALL);	/* be sure, chmod a+x */
	close(fd);
	if (Verbose)
	    printf("Running post-install for %s..\n", Plist.name);
	if (!Fake && vsystem("./%s %s %s", post_script, Plist.name, post_arg)) {
	    warnx("install script returned error status");
	    unlink(post_script);
	    code = 1;
	    goto fail;
	}
    }

    /* Time to record the deed? */
    if (!NoRecord && !Fake) {
	char contents[FILENAME_MAX];
	char **depnames = NULL, **deporigins = NULL, ***depmatches;
	int i, dep_count = 0;
	FILE *contfile;

	if (getuid() != 0)
	    warnx("not running as root - trying to record install anyway");
	sprintf(LogDir, "%s/%s", LOG_DIR, Plist.name);
	zapLogDir = 1;
	if (Verbose)
	    printf("Attempting to record package into %s..\n", LogDir);
	if (make_hierarchy(LogDir, FALSE)) {
	    warnx("can't record package into '%s', you're on your own!",
		   LogDir);
	    bzero(LogDir, FILENAME_MAX);
	    code = 1;
	    goto success;	/* close enough for government work */
	}
	/* Make sure pkg_info can read the entry */
	fd = open(LogDir, O_RDWR);
	fstat(fd, &sb);
	fchmod(fd, sb.st_mode | S_IRALL | S_IXALL);	/* be sure, chmod a+rx */
	close(fd);
	move_file(".", DESC_FNAME, LogDir);
	move_file(".", COMMENT_FNAME, LogDir);
	if (fexists(INSTALL_FNAME))
	    move_file(".", INSTALL_FNAME, LogDir);
	if (fexists(POST_INSTALL_FNAME))
	    move_file(".", POST_INSTALL_FNAME, LogDir);
	if (fexists(DEINSTALL_FNAME))
	    move_file(".", DEINSTALL_FNAME, LogDir);
	if (fexists(POST_DEINSTALL_FNAME))
	    move_file(".", POST_DEINSTALL_FNAME, LogDir);
	if (fexists(REQUIRE_FNAME))
	    move_file(".", REQUIRE_FNAME, LogDir);
	if (fexists(DISPLAY_FNAME))
	    move_file(".", DISPLAY_FNAME, LogDir);
	if (fexists(MTREE_FNAME))
	    move_file(".", MTREE_FNAME, LogDir);
	sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME);
	contfile = fopen(contents, "w");
	if (!contfile) {
	    warnx("can't open new contents file '%s'! can't register pkg",
		contents);
	    goto success; /* can't log, but still keep pkg */
	}
	write_plist(&Plist, contfile);
	fclose(contfile);
	for (p = Plist.head; p ; p = p->next) {
	    char *deporigin;

	    if (p->type != PLIST_PKGDEP)
		continue;
	    deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name :
							     NULL;
	    if (Verbose) {
		printf("Trying to record dependency on package '%s'", p->name);
		if (deporigin != NULL)
		    printf(" with '%s' origin", deporigin);
		printf(".\n");
	    }

	    if (deporigin) {
		/* Defer to origin lookup */
		depnames = realloc(depnames, (dep_count + 1) * sizeof(*depnames));
		depnames[dep_count] = p->name;
		deporigins = realloc(deporigins, (dep_count + 2) * sizeof(*deporigins));
		deporigins[dep_count] = deporigin;
		deporigins[dep_count + 1] = NULL;
		dep_count++;
	    } else {
	       /* No origin recorded, try to register on literal package name */
	       sprintf(contents, "%s/%s/%s", LOG_DIR, p->name,
		     REQUIRED_BY_FNAME);
	       contfile = fopen(contents, "a");
	       if (!contfile) {
		  warnx("can't open dependency file '%s'!\n"
			"dependency registration is incomplete", contents);
	       } else {
		  fprintf(contfile, "%s\n", Plist.name);
		  if (fclose(contfile) == EOF) {
		     warnx("cannot properly close file %s", contents);
		  }
	       }
	    }
	}
	if (dep_count > 0) {
	    depmatches = matchallbyorigin((const char **)deporigins, NULL);
	    free(deporigins);
	    if (!IgnoreDeps && depmatches) {
		for (i = 0; i < dep_count; i++) {
		    if (depmatches[i]) {
			int j;
			char **tmp = depmatches[i];
			for (j = 0; tmp[j] != NULL; j++) {
			    /* Origin looked up */
			    sprintf(contents, "%s/%s/%s", LOG_DIR, tmp[j],
				REQUIRED_BY_FNAME);
			    if (depnames[i] && strcmp(depnames[i], tmp[j]) != 0)
				warnx("warning: package '%s' requires '%s', but '%s' "
				    "is installed", Plist.name, depnames[i], tmp[j]);
			    contfile = fopen(contents, "a");
			    if (!contfile) {
				warnx("can't open dependency file '%s'!\n"
				    "dependency registration is incomplete", contents);
			    } else {
				fprintf(contfile, "%s\n", Plist.name);
				if (fclose(contfile) == EOF)
				    warnx("cannot properly close file %s", contents);
			    }
			}
		    } else if (depnames[i]) {
			/* No package present with this origin, try literal package name */
			sprintf(contents, "%s/%s/%s", LOG_DIR, depnames[i],
			    REQUIRED_BY_FNAME);
			contfile = fopen(contents, "a");
			if (!contfile) {
			    warnx("can't open dependency file '%s'!\n"
				"dependency registration is incomplete", contents);
			} else {
			    fprintf(contfile, "%s\n", Plist.name);
			    if (fclose(contfile) == EOF) {
				warnx("cannot properly close file %s", contents);
			    }
			}
		    }
		}
	    }
	}
	if (Verbose)
	    printf("Package %s registered in %s\n", Plist.name, LogDir);
    }

    if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) {
	FILE *fp;
	char buf[BUFSIZ];

	snprintf(buf, sizeof buf, "%s/%s", LogDir, p->name);
	fp = fopen(buf, "r");
	if (fp) {
	    putc('\n', stdout);
	    while (fgets(buf, sizeof(buf), fp))
		fputs(buf, stdout);
	    putc('\n', stdout);
	    (void) fclose(fp);
	} else {
    	    if (!Fake) {
		warnx("cannot open %s as display file", buf);  
	    }
	}
    }

    goto success;

 bomb:
    code = 1;
    goto success;

 fail:
    /* Nuke the whole (installed) show, XXX but don't clean directories */
    if (!Fake)
	delete_package(FALSE, FALSE, &Plist);

 success:
    /* delete the packing list contents */
    free_plist(&Plist);
    leave_playpen();
    return code;
}
Пример #8
0
int
pkg_perform(char **pkgs)
{
    static const char *home;
    char *pkg = *pkgs;		/* Only one arg to create */
    char *cp;
    FILE *pkg_in, *fp;
    Package plist;
    int len;
    const char *suf;

    /* Preliminary setup */
    if (InstalledPkg == NULL)
	sanity_check();
    if (Verbose && !PlistOnly)
	printf("Creating package %s\n", pkg);

    /* chop suffix off if already specified, remembering if we want to compress  */
    len = strlen(pkg);
    if (len > 4) {
	if (!strcmp(&pkg[len - 4], ".tbz")) {
	    Zipper = BZIP2;
	    pkg[len - 4] = '\0';
	}
	else if (!strcmp(&pkg[len - 4], ".tgz")) {
	    Zipper = GZIP;
	    pkg[len - 4] = '\0';
	}
	else if (!strcmp(&pkg[len - 4], ".txz")) {
	    Zipper = XZ;
	    pkg[len - 4] = '\0';
	}
	else if (!strcmp(&pkg[len - 4], ".tar")) {
	    Zipper = NONE;
	    pkg[len - 4] = '\0';
	}
    }
    if (Zipper == BZIP2) {
	suf = "tbz";
	setenv("BZIP2", "--best", 0);
    } else if (Zipper == GZIP) {
	suf = "tgz";
	setenv("GZIP", "-9", 0);
    } else if (Zipper == XZ) {
	suf = "txz";
    } else
	suf = "tar";

    if (InstalledPkg != NULL) {
	char *pkgglob[] = { InstalledPkg, NULL };
	char **matched, **pkgs;
	int i, error;

	pkgs = pkgglob;
	if (MatchType != MATCH_EXACT) {
		matched = matchinstalled(MatchType, pkgs, &error);
		if (!error && matched != NULL)
			pkgs = matched;
		else if (MatchType != MATCH_GLOB)
	    		errx(1, "no packages match pattern");
	}
	/*
	 * Is there is only one installed package matching the pattern,
	 * we need to respect the optional pkg-filename parameter.  If,
	 * however, the pattern matches several packages, this parameter
	 * makes no sense and is ignored.
	 */
	if (pkgs[1] == NULL) {
	    if (pkg == InstalledPkg)
		pkg = *pkgs;
	    InstalledPkg = *pkgs;
	    if (!Recursive)
		return (create_from_installed(InstalledPkg, pkg, suf));
	    return (create_from_installed_recursive(pkg, suf));
	}
	for (i = 0; pkgs[i] != NULL; i++) {
	    InstalledPkg = pkg = pkgs[i];
	    if (!Recursive)
		create_from_installed(pkg, pkg, suf);
	    else
	        create_from_installed_recursive(pkg, suf);
	}
	return TRUE;
    }

    get_dash_string(&Comment);
    get_dash_string(&Desc);
    if (!strcmp(Contents, "-"))
	pkg_in = stdin;
    else {
	pkg_in = fopen(Contents, "r");
	if (!pkg_in) {
	    cleanup(0);
	    errx(2, "%s: unable to open contents file '%s' for input",
		__func__, Contents);
	}
    }
    plist.head = plist.tail = NULL;

    /* Stick the dependencies, if any, at the top */
    if (Pkgdeps) {
	char **deps, *deporigin;
	int i;
	int ndeps = 0;

	if (Verbose && !PlistOnly)
	    printf("Registering depends:");

	/* Count number of dependencies */
	for (cp = Pkgdeps; cp != NULL && *cp != '\0';
			   cp = strpbrk(++cp, " \t\n")) {
	    ndeps++;
	}

	if (ndeps != 0) {
	    /* Create easy to use NULL-terminated list */
	    deps = alloca(sizeof(*deps) * ndeps + 1);
	    if (deps == NULL) {
		errx(2, "%s: alloca() failed", __func__);
		/* Not reached */
	    }
	    for (i = 0; Pkgdeps;) {
		cp = strsep(&Pkgdeps, " \t\n");
		if (*cp) {
		    deps[i] = cp;
		    i++;
		}
	    }
	    ndeps = i;
	    deps[ndeps] = NULL;

	    sortdeps(deps);
	    for (i = 0; i < ndeps; i++) {
		deporigin = strchr(deps[i], ':');
		if (deporigin != NULL) {
		    *deporigin = '\0';
		    add_plist_top(&plist, PLIST_DEPORIGIN, ++deporigin);
		}
		add_plist_top(&plist, PLIST_PKGDEP, deps[i]);
		if (Verbose && !PlistOnly)
		    printf(" %s", deps[i]);
	    }
	}

	if (Verbose && !PlistOnly)
	    printf(".\n");
    }

    /* Put the conflicts directly after the dependencies, if any */
    if (Conflicts) {
	if (Verbose && !PlistOnly)
	    printf("Registering conflicts:");
	while (Conflicts) {
	   cp = strsep(&Conflicts, " \t\n");
	   if (*cp) {
		add_plist(&plist, PLIST_CONFLICTS, cp);
		if (Verbose && !PlistOnly)
		    printf(" %s", cp);
	   }
	}
	if (Verbose && !PlistOnly)
	    printf(".\n");
    }

    /* If a SrcDir override is set, add it now */
    if (SrcDir) {
	if (Verbose && !PlistOnly)
	    printf("Using SrcDir value of %s\n", SrcDir);
	add_plist(&plist, PLIST_SRC, SrcDir);
    }

    /* Slurp in the packing list */
    read_plist(&plist, pkg_in);

    /* Prefix should add an @cwd to the packing list */
    if (Prefix) {
        char resolved_prefix[PATH_MAX];
        if (realpath(Prefix, resolved_prefix) == NULL)
	    err(EXIT_FAILURE, "couldn't resolve path for prefix: %s", Prefix);
	add_plist_top(&plist, PLIST_CWD, resolved_prefix);
    }

    /* Add the origin if asked, at the top */
    if (Origin)
	add_plist_top(&plist, PLIST_ORIGIN, Origin);

    /*
     * 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(pkg));

    if (asprintf(&cp, "PKG_FORMAT_REVISION:%d.%d", PLIST_FMT_VER_MAJOR,
		 PLIST_FMT_VER_MINOR) == -1) {
	errx(2, "%s: asprintf() failed", __func__);
    }
    add_plist_top(&plist, PLIST_COMMENT, cp);
    free(cp);

    /*
     * 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) {
	check_list(home, &plist);
	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 */
    if (!Prefix) {
	add_plist(&plist, PLIST_CWD, ".");
    }
    write_file(COMMENT_FNAME, Comment);
    add_plist(&plist, PLIST_IGNORE, NULL);
    add_plist(&plist, PLIST_FILE, COMMENT_FNAME);
    add_cksum(&plist, plist.tail, COMMENT_FNAME);
    write_file(DESC_FNAME, Desc);
    add_plist(&plist, PLIST_IGNORE, NULL);
    add_plist(&plist, PLIST_FILE, DESC_FNAME);
    add_cksum(&plist, plist.tail, DESC_FNAME);

    if (Install) {
	copy_file(home, Install, INSTALL_FNAME);
	add_plist(&plist, PLIST_IGNORE, NULL);
	add_plist(&plist, PLIST_FILE, INSTALL_FNAME);
	add_cksum(&plist, plist.tail, INSTALL_FNAME);
    }
    if (PostInstall) {
	copy_file(home, PostInstall, POST_INSTALL_FNAME);
	add_plist(&plist, PLIST_IGNORE, NULL);
	add_plist(&plist, PLIST_FILE, POST_INSTALL_FNAME);
	add_cksum(&plist, plist.tail, POST_INSTALL_FNAME);
    }
    if (DeInstall) {
	copy_file(home, DeInstall, DEINSTALL_FNAME);
	add_plist(&plist, PLIST_IGNORE, NULL);
	add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME);
	add_cksum(&plist, plist.tail, DEINSTALL_FNAME);
    }
    if (PostDeInstall) {
	copy_file(home, PostDeInstall, POST_DEINSTALL_FNAME);
	add_plist(&plist, PLIST_IGNORE, NULL);
	add_plist(&plist, PLIST_FILE, POST_DEINSTALL_FNAME);
	add_cksum(&plist, plist.tail, POST_DEINSTALL_FNAME);
    }
    if (Require) {
	copy_file(home, Require, REQUIRE_FNAME);
	add_plist(&plist, PLIST_IGNORE, NULL);
	add_plist(&plist, PLIST_FILE, REQUIRE_FNAME);
	add_cksum(&plist, plist.tail, REQUIRE_FNAME);
    }
    if (Display) {
	copy_file(home, Display, DISPLAY_FNAME);
	add_plist(&plist, PLIST_IGNORE, NULL);
	add_plist(&plist, PLIST_FILE, DISPLAY_FNAME);
	add_cksum(&plist, plist.tail, 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_cksum(&plist, plist.tail, MTREE_FNAME);
	add_plist(&plist, PLIST_MTREE, MTREE_FNAME);
    }

    /* Finally, write out the packing list */
    fp = fopen(CONTENTS_FNAME, "w");
    if (!fp) {
	cleanup(0);
	errx(2, "%s: can't open file %s for writing",
	    __func__, CONTENTS_FNAME);
    }
    write_plist(&plist, fp);
    if (fclose(fp)) {
	cleanup(0);
	errx(2, "%s: error while closing %s",
	    __func__, CONTENTS_FNAME);
    }

    /* And stick it into a tar ball */
    make_dist(home, pkg, suf, &plist);

    /* Cleanup */
    free(Comment);
    free(Desc);
    free_plist(&plist);
    leave_playpen();
    return TRUE;	/* Success */
}
Пример #9
0
int
pkg_perform(const char *pkg)
{
	char   *cp;
	FILE   *pkg_in;
	package_t plist;
	const char *full_pkg, *suffix;
	char *allocated_pkg;
	int retval;

	/* Break the package name into base and desired suffix (if any) */
	if ((cp = strrchr(pkg, '.')) != NULL) {
		if ((allocated_pkg = malloc(cp - pkg + 1)) == NULL)
			err(2, "malloc failed");
		memcpy(allocated_pkg, pkg, cp - pkg);
		allocated_pkg[cp - pkg] = '\0';
		suffix = cp + 1;
		full_pkg = pkg;
		pkg = allocated_pkg;
	} else {
		allocated_pkg = NULL;
		full_pkg = pkg;
		suffix = "tgz";
	}

	/* Preliminary setup */
	sanity_check();
	if (Verbose && !PlistOnly)
		printf("Creating package %s\n", pkg);
	get_dash_string(&Comment);
	get_dash_string(&Desc);
	if (IS_STDIN(Contents))
		pkg_in = stdin;
	else {
		pkg_in = fopen(Contents, "r");
		if (!pkg_in)
			errx(2, "unable to open contents file '%s' for input", Contents);
	}
	plist.head = plist.tail = NULL;

	/* If a SrcDir override is set, add it now */
	if (SrcDir) {
		if (Verbose && !PlistOnly)
			printf("Using SrcDir value of %s\n", (realprefix) ? realprefix : SrcDir);
		add_plist(&plist, PLIST_SRC, SrcDir);
	}

	/* Stick the dependencies, if any, at the top */
	if (Pkgdeps)
		register_depends(&plist, Pkgdeps, 0);

	/*
	 * Put the build dependencies after the dependencies.
	 * This works due to the evaluation order in pkg_add.
	 */
	if (BuildPkgdeps)
		register_depends(&plist, BuildPkgdeps, 1);

	/* Put the conflicts directly after the dependencies, if any */
	if (Pkgcfl) {
		if (Verbose && !PlistOnly)
			printf("Registering conflicts:");
		while (Pkgcfl) {
			cp = strsep(&Pkgcfl, " \t\n");
			if (*cp) {
				add_plist(&plist, PLIST_PKGCFL, cp);
				if (Verbose && !PlistOnly)
					printf(" %s", cp);
			}
		}
		if (Verbose && !PlistOnly)
			printf(".\n");
	}

	/* Slurp in the packing list */
	read_plist(&plist, pkg_in);

	if (pkg_in != stdin)
		fclose(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));
	}

	/* Make first "real contents" pass over it */
	check_list(&plist, 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, realprefix);
		retval = TRUE;
	} else {
#ifdef BOOTSTRAP
		warnx("Package building is not supported in bootstrap mode");
		retval = FALSE;
#else
		retval = pkg_build(pkg, full_pkg, suffix, &plist);
#endif
	}

	/* Cleanup */
	free(Comment);
	free(Desc);
	free_plist(&plist);

	free(allocated_pkg);

	return retval;
}