[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.103

1.103   ! wiz         1: /*     $NetBSD: perform.c,v 1.102 2012/02/21 13:32:24 wiz Exp $        */
1.8       jlam        2: #if HAVE_CONFIG_H
                      3: #include "config.h"
                      4: #endif
1.9       jlam        5: #include <nbcompat.h>
1.8       jlam        6: #if HAVE_SYS_CDEFS_H
1.1       schmonz     7: #include <sys/cdefs.h>
1.8       jlam        8: #endif
1.103   ! wiz         9: __RCSID("$NetBSD: perform.c,v 1.102 2012/02/21 13:32:24 wiz Exp $");
1.1       schmonz    10:
1.74      joerg      11: /*-
                     12:  * Copyright (c) 2003 Grant Beattie <grant@NetBSD.org>
                     13:  * Copyright (c) 2005 Dieter Baron <dillo@NetBSD.org>
                     14:  * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org>
                     15:  * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>
1.99      wiz        16:  * Copyright (c) 2010 Thomas Klausner <wiz@NetBSD.org>
1.74      joerg      17:  * All rights reserved.
1.1       schmonz    18:  *
                     19:  * Redistribution and use in source and binary forms, with or without
                     20:  * modification, are permitted provided that the following conditions
                     21:  * are met:
1.74      joerg      22:  *
1.1       schmonz    23:  * 1. Redistributions of source code must retain the above copyright
                     24:  *    notice, this list of conditions and the following disclaimer.
                     25:  * 2. Redistributions in binary form must reproduce the above copyright
1.74      joerg      26:  *    notice, this list of conditions and the following disclaimer in
                     27:  *    the documentation and/or other materials provided with the
                     28:  *    distribution.
1.1       schmonz    29:  *
1.74      joerg      30:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
                     31:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
                     32:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
                     33:  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
                     34:  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
                     35:  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     36:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     37:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     38:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     39:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
                     40:  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     41:  * SUCH DAMAGE.
1.1       schmonz    42:  */
                     43:
1.74      joerg      44: #include <sys/utsname.h>
1.101     joerg      45: #include <sys/stat.h>
1.72      joerg      46: #if HAVE_ERR_H
1.1       schmonz    47: #include <err.h>
1.72      joerg      48: #endif
1.33      hubertf    49: #include <errno.h>
1.75      joerg      50: #if HAVE_FCNTL_H
                     51: #include <fcntl.h>
                     52: #endif
1.74      joerg      53: #include <stdlib.h>
                     54: #include <string.h>
                     55: #include <unistd.h>
                     56:
                     57: #include <archive.h>
                     58: #include <archive_entry.h>
                     59:
1.1       schmonz    60: #include "lib.h"
                     61: #include "add.h"
1.94      joerg      62: #include "version.h"
1.1       schmonz    63:
1.74      joerg      64: struct pkg_meta {
                     65:        char *meta_contents;
                     66:        char *meta_comment;
                     67:        char *meta_desc;
                     68:        char *meta_mtree;
                     69:        char *meta_build_version;
                     70:        char *meta_build_info;
                     71:        char *meta_size_pkg;
                     72:        char *meta_size_all;
                     73:        char *meta_required_by;
                     74:        char *meta_display;
                     75:        char *meta_install;
                     76:        char *meta_deinstall;
                     77:        char *meta_preserve;
                     78:        char *meta_views;
                     79:        char *meta_installed_info;
                     80: };
                     81:
                     82: struct pkg_task {
                     83:        char *pkgname;
                     84:
                     85:        const char *prefix;
                     86:        char *install_prefix;
                     87:
                     88:        char *logdir;
                     89:        char *install_logdir;
1.93      joerg      90:        char *install_logdir_real;
1.74      joerg      91:        char *other_version;
                     92:
                     93:        package_t plist;
1.71      joerg      94:
1.74      joerg      95:        struct pkg_meta meta_data;
1.71      joerg      96:
1.74      joerg      97:        struct archive *archive;
                     98:        struct archive_entry *entry;
1.71      joerg      99:
1.74      joerg     100:        char *buildinfo[BI_ENUM_COUNT];
1.71      joerg     101:
1.74      joerg     102:        size_t dep_length, dep_allocated;
                    103:        char **dependencies;
1.71      joerg     104: };
1.35      ben       105:
1.74      joerg     106: static const struct pkg_meta_desc {
                    107:        size_t entry_offset;
                    108:        const char *entry_filename;
                    109:        int required_file;
                    110:        mode_t perm;
                    111: } pkg_meta_descriptors[] = {
                    112:        { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 1, 0644 },
                    113:        { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 1, 0444},
                    114:        { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 1, 0444},
                    115:        { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 0, 0555 },
                    116:        { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 0, 0555 },
                    117:        { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 0, 0444 },
                    118:        { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 0, 0444 },
                    119:        { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 0, 0444 },
                    120:        { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 0, 0444 },
                    121:        { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 0, 0444 },
                    122:        { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 0, 0444 },
                    123:        { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 0, 0444 },
                    124:        { offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, 0, 0444 },
                    125:        { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 },
                    126:        { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 },
1.88      joerg     127:        { 0, NULL, 0, 0 },
1.74      joerg     128: };
1.24      jlam      129:
1.81      joerg     130: static int pkg_do(const char *, int, int);
1.37      joerg     131:
1.24      jlam      132: static int
1.99      wiz       133: end_of_version(const char *opsys, const char *version_end)
                    134: {
                    135:     if (*version_end == '\0')
                    136:        return 1;
                    137:
                    138:     if (strcmp(opsys, "NetBSD") == 0) {
                    139:        if (strncmp(version_end, "_ALPHA", 6) == 0
                    140:            || strncmp(version_end, "_BETA", 5) == 0
                    141:            || strncmp(version_end, "_RC", 3) == 0
                    142:            || strncmp(version_end, "_STABLE", 7) == 0
                    143:            || strncmp(version_end, "_PATCH", 6) == 0)
                    144:            return 1;
                    145:     }
                    146:
                    147:     return 0;
                    148: }
                    149:
                    150: static int
                    151: compatible_platform(const char *opsys, const char *host, const char *package)
                    152: {
                    153:     int i = 0;
                    154:
                    155:     /* returns 1 if host and package operating system match */
                    156:     if (strcmp(host, package) == 0)
                    157:        return 1;
                    158:
1.103   ! wiz       159:     /* accept, if host version is a minor release of package version */
        !           160:     if (strncmp(host, package, strlen(package)) == 0)
        !           161:        return 1;
        !           162:
1.99      wiz       163:     /* find offset of first difference */
                    164:     for (i=0; (host[i] != '\0') && (host[i] == package[i]);)
                    165:        i++;
                    166:
                    167:     if (end_of_version(opsys, host+i) && end_of_version(opsys, package+i))
                    168:        return 1;
                    169:
                    170:     return 0;
                    171: }
                    172:
                    173: static int
1.74      joerg     174: mkdir_p(const char *path)
1.24      jlam      175: {
1.74      joerg     176:        char *p, *cur_end;
1.101     joerg     177:        int done, saved_errno;
                    178:        struct stat sb;
1.71      joerg     179:
1.74      joerg     180:        /*
                    181:         * Handle the easy case of direct success or
                    182:         * pre-existing directory first.
                    183:         */
1.101     joerg     184:        if (mkdir(path, 0777) == 0)
1.72      joerg     185:                return 0;
1.101     joerg     186:        if (stat(path, &sb) == 0) {
                    187:                if (S_ISDIR(sb.st_mode))
                    188:                        return 0;
                    189:                errno = ENOTDIR;
1.74      joerg     190:                return -1;
1.101     joerg     191:        }
1.24      jlam      192:
1.74      joerg     193:        cur_end = p = xstrdup(path);
1.24      jlam      194:
1.74      joerg     195:        for (;;) {
                    196:                /*
                    197:                 * First skip leading slashes either from / or
                    198:                 * from the last iteration.
                    199:                 */
                    200:                cur_end += strspn(cur_end, "/");
                    201:                /* Find end of actual directory name. */
                    202:                cur_end += strcspn(cur_end, "/");
1.71      joerg     203:
1.72      joerg     204:                /*
1.74      joerg     205:                 * Remember if this is the last component and
                    206:                 * overwrite / if needed.
1.72      joerg     207:                 */
1.74      joerg     208:                done = (*cur_end == '\0');
                    209:                *cur_end = '\0';
1.24      jlam      210:
1.101     joerg     211:                if (mkdir(p, 0777) == -1) {
                    212:                        saved_errno = errno;
1.102     wiz       213:                        if (stat(p, &sb) == 0) {
1.101     joerg     214:                                if (S_ISDIR(sb.st_mode))
                    215:                                        goto pass;
                    216:                                errno = ENOTDIR;
                    217:                        } else {
                    218:                                errno = saved_errno;
                    219:                        }
1.74      joerg     220:                        free(p);
                    221:                        return -1;
                    222:                }
1.101     joerg     223: pass:
1.74      joerg     224:                if (done)
                    225:                        break;
                    226:                *cur_end = '/';
                    227:        }
                    228:
                    229:        free(p);
1.101     joerg     230:        return 0;
1.74      joerg     231: }
                    232:
                    233: /*
                    234:  * Read meta data from archive.
                    235:  * Bail out if a required entry is missing or entries are in the wrong order.
                    236:  */
                    237: static int
                    238: read_meta_data(struct pkg_task *pkg)
                    239: {
                    240:        const struct pkg_meta_desc *descr, *last_descr;
                    241:        const char *fname;
                    242:        char **target;
                    243:        int64_t size;
                    244:        int r, found_required;
                    245:
                    246:        found_required = 0;
                    247:
                    248:        r = ARCHIVE_OK;
                    249:        last_descr = 0;
                    250:
                    251:        if (pkg->entry != NULL)
                    252:                goto skip_header;
                    253:
                    254:        for (;;) {
                    255:                r = archive_read_next_header(pkg->archive, &pkg->entry);
                    256:                if (r != ARCHIVE_OK)
                    257:                                break;
                    258: skip_header:
                    259:                fname = archive_entry_pathname(pkg->entry);
                    260:
                    261:                for (descr = pkg_meta_descriptors; descr->entry_filename;
                    262:                     ++descr) {
                    263:                        if (strcmp(descr->entry_filename, fname) == 0)
                    264:                                break;
                    265:                }
                    266:                if (descr->entry_filename == NULL)
                    267:                        break;
                    268:
                    269:                if (descr->required_file)
                    270:                        ++found_required;
                    271:
                    272:                target = (char **)((char *)&pkg->meta_data +
                    273:                    descr->entry_offset);
                    274:                if (*target) {
                    275:                        warnx("duplicate entry, package corrupt");
                    276:                        return -1;
                    277:                }
                    278:                if (descr < last_descr) {
                    279:                        warnx("misordered package");
                    280:                        return -1;
                    281:                }
                    282:                last_descr = descr;
                    283:
                    284:                size = archive_entry_size(pkg->entry);
                    285:                if (size > SSIZE_MAX - 1) {
                    286:                        warnx("package meta data too large to process");
                    287:                        return -1;
                    288:                }
                    289:                *target = xmalloc(size + 1);
                    290:                if (archive_read_data(pkg->archive, *target, size) != size) {
                    291:                        warnx("cannot read package meta data");
                    292:                        return -1;
                    293:                }
                    294:                (*target)[size] = '\0';
                    295:        }
                    296:
                    297:        if (r != ARCHIVE_OK)
                    298:                pkg->entry = NULL;
                    299:        if (r == ARCHIVE_EOF)
                    300:                r = ARCHIVE_OK;
                    301:
                    302:        for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
                    303:                if (descr->required_file)
                    304:                        --found_required;
                    305:        }
                    306:
                    307:        return !found_required && r == ARCHIVE_OK ? 0 : -1;
                    308: }
                    309:
                    310: /*
                    311:  * Free meta data.
                    312:  */
                    313: static void
                    314: free_meta_data(struct pkg_task *pkg)
                    315: {
                    316:        const struct pkg_meta_desc *descr;
                    317:        char **target;
                    318:
                    319:        for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
                    320:                target = (char **)((char *)&pkg->meta_data +
                    321:                    descr->entry_offset);
                    322:                free(*target);
                    323:                *target = NULL;
1.24      jlam      324:        }
                    325: }
                    326:
1.74      joerg     327: /*
                    328:  * Parse PLIST and populate pkg.
                    329:  */
1.1       schmonz   330: static int
1.74      joerg     331: pkg_parse_plist(struct pkg_task *pkg)
1.1       schmonz   332: {
1.74      joerg     333:        plist_t *p;
1.1       schmonz   334:
1.74      joerg     335:        parse_plist(&pkg->plist, pkg->meta_data.meta_contents);
                    336:        if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) {
                    337:                warnx("Invalid PLIST: missing @name");
                    338:                return -1;
                    339:        }
                    340:        if (pkg->pkgname == NULL)
                    341:                pkg->pkgname = xstrdup(p->name);
                    342:        else if (strcmp(pkg->pkgname, p->name) != 0) {
                    343:                warnx("Signature and PLIST differ on package name");
                    344:                return -1;
1.1       schmonz   345:        }
1.74      joerg     346:        if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) {
                    347:                warnx("Invalid PLIST: missing @cwd");
                    348:                return -1;
                    349:        }
                    350:
                    351:        if (Prefix != NULL &&
                    352:            strcmp(p->name, Prefix) != 0) {
                    353:                size_t len;
                    354:
                    355:                delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL);
                    356:                add_plist_top(&pkg->plist, PLIST_CWD, Prefix);
                    357:                free(pkg->meta_data.meta_contents);
                    358:                stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len,
                    359:                    Prefix);
                    360:                pkg->prefix = Prefix;
                    361:        } else
                    362:                pkg->prefix = p->name;
                    363:
                    364:        if (Destdir != NULL)
                    365:                pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix);
                    366:        else
                    367:                pkg->install_prefix = xstrdup(pkg->prefix);
                    368:
                    369:        return 0;
                    370: }
                    371:
                    372: /*
                    373:  * Helper function to extract value from a string of the
                    374:  * form key=value ending at eol.
                    375:  */
                    376: static char *
                    377: dup_value(const char *line, const char *eol)
                    378: {
                    379:        const char *key;
                    380:        char *val;
                    381:
                    382:        key = strchr(line, '=');
                    383:        val = xmalloc(eol - key);
                    384:        memcpy(val, key + 1, eol - key - 1);
                    385:        val[eol - key - 1] = '\0';
                    386:        return val;
1.1       schmonz   387: }
                    388:
                    389: static int
1.74      joerg     390: check_already_installed(struct pkg_task *pkg)
1.1       schmonz   391: {
1.74      joerg     392:        char *filename;
                    393:        int fd;
                    394:
                    395:        filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME);
                    396:        fd = open(filename, O_RDONLY);
                    397:        free(filename);
                    398:        if (fd == -1)
1.93      joerg     399:                return 1;
1.100     agc       400:        close(fd);
1.93      joerg     401:
                    402:        if (ReplaceSame) {
                    403:                struct stat sb;
                    404:
                    405:                pkg->install_logdir_real = pkg->install_logdir;
                    406:                pkg->install_logdir = xasprintf("%s.xxxxxx", pkg->install_logdir);
                    407:                if (stat(pkg->install_logdir, &sb) == 0) {
                    408:                        warnx("package `%s' already has a temporary update "
                    409:                            "directory `%s', remove it manually",
                    410:                            pkg->pkgname, pkg->install_logdir);
                    411:                        return -1;
                    412:                }
                    413:                return 1;
                    414:        }
1.12      grant     415:
1.97      joerg     416:        if (Force)
                    417:                return 1;
                    418:
1.74      joerg     419:        /* We can only arrive here for explicitly requested packages. */
                    420:        if (!Automatic && is_automatic_installed(pkg->pkgname)) {
                    421:                if (Fake ||
                    422:                    mark_as_automatic_installed(pkg->pkgname, 0) == 0)
                    423:                        warnx("package `%s' was already installed as "
                    424:                              "dependency, now marked as installed "
                    425:                              "manually", pkg->pkgname);
1.1       schmonz   426:        } else {
1.74      joerg     427:                warnx("package `%s' already recorded as installed",
                    428:                      pkg->pkgname);
1.1       schmonz   429:        }
1.74      joerg     430:        return 0;
1.1       schmonz   431:
                    432: }
                    433:
1.58      joerg     434: static int
1.74      joerg     435: check_other_installed(struct pkg_task *pkg)
1.58      joerg     436: {
1.74      joerg     437:        FILE *f, *f_pkg;
                    438:        size_t len;
                    439:        char *pkgbase, *iter, *filename;
                    440:        package_t plist;
                    441:        plist_t *p;
                    442:        int status;
1.72      joerg     443:
1.93      joerg     444:        if (pkg->install_logdir_real) {
                    445:                pkg->other_version = xstrdup(pkg->pkgname);
                    446:                return 0;
                    447:        }
                    448:
1.74      joerg     449:        pkgbase = xstrdup(pkg->pkgname);
1.71      joerg     450:
1.74      joerg     451:        if ((iter = strrchr(pkgbase, '-')) == NULL) {
                    452:                free(pkgbase);
                    453:                warnx("Invalid package name %s", pkg->pkgname);
1.71      joerg     454:                return -1;
                    455:        }
1.74      joerg     456:        *iter = '\0';
                    457:        pkg->other_version = find_best_matching_installed_pkg(pkgbase);
                    458:        free(pkgbase);
                    459:        if (pkg->other_version == NULL)
1.71      joerg     460:                return 0;
1.58      joerg     461:
1.74      joerg     462:        if (!Replace) {
                    463:                /* XXX This is redundant to the implicit conflict check. */
                    464:                warnx("A different version of %s is already installed: %s",
                    465:                    pkg->pkgname, pkg->other_version);
                    466:                return -1;
                    467:        }
                    468:
                    469:        filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME);
                    470:        errno = 0;
                    471:        f = fopen(filename, "r");
                    472:        free(filename);
                    473:        if (f == NULL) {
                    474:                if (errno == ENOENT) {
                    475:                        /* No packages depend on this, so everything is well. */
                    476:                        return 0;
                    477:                }
                    478:                warnx("Can't open +REQUIRED_BY of %s", pkg->other_version);
                    479:                return -1;
                    480:        }
                    481:
                    482:        status = 0;
                    483:
                    484:        while ((iter = fgetln(f, &len)) != NULL) {
                    485:                if (iter[len - 1] == '\n')
                    486:                        iter[len - 1] = '\0';
                    487:                filename = pkgdb_pkg_file(iter, CONTENTS_FNAME);
                    488:                if ((f_pkg = fopen(filename, "r")) == NULL) {
                    489:                        warnx("Can't open +CONTENTS of depending package %s",
                    490:                            iter);
                    491:                        fclose(f);
                    492:                        return -1;
                    493:                }
                    494:                read_plist(&plist, f_pkg);
                    495:                fclose(f_pkg);
                    496:                for (p = plist.head; p != NULL; p = p->next) {
                    497:                        if (p->type == PLIST_IGNORE) {
                    498:                                p = p->next;
                    499:                                continue;
                    500:                        } else if (p->type != PLIST_PKGDEP)
                    501:                                continue;
                    502:                        /*
                    503:                         * XXX This is stricter than necessary.
                    504:                         * XXX One pattern might be fulfilled by
                    505:                         * XXX a different package and still need this
                    506:                         * XXX one for a different pattern.
                    507:                         */
                    508:                        if (pkg_match(p->name, pkg->other_version) == 0)
                    509:                                continue;
                    510:                        if (pkg_match(p->name, pkg->pkgname) == 1)
                    511:                                continue; /* Both match, ok. */
                    512:                        warnx("Dependency of %s fulfilled by %s, but not by %s",
                    513:                            iter, pkg->other_version, pkg->pkgname);
1.98      gdt       514:                        if (!ForceDepending)
1.74      joerg     515:                                status = -1;
                    516:                        break;
1.72      joerg     517:                }
1.74      joerg     518:                free_plist(&plist);
1.71      joerg     519:        }
1.62      rillig    520:
1.74      joerg     521:        fclose(f);
                    522:
                    523:        return status;
                    524: }
                    525:
                    526: /*
                    527:  * Read package build information from meta data.
                    528:  */
                    529: static int
                    530: read_buildinfo(struct pkg_task *pkg)
                    531: {
                    532:        const char *data, *eol, *next_line;
                    533:
                    534:        data = pkg->meta_data.meta_build_info;
                    535:
1.76      joerg     536:        for (; data != NULL && *data != '\0'; data = next_line) {
1.74      joerg     537:                if ((eol = strchr(data, '\n')) == NULL) {
                    538:                        eol = data + strlen(data);
                    539:                        next_line = eol;
                    540:                } else
                    541:                        next_line = eol + 1;
1.58      joerg     542:
1.74      joerg     543:                if (strncmp(data, "OPSYS=", 6) == 0)
                    544:                        pkg->buildinfo[BI_OPSYS] = dup_value(data, eol);
                    545:                else if (strncmp(data, "OS_VERSION=", 11) == 0)
                    546:                        pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol);
                    547:                else if (strncmp(data, "MACHINE_ARCH=", 13) == 0)
                    548:                        pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol);
                    549:                else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0)
                    550:                        pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data,
                    551:                            eol);
                    552:                else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0)
                    553:                        pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data,
                    554:                            eol);
1.89      joerg     555:                else if (strncmp(data, "LICENSE=", 8) == 0)
                    556:                        pkg->buildinfo[BI_LICENSE] = dup_value(data, eol);
1.94      joerg     557:                else if (strncmp(data, "PKGTOOLS_VERSION=", 17) == 0)
                    558:                        pkg->buildinfo[BI_PKGTOOLS_VERSION] = dup_value(data,
                    559:                            eol);
1.74      joerg     560:        }
                    561:        if (pkg->buildinfo[BI_OPSYS] == NULL ||
                    562:            pkg->buildinfo[BI_OS_VERSION] == NULL ||
                    563:            pkg->buildinfo[BI_MACHINE_ARCH] == NULL) {
                    564:                warnx("Not all required build information are present.");
                    565:                return -1;
                    566:        }
1.71      joerg     567:
1.74      joerg     568:        if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL &&
                    569:            strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) ||
                    570:            (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL &&
                    571:            strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) {
                    572:                warnx("%s was built to ignore ABI dependencies", pkg->pkgname);
                    573:        }
1.72      joerg     574:
1.74      joerg     575:        return 0;
                    576: }
1.58      joerg     577:
1.74      joerg     578: /*
                    579:  * Free buildinfo.
                    580:  */
                    581: static void
                    582: free_buildinfo(struct pkg_task *pkg)
                    583: {
                    584:        size_t i;
1.58      joerg     585:
1.74      joerg     586:        for (i = 0; i < BI_ENUM_COUNT; ++i) {
                    587:                free(pkg->buildinfo[i]);
                    588:                pkg->buildinfo[i] = NULL;
1.72      joerg     589:        }
1.74      joerg     590: }
1.58      joerg     591:
1.74      joerg     592: /*
                    593:  * Write meta data files to pkgdb after creating the directory.
                    594:  */
                    595: static int
                    596: write_meta_data(struct pkg_task *pkg)
                    597: {
                    598:        const struct pkg_meta_desc *descr;
                    599:        char *filename, **target;
                    600:        size_t len;
                    601:        ssize_t ret;
                    602:        int fd;
                    603:
                    604:        if (Fake)
                    605:                return 0;
                    606:
                    607:        if (mkdir_p(pkg->install_logdir)) {
                    608:                warn("Can't create pkgdb entry: %s", pkg->install_logdir);
                    609:                return -1;
1.58      joerg     610:        }
                    611:
1.74      joerg     612:        for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
                    613:                target = (char **)((char *)&pkg->meta_data +
                    614:                    descr->entry_offset);
                    615:                if (*target == NULL)
                    616:                        continue;
                    617:                filename = xasprintf("%s/%s", pkg->install_logdir,
                    618:                    descr->entry_filename);
                    619:                (void)unlink(filename);
                    620:                fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm);
                    621:                if (fd == -1) {
                    622:                        warn("Can't open meta data file: %s", filename);
                    623:                        return -1;
                    624:                }
                    625:                len = strlen(*target);
                    626:                do {
                    627:                        ret = write(fd, *target, len);
                    628:                        if (ret == -1) {
                    629:                                warn("Can't write meta data file: %s",
                    630:                                    filename);
                    631:                                free(filename);
1.82      joerg     632:                                close(fd);
1.74      joerg     633:                                return -1;
                    634:                        }
                    635:                        len -= ret;
                    636:                } while (ret > 0);
                    637:                if (close(fd) == -1) {
                    638:                        warn("Can't close meta data file: %s", filename);
                    639:                        free(filename);
                    640:                        return -1;
                    641:                }
                    642:                free(filename);
                    643:        }
