From d71d2b9e1daf8bfc7c8c1dc027d2a6f19214c0f0 Mon Sep 17 00:00:00 2001 From: joerg Date: Wed, 23 Apr 2008 16:58:07 +0000 Subject: pkg_install-20080423: Make the linkresolver code more robust. --- pkgtools/pkg_install/files/create/build.c | 119 ++++++++++++++++++------------ pkgtools/pkg_install/files/lib/version.h | 4 +- 2 files changed, 75 insertions(+), 48 deletions(-) (limited to 'pkgtools/pkg_install') diff --git a/pkgtools/pkg_install/files/create/build.c b/pkgtools/pkg_install/files/create/build.c index 6222a7226d2..4cc1a405e21 100644 --- a/pkgtools/pkg_install/files/create/build.c +++ b/pkgtools/pkg_install/files/create/build.c @@ -1,4 +1,4 @@ -/* $NetBSD: build.c,v 1.7 2008/04/22 14:27:51 joerg Exp $ */ +/* $NetBSD: build.c,v 1.8 2008/04/23 16:58:07 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -11,7 +11,7 @@ #if 0 static const char *rcsid = "from FreeBSD Id: perform.c,v 1.38 1997/10/13 15:03:51 jkh Exp"; #else -__RCSID("$NetBSD: build.c,v 1.7 2008/04/22 14:27:51 joerg Exp $"); +__RCSID("$NetBSD: build.c,v 1.8 2008/04/23 16:58:07 joerg Exp $"); #endif #endif @@ -121,17 +121,65 @@ write_meta_file(struct memory_file *file, struct archive *archive) archive_entry_free(entry); } +static void +write_entry(struct archive *archive, struct archive_entry *entry) +{ + char buf[16384]; + const char *name; + int fd; + off_t len; + ssize_t buf_len; + + if (archive_entry_pathname(entry) == NULL) { + warnx("entry with NULL path"); + return; + } + + if (archive_write_header(archive, entry)) { + errx(2, "cannot write to archive: %s", + archive_error_string(archive)); + } + + /* Only regular files can have data. */ + if (archive_entry_filetype(entry) != AE_IFREG || + archive_entry_size(entry) == 0) { + archive_entry_free(entry); + return; + } + + name = archive_entry_pathname(entry); + + if ((fd = open(name, O_RDONLY)) == -1) + err(2, "cannot open data file %s", name); + + len = archive_entry_size(entry); + + while (len > 0) { + buf_len = (len > sizeof(buf)) ? sizeof(buf) : (ssize_t)len; + + if ((buf_len = read(fd, buf, buf_len)) == 0) + break; + else if (buf_len < 0) + err(2, "cannot read from %s", name); + + archive_write_data(archive, buf, (size_t)buf_len); + len -= buf_len; + } + + close(fd); + + archive_entry_free(entry); +} + static void write_normal_file(const char *name, struct archive *archive, struct archive_entry_linkresolver *resolver, const char *owner, const char *group) { char buf[16384]; - off_t len; ssize_t buf_len; - struct archive_entry *entry, *linked_entry; + struct archive_entry *entry, *sparse_entry; struct stat st; - int fd; if (lstat(name, &st) == -1) err(2, "lstat failed for file %s", name); @@ -162,51 +210,20 @@ write_normal_file(const char *name, struct archive *archive, archive_entry_set_gname(entry, group_from_gid(st.st_gid, 1)); } - archive_entry_linkify(resolver, &entry, &linked_entry); - - switch (st.st_mode & S_IFMT) { - case S_IFLNK: + if ((st.st_mode & S_IFMT) == S_IFLNK) { buf_len = readlink(name, buf, sizeof buf); if (buf_len < 0) err(2, "cannot read symlink %s", name); buf[buf_len] = '\0'; archive_entry_set_symlink(entry, buf); - - if (archive_write_header(archive, entry)) - errx(2, "cannot write to archive: %s", archive_error_string(archive)); - break; - - case S_IFREG: - if (archive_write_header(archive, entry)) - errx(2, "cannot write to archive: %s", archive_error_string(archive)); - - if (archive_entry_size(entry) == 0) - break; - - if ((fd = open(name, O_RDONLY)) == -1) - err(2, "cannot open data file %s", name); - - len = archive_entry_size(entry); - - while (len > 0) { - if (len > sizeof(buf)) - buf_len = sizeof(buf); - else - buf_len = (ssize_t)len; - if ((buf_len = read(fd, buf, buf_len)) <= 0) - break; - archive_write_data(archive, buf, (size_t)buf_len); - len -= buf_len; - } - - close(fd); - break; - - default: - errx(2, "PLIST entry neither symlink nor directory: %s", name); } - archive_entry_free(entry); + archive_entry_linkify(resolver, &entry, &sparse_entry); + + if (entry != NULL) + write_entry(archive, entry); + if (sparse_entry != NULL) + write_entry(archive, sparse_entry); } static void @@ -216,6 +233,7 @@ make_dist(const char *pkg, const char *suffix, const package_t *plist) const char *owner, *group; const plist_t *p; struct archive *archive; + struct archive_entry *entry, *sparse_entry; struct archive_entry_linkresolver *resolver; char *initial_cwd; @@ -224,7 +242,7 @@ make_dist(const char *pkg, const char *suffix, const package_t *plist) if ((resolver = archive_entry_linkresolver_new()) == NULL) errx(2, "cannot create link resolver"); archive_entry_linkresolver_set_strategy(resolver, - ARCHIVE_FORMAT_TAR_USTAR); + archive_format(archive)); if (strcmp(suffix, "tbz") == 0 || strcmp(suffix, "tar.bz2") == 0) archive_write_set_compression_bzip2(archive); @@ -294,14 +312,23 @@ make_dist(const char *pkg, const char *suffix, const package_t *plist) group = DefaultGroup; } } - chdir(initial_cwd); - free(initial_cwd); + + entry = NULL; + archive_entry_linkify(resolver, &entry, &sparse_entry); + while (entry != NULL) { + write_entry(archive, entry); + entry = NULL; + archive_entry_linkify(resolver, &entry, &sparse_entry); + } archive_entry_linkresolver_free(resolver); if (archive_write_close(archive)) errx(2, "cannot finish archive: %s", archive_error_string(archive)); archive_write_finish(archive); + + chdir(initial_cwd); + free(initial_cwd); } static struct memory_file * diff --git a/pkgtools/pkg_install/files/lib/version.h b/pkgtools/pkg_install/files/lib/version.h index 185c49b9884..38ed5813f38 100644 --- a/pkgtools/pkg_install/files/lib/version.h +++ b/pkgtools/pkg_install/files/lib/version.h @@ -1,4 +1,4 @@ -/* $NetBSD: version.h,v 1.101 2008/04/22 13:47:08 joerg Exp $ */ +/* $NetBSD: version.h,v 1.102 2008/04/23 16:58:07 joerg Exp $ */ /* * Copyright (c) 2001 Thomas Klausner. All rights reserved. @@ -33,6 +33,6 @@ #ifndef _INST_LIB_VERSION_H_ #define _INST_LIB_VERSION_H_ -#define PKGTOOLS_VERSION "20080422" +#define PKGTOOLS_VERSION "20080423" #endif /* _INST_LIB_VERSION_H_ */ -- cgit v1.2.3