[BACK]Return to perform.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / pkgsrc / pkgtools / pkg_install / files / add

Annotation of pkgsrc/pkgtools/pkg_install/files/add/perform.c, Revision 1.15

1.15    ! jlam        1: /*     $NetBSD: perform.c,v 1.94 2004/01/14 23:32:36 jlam Exp $        */
1.1       schmonz     2:
1.8       jlam        3: #if HAVE_CONFIG_H
                      4: #include "config.h"
                      5: #endif
1.9       jlam        6: #include <nbcompat.h>
1.8       jlam        7: #if HAVE_SYS_CDEFS_H
1.1       schmonz     8: #include <sys/cdefs.h>
1.8       jlam        9: #endif
1.1       schmonz    10: #ifndef lint
                     11: #if 0
                     12: static const char *rcsid = "from FreeBSD Id: perform.c,v 1.44 1997/10/13 15:03:46 jkh Exp";
                     13: #else
1.15    ! jlam       14: __RCSID("$NetBSD: perform.c,v 1.94 2004/01/14 23:32:36 jlam Exp $");
1.1       schmonz    15: #endif
                     16: #endif
                     17:
                     18: /*
                     19:  * FreeBSD install - a package for the installation and maintainance
                     20:  * of non-core utilities.
                     21:  *
                     22:  * Redistribution and use in source and binary forms, with or without
                     23:  * modification, are permitted provided that the following conditions
                     24:  * are met:
                     25:  * 1. Redistributions of source code must retain the above copyright
                     26:  *    notice, this list of conditions and the following disclaimer.
                     27:  * 2. Redistributions in binary form must reproduce the above copyright
                     28:  *    notice, this list of conditions and the following disclaimer in the
                     29:  *    documentation and/or other materials provided with the distribution.
                     30:  *
                     31:  * Jordan K. Hubbard
                     32:  * 18 July 1993
                     33:  *
                     34:  * This is the main body of the add module.
                     35:  *
                     36:  */
                     37:
1.8       jlam       38: #if HAVE_ASSERT_H
1.1       schmonz    39: #include <assert.h>
                     40: #endif
1.8       jlam       41: #if HAVE_ERR_H
1.1       schmonz    42: #include <err.h>
                     43: #endif
                     44: #include "lib.h"
                     45: #include "add.h"
                     46: #include "verify.h"
                     47:
1.8       jlam       48: #if HAVE_SIGNAL_H
1.1       schmonz    49: #include <signal.h>
1.8       jlam       50: #endif
                     51: #if HAVE_STRING_H
1.1       schmonz    52: #include <string.h>
                     53: #endif
1.13      grant      54: #if HAVE_SYS_UTSNAME_H
                     55: #include <sys/utsname.h>
                     56: #endif
                     57:
                     58: static int read_buildinfo(char **);