1.58      joerg     644:
1.71      joerg     645:        return 0;
                    646: }
1.58      joerg     647:
1.71      joerg     648: /*
1.74      joerg     649:  * Helper function for extract_files.
1.1       schmonz   650:  */
                    651: static int
1.74      joerg     652: copy_data_to_disk(struct archive *reader, struct archive *writer,
                    653:     const char *filename)
1.1       schmonz   654: {
1.74      joerg     655:        int r;
                    656:        const void *buff;
                    657:        size_t size;
                    658:        off_t offset;
                    659:
                    660:        for (;;) {
                    661:                r = archive_read_data_block(reader, &buff, &size, &offset);
                    662:                if (r == ARCHIVE_EOF)
                    663:                        return 0;
                    664:                if (r != ARCHIVE_OK) {
                    665:                        warnx("Read error for %s: %s", filename,
                    666:                            archive_error_string(reader));
                    667:                        return -1;
                    668:                }
                    669:                r = archive_write_data_block(writer, buff, size, offset);
                    670:                if (r != ARCHIVE_OK) {
                    671:                        warnx("Write error for %s: %s", filename,
                    672:                            archive_error_string(writer));
                    673:                        return -1;
                    674:                }
                    675:        }
                    676: }
                    677:
                    678: /*
                    679:  * Extract package.
                    680:  * Any misordered, missing or unlisted file in the package is an error.
                    681:  */
                    682:
1.87      joerg     683: static const int extract_flags = ARCHIVE_EXTRACT_OWNER |
1.74      joerg     684:     ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK |
                    685:     ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR;
                    686:
                    687: static int
                    688: extract_files(struct pkg_task *pkg)
                    689: {
                    690:        char    cmd[MaxPathSize];
                    691:        const char *owner, *group, *permissions;
                    692:        struct archive *writer;
                    693:        int r;
1.72      joerg     694:        plist_t *p;
1.74      joerg     695:        const char *last_file;
                    696:        char *fullpath;
                    697:
                    698:        if (Fake)
                    699:                return 0;
                    700:
                    701:        if (mkdir_p(pkg->install_prefix)) {
                    702:                warn("Can't create prefix: %s", pkg->install_prefix);
                    703:                return -1;
                    704:        }
                    705:
                    706:        if (!NoRecord && !pkgdb_open(ReadWrite)) {
                    707:                warn("Can't open pkgdb for writing");
                    708:                return -1;
1.72      joerg     709:        }
                    710:
1.74      joerg     711:        if (chdir(pkg->install_prefix) == -1) {
                    712:                warn("Can't change into prefix: %s", pkg->install_prefix);
                    713:                return -1;
                    714:        }
1.72      joerg     715:
1.74      joerg     716:        writer = archive_write_disk_new();
                    717:        archive_write_disk_set_options(writer, extract_flags);
                    718:        archive_write_disk_set_standard_lookup(writer);
                    719:
                    720:        owner = NULL;
                    721:        group = NULL;
                    722:        permissions = NULL;
                    723:        last_file = NULL;
                    724:
                    725:        r = -1;
                    726:
                    727:        for (p = pkg->plist.head; p != NULL; p = p->next) {
                    728:                switch (p->type) {
                    729:                case PLIST_FILE:
                    730:                        last_file = p->name;
                    731:                        if (pkg->entry == NULL) {
                    732:                                warnx("PLIST entry not in package (%s)",
                    733:                                    archive_entry_pathname(pkg->entry));
                    734:                                goto out;
                    735:                        }
                    736:                        if (strcmp(p->name, archive_entry_pathname(pkg->entry))) {
                    737:                                warnx("PLIST entry and package don't match (%s vs %s)",
                    738:                                    p->name, archive_entry_pathname(pkg->entry));
                    739:                                goto out;
1.1       schmonz   740:                        }
1.74      joerg     741:                        fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
                    742:                        pkgdb_store(fullpath, pkg->pkgname);
                    743:                        free(fullpath);
                    744:                        if (Verbose)
                    745:                                printf("%s", p->name);
                    746:                        break;
                    747:
1.86      joerg     748:                case PLIST_PKGDIR:
                    749:                        fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
                    750:                        mkdir_p(fullpath);
                    751:                        free(fullpath);
                    752:                        add_pkgdir(pkg->pkgname, pkg->prefix, p->name);
                    753:                        continue;
                    754:
1.74      joerg     755:                case PLIST_CMD:
                    756:                        if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file))
                    757:                                return -1;
                    758:                        printf("Executing '%s'\n", cmd);
                    759:                        if (!Fake && system(cmd))
                    760:                                warnx("command '%s' failed", cmd); /* XXX bail out? */
                    761:                        continue;
                    762:
                    763:                case PLIST_CHMOD:
                    764:                        permissions = p->name;
                    765:                        continue;
                    766:
                    767:                case PLIST_CHOWN:
                    768:                        owner = p->name;
                    769:                        continue;
                    770:
                    771:                case PLIST_CHGRP:
                    772:                        group = p->name;
                    773:                        continue;
                    774:
                    775:                case PLIST_IGNORE:
                    776:                        p = p->next;
                    777:                        continue;
                    778:
                    779:                default:
                    780:                        continue;
                    781:                }
                    782:
                    783:                r = archive_write_header(writer, pkg->entry);
                    784:                if (r != ARCHIVE_OK) {
1.95      joerg     785:                        warnx("Failed to write %s for %s: %s",
1.74      joerg     786:                            archive_entry_pathname(pkg->entry),
1.95      joerg     787:                            pkg->pkgname,
1.74      joerg     788:                            archive_error_string(writer));
                    789:                        goto out;
                    790:                }
                    791:
                    792:                if (owner != NULL)
                    793:                        archive_entry_set_uname(pkg->entry, owner);
                    794:                if (group != NULL)
                    795:                        archive_entry_set_uname(pkg->entry, group);
                    796:                if (permissions != NULL) {
                    797:                        mode_t mode;
                    798:
                    799:                        mode = archive_entry_mode(pkg->entry);
                    800:                        mode = getmode(setmode(permissions), mode);
                    801:                        archive_entry_set_mode(pkg->entry, mode);
                    802:                }
                    803:
                    804:                r = copy_data_to_disk(pkg->archive, writer,
                    805:                    archive_entry_pathname(pkg->entry));
                    806:                if (r)
                    807:                        goto out;
                    808:                if (Verbose)
                    809:                        printf("\n");
                    810:
                    811:                r = archive_read_next_header(pkg->archive, &pkg->entry);
                    812:                if (r == ARCHIVE_EOF) {
                    813:                        pkg->entry = NULL;
                    814:                        continue;
1.1       schmonz   815:                }
1.74      joerg     816:                if (r != ARCHIVE_OK) {
1.95      joerg     817:                        warnx("Failed to read from archive for %s: %s",
                    818:                            pkg->pkgname,
1.74      joerg     819:                            archive_error_string(pkg->archive));
                    820:                        goto out;
1.1       schmonz   821:                }
1.56      joerg     822:        }
1.1       schmonz   823:
1.74      joerg     824:        if (pkg->entry != NULL) {
                    825:                warnx("Package contains entries not in PLIST: %s",
                    826:                    archive_entry_pathname(pkg->entry));
                    827:                goto out;
1.71      joerg     828:        }
                    829:
1.74      joerg     830:        r = 0;
                    831:
                    832: out:
                    833:        if (!NoRecord)
                    834:                pkgdb_close();
                    835:        archive_write_close(writer);
                    836:        archive_write_finish(writer);
                    837:
                    838:        return r;
                    839: }
                    840:
                    841: /*
                    842:  * Register dependencies after sucessfully installing the package.
                    843:  */
                    844: static void
                    845: pkg_register_depends(struct pkg_task *pkg)
                    846: {
                    847:        int fd;
                    848:        size_t text_len, i;
                    849:        char *required_by, *text;
                    850:
                    851:        if (Fake)
                    852:                return;
                    853:
                    854:        text = xasprintf("%s\n", pkg->pkgname);
                    855:        text_len = strlen(text);
1.1       schmonz   856:
1.74      joerg     857:        for (i = 0; i < pkg->dep_length; ++i) {
                    858:                required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME);
1.1       schmonz   859:
1.74      joerg     860:                fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644);
1.82      joerg     861:                if (fd == -1) {
1.74      joerg     862:                        warn("can't open dependency file '%s',"
                    863:                            "registration is incomplete!", required_by);
1.88      joerg     864:                } else if (write(fd, text, text_len) != (ssize_t)text_len) {
1.74      joerg     865:                        warn("can't write to dependency file `%s'", required_by);
1.82      joerg     866:                        close(fd);
                    867:                } else if (close(fd) == -1)
1.74      joerg     868:                        warn("cannot close file %s", required_by);
1.71      joerg     869:
1.74      joerg     870:                free(required_by);
1.13      grant     871:        }
                    872:
1.74      joerg     873:        free(text);
                    874: }
                    875:
                    876: /*
                    877:  * Reduce the result from uname(3) to a canonical form.
                    878:  */
                    879: static void
                    880: normalise_platform(struct utsname *host_name)
                    881: {
                    882: #ifdef NUMERIC_VERSION_ONLY
                    883:        size_t span;
1.71      joerg     884:
1.74      joerg     885:        span = strspn(host_name->release, "0123456789.");
                    886:        host_name->release[span] = '\0';
                    887: #endif
                    888: }
1.24      jlam      889:
1.74      joerg     890: /*
                    891:  * Check build platform of the package against local host.
                    892:  */
                    893: static int
                    894: check_platform(struct pkg_task *pkg)
                    895: {
                    896:        struct utsname host_uname;
                    897:        const char *effective_arch;
                    898:        int fatal;
1.24      jlam      899:
1.74      joerg     900:        if (uname(&host_uname) < 0) {
                    901:                if (Force) {
                    902:                        warnx("uname() failed, continuing.");
                    903:                        return 0;
                    904:                } else {
                    905:                        warnx("uname() failed, aborting.");
                    906:                        return -1;
1.13      grant     907:                }
                    908:        }
                    909:
1.74      joerg     910:        normalise_platform(&host_uname);
1.72      joerg     911:
1.74      joerg     912:        if (OverrideMachine != NULL)
                    913:                effective_arch = OverrideMachine;
                    914:        else
                    915:                effective_arch = MACHINE_ARCH;
                    916:
                    917:        /* If either the OS or arch are different, bomb */
                    918:        if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) ||
                    919:            strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0)
                    920:                fatal = 1;
                    921:        else
                    922:                fatal = 0;
                    923:
                    924:        if (fatal ||
1.99      wiz       925:            compatible_platform(OPSYS_NAME, host_uname.release,
                    926:                                pkg->buildinfo[BI_OS_VERSION]) != 1) {
1.74      joerg     927:                warnx("Warning: package `%s' was built for a platform:",
                    928:                    pkg->pkgname);
                    929:                warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)",
                    930:                    pkg->buildinfo[BI_OPSYS],
                    931:                    pkg->buildinfo[BI_MACHINE_ARCH],
                    932:                    pkg->buildinfo[BI_OS_VERSION],
                    933:                    OPSYS_NAME,
                    934:                    effective_arch,
                    935:                    host_uname.release);
                    936:                if (!Force && fatal)
                    937:                        return -1;
1.72      joerg     938:        }
1.74      joerg     939:        return 0;
                    940: }
                    941:
1.94      joerg     942: static int
                    943: check_pkgtools_version(struct pkg_task *pkg)
                    944: {
                    945:        const char *val = pkg->buildinfo[BI_PKGTOOLS_VERSION];
                    946:        int version;
                    947:
                    948:        if (val == NULL) {
                    949:                warnx("Warning: package `%s' lacks pkg_install version data",
                    950:                    pkg->pkgname);
                    951:                return 0;
                    952:        }
                    953:
                    954:        if (strlen(val) != 8 || strspn(val, "0123456789") != 8) {
                    955:                warnx("Warning: package `%s' contains an invalid pkg_install version",
                    956:                    pkg->pkgname);
                    957:                return Force ? 0 : -1;
                    958:        }
                    959:        version = atoi(val);
                    960:        if (version > PKGTOOLS_VERSION) {
                    961:                warnx("%s: package `%s' was built with a newer pkg_install version",
                    962:                    Force ? "Warning" : "Error", pkg->pkgname);
                    963:                return Force ? 0 : -1;
                    964:        }
                    965:        return 0;
                    966: }
                    967:
1.74      joerg     968: /*
                    969:  * Run the install script.
                    970:  */
                    971: static int
                    972: run_install_script(struct pkg_task *pkg, const char *argument)
                    973: {
                    974:        int ret;
                    975:        char *filename;
1.72      joerg     976:
1.74      joerg     977:        if (pkg->meta_data.meta_install == NULL || NoInstall)
                    978:                return 0;
1.8       jlam      979:
1.74      joerg     980:        if (Destdir != NULL)
                    981:                setenv(PKG_DESTDIR_VNAME, Destdir, 1);
                    982:        setenv(PKG_PREFIX_VNAME, pkg->prefix, 1);
                    983:        setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1);
1.92      joerg     984:        setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1);
1.74      joerg     985:
                    986:        if (Verbose)
                    987:                printf("Running install with PRE-INSTALL for %s.\n", pkg->pkgname);
                    988:        if (Fake)
                    989:                return 0;
                    990:
                    991:        filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME);
                    992:
                    993:        ret = 0;
                    994:        errno = 0;
                    995:        if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument,
                    996:            (void *)NULL)) {
                    997:                if (errno != 0)
                    998:                        warn("exec of install script failed");
                    999:                else
                   1000:                        warnx("install script returned error status");
                   1001:                ret = -1;
1.8       jlam     1002:        }
1.74      joerg    1003:        free(filename);
1.8       jlam     1004:
1.74      joerg    1005:        return ret;
                   1006: }
1.1       schmonz  1007:
1.78      joerg    1008: struct find_conflict_data {
                   1009:        const char *pkg;
                   1010:        const char *old_pkg;
                   1011:        const char *pattern;
                   1012: };
                   1013:
                   1014: static int
                   1015: check_explicit_conflict_iter(const char *cur_pkg, void *cookie)
                   1016: {
                   1017:        struct find_conflict_data *data = cookie;
                   1018:
1.80      joerg    1019:        if (data->old_pkg && strcmp(data->old_pkg, cur_pkg) == 0)
1.78      joerg    1020:                return 0;
                   1021:
                   1022:        warnx("Package `%s' conflicts with `%s', and `%s' is installed.",
                   1023:            data->pkg, data->pattern, cur_pkg);
                   1024:
                   1025:        return 1;
                   1026: }
                   1027:
1.74      joerg    1028: static int
                   1029: check_explicit_conflict(struct pkg_task *pkg)
                   1030: {
1.78      joerg    1031:        struct find_conflict_data data;
1.74      joerg    1032:        char *installed, *installed_pattern;
                   1033:        plist_t *p;
                   1034:        int status;
1.1       schmonz  1035:
1.74      joerg    1036:        status = 0;
1.1       schmonz  1037:
1.74      joerg    1038:        for (p = pkg->plist.head; p != NULL; p = p->next) {
                   1039:                if (p->type == PLIST_IGNORE) {
                   1040:                        p = p->next;
                   1041:                        continue;
1.78      joerg    1042:                }
                   1043:                if (p->type != PLIST_PKGCFL)
1.71      joerg    1044:                        continue;
1.78      joerg    1045:                data.pkg = pkg->pkgname;
                   1046:                data.old_pkg = pkg->other_version;
                   1047:                data.pattern = p->name;
                   1048:                status |= match_installed_pkgs(p->name,
                   1049:                    check_explicit_conflict_iter, &data);
1.1       schmonz  1050:        }
                   1051:
1.74      joerg    1052:        if (some_installed_package_conflicts_with(pkg->pkgname,
                   1053:            pkg->other_version, &installed, &installed_pattern)) {
                   1054:                warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.",
                   1055:                        installed, installed_pattern, pkg->pkgname);
                   1056:                free(installed);
                   1057:                free(installed_pattern);
1.78      joerg    1058:                status |= -1;
1.74      joerg    1059:        }
1.71      joerg    1060:
1.74      joerg    1061:        return status;
                   1062: }
                   1063:
                   1064: static int
                   1065: check_implicit_conflict(struct pkg_task *pkg)
                   1066: {
                   1067:        plist_t *p;
                   1068:        char *fullpath, *existing;
                   1069:        int status;
                   1070:
                   1071:        if (!pkgdb_open(ReadOnly)) {
                   1072: #if notyet /* XXX empty pkgdb without database? */
                   1073:                warn("Can't open pkgdb for reading");
                   1074:                return -1;
                   1075: #else
                   1076:                return 0;
                   1077: #endif
1.68      rillig   1078:        }
                   1079:
1.74      joerg    1080:        status = 0;
                   1081:
                   1082:        for (p = pkg->plist.head; p != NULL; p = p->next) {
                   1083:                if (p->type == PLIST_IGNORE) {
                   1084:                        p = p->next;
                   1085:                        continue;
                   1086:                } else if (p->type != PLIST_FILE)
                   1087:                        continue;
                   1088:
                   1089:                fullpath = xasprintf("%s/%s", pkg->prefix, p->name);
                   1090:                existing = pkgdb_retrieve(fullpath);
                   1091:                free(fullpath);
                   1092:                if (existing == NULL)
                   1093:                        continue;
                   1094:                if (pkg->other_version != NULL &&
                   1095:                    strcmp(pkg->other_version, existing) == 0)
1.71      joerg    1096:                        continue;
                   1097:
1.74      joerg    1098:                warnx("Conflicting PLIST with %s: %s", existing, p->name);
                   1099:                if (!Force) {
                   1100:                        status = -1;
                   1101:                        if (!Verbose)
                   1102:                                break;
1.1       schmonz  1103:                }
                   1104:        }
                   1105:
1.74      joerg    1106:        pkgdb_close();
                   1107:        return status;
                   1108: }
                   1109:
                   1110: static int
                   1111: check_dependencies(struct pkg_task *pkg)
                   1112: {
                   1113:        plist_t *p;
                   1114:        char *best_installed;
                   1115:        int status;
                   1116:        size_t i;
                   1117:
                   1118:        status = 0;
                   1119:
                   1120:        for (p = pkg->plist.head; p != NULL; p = p->next) {
                   1121:                if (p->type == PLIST_IGNORE) {
                   1122:                        p = p->next;
                   1123:                        continue;
                   1124:                } else if (p->type != PLIST_PKGDEP)
1.1       schmonz  1125:                        continue;
1.8       jlam     1126:
1.52      joerg    1127:                best_installed = find_best_matching_installed_pkg(p->name);
                   1128:
                   1129:                if (best_installed == NULL) {
1.74      joerg    1130:                        /* XXX check cyclic dependencies? */
                   1131:                        if (Fake || NoRecord) {
                   1132:                                if (!Force) {
                   1133:                                        warnx("Missing dependency %s\n",
                   1134:                                             p->name);
                   1135:                                        status = -1;
                   1136:                                        break;
1.1       schmonz  1137:                                }
1.74      joerg    1138:                                warnx("Missing dependency %s, continuing",
                   1139:                                    p->name);
                   1140:                                continue;
1.71      joerg    1141:                        }
1.81      joerg    1142:                        if (pkg_do(p->name, 1, 0)) {
1.91      joerg    1143:                                if (ForceDepends) {
                   1144:                                        warnx("Can't install dependency %s, "
                   1145:                                            "continuing", p->name);
                   1146:                                        continue;
                   1147:                                } else {
                   1148:                                        warnx("Can't install dependency %s",
                   1149:                                            p->name);
                   1150:                                        status = -1;
                   1151:                                        break;
                   1152:                                }
1.74      joerg    1153:                        }
                   1154:                        best_installed = find_best_matching_installed_pkg(p->name);
1.91      joerg    1155:                        if (best_installed == NULL && ForceDepends) {
1.74      joerg    1156:                                warnx("Missing dependency %s ignored", p->name);
                   1157:                                continue;
                   1158:                        } else if (best_installed == NULL) {
                   1159:                                warnx("Just installed dependency %s disappeared", p->name);
                   1160:                                status = -1;
                   1161:                                break;
                   1162:                        }
                   1163:                }
                   1164:                for (i = 0; i < pkg->dep_length; ++i) {
                   1165:                        if (strcmp(best_installed, pkg->dependencies[i]) == 0)
                   1166:                                break;
                   1167:                }
                   1168:                if (i < pkg->dep_length) {
                   1169:                        /* Already used as dependency, so skip it. */
1.52      joerg    1170:                        free(best_installed);
1.74      joerg    1171:                        continue;
                   1172:                }
                   1173:                if (pkg->dep_length + 1 >= pkg->dep_allocated) {
                   1174:                        char **tmp;
                   1175:                        pkg->dep_allocated = 2 * pkg->dep_allocated + 1;
                   1176:                        pkg->dependencies = xrealloc(pkg->dependencies,
                   1177:                            pkg->dep_allocated * sizeof(*tmp));
1.1       schmonz  1178:                }
1.74      joerg    1179:                pkg->dependencies[pkg->dep_length++] = best_installed;
1.1       schmonz  1180:        }
                   1181:
1.74      joerg    1182:        return status;
                   1183: }
1.1       schmonz  1184:
1.74      joerg    1185: /*
                   1186:  * If this package uses pkg_views, register it in the default view.
                   1187:  */
                   1188: static void
                   1189: pkg_register_views(struct pkg_task *pkg)
                   1190: {
                   1191:        if (Fake || NoView || pkg->meta_data.meta_views == NULL)
                   1192:                return;
                   1193:
                   1194:        if (Verbose) {
                   1195:                printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n",
1.92      joerg    1196:                        BINDIR, pkgdb_get_dir(),
1.74      joerg    1197:                        View ? "-w " : "", View ? View : "",
                   1198:                        Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
                   1199:                        Verbose ? "-v " : "", pkg->pkgname);
1.1       schmonz  1200:        }
                   1201:
1.92      joerg    1202:        fexec_skipempty(BINDIR "/pkg_view", "-d", pkgdb_get_dir(),
1.74      joerg    1203:                        View ? "-w " : "", View ? View : "",
                   1204:                        Viewbase ? "-W " : "", Viewbase ? Viewbase : "",
                   1205:                        Verbose ? "-v " : "", "add", pkg->pkgname,
                   1206:                        (void *)NULL);
                   1207: }
                   1208:
                   1209: static int
                   1210: preserve_meta_data_file(struct pkg_task *pkg, const char *name)
                   1211: {
                   1212:        char *old_file, *new_file;
                   1213:        int rv;
                   1214:
                   1215:        if (Fake)
                   1216:                return 0;
                   1217:
                   1218:        old_file = pkgdb_pkg_file(pkg->other_version, name);
1.93      joerg    1219:        new_file = xasprintf("%s/%s", pkg->install_logdir, name);
1.74      joerg    1220:        rv = 0;
                   1221:        if (rename(old_file, new_file) == -1 && errno != ENOENT) {
                   1222:                warn("Can't move %s from %s to %s", name, old_file, new_file);
                   1223:                rv = -1;
                   1224:        }
                   1225:        free(old_file);
                   1226:        free(new_file);
                   1227:        return rv;
                   1228: }
                   1229:
                   1230: static int
                   1231: start_replacing(struct pkg_task *pkg)
                   1232: {
                   1233:        if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME))
                   1234:                return -1;
                   1235:
1.79      joerg    1236:        if (preserve_meta_data_file(pkg, PRESERVE_FNAME))
1.74      joerg    1237:                return -1;
                   1238:
                   1239:        if (pkg->meta_data.meta_installed_info == NULL &&
                   1240:            preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME))
                   1241:                return -1;
                   1242:
                   1243:        if (Verbose || Fake) {
                   1244:                printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n",
1.92      joerg    1245:                        BINDIR, pkgdb_get_dir(), pkg->prefix,
1.74      joerg    1246:                        Destdir ? " -P ": "", Destdir ? Destdir : "",
                   1247:                        pkg->other_version);
