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

Annotation of pkgsrc/pkgtools/pkg_install/files/create/build.c, Revision 1.2

1.2     ! joerg       1: /*     $NetBSD: build.c,v 1.1 2007/08/03 13:15:59 joerg Exp $  */
1.1       joerg       2:
                      3: #if HAVE_CONFIG_H
                      4: #include "config.h"
                      5: #endif
                      6: #include <nbcompat.h>
                      7: #if HAVE_SYS_CDEFS_H
                      8: #include <sys/cdefs.h>
                      9: #endif
                     10: #ifndef lint
                     11: #if 0
                     12: static const char *rcsid = "from FreeBSD Id: perform.c,v 1.38 1997/10/13 15:03:51 jkh Exp";
                     13: #else
1.2     ! joerg      14: __RCSID("$NetBSD: build.c,v 1.1 2007/08/03 13:15:59 joerg Exp $");
1.1       joerg      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 create module.
                     35:  *
                     36:  */
                     37:
                     38: #include "lib.h"
                     39: #include "create.h"
                     40:
                     41: #if HAVE_ERR_H
                     42: #include <err.h>
                     43: #endif
1.2     ! joerg      44: #if HAVE_GRP_H
        !            45: #include <grp.h>
        !            46: #endif
        !            47: #if HAVE_PWD_H
        !            48: #include <pwd.h>