1.1       schmonz    59:
                     60: static char LogDir[FILENAME_MAX];
                     61: static int zapLogDir;          /* Should we delete LogDir? */
                     62:
                     63: static package_t Plist;
                     64: static char *Home;
                     65:
                     66: static int
                     67: sanity_check(const char *pkg)
                     68: {
                     69:        int     errc = 0;
                     70:
                     71:        if (!fexists(CONTENTS_FNAME)) {
                     72:                warnx("package %s has no CONTENTS file!", pkg);
                     73:                errc = 1;
                     74:        } else if (!fexists(COMMENT_FNAME)) {
                     75:                warnx("package %s has no COMMENT file!", pkg);
                     76:                errc = 1;
                     77:        } else if (!fexists(DESC_FNAME)) {
                     78:                warnx("package %s has no DESC file!", pkg);
                     79:                errc = 1;
                     80:        }
                     81:        return errc;
                     82: }
                     83:
                     84: /* install a pre-requisite package. Returns 1 if it installed it */
                     85: static int
                     86: installprereq(const char *name, int *errc)
                     87: {
1.12      grant      88:        int ret;
1.1       schmonz    89:        ret = 0;
                     90:
                     91:        if (Verbose)
                     92:                printf("Loading it from %s.\n", name);
                     93:        path_setenv("PKG_PATH");
1.12      grant      94:
                     95:        if (fexec_skipempty(BINDIR "/pkg_add", "-K", _pkgdb_getPKGDB_DIR(),
                     96:                            "-s", get_verification(),
                     97:                            NoView ? "-L" : "",
                     98:                            View ? "-w" : "", View ? View : "",
                     99:                            Viewbase ? "-W" : "", Viewbase ? Viewbase : "",
                    100:                            Force ? "-f" : "",
                    101:                            Prefix ? "-p" : "", Prefix ? Prefix : "",
                    102:                            Verbose ? "-v" : "", name, NULL)) {
1.1       schmonz   103:                warnx("autoload of dependency `%s' failed%s",
                    104:                        name, Force ? " (proceeding anyway)" : "!");
                    105:                if (!Force)
                    106:                        ++(*errc);
                    107:        } else {
                    108:                ret = 1;
                    109:        }
                    110:
                    111:        return ret;
                    112: }
                    113:
                    114: /*
                    115:  * Install a single package
                    116:  * Returns 0 if everything is ok, >0 else
                    117:  */
                    118: static int
                    119: pkg_do(const char *pkg)
                    120: {
                    121:        char    playpen[FILENAME_MAX];
1.8       jlam      122:        char    replace_from[FILENAME_MAX];
                    123:        char    replace_via[FILENAME_MAX];
                    124:        char    replace_to[FILENAME_MAX];
1.13      grant     125:        char   *buildinfo[BI_ENUM_COUNT];
1.8       jlam      126:        int     replacing = 0;
1.12      grant     127:        char   *where_to;
1.10      jlam      128:        char   dbdir[FILENAME_MAX];
1.13      grant     129:        const char *exact, *extra1;
1.1       schmonz   130:        FILE   *cfile;
1.14      hubertf   131:        int     errc, err_prescan;
1.1       schmonz   132:        plist_t *p;
                    133:        struct stat sb;
1.13      grant     134:        struct utsname host_uname;
1.1       schmonz   135:        int     inPlace;
                    136:        int     rc;
1.8       jlam      137:        Boolean is_depoted_pkg = FALSE;
1.1       schmonz   138:
                    139:        errc = 0;
                    140:        zapLogDir = 0;
                    141:        LogDir[0] = '\0';
1.8       jlam      142:        strlcpy(playpen, FirstPen, sizeof(playpen));
1.1       schmonz   143:        inPlace = 0;
                    144:
                    145:        /* Are we coming in for a second pass, everything already extracted?
                    146:         * (Slave mode) */
                    147:        if (!pkg) {
                    148:                fgets(playpen, FILENAME_MAX, stdin);
                    149:                playpen[strlen(playpen) - 1] = '\0';    /* remove newline! */
                    150:                if (chdir(playpen) == FAIL) {
                    151:                        warnx("add in SLAVE mode can't chdir to %s", playpen);
                    152:                        return 1;
                    153:                }
                    154:                read_plist(&Plist, stdin);
                    155:                where_to = playpen;
                    156:        }
                    157:        /* Nope - do it now */
                    158:        else {
                    159:                const char *tmppkg;
                    160:
                    161:                tmppkg = fileFindByPath(pkg);
                    162:                if (tmppkg == NULL) {
                    163:                        warnx("no pkg found for '%s', sorry.", pkg);
                    164:                        return 1;
                    165:                }
                    166:
                    167:                pkg = tmppkg;
                    168:
                    169:                if (IS_URL(pkg)) {
                    170:                        Home = fileGetURL(pkg);
                    171:                        if (Home == NULL) {
                    172:                                warnx("unable to fetch `%s' by URL", pkg);
                    173:                        }
                    174:                        where_to = Home;
                    175:
                    176:                        /* make sure the pkg is verified */
                    177:                        if (!verify(pkg)) {
                    178:                                warnx("Package %s will not be extracted", pkg);
                    179:                                goto bomb;
                    180:                        }
1.8       jlam      181:                } else { /* local */
1.1       schmonz   182:                        if (!IS_STDIN(pkg)) {
                    183:                                /* not stdin */
                    184:                                if (!ispkgpattern(pkg)) {
                    185:                                        if (stat(pkg, &sb) == FAIL) {
                    186:                                                warnx("can't stat package file '%s'", pkg);
                    187:                                                goto bomb;
                    188:                                        }
                    189:                                        /* make sure the pkg is verified */
                    190:                                        if (!verify(pkg)) {
                    191:                                                warnx("Package %s will not be extracted", pkg);
                    192:                                                goto bomb;
                    193:                                        }
                    194:                                }
1.13      grant     195:                                extra1 = CONTENTS_FNAME;
1.1       schmonz   196:                        } else {
                    197:                                /* some values for stdin */
1.13      grant     198:                                extra1 = NULL;
1.1       schmonz   199:                                sb.st_size = 100000;    /* Make up a plausible average size */
                    200:                        }
                    201:                        Home = make_playpen(playpen, sizeof(playpen), sb.st_size * 4);
                    202:                        if (!Home)
                    203:                                warnx("unable to make playpen for %ld bytes",
                    204:                                      (long) (sb.st_size * 4));
                    205:                        where_to = Home;
1.13      grant     206:                        if (unpack(pkg, extra1)) {
1.1       schmonz   207:                                warnx("unable to extract table of contents file from `%s' - not a package?",
                    208:                                      pkg);
                    209:                                goto bomb;
                    210:                        }
                    211:                }
                    212:
                    213:                cfile = fopen(CONTENTS_FNAME, "r");
                    214:                if (!cfile) {
                    215:                        warnx("unable to open table of contents file `%s' - not a package?",
                    216:                              CONTENTS_FNAME);
                    217:                        goto bomb;
                    218:                }
                    219:                read_plist(&Plist, cfile);
                    220:                fclose(cfile);
                    221:
                    222:                if (!IS_URL(pkg)) {
                    223:                        /* Extract directly rather than moving?  Oh goodie! */
                    224:                        if (find_plist_option(&Plist, "extract-in-place")) {
                    225:                                if (Verbose)
                    226:                                        printf("Doing in-place extraction for %s\n", pkg);
                    227:                                p = find_plist(&Plist, PLIST_CWD);
                    228:                                if (p) {
                    229:                                        if (!(isdir(p->name) || islinktodir(p->name)) && !Fake) {
                    230:                                                if (Verbose)
                    231:                                                        printf("Desired prefix of %s does not exist, creating.\n", p->name);
1.8       jlam      232:                                                (void) fexec("mkdir", "-p", p->name, NULL);
1.1       schmonz   233:                                        }
                    234:                                        if (chdir(p->name) == -1) {
                    235:                                                warn("unable to change directory to `%s'", p->name);
                    236:                                                goto bomb;
                    237:                                        }
                    238:                                        where_to = p->name;
                    239:                                        inPlace = 1;
                    240:                                } else {
                    241:                                        warnx(
                    242:                                            "no prefix specified in `%s' - this is a bad package!",
                    243:                                            pkg);
                    244:                                        goto bomb;
                    245:                                }
                    246:                        }
                    247:
                    248:                        /*
                    249:                         * Apply a crude heuristic to see how much space the package will
                    250:                         * take up once it's unpacked.  I've noticed that most packages
                    251:                         * compress an average of 75%, so multiply by 4 for good measure.
                    252:                         */
                    253:
1.6       grant     254:                        if (!inPlace && min_free(playpen) < sb.st_size * 4) {
1.5       grant     255:                                warnx("projected size of %ld bytes exceeds available free space\n"
                    256:                                    "in %s. Please set your PKG_TMPDIR variable to point\n"
                    257:                                    "to a location with more free space and try again.",
                    258:                                        (long) (sb.st_size * 4), playpen);
1.1       schmonz   259:                                goto bomb;
                    260:                        }
                    261:
                    262:                        /* If this is a direct extract and we didn't want it, stop now */
                    263:                        if (inPlace && Fake)
                    264:                                goto success;
                    265:
                    266:                        /* Finally unpack the whole mess */
1.13      grant     267:                        if (unpack(pkg, NULL)) {
1.1       schmonz   268:                                warnx("unable to extract `%s'!", pkg);
                    269:                                goto bomb;
                    270:                        }
                    271:                }
                    272:
                    273:                /* Check for sanity */
                    274:                if (sanity_check(pkg))
                    275:                        goto bomb;
                    276:
                    277:                /* If we're running in MASTER mode, just output the plist and return */
                    278:                if (AddMode == MASTER) {
                    279:                        printf("%s\n", where_playpen());
                    280:                        write_plist(&Plist, stdout, NULL);
                    281:                        return 0;
                    282:                }
                    283:        }
                    284:
1.13      grant     285:        /* Check OS, version and architecture */
                    286:        if (read_buildinfo(buildinfo) != 0 && !Force) {
                    287:                warnx("aborting.");
                    288:                goto bomb;
                    289:        }
                    290:
1.15    ! jlam      291:        if (uname(&host_uname) < 0) {
        !           292:                warnx("uname() failed.");
        !           293:                if (!Force) {
        !           294:                        warnx("aborting.");
        !           295:                        goto bomb;
        !           296:                }
        !           297:        } else {
1.13      grant     298:                int     osbad = 0;
                    299:
                    300:                /* If either the OS or arch are different, bomb */
1.15    ! jlam      301:                if (strcmp(OPSYS_NAME, buildinfo[BI_OPSYS]) != 0 ||
        !           302:                strcmp(MACHINE_ARCH, buildinfo[BI_MACHINE_ARCH]) != 0)
1.13      grant     303:                        osbad = 2;
                    304:
                    305:                /* If OS and arch are the same, warn if version differs */
1.15    ! jlam      306:                if (strcmp(OPSYS_NAME, buildinfo[BI_OPSYS]) == 0 &&
        !           307:                    strcmp(MACHINE_ARCH, buildinfo[BI_MACHINE_ARCH]) == 0) {
1.13      grant     308:                        if (strcmp(host_uname.release, buildinfo[BI_OS_VERSION]) != 0)
                    309:                                osbad = 1;
                    310:                } else
                    311:                        osbad = 2;
                    312:
                    313:                if (osbad) {
                    314:                        warnx("Package `%s' OS mismatch:", pkg);
                    315:                        warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)",
                    316:                            buildinfo[BI_OPSYS],
                    317:                            buildinfo[BI_MACHINE_ARCH],
                    318:                            buildinfo[BI_OS_VERSION],
1.15    ! jlam      319:                            OPSYS_NAME,
        !           320:                            MACHINE_ARCH,
1.13      grant     321:                            host_uname.release);
                    322:                }
                    323:                if (!Force && (osbad >= 2)) {
                    324:                            warnx("aborting.");
                    325:                            goto bomb;
                    326:                }
                    327:        }
                    328:
1.1       schmonz   329:        /*
                    330:          * If we have a prefix, delete the first one we see and add this
                    331:          * one in place of it.
                    332:          */
                    333:        if (Prefix) {
                    334:                delete_plist(&Plist, FALSE, PLIST_CWD, NULL);
                    335:                add_plist_top(&Plist, PLIST_CWD, Prefix);
                    336:        }
                    337:
                    338:        setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1);
                    339:        /* Protect against old packages with bogus @name fields */
                    340:        PkgName = (p = find_plist(&Plist, PLIST_NAME)) ? p->name : "anonymous";
                    341:
1.8       jlam      342:        if (fexists(VIEWS_FNAME))
                    343:                is_depoted_pkg = TRUE;
                    344:
1.10      jlam      345:        /*
                    346:         * Depoted packages' dbdir is the same as DEPOTBASE.  Non-depoted
                    347:         * packages' dbdir comes from the command-line or the environment.
                    348:         */
1.8       jlam      349:        if (is_depoted_pkg) {
1.10      jlam      350:                p = find_plist(&Plist, PLIST_CWD);
                    351:                (void) strlcpy(dbdir, dirname_of(p->name), sizeof(dbdir));
                    352:                (void) strlcpy(LogDir, p->name, sizeof(LogDir));
                    353:        } else {
                    354:                (void) strlcpy(dbdir, _pkgdb_getPKGDB_DIR(), sizeof(dbdir));
                    355:                (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", dbdir, PkgName);
1.8       jlam      356:        }
                    357:
                    358:        /* make sure dbdir actually exists! */
                    359:        if (!(isdir(dbdir) || islinktodir(dbdir))) {
                    360:                if (fexec("mkdir", "-m", "755", "-p", dbdir, NULL)) {
                    361:                        errx(EXIT_FAILURE,
                    362:                            "Database-dir %s cannot be generated, aborting.",
                    363:                            dbdir);
                    364:                }
                    365:        }
                    366:
1.1       schmonz   367:        /* See if this package (exact version) is already registered */
                    368:        if ((isdir(LogDir) || islinktodir(LogDir)) && !Force) {
                    369:                warnx("package `%s' already recorded as installed", PkgName);
                    370:                goto success;   /* close enough for government work */
                    371:        }
                    372:
                    373:        /* See if some other version of us is already installed */
                    374:        {
                    375:                char   *s;
                    376:
                    377:                if ((s = strrchr(PkgName, '-')) != NULL) {
                    378:                        char    buf[FILENAME_MAX];
                    379:                        char    installed[FILENAME_MAX];
                    380:
                    381:                        /*
                    382:                         * See if the pkg is already installed. If so, we might
1.8       jlam      383:                         * want to upgrade/replace it.
1.1       schmonz   384:                         */
                    385:                        (void) snprintf(buf, sizeof(buf), "%.*s[0-9]*",
                    386:                                (int)(s - PkgName) + 1, PkgName);
                    387:                        if (findmatchingname(dbdir, buf, note_whats_installed, installed) > 0) {
1.8       jlam      388:                                if (Replace) {
                    389:                                        snprintf(replace_from, sizeof(replace_from), "%s/%s/" REQUIRED_BY_FNAME,
1.1       schmonz   390:                                                 dbdir, installed);
1.8       jlam      391:                                        snprintf(replace_via, sizeof(replace_via), "%s/.%s." REQUIRED_BY_FNAME,
1.1       schmonz   392:                                                 dbdir, installed);
1.8       jlam      393:                                        snprintf(replace_to, sizeof(replace_to), "%s/%s/" REQUIRED_BY_FNAME,
1.1       schmonz   394:                                                 dbdir, PkgName);
                    395:
                    396:                                        if (Verbose)
                    397:                                                printf("Upgrading %s to %s.\n", installed, PkgName);
                    398:
1.8       jlam      399:                                        if (fexists(replace_from)) {  /* Are there any dependencies? */
1.4       jschauma  400:                                                /*
                    401:                                                 * Upgrade step 1/4: Check if the new version is ok with all pkgs
                    402:                                                 * (from +REQUIRED_BY) that require this pkg
                    403:                                                 */
                    404:                                                FILE *rb;                     /* +REQUIRED_BY file */
                    405:                                                char pkg2chk[FILENAME_MAX];
                    406:
1.8       jlam      407:                                                rb = fopen(replace_from, "r");
1.4       jschauma  408:                                                if (! rb) {
1.8       jlam      409:                                                        warnx("Cannot open '%s' for reading%s", replace_from,
1.4       jschauma  410:                                                              Force ? " (proceeding anyways)" : "");
                    411:                                                        if (Force)
1.8       jlam      412:                                                                goto ignore_replace_depends_check;
1.4       jschauma  413:                                                        else
                    414:                                                                goto bomb;
                    415:                                                }
                    416:                                                while (fgets(pkg2chk, sizeof(pkg2chk), rb)) {
                    417:                                                        package_t depPlist;
                    418:                                                        FILE *depf;
                    419:                                                        plist_t *depp;
                    420:                                                        char depC[FILENAME_MAX];
                    421:
                    422:                                                        s = strrchr(pkg2chk, '\n');
                    423:                                                        if (s)
                    424:                                                                *s = '\0'; /* strip trailing '\n' */
                    425:
                    426:                                                        /*
                    427:                                                         * step into pkg2chk, read it's +CONTENTS file and see if
                    428:                                                         * all @pkgdep lines agree with PkgName (using pmatch())
                    429:                                                         */
                    430:                                                        snprintf(depC, sizeof(depC), "%s/%s/%s", dbdir, pkg2chk, CONTENTS_FNAME);
                    431:                                                        depf = fopen(depC , "r");
                    432:                                                        if (depf == NULL) {
                    433:                                                                warnx("Cannot check depends in '%s'%s", depC,
                    434:                                                                      Force ? " (proceeding anyways)" : "!" );
                    435:                                                                if (Force)
1.8       jlam      436:                                                                        goto ignore_replace_depends_check;
1.4       jschauma  437:                                                                else
                    438:                                                                        goto bomb;
                    439:                                                        }
                    440:                                                        read_plist(&depPlist, depf);
                    441:                                                        fclose(depf);
                    442:
                    443:                                                        for (depp = depPlist.head; depp; depp = depp->next) {
                    444:                                                                char base_new[FILENAME_MAX];
                    445:                                                                char base_exist[FILENAME_MAX];
                    446:                                                                char *s2;
                    447:
                    448:                                                                if (depp->type != PLIST_PKGDEP)
                    449:                                                                        continue;
                    450:
                    451:                                                                /*  Prepare basename (no versions) of both pkgs,
                    452:                                                                 *  to see if we want to compare against that
                    453:                                                                 *  one at all.
                    454:                                                                 */
1.8       jlam      455:                                                                strlcpy(base_new, PkgName, sizeof(base_new));
1.4       jschauma  456:                                                                s2 = strpbrk(base_new, "<>[]?*{");
                    457:                                                                if (s2)
                    458:                                                                        *s2 = '\0';
                    459:                                                                else {
                    460:                                                                        s2 = strrchr(base_new, '-');
                    461:                                                                        if (s2)
                    462:                                                                                *s2 = '\0';
                    463:                                                                }
1.8       jlam      464:                                                                strlcpy(base_exist, depp->name, sizeof(base_exist));
1.4       jschauma  465:                                                                s2 = strpbrk(base_exist, "<>[]?*{");
                    466:                                                                if (s2)
                    467:                                                                        *s2 = '\0';
                    468:                                                                else {
                    469:                                                                        s2 = strrchr(base_exist, '-');
                    470:                                                                        if (s2)
                    471:                                                                                *s2 = '\0';
                    472:                                                                }
                    473:                                                                if (strcmp(base_new, base_exist) == 0) {
                    474:                                                                        /* Same pkg, so do the interesting compare */
                    475:                                                                        if (pmatch(depp->name, PkgName)) {
                    476:                                                                                if (Verbose)
                    477:                                                                                        printf("@pkgdep check: %s is ok for %s (in %s pkg)\n",
                    478:                                                                                               PkgName, depp->name, pkg2chk);
                    479:                                                                        } else {
1.8       jlam      480:                                                                                printf("Package %s requires %s, \n\tCannot replace with %s%s\n",
1.4       jschauma  481:                                                                                       pkg2chk, depp->name, PkgName,
                    482:                                                                                       Force? " (proceeding anyways)" : "!");
                    483:                                                                                if (! Force)
                    484:                                                                                        goto bomb;
                    485:                                                                        }
                    486:                                                                }
                    487:                                                        }
                    488:                                                }
                    489:                                                fclose(rb);
                    490:
1.8       jlam      491: ignore_replace_depends_check:
1.4       jschauma  492:                                                /*
                    493:                                                 * Upgrade step 2/4: Do the actual update by moving aside
                    494:                                                 * the +REQUIRED_BY file, deinstalling the old pkg, adding
                    495:                                                 * the new one and moving the +REQUIRED_BY file back
                    496:                                                 * into place (finished in step 3/4)
                    497:                                                 */
1.1       schmonz   498:                                                if (Verbose)
1.8       jlam      499:                                                        printf("mv %s %s\n", replace_from, replace_via);
                    500:                                                rc = rename(replace_from, replace_via);
1.1       schmonz   501:                                                assert(rc == 0);
                    502:
1.8       jlam      503:                                                replacing = 1;
                    504:                                        }
                    505:
                    506:                                        if (Verbose) {
                    507:                                                printf("%s/pkg_delete -K %s '%s'\n",
                    508:                                                        BINDIR,
                    509:                                                        dbdir,
                    510:                                                        installed);
1.1       schmonz   511:                                        }
1.12      grant     512:                                        fexec(BINDIR "/pkg_delete", "-K", dbdir, installed, NULL);
1.15    ! jlam      513:                                } else if (!is_depoted_pkg) {
1.1       schmonz   514:                                        warnx("other version '%s' already installed", installed);
                    515:
                    516:                                        errc = 1;
                    517:                                        goto success;   /* close enough for government work */
                    518:                                }
                    519:                        }
                    520:                }
                    521:        }
                    522:
                    523:        /* See if there are conflicting packages installed */
                    524:        for (p = Plist.head; p; p = p->next) {
                    525:                char    installed[FILENAME_MAX];
                    526:
                    527:                if (p->type != PLIST_PKGCFL)
                    528:                        continue;
                    529:                if (Verbose)
                    530:                        printf("Package `%s' conflicts with `%s'.\n", PkgName, p->name);
                    531:                if (findmatchingname(dbdir, p->name, note_whats_installed, installed) > 0) {
                    532:                        warnx("Conflicting package `%s'installed, please use\n"
                    533:                              "\t\"pkg_delete %s\" first to remove it!", installed, installed);
                    534:                        ++errc;
                    535:                }
                    536:        }
                    537:
                    538:        /* Quick pre-check if any conflicting dependencies are installed
                    539:         * (e.g. version X is installed, but version Y is required)
                    540:         */
1.14      hubertf   541:        err_prescan=0;
1.1       schmonz   542:        for (p = Plist.head; p; p = p->next) {
                    543:                char installed[FILENAME_MAX];
                    544:
                    545:                if (p->type != PLIST_PKGDEP)
                    546:                        continue;
                    547:                if (Verbose)
                    548:                        printf("Depends pre-scan: `%s' required.\n", p->name);
                    549:                if (findmatchingname(dbdir, p->name, note_whats_installed, installed) <= 0) {
                    550:                        /*
                    551:                         * required pkg not found. look if it's available with a more liberal
                    552:                         * pattern. If so, this will lead to problems later (check on "some
                    553:                         * other version of us is already installed" will fail, see above),
                    554:                         * and we better stop right now.
                    555:                         */
                    556:                        char *s;
                    557:                        int skip = -1;
                    558:
                    559:                        /* doing this right required to parse the full version(s),
                    560:                         * do a 99% solution here for now */
                    561:                        if (strchr(p->name, '{'))
                    562:                                continue;       /* would remove trailing '}' else */
                    563:
                    564:                        if ((s = strpbrk(p->name, "<>")) != NULL) {
                    565:                                skip = 0;
1.7       seb       566:                        } else if (((s = strstr(p->name, "-[0-9]*")) != NULL) &&
                    567:                                    (*(s + sizeof("-[0-9]*") - 1) == '\0')) {
                    568:                                /* -[0-9]* already present so no need to */
                    569:                                /* add it a second time */
                    570:                                skip = -1;
1.1       schmonz   571:                        } else if ((s = strrchr(p->name, '-')) != NULL) {
                    572:                                skip = 1;
                    573:                        }
                    574:
                    575:                        if (skip >= 0) {
                    576:                                char    buf[FILENAME_MAX];
                    577:
                    578:                                (void) snprintf(buf, sizeof(buf),
                    579:                                    skip ? "%.*s[0-9]*" : "%.*s-[0-9]*",
                    580:                                    (int)(s - p->name) + skip, p->name);
                    581:                                if (findmatchingname(dbdir, buf, note_whats_installed, installed) > 0) {
                    582:                                        warnx("pkg `%s' required, but `%s' found installed.",
                    583:                                              p->name, installed);
                    584:
1.8       jlam      585:                                        if (replacing) {
                    586:                                                printf("HF: replace note -- could 'pkg_delete %s', and let the normal\n"
                    587:                                                       "dependency handling reinstall the replaced package, assuming one IS\n"
1.1       schmonz   588:                                                       "available. But then I'd expect proper binary pkgs being available for\n"
1.8       jlam      589:                                                       "the replace case.\n", installed);
1.1       schmonz   590:                                        }
                    591:
                    592:                                        if (Force) {
1.8       jlam      593:                                                warnx("Proceeding anyway.");
1.14      hubertf   594:                                        } else {
                    595:                                                err_prescan++;
1.1       schmonz   596:                                        }
                    597:                                }
                    598:                        }
                    599:                }
                    600:        }
1.14      hubertf   601:        if (err_prescan > 0) {
                    602:                warnx("Please resolve this conflict!");
                    603:                errc += err_prescan;
                    604:                goto success; /* close enough */
                    605:        }
1.1       schmonz   606:
                    607:
                    608:        /* Now check the packing list for dependencies */
                    609:        for (exact = NULL, p = Plist.head; p; p = p->next) {
                    610:                char    installed[FILENAME_MAX];
                    611:
                    612:                if (p->type == PLIST_BLDDEP) {
                    613:                        exact = p->name;
                    614:                        continue;
                    615:                }
                    616:                if (p->type != PLIST_PKGDEP) {
                    617:                        exact = NULL;
                    618:                        continue;
                    619:                }
                    620:                if (Verbose)
                    621:                        printf("Package `%s' depends on `%s'.\n", PkgName, p->name);
1.8       jlam      622:
1.1       schmonz   623:                if (findmatchingname(dbdir, p->name, note_whats_installed, installed) != 1) {
                    624:                        /* required pkg not found - need to pull in */
1.8       jlam      625:
1.1       schmonz   626:                        if (Fake) {
1.8       jlam      627:                                /* fake install (???) */
1.1       schmonz   628:                                if (Verbose)
                    629:                                        printf("Package dependency %s for %s not installed%s\n", p->name, pkg,
                    630:                                            Force ? " (proceeding anyway)" : "!");
                    631:                        } else {
                    632:                                int done = 0;
                    633:                                int errc0 = 0;
                    634:
                    635:                                if (exact != NULL) {
                    636:                                        /* first try the exact name, from the @blddep */
                    637:                                        done = installprereq(exact, &errc0);
                    638:                                }
                    639:                                if (!done) {
                    640:                                        done = installprereq(p->name, &errc0);
                    641:                                }
                    642:                                if (!done && !Force) {
                    643:                                        errc += errc0;
                    644:                                }
                    645:                        }
1.8       jlam      646:                } else if (Verbose) {
1.1       schmonz   647:                        printf(" - %s already installed.\n", installed);
                    648:                }
                    649:        }
                    650:
                    651:        if (errc != 0)
                    652:                goto bomb;
                    653:
                    654:        /* Look for the requirements file */
                    655:        if (fexists(REQUIRE_FNAME)) {
1.8       jlam      656:                (void) fexec(CHMOD_CMD, "+x", REQUIRE_FNAME, NULL);     /* be sure */
1.1       schmonz   657:                if (Verbose)
                    658:                        printf("Running requirements file first for %s.\n", PkgName);
1.12      grant     659:                if (!Fake && fexec("./" REQUIRE_FNAME, PkgName, "INSTALL", NULL)) {
1.1       schmonz   660:                        warnx("package %s fails requirements %s", pkg,
                    661:                            Force ? "installing anyway" : "- not installed");
                    662:                        if (!Force) {
                    663:                                errc = 1;
                    664:                                goto success;   /* close enough for government work */
                    665:                        }
                    666:                }
                    667:        }
                    668:
                    669:        /* If we're really installing, and have an installation file, run it */
                    670:        if (!NoInstall && fexists(INSTALL_FNAME)) {
1.8       jlam      671:                (void) fexec(CHMOD_CMD, "+x", INSTALL_FNAME, NULL);     /* make sure */
1.1       schmonz   672:                if (Verbose)
                    673:                        printf("Running install with PRE-INSTALL for %s.\n", PkgName);
1.12      grant     674:                if (!Fake && fexec("./" INSTALL_FNAME, PkgName, "PRE-INSTALL", NULL)) {
1.1       schmonz   675:                        warnx("install script returned error status");
                    676:                        errc = 1;
                    677:                        goto success;   /* nothing to uninstall yet */
                    678:                }
                    679:        }
                    680:
1.10      jlam      681:        /*
                    682:         * Now finally extract the entire show if we're not going direct.
                    683:         * We need to reset the package dbdir so that extract_plist()
                    684:         * updates the correct pkgdb.byfile.db database.
                    685:         */
                    686:        if (!inPlace && !Fake) {
                    687:                _pkgdb_setPKGDB_DIR(dbdir);
                    688:                if (!extract_plist(".", &Plist)) {
                    689:                        errc = 1;
                    690:                        goto fail;
                    691:                }
                    692:        }
1.1       schmonz   693:
                    694:        if (!Fake && fexists(MTREE_FNAME)) {
                    695:                if (Verbose)
                    696:                        printf("Running mtree for %s.\n", PkgName);
                    697:                p = find_plist(&Plist, PLIST_CWD);
                    698:                if (Verbose)
1.8       jlam      699:                        printf("mtree -U -f %s -d -e -p %s\n", MTREE_FNAME, p ? p->name : "/");
1.1       schmonz   700:                if (!Fake) {
1.12      grant     701:                        if (fexec(MTREE_CMD, "-U", "-f", MTREE_FNAME, "-d", "-e", "-p",
                    702:                                  p ? p->name : "/", NULL))
1.1       schmonz   703:                                warnx("mtree returned a non-zero status - continuing");
                    704:                }
                    705:                unlink(MTREE_FNAME); /* remove this line to tar up pkg later  - HF */
                    706:        }
                    707:
                    708:        /* Run the installation script one last time? */
                    709:        if (!NoInstall && fexists(INSTALL_FNAME)) {
                    710:                if (Verbose)
                    711:                        printf("Running install with POST-INSTALL for %s.\n", PkgName);
1.12      grant     712:                if (!Fake && fexec("./" INSTALL_FNAME, PkgName, "POST-INSTALL", NULL)) {
1.1       schmonz   713:                        warnx("install script returned error status");
                    714:                        errc = 1;
                    715:                        goto fail;
                    716:                }
                    717:        }
                    718:
                    719:        /* Time to record the deed? */
                    720:        if (!NoRecord && !Fake) {
                    721:                char    contents[FILENAME_MAX];
                    722:
                    723:                umask(022);
                    724:                if (getuid() != 0)
                    725:                        warnx("not running as root - trying to record install anyway");
                    726:                if (!PkgName) {
                    727:                        warnx("no package name! can't record package, sorry");
                    728:                        errc = 1;
                    729:                        goto success;   /* well, partial anyway */
                    730:                }
                    731:                (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", dbdir, PkgName);
                    732:                zapLogDir = 1; /* LogDir contains something valid now */
                    733:                if (Verbose)
                    734:                        printf("Attempting to record package into %s.\n", LogDir);
                    735:                if (make_hierarchy(LogDir)) {
                    736:                        warnx("can't record package into '%s', you're on your own!",
                    737:                            LogDir);
                    738:                        memset(LogDir, 0, sizeof(LogDir));
                    739:                        errc = 1;
                    740:                        goto success;   /* close enough for government work */
                    741:                }
                    742:                /* Make sure pkg_info can read the entry */
1.8       jlam      743:                (void) fexec(CHMOD_CMD, "a+rx", LogDir, NULL);
                    744:                if (fexists(INSTALL_FNAME))
                    745:                        move_file(".", INSTALL_FNAME, LogDir);
1.1       schmonz   746:                if (fexists(DEINSTALL_FNAME))
                    747:                        move_file(".", DEINSTALL_FNAME, LogDir);
                    748:                if (fexists(REQUIRE_FNAME))
                    749:                        move_file(".", REQUIRE_FNAME, LogDir);
                    750:                if (fexists(SIZE_PKG_FNAME))
                    751:                        move_file(".", SIZE_PKG_FNAME, LogDir);
                    752:                if (fexists(SIZE_ALL_FNAME))
                    753:                        move_file(".", SIZE_ALL_FNAME, LogDir);
                    754:                (void) snprintf(contents, sizeof(contents), "%s/%s", LogDir, CONTENTS_FNAME);
                    755:                cfile = fopen(contents, "w");
                    756:                if (!cfile) {
                    757:                        warnx("can't open new contents file '%s'! can't register pkg",
                    758:                            contents);
                    759:                        goto success;   /* can't log, but still keep pkg */
                    760:                }
                    761:                write_plist(&Plist, cfile, NULL);
                    762:                fclose(cfile);
                    763:                move_file(".", DESC_FNAME, LogDir);
                    764:                move_file(".", COMMENT_FNAME, LogDir);
                    765:                if (fexists(BUILD_VERSION_FNAME))
                    766:                        move_file(".", BUILD_VERSION_FNAME, LogDir);
                    767:                if (fexists(BUILD_INFO_FNAME))
                    768:                        move_file(".", BUILD_INFO_FNAME, LogDir);
                    769:                if (fexists(DISPLAY_FNAME))
                    770:                        move_file(".", DISPLAY_FNAME, LogDir);
1.3       jschauma  771:                if (fexists(PRESERVE_FNAME))
                    772:                        move_file(".", PRESERVE_FNAME, LogDir);
1.8       jlam      773:                if (fexists(VIEWS_FNAME)) {
                    774:                        is_depoted_pkg = TRUE;
                    775:                        move_file(".", VIEWS_FNAME, LogDir);
                    776:                }
1.1       schmonz   777:
                    778:                /* register dependencies */
                    779:                /* we could save some cycles here if we remembered what we
                    780:                 * installed above (in case we got a wildcard dependency)  */
                    781:                /* XXX remembering in p->name would NOT be good! */
                    782:                for (p = Plist.head; p; p = p->next) {
                    783:                        if (p->type != PLIST_PKGDEP)
                    784:                                continue;
                    785:                        if (Verbose)
                    786:                                printf("Attempting to record dependency on package `%s'\n", p->name);
                    787:                        (void) snprintf(contents, sizeof(contents), "%s/%s", dbdir,
                    788:                            basename_of(p->name));
                    789:                        if (ispkgpattern(p->name)) {
                    790:                                char   *s;
                    791:                                s = findbestmatchingname(dirname_of(contents),
                    792:                                    basename_of(contents));
                    793:                                if (s != NULL) {
                    794:                                        char   *t;
                    795:                                        t = strrchr(contents, '/');
                    796:                                        strcpy(t + 1, s);
                    797:                                        free(s);
                    798:                                } else {
1.2       jschauma  799:                                        errx(EXIT_FAILURE, "Where did our dependency go?!");
1.1       schmonz   800:                                        /* this shouldn't happen... X-) */
                    801:                                }
                    802:                        }
1.8       jlam      803:                        strlcat(contents, "/", sizeof(contents));
                    804:                        strlcat(contents, REQUIRED_BY_FNAME, sizeof(contents));
1.1       schmonz   805:
                    806:                        cfile = fopen(contents, "a");
                    807:                        if (!cfile)
                    808:                                warnx("can't open dependency file '%s'!\n"
                    809:                                    "dependency registration is incomplete", contents);
                    810:                        else {
                    811:                                fprintf(cfile, "%s\n", PkgName);
                    812:                                if (fclose(cfile) == EOF)
                    813:                                        warnx("cannot properly close file %s", contents);
                    814:                        }
                    815:                }
                    816:                if (Verbose)
                    817:                        printf("Package %s registered in %s\n", PkgName, LogDir);
                    818:        }
                    819:
                    820:        if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) {
                    821:                FILE   *fp;
                    822:                char    buf[BUFSIZ];
                    823:
                    824:                (void) snprintf(buf, sizeof(buf), "%s/%s", LogDir, p->name);
                    825:                fp = fopen(buf, "r");
                    826:                if (fp) {
                    827:                        putc('\n', stdout);
                    828:                        while (fgets(buf, sizeof(buf), fp))
                    829:                                fputs(buf, stdout);
                    830:                        putc('\n', stdout);
                    831:                        (void) fclose(fp);
                    832:                } else
                    833:                        warnx("cannot open %s as display file", buf);
                    834:        }
                    835:
1.8       jlam      836:        /* Add the package to a default view. */
                    837:        if (!Fake && !NoView && is_depoted_pkg) {
                    838:                if (Verbose) {
1.10      jlam      839:                        printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n",
1.12      grant     840:                                BINDIR, dbdir,
                    841:                                View ? "-w " : "", View ? View : "",
                    842:                                Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
                    843:                                Verbose ? "-v " : "", PkgName);
                    844:                }
                    845:
                    846:                fexec_skipempty(BINDIR "/pkg_view", "-d", dbdir,
                    847:                                View ? "-w " : "", View ? View : "",
                    848:                                Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
                    849:                                Verbose ? "-v " : "", "add", PkgName, NULL);
1.8       jlam      850:        }
                    851:
1.1       schmonz   852:        goto success;
                    853:
                    854: bomb:
                    855:        errc = 1;
                    856:        goto success;
                    857:
                    858: fail:
                    859:        /* Nuke the whole (installed) show, XXX but don't clean directories */
                    860:        if (!Fake)
                    861:                delete_package(FALSE, FALSE, &Plist);
                    862:
                    863: success:
                    864:        /* delete the packing list contents */
                    865:        free_plist(&Plist);
                    866:        leave_playpen(Home);
                    867:
1.8       jlam      868:        if (replacing) {
1.1       schmonz   869:                /*
                    870:                 * Upgrade step 3/4: move back +REQUIRED_BY file
                    871:                 * (see also step 2/4)
                    872:                 */
1.8       jlam      873:                rc = rename(replace_via, replace_to);
1.1       schmonz   874:                assert(rc == 0);
                    875:
                    876:                /*
                    877:                 * Upgrade step 4/4: Fix pkgs that depend on us to
                    878:                 * depend on the new version instead of the old
                    879:                 * one by fixing @pkgdep lines in +CONTENTS files.
                    880:                 */
                    881:                /* TODO */
                    882:        }
                    883:
                    884:        return errc;
                    885: }
                    886:
                    887: void
                    888: cleanup(int signo)
                    889: {
                    890:        static int alreadyCleaning;
                    891:        void    (*oldint) (int);
                    892:        void    (*oldhup) (int);
                    893:        oldint = signal(SIGINT, SIG_IGN);
                    894:        oldhup = signal(SIGHUP, SIG_IGN);
                    895:
                    896:        if (!alreadyCleaning) {
                    897:                alreadyCleaning = 1;
                    898:                if (signo)
                    899:                        printf("Signal %d received, cleaning up.\n", signo);
                    900:                if (!Fake && zapLogDir && LogDir[0])
1.8       jlam      901:                        (void) fexec(REMOVE_CMD, "-fr", LogDir, NULL);
1.1       schmonz   902:                leave_playpen(Home);
                    903:                if (signo)
                    904:                        exit(1);
                    905:        }
                    906:        signal(SIGINT, oldint);
                    907:        signal(SIGHUP, oldhup);
                    908: }
                    909:
                    910: int
                    911: pkg_perform(lpkg_head_t *pkgs)
                    912: {
                    913:        int     err_cnt = 0;
                    914:        lpkg_t *lpp;
                    915:
                    916:        signal(SIGINT, cleanup);
                    917:        signal(SIGHUP, cleanup);
                    918:
                    919:        if (AddMode == SLAVE)
                    920:                err_cnt = pkg_do(NULL);
                    921:        else {
                    922:                while ((lpp = TAILQ_FIRST(pkgs)) != NULL) {
                    923:                        path_prepend_from_pkgname(lpp->lp_name);
                    924:                        err_cnt += pkg_do(lpp->lp_name);
                    925:                        path_prepend_clear();
                    926:                        TAILQ_REMOVE(pkgs, lpp, lp_link);
                    927:                        free_lpkg(lpp);
                    928:                }
                    929:        }
                    930:
                    931:        ftp_stop();
                    932:
                    933:        return err_cnt;
                    934: }