1.10      jlam     1248:        }
1.74      joerg    1249:        if (!Fake)
1.92      joerg    1250:                fexec_skipempty(BINDIR "/pkg_delete", "-K", pkgdb_get_dir(),
1.74      joerg    1251:                    "-p", pkg->prefix,
                   1252:                    Destdir ? "-P": "", Destdir ? Destdir : "",
                   1253:                    pkg->other_version, NULL);
1.1       schmonz  1254:
1.74      joerg    1255:        /* XXX Check return value and do what? */
                   1256:        return 0;
                   1257: }
                   1258:
                   1259: static int check_input(const char *line, size_t len)
                   1260: {
                   1261:        if (line == NULL || len == 0)
                   1262:                return 1;
                   1263:        switch (*line) {
                   1264:        case 'Y':
                   1265:        case 'y':
                   1266:        case 'T':
                   1267:        case 't':
                   1268:        case '1':
                   1269:                return 0;
                   1270:        default:
                   1271:                return 1;
1.1       schmonz  1272:        }
1.74      joerg    1273: }
1.71      joerg    1274:
1.74      joerg    1275: static int
1.84      joerg    1276: check_signature(struct pkg_task *pkg, int invalid_sig)
1.74      joerg    1277: {
                   1278:        char *line;
                   1279:        size_t len;
                   1280:
                   1281:        if (strcasecmp(verified_installation, "never") == 0)
                   1282:                return 0;
                   1283:        if (strcasecmp(verified_installation, "always") == 0) {
                   1284:                if (invalid_sig)
                   1285:                        warnx("No valid signature found, rejected");
                   1286:                return invalid_sig;
                   1287:        }
                   1288:        if (strcasecmp(verified_installation, "trusted") == 0) {
                   1289:                if (!invalid_sig)
                   1290:                        return 0;
                   1291:                fprintf(stderr, "No valid signature found for %s.\n",
                   1292:                    pkg->pkgname);
                   1293:                fprintf(stderr,
                   1294:                    "Do you want to proceed with the installation [y/n]?\n");
                   1295:                line = fgetln(stdin, &len);
                   1296:                if (check_input(line, len)) {
                   1297:                        fprintf(stderr, "Cancelling installation\n");
                   1298:                        return 1;
                   1299:                }
                   1300:                return 0;
                   1301:        }
                   1302:        if (strcasecmp(verified_installation, "interactive") == 0) {
                   1303:                fprintf(stderr, "Do you want to proceed with "
                   1304:                    "the installation of %s [y/n]?\n", pkg->pkgname);
                   1305:                line = fgetln(stdin, &len);
                   1306:                if (check_input(line, len)) {
                   1307:                        fprintf(stderr, "Cancelling installation\n");
                   1308:                        return 1;
1.72      joerg    1309:                }
1.74      joerg    1310:                return 0;
                   1311:        }
                   1312:        warnx("Unknown value of configuration variable VERIFIED_INSTALLATION");
                   1313:        return 1;
                   1314: }
                   1315:
                   1316: static int
                   1317: check_vulnerable(struct pkg_task *pkg)
                   1318: {
                   1319:        static struct pkg_vulnerabilities *pv;
                   1320:        int require_check;
                   1321:        char *line;
                   1322:        size_t len;
                   1323:
                   1324:        if (strcasecmp(check_vulnerabilities, "never") == 0)
                   1325:                return 0;
1.97      joerg    1326:        else if (strcasecmp(check_vulnerabilities, "always") == 0)
1.74      joerg    1327:                require_check = 1;
1.97      joerg    1328:        else if (strcasecmp(check_vulnerabilities, "interactive") == 0)
1.74      joerg    1329:                require_check = 0;
                   1330:        else {
                   1331:                warnx("Unknown value of the configuration variable"
                   1332:                    "CHECK_VULNERABILITIES");
                   1333:                return 1;
1.72      joerg    1334:        }
1.1       schmonz  1335:
1.74      joerg    1336:        if (pv == NULL) {
1.96      joerg    1337:                pv = read_pkg_vulnerabilities_file(pkg_vulnerabilities_file,
1.74      joerg    1338:                    require_check, 0);
                   1339:                if (pv == NULL)
                   1340:                        return require_check;
                   1341:        }
1.71      joerg    1342:
1.97      joerg    1343:        if (!audit_package(pv, pkg->pkgname, NULL, 2))
1.74      joerg    1344:                return 0;
                   1345:
                   1346:        if (require_check)
                   1347:                return 1;
                   1348:
                   1349:        fprintf(stderr, "Do you want to proceed with the installation of %s"
                   1350:            " [y/n]?\n", pkg->pkgname);
                   1351:        line = fgetln(stdin, &len);
                   1352:        if (check_input(line, len)) {
                   1353:                fprintf(stderr, "Cancelling installation\n");
                   1354:                return 1;
                   1355:        }
                   1356:        return 0;
                   1357: }
1.71      joerg    1358:
1.89      joerg    1359: static int
                   1360: check_license(struct pkg_task *pkg)
                   1361: {
                   1362:        if (LicenseCheck == 0)
                   1363:                return 0;
                   1364:
                   1365:        if ((pkg->buildinfo[BI_LICENSE] == NULL ||
                   1366:             *pkg->buildinfo[BI_LICENSE] == '\0')) {
                   1367:
                   1368:                if (LicenseCheck == 1)
                   1369:                        return 0;
                   1370:                warnx("No LICENSE set for package `%s'", pkg->pkgname);
                   1371:                return 1;
                   1372:        }
                   1373:
                   1374:        switch (acceptable_license(pkg->buildinfo[BI_LICENSE])) {
                   1375:        case 0:
                   1376:                warnx("License `%s' of package `%s' is not acceptable",
                   1377:                    pkg->buildinfo[BI_LICENSE], pkg->pkgname);
                   1378:                return 1;
                   1379:        case 1:
                   1380:                return 0;
                   1381:        default:
                   1382:                warnx("Invalid LICENSE for package `%s'", pkg->pkgname);
                   1383:                return 1;
                   1384:        }
                   1385: }
                   1386:
1.74      joerg    1387: /*
                   1388:  * Install a single package.
                   1389:  */
                   1390: static int