1.1       joerg      49: #endif
                     50: #if HAVE_UNISTD_H
                     51: #include <unistd.h>
                     52: #endif
                     53:
                     54: #include <archive.h>
                     55: #include <archive_entry.h>
                     56:
                     57: static struct memory_file *contents_file;
                     58: static struct memory_file *comment_file;
                     59: static struct memory_file *desc_file;
                     60: static struct memory_file *install_file;
                     61: static struct memory_file *deinstall_file;
                     62: static struct memory_file *display_file;
                     63: static struct memory_file *build_version_file;
                     64: static struct memory_file *build_info_file;
                     65: static struct memory_file *size_pkg_file;
                     66: static struct memory_file *size_all_file;
                     67: static struct memory_file *preserve_file;
                     68: static struct memory_file *views_file;
                     69:
                     70: static void
                     71: write_meta_file(struct memory_file *file, struct archive *archive)
                     72: {
                     73:        struct archive_entry *entry;
                     74:
                     75:        entry = archive_entry_new();
                     76:        archive_entry_set_pathname(entry, file->name);
                     77:        archive_entry_copy_stat(entry, &file->st);
                     78:
                     79:        archive_entry_set_uname(entry, file->owner);
                     80:        archive_entry_set_gname(entry, file->group);
                     81:
                     82:        if (archive_write_header(archive, entry))
                     83:                errx(2, "cannot write to archive: %s", archive_error_string(archive));
                     84:
                     85:        archive_write_data(archive, file->data, file->len);
                     86:
                     87:        archive_entry_free(entry);
                     88: }
                     89:
                     90: LIST_HEAD(hardlink_list, hardlinked_entry);
                     91: struct hardlink_list written_hardlinks;
                     92:
                     93: struct hardlinked_entry {
                     94:        LIST_ENTRY(hardlinked_entry) link;
                     95:        const char *existing_name;
                     96:        nlink_t remaining_links;
                     97:        dev_t existing_device;
                     98:        ino_t existing_ino;
                     99: };
                    100:
                    101: static void
                    102: write_normal_file(const char *name, struct archive *archive, const char *owner, const char *group)
                    103: {
                    104:        char buf[16384];
                    105:        off_t len;
                    106:        ssize_t buf_len;
                    107:        struct hardlinked_entry *older_link;
                    108:        struct archive_entry *entry;
                    109:        struct stat st;
                    110:        int fd;
                    111:
                    112:        if (lstat(name, &st) == -1)
                    113:                err(2, "lstat failed for file %s", name);
                    114:
                    115:        entry = archive_entry_new();
                    116:        archive_entry_set_pathname(entry, name);
                    117:
                    118:        if (!S_ISDIR(st.st_mode) && st.st_nlink > 1) {
                    119:                LIST_FOREACH(older_link, &written_hardlinks, link) {
                    120:                        if (st.st_dev == older_link->existing_device &&
                    121:                            st.st_ino == older_link->existing_ino) {
                    122:                                archive_entry_copy_hardlink(entry,
                    123:                                    older_link->existing_name);
                    124:                                if (archive_write_header(archive, entry)) {
                    125:                                        errx(2, "cannot write to archive: %s",
                    126:                                            archive_error_string(archive));
                    127:                                }
                    128:
                    129:                                if (--older_link->remaining_links > 0)
                    130:                                        return;
                    131:                                LIST_REMOVE(older_link, link);
                    132:                                free(older_link);
                    133:                                return;
                    134:                        }
                    135:                }
                    136:                /* Not yet linked */
                    137:                if ((older_link = malloc(sizeof(*older_link))) == NULL)
                    138:                        err(2, "malloc failed");
                    139:                older_link->existing_name = name;
                    140:                older_link->remaining_links = st.st_nlink - 1;
                    141:                older_link->existing_device = st.st_dev;
                    142:                older_link->existing_ino = st.st_ino;
                    143:                LIST_INSERT_HEAD(&written_hardlinks, older_link, link);
                    144:        }
                    145:
                    146:        archive_entry_copy_stat(entry, &st);
                    147:
                    148:        if (owner != NULL) {
                    149:                uid_t uid;
                    150:
                    151:                archive_entry_set_uname(entry, owner);
                    152:                if (uid_from_user(owner, &uid) == -1)
                    153:                        errx(2, "user %s unknown", owner);
                    154:                archive_entry_set_uid(entry, uid);
                    155:        } else {
                    156:                archive_entry_set_uname(entry, user_from_uid(st.st_uid, 1));
                    157:        }
                    158:
                    159:        if (group != NULL) {
                    160:                gid_t gid;
                    161:
                    162:                archive_entry_set_gname(entry, group);
                    163:                if (gid_from_group(group, &gid) == -1)
                    164:                        errx(2, "group %s unknown", group);
                    165:                archive_entry_set_gid(entry, gid);
                    166:        } else {
                    167:                archive_entry_set_gname(entry, group_from_gid(st.st_gid, 1));
                    168:        }
                    169:
                    170:        switch (st.st_mode & S_IFMT) {
                    171:        case S_IFLNK:
                    172:                buf_len = readlink(name, buf, sizeof buf);
                    173:                if (buf_len < 0)
                    174:                        err(2, "cannot read symlink %s", name);
                    175:                buf[buf_len] = '\0';
                    176:                archive_entry_set_symlink(entry, buf);
                    177:
                    178:                if (archive_write_header(archive, entry))
                    179:                        errx(2, "cannot write to archive: %s", archive_error_string(archive));
                    180:
                    181:                break;
                    182:
                    183:        case S_IFREG:
                    184:                fd = open(name, O_RDONLY);
                    185:                if (fd == -1)
                    186:                        errx(2, "cannot open data file %s: %s", name, archive_error_string(archive));
                    187:
                    188:                len = st.st_size;
                    189:
                    190:                if (archive_write_header(archive, entry))
                    191:                        errx(2, "cannot write to archive: %s", archive_error_string(archive));
                    192:
                    193:                while (len > 0) {
                    194:                        if (len > sizeof(buf))
                    195:                                buf_len = sizeof(buf);
                    196:                        else
                    197:                                buf_len = (ssize_t)len;
                    198:                        if ((buf_len = read(fd, buf, buf_len)) <= 0)
                    199:                                break;
                    200:                        archive_write_data(archive, buf, (size_t)buf_len);
                    201:                        len -= buf_len;
                    202:                }
                    203:
                    204:                close(fd);
                    205:                break;
                    206:
                    207:        default:
                    208:                errx(2, "PLIST entry neither symlink nor directory: %s", name);
                    209:        }
                    210:
                    211:        archive_entry_free(entry);
                    212: }
                    213:
                    214: static void
                    215: make_dist(const char *pkg, const char *suffix, const package_t *plist)
                    216: {
                    217:        char *archive_name;
                    218:        const char *owner, *group;
                    219:        const plist_t *p;
                    220:        struct archive *archive;
                    221:        char *initial_cwd;
                    222:
                    223:        archive = archive_write_new();
                    224:        archive_write_set_format_pax_restricted(archive);
                    225:
                    226:        if (strcmp(suffix, "tbz") == 0 || strcmp(suffix, "tar.bz2") == 0)
                    227:                archive_write_set_compression_bzip2(archive);
                    228:        else if (strcmp(suffix, "tgz") == 0 || strcmp(suffix, "tar.gz") == 0)
                    229:                archive_write_set_compression_gzip(archive);
                    230:        else
                    231:                archive_write_set_compression_none(archive);
                    232:
                    233:        if (asprintf(&archive_name, "%s.%s", pkg, suffix) == -1)
                    234:                err(2, "cannot compute output name");
                    235:
                    236:        if (archive_write_open_file(archive, archive_name))
                    237:                errx(2, "cannot create archive: %s", archive_error_string(archive));
                    238:
                    239:        free(archive_name);
                    240:
                    241:        owner = DefaultOwner;
                    242:        group = DefaultGroup;
                    243:
                    244:        write_meta_file(contents_file, archive);
                    245:        write_meta_file(comment_file, archive);
                    246:        write_meta_file(desc_file, archive);
                    247:
                    248:        if (Install)
                    249:                write_meta_file(install_file, archive);
                    250:        if (DeInstall)
                    251:                write_meta_file(deinstall_file, archive);
                    252:        if (Display)
                    253:                write_meta_file(display_file, archive);
                    254:        if (BuildVersion)
                    255:                write_meta_file(build_version_file, archive);
                    256:        if (BuildInfo)
                    257:                write_meta_file(build_info_file, archive);
                    258:        if (SizePkg)
                    259:                write_meta_file(size_pkg_file, archive);
                    260:        if (SizeAll)
                    261:                write_meta_file(size_all_file, archive);
                    262:        if (Preserve)
                    263:                write_meta_file(preserve_file, archive);
                    264:        if (create_views)
                    265:                write_meta_file(views_file, archive);
                    266:
                    267:        initial_cwd = getcwd(NULL, 0);
                    268:
                    269:        for (p = plist->head; p; p = p->next) {
                    270:                if (p->type == PLIST_FILE) {
                    271:                        write_normal_file(p->name, archive, owner, group);
                    272:                } else if (p->type == PLIST_CWD || p->type == PLIST_SRC) {
                    273:
                    274:                        /* XXX let PLIST_SRC override PLIST_CWD */
                    275:                        if (p->type == PLIST_CWD && p->next != NULL &&
                    276:                            p->next->type == PLIST_SRC) {
                    277:                                continue;
                    278:                        }
                    279:                        chdir(p->name);
                    280:                } else if (p->type == PLIST_IGNORE) {
                    281:                        p = p->next;
                    282:                } else if (p->type == PLIST_CHOWN) {
                    283:                        if (p->name != NULL)
                    284:                                owner = p->name;
                    285:                        else
                    286:                                owner = DefaultOwner;
                    287:                } else if (p->type == PLIST_CHGRP) {
                    288:                        if (p->name != NULL)
                    289:                                group = p->name;
                    290:                        else
                    291:                                group = DefaultGroup;
                    292:                }
                    293:        }
                    294:        chdir(initial_cwd);
                    295:        free(initial_cwd);
                    296:
                    297:        if (archive_write_close(archive))
                    298:                errx(2, "cannot finish archive: %s", archive_error_string(archive));
                    299:        archive_write_finish(archive);
                    300: }
                    301:
                    302: static struct memory_file *
                    303: load_and_add(package_t *plist, const char *input_name,
                    304:     const char *target_name, mode_t perm)
                    305: {
                    306:        struct memory_file *file;
                    307:
                    308:        file = load_memory_file(input_name, target_name, DefaultOwner,
                    309:            DefaultGroup, perm);
                    310:        add_plist(plist, PLIST_IGNORE, NULL);
                    311:        add_plist(plist, PLIST_FILE, target_name);
                    312:
                    313:        return file;
                    314: }
                    315:
                    316: static struct memory_file *
                    317: make_and_add(package_t *plist, const char *target_name,
                    318:     char *content, mode_t perm)
                    319: {
                    320:        struct memory_file *file;
                    321:
                    322:        file = make_memory_file(target_name, content, strlen(content),
                    323:            DefaultOwner, DefaultGroup, perm);
                    324:        add_plist(plist, PLIST_IGNORE, NULL);
                    325:        add_plist(plist, PLIST_FILE, target_name);
                    326:
                    327:        return file;
                    328: }
                    329:
                    330: int
                    331: pkg_build(const char *pkg, const char *full_pkg, const char *suffix,
                    332:     package_t *plist)
                    333: {
                    334:        char *plist_buf;
                    335:        size_t plist_len;
                    336:
                    337:        /* Now put the release specific items in */
                    338:        add_plist(plist, PLIST_CWD, ".");
                    339:        comment_file = make_and_add(plist, COMMENT_FNAME, Comment, 0444);
                    340:        desc_file = make_and_add(plist, DESC_FNAME, Desc, 0444);
                    341:
                    342:        if (Install) {
                    343:                install_file = load_and_add(plist, Install, INSTALL_FNAME,
                    344:                    0555);
                    345:        }
                    346:        if (DeInstall) {
                    347:                deinstall_file = load_and_add(plist, DeInstall,
                    348:                    DEINSTALL_FNAME, 0555);
                    349:        }
                    350:        if (Display) {
                    351:                display_file = load_and_add(plist, Display,
                    352:                    DISPLAY_FNAME, 0444);
                    353:                add_plist(plist, PLIST_DISPLAY, DISPLAY_FNAME);
                    354:        }
                    355:        if (BuildVersion) {
                    356:                build_version_file = load_and_add(plist, BuildVersion,
                    357:                    BUILD_VERSION_FNAME, 0444);
                    358:        }
                    359:        if (BuildInfo) {
                    360:                build_info_file = load_and_add(plist, BuildInfo,
                    361:                    BUILD_INFO_FNAME, 0444);
                    362:        }
                    363:        if (SizePkg) {
                    364:                size_pkg_file = load_and_add(plist, SizePkg,
                    365:                    SIZE_PKG_FNAME, 0444);
                    366:        }
                    367:        if (SizeAll) {
                    368:                size_all_file = load_and_add(plist, SizeAll,
                    369:                    SIZE_ALL_FNAME, 0444);
                    370:        }
                    371:        if (Preserve) {
                    372:                preserve_file = load_and_add(plist, Preserve,
                    373:                    PRESERVE_FNAME, 0444);
                    374:        }
                    375:        if (create_views)
                    376:                views_file = make_and_add(plist, VIEWS_FNAME, "", 0444);
                    377:
                    378:        /* Finally, write out the packing list */
                    379:        stringify_plist(plist, &plist_buf, &plist_len, realprefix);
                    380:        contents_file = make_memory_file(CONTENTS_FNAME, plist_buf, plist_len,
                    381:            DefaultOwner, DefaultGroup, 0644);
                    382:
                    383:        /* And stick it into a tar ball */
                    384:        make_dist(pkg, suffix, plist);
                    385:
                    386:        return TRUE;            /* Success */
                    387: }

CVSweb <webmaster@jp.NetBSD.org>