1.13      grant     935:
                    936: /* Read package build information */
                    937: static int
                    938: read_buildinfo(char **buildinfo)
                    939: {
                    940:        char   *key;
                    941:        char   *line;
                    942:        size_t  len;
                    943:        FILE   *fp;
                    944:
                    945:        fp = fopen(BUILD_INFO_FNAME, "r");
                    946:        if (!fp) {
                    947:                warnx("unable to open %s file.", BUILD_INFO_FNAME);
                    948:                return 1;
                    949:        }
                    950:
                    951:        while ((line = fgetln(fp, &len)) != NULL) {
                    952:                if (line[len - 1] == '\n')
                    953:                        line[len - 1] = '\0';
                    954:
                    955:                if ((key = strsep(&line, "=")) == NULL)
                    956:                        continue;
                    957:
                    958:                /*
                    959:                 * pkgsrc used to create the BUILDINFO file using
                    960:                 * "key= value", so skip the space if it's there.
                    961:                 */
                    962:                if (line == NULL)
                    963:                        continue;
                    964:                if (line[0] == ' ')
                    965:                        line += sizeof(char);
                    966:
                    967:                /* we only care about opsys, arch and version */
                    968:                if (line[0] != '\0') {
                    969:                        if (strcmp(key, "OPSYS") == 0)
                    970:                            buildinfo[BI_OPSYS] = strdup(line);
                    971:                        else if (strcmp(key, "OS_VERSION") == 0)
                    972:                            buildinfo[BI_OS_VERSION] = strdup(line);
                    973:                        else if (strcmp(key, "MACHINE_ARCH") == 0)
                    974:                            buildinfo[BI_MACHINE_ARCH] = strdup(line);
                    975:                }
                    976:        }
                    977:        if (buildinfo[BI_OPSYS] == NULL ||
                    978:            buildinfo[BI_OS_VERSION] == NULL ||
                    979:            buildinfo[BI_MACHINE_ARCH] == NULL) {
                    980:                warnx("couldn't extract build information from package.");
                    981:                return 1;
                    982:        }
                    983:        return 0;
                    984: }

CVSweb <webmaster@jp.NetBSD.org>