1.81      joerg    1391: pkg_do(const char *pkgpath, int mark_automatic, int top_level)
1.74      joerg    1392: {
1.95      joerg    1393:        char *archive_name;
1.74      joerg    1394:        int status, invalid_sig;
                   1395:        struct pkg_task *pkg;
1.71      joerg    1396:
1.74      joerg    1397:        pkg = xcalloc(1, sizeof(*pkg));
1.1       schmonz  1398:
1.74      joerg    1399:        status = -1;
1.1       schmonz  1400:
1.95      joerg    1401:        pkg->archive = find_archive(pkgpath, top_level, &archive_name);
1.81      joerg    1402:        if (pkg->archive == NULL) {
1.74      joerg    1403:                warnx("no pkg found for '%s', sorry.", pkgpath);
                   1404:                goto clean_find_archive;
1.72      joerg    1405:        }
1.52      joerg    1406:
1.95      joerg    1407:        invalid_sig = pkg_verify_signature(archive_name, &pkg->archive, &pkg->entry,
1.84      joerg    1408:            &pkg->pkgname);
1.95      joerg    1409:        free(archive_name);
1.77      joerg    1410:
                   1411:        if (pkg->archive == NULL)
                   1412:                goto clean_memory;
1.74      joerg    1413:
                   1414:        if (read_meta_data(pkg))
                   1415:                goto clean_memory;
                   1416:
                   1417:        /* Parse PLIST early, so that messages can use real package name. */
                   1418:        if (pkg_parse_plist(pkg))
                   1419:                goto clean_memory;
                   1420:
1.84      joerg    1421:        if (check_signature(pkg, invalid_sig))
1.74      joerg    1422:                goto clean_memory;
                   1423:
1.89      joerg    1424:        if (read_buildinfo(pkg))
                   1425:                goto clean_memory;
                   1426:
1.94      joerg    1427:        if (check_pkgtools_version(pkg))
                   1428:                goto clean_memory;
                   1429:
1.74      joerg    1430:        if (check_vulnerable(pkg))
                   1431:                goto clean_memory;
                   1432:
1.89      joerg    1433:        if (check_license(pkg))
                   1434:                goto clean_memory;
                   1435:
1.74      joerg    1436:        if (pkg->meta_data.meta_mtree != NULL)
                   1437:                warnx("mtree specification in pkg `%s' ignored", pkg->pkgname);
                   1438:
                   1439:        if (pkg->meta_data.meta_views != NULL) {
                   1440:                pkg->logdir = xstrdup(pkg->prefix);
1.92      joerg    1441:                pkgdb_set_dir(dirname_of(pkg->logdir), 4);
1.74      joerg    1442:        } else {
1.92      joerg    1443:                pkg->logdir = xasprintf("%s/%s", config_pkg_dbdir, pkg->pkgname);
1.71      joerg    1444:        }
1.52      joerg    1445:
1.90      joerg    1446:        if (Destdir != NULL)
1.74      joerg    1447:                pkg->install_logdir = xasprintf("%s/%s", Destdir, pkg->logdir);
1.90      joerg    1448:        else
1.74      joerg    1449:                pkg->install_logdir = xstrdup(pkg->logdir);
                   1450:
                   1451:        if (NoRecord && !Fake) {
                   1452:                const char *tmpdir;
                   1453:
                   1454:                tmpdir = getenv("TMPDIR");
                   1455:                if (tmpdir == NULL)
                   1456:                        tmpdir = "/tmp";
                   1457:
                   1458:                free(pkg->install_logdir);
                   1459:                pkg->install_logdir = xasprintf("%s/pkg_install.XXXXXX", tmpdir);
                   1460:                /* XXX pkg_add -u... */
                   1461:                if (mkdtemp(pkg->install_logdir) == NULL) {
                   1462:                        warn("mkdtemp failed");
                   1463:                        goto clean_memory;
1.1       schmonz  1464:                }
1.74      joerg    1465:        }
1.1       schmonz  1466:
1.93      joerg    1467:        switch (check_already_installed(pkg)) {
                   1468:        case 0:
1.74      joerg    1469:                status = 0;
                   1470:                goto clean_memory;
1.93      joerg    1471:        case 1:
                   1472:                break;
                   1473:        case -1:
                   1474:                goto clean_memory;
1.1       schmonz  1475:        }
                   1476:
1.74      joerg    1477:        if (check_platform(pkg))
                   1478:                goto clean_memory;
1.1       schmonz  1479:
1.74      joerg    1480:        if (check_other_installed(pkg))
                   1481:                goto clean_memory;
                   1482:
                   1483:        if (check_explicit_conflict(pkg))
                   1484:                goto clean_memory;
1.1       schmonz  1485:
1.74      joerg    1486:        if (check_implicit_conflict(pkg))
                   1487:                goto clean_memory;
1.1       schmonz  1488:
1.74      joerg    1489:        if (pkg->other_version != NULL) {
1.1       schmonz  1490:                /*
1.74      joerg    1491:                 * Replacing an existing package.
                   1492:                 * Write meta-data, get rid of the old version,
                   1493:                 * install/update dependencies and finally extract.
1.1       schmonz  1494:                 */
1.74      joerg    1495:                if (write_meta_data(pkg))
                   1496:                        goto nuke_pkgdb;
                   1497:
                   1498:                if (start_replacing(pkg))
                   1499:                        goto nuke_pkgdb;
                   1500:
1.93      joerg    1501:                if (pkg->install_logdir_real) {
                   1502:                        rename(pkg->install_logdir, pkg->install_logdir_real);
                   1503:                        free(pkg->install_logdir);
                   1504:                        pkg->install_logdir = pkg->install_logdir_real;
                   1505:                        pkg->install_logdir_real = NULL;
                   1506:                }
                   1507:
1.74      joerg    1508:                if (check_dependencies(pkg))
                   1509:                        goto nuke_pkgdb;
                   1510:        } else {
1.1       schmonz  1511:                /*
1.74      joerg    1512:                 * Normal installation.
                   1513:                 * Install/update dependencies first and
                   1514:                 * write the current package to disk afterwards.
                   1515:                 */
                   1516:                if (check_dependencies(pkg))
                   1517:                        goto clean_memory;
                   1518:
                   1519:                if (write_meta_data(pkg))
                   1520:                        goto nuke_pkgdb;
1.1       schmonz  1521:        }
                   1522:
1.74      joerg    1523:        if (run_install_script(pkg, "PRE-INSTALL"))
                   1524:                goto nuke_pkgdb;
                   1525:
                   1526:        if (extract_files(pkg))
                   1527:                goto nuke_pkg;
                   1528:
                   1529:        if (run_install_script(pkg, "POST-INSTALL"))
                   1530:                goto nuke_pkgdb;
                   1531:
                   1532:        /* XXX keep +INSTALL_INFO for updates? */
                   1533:        /* XXX keep +PRESERVE for updates? */
                   1534:        if (mark_automatic)
                   1535:                mark_as_automatic_installed(pkg->pkgname, 1);
                   1536:
                   1537:        pkg_register_depends(pkg);
                   1538:
                   1539:        if (Verbose)
                   1540:                printf("Package %s registered in %s\n", pkg->pkgname, pkg->install_logdir);
                   1541:
                   1542:        if (pkg->meta_data.meta_display != NULL)
                   1543:                fputs(pkg->meta_data.meta_display, stdout);
1.71      joerg    1544:
1.74      joerg    1545:        pkg_register_views(pkg);
1.71      joerg    1546:
1.74      joerg    1547:        status = 0;
                   1548:        goto clean_memory;
1.71      joerg    1549:
1.74      joerg    1550: nuke_pkg:
                   1551:        if (!Fake) {
                   1552:                if (pkg->other_version) {
                   1553:                        warnx("Updating of %s to %s failed.",
                   1554:                            pkg->other_version, pkg->pkgname);
                   1555:                        warnx("Remember to run pkg_admin rebuild-tree after fixing this.");
                   1556:                }
1.86      joerg    1557:                delete_package(FALSE, &pkg->plist, FALSE, Destdir);
1.1       schmonz  1558:        }
1.74      joerg    1559:
                   1560: nuke_pkgdb:
                   1561:        if (!Fake) {
                   1562:                if (recursive_remove(pkg->install_logdir, 1))
                   1563:                        warn("Couldn't remove %s", pkg->install_logdir);
1.93      joerg    1564:                free(pkg->install_logdir_real);
1.74      joerg    1565:                free(pkg->install_logdir);
                   1566:                free(pkg->logdir);
1.93      joerg    1567:                pkg->install_logdir_real = NULL;
1.74      joerg    1568:                pkg->install_logdir = NULL;
                   1569:                pkg->logdir = NULL;
                   1570:        }
                   1571:
                   1572: clean_memory:
                   1573:        if (pkg->logdir != NULL && NoRecord && !Fake) {
                   1574:                if (recursive_remove(pkg->install_logdir, 1))
                   1575:                        warn("Couldn't remove %s", pkg->install_logdir);
                   1576:        }
                   1577:        free(pkg->install_prefix);
1.93      joerg    1578:        free(pkg->install_logdir_real);
1.74      joerg    1579:        free(pkg->install_logdir);
                   1580:        free(pkg->logdir);
                   1581:        free_buildinfo(pkg);
                   1582:        free_plist(&pkg->plist);
                   1583:        free_meta_data(pkg);
1.84      joerg    1584:        if (pkg->archive)
                   1585:                archive_read_finish(pkg->archive);
1.74      joerg    1586:        free(pkg->other_version);
                   1587:        free(pkg->pkgname);
                   1588: clean_find_archive:
                   1589:        free(pkg);
                   1590:        return status;
1.1       schmonz  1591: }
                   1592:
                   1593: int
                   1594: pkg_perform(lpkg_head_t *pkgs)
                   1595: {
1.81      joerg    1596:        int     errors = 0;
1.1       schmonz  1597:        lpkg_t *lpp;
                   1598:
1.51      joerg    1599:        while ((lpp = TAILQ_FIRST(pkgs)) != NULL) {
1.81      joerg    1600:                if (pkg_do(lpp->lp_name, Automatic, 1))
1.74      joerg    1601:                        ++errors;
1.51      joerg    1602:                TAILQ_REMOVE(pkgs, lpp, lp_link);
                   1603:                free_lpkg(lpp);
1.1       schmonz  1604:        }
1.74      joerg    1605:
                   1606:        return errors;
1.1       schmonz  1607: }

CVSweb <webmaster@jp.NetBSD.org>