Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Allow pkg add to read from a pipe or a non-regular file -- so now, all of the following work:
Matthew Seaman committed 12 years ago
commit de0ce87e266698a6dc622e214a0dfc3ce5faf845
parent 740aca8
4 files changed +109 -29
modified libpkg/pkg.c
@@ -30,6 +30,8 @@
#include <archive.h>
#include <archive_entry.h>
#include <assert.h>
+
#include <errno.h>
+
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>

@@ -1069,16 +1071,18 @@ int
pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae,
		const char *path, struct pkg_manifest_key *keys, int flags)
{
-
	struct pkg *pkg;
-
	pkg_error_t retcode = EPKG_OK;
-
	int ret;
-
	const char *fpath;
-
	bool manifest = false;
-
	const void *buf;
-
	size_t size;
-
	off_t offset = 0;
-
	struct sbuf **sbuf;
-
	int i, r;
+
	struct pkg	 *pkg;
+
	pkg_error_t	  retcode = EPKG_OK;
+
	int		  ret;
+
	const char	 *fpath;
+
	bool		  manifest = false;
+
	const void	 *buf;
+
	size_t		  size;
+
	off_t		  offset = 0;
+
	struct sbuf	**sbuf;
+
	int		  i, r, fd = -1;
+
	bool		  read_from_stdin = 0;
+
	struct stat	  sb;

	struct {
		const char *name;
@@ -1094,9 +1098,51 @@ pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae,
	archive_read_support_filter_all(*a);
	archive_read_support_format_tar(*a);

-
	if (archive_read_open_filename(*a, path, 4096) != ARCHIVE_OK) {
-
		pkg_emit_error("archive_read_open_filename(%s): %s", path,
-
				   archive_error_string(*a));
+
	/* archive_read_open_filename() treats a path of NULL as
+
	 * meaning "read from stdin," but we want this behaviour if
+
	 * path is exactly "-". In the unlikely event of wanting to
+
	 * read an on-disk file called "-", just say "./-" or some
+
	 * other leading path. */
+

+
	read_from_stdin = (strncmp(path, "-", 2) == 0);
+

+
	if (read_from_stdin) {
+
		fd = STDIN_FILENO;
+
	} else {
+
		fd = open(path, O_RDONLY);
+
		if (fd == -1) {
+
			pkg_emit_error("open(%s) failed: %s", path,
+
				       strerror(errno));
+
			retcode = EPKG_FATAL;
+
			goto cleanup;
+
		}
+
	}
+

+
	if (fstat(fd, &sb) == -1) {
+
		pkg_emit_error("fstat() %s: %s", path, strerror(errno));
+
		retcode = EPKG_FATAL;
+
		goto cleanup;
+
	}
+

+
	/* Is this a file type we can't read a package from?  S_ISLNK
+
	   shouldn't happen -- we should be resolving sym-links during
+
	   the call to open() -- so assume S_ISLNK means something
+
	   went wrong. S_ISBLK shouldn't happen on modern FreeBSD, so
+
	   we'll ignore it.  S_ISCHR would result from opening
+
	   /dev/stdin or /dev/fd/0 which should be fine.  Ditto
+
	   S_ISFIFO.  Not sure about S_ISSOCK or S_ISWHT (?) */
+

+
	if (S_ISDIR(sb.st_mode) || S_ISLNK(sb.st_mode)) {
+
		pkg_emit_error("can't read %s -- is a directory or broken link",
+
			       path);
+
		retcode = EPKG_FATAL;
+
		goto cleanup;
+
	}
+

+
	ret = archive_read_open_fd(*a, fd, 4096);
+
	if (ret != ARCHIVE_OK) {
+
		pkg_emit_error("archive_read_open_fd() %s: %s", path,
+
			       archive_error_string(*a));
		retcode = EPKG_FATAL;
		goto cleanup;
	}
@@ -1109,7 +1155,11 @@ pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae,
		pkg_reset(*pkg_p, PKG_FILE);

	pkg = *pkg_p;
-
	pkg->type = PKG_FILE;
+

+
	if (S_ISREG(sb.st_mode) && !read_from_stdin) 
+
		pkg->type = PKG_FILE;
+
	else
+
		pkg->type = PKG_STREAM;

	while ((ret = archive_read_next_header(*a, ae)) == ARCHIVE_OK) {
		fpath = archive_entry_pathname(*ae);
@@ -1174,8 +1224,11 @@ pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae,
		retcode = EPKG_FATAL;
	}

-
	if (ret == ARCHIVE_EOF)
+
	if (ret == ARCHIVE_EOF) {
+
		if (!read_from_stdin) 
+
			close(fd);
		retcode = EPKG_END;
+
	}

	if (!manifest) {
		retcode = EPKG_FATAL;
@@ -1188,6 +1241,8 @@ pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae,
			archive_read_free(*a);
		*a = NULL;
		*ae = NULL;
+
		if (!read_from_stdin && fd >= 0) 
+
			close(fd);
	}

	return (retcode);
modified libpkg/pkg.h.in
@@ -178,18 +178,23 @@ typedef enum {
	 */
	PKG_FILE = (1U << 0),
	/**
+
         * The pkg refers to data read from a non-regular file
+
         * (device, pipeline, unix dmain socket etc.)
+
	 */
+
	PKG_STREAM = (1U << 1),
+
	/**
	 * The pkg refers to a package available on the remote repository.
	 * @todo Document which attributes are available.
	 */
-
	PKG_REMOTE = (1U << 1),
+
	PKG_REMOTE = (1U << 2),
	/**
	 * The pkg refers to a localy installed package.
	 */
-
	PKG_INSTALLED = (1U << 2),
+
	PKG_INSTALLED = (1U << 3),
	/**
	 * The pkg refers to a local file old archive.
	 */
-
	PKG_OLD_FILE = (1U << 3),
+
	PKG_OLD_FILE = (1U << 4),
} pkg_t;

/**
modified libpkg/pkg_add.c
@@ -237,16 +237,29 @@ pkg_add(struct pkgdb *db, const char *path, unsigned flags, struct pkg_manifest_
	}

	/*
-
	 * Check for dependencies
+
	 * Check for dependencies by searching the same directory as
+
	 * the package archive we're reading.  Of course, if we're
+
	 * reading from a file descriptor or a unix domain socket or
+
	 * somesuch, there's no valid directory to search.
	 */

-
	basedir = dirname(path);
-
	if ((ext = strrchr(path, '.')) == NULL) {
-
		ext = "";
+
	if (pkg_type(pkg) == PKG_FILE) {
+
		basedir = dirname(path);
+
		if ((ext = strrchr(path, '.')) == NULL) {
+
			pkg_emit_error("%s has no extension", path);
+
			retcode = EPKG_FATAL;
+
			goto cleanup;
+
		}
+
	} else {
+
		basedir = NULL;
+
		ext = NULL;
	}

	while (pkg_deps(pkg, &dep) == EPKG_OK) {
-
		if (pkg_is_installed(db, pkg_dep_origin(dep)) != EPKG_OK) {
+
		if (pkg_is_installed(db, pkg_dep_origin(dep)) == EPKG_OK)
+
			continue;
+

+
		if (basedir != NULL) {
			const char *dep_name = pkg_dep_name(dep);
			const char *dep_ver = pkg_dep_version(dep);

@@ -260,11 +273,11 @@ pkg_add(struct pkgdb *db, const char *path, unsigned flags, struct pkg_manifest_
					retcode = EPKG_FATAL;
					goto cleanup;
				}
-
			} else {
-
				retcode = EPKG_FATAL;
-
				pkg_emit_missing_dep(pkg, dep);
-
				goto cleanup;
			}
+
		} else {
+
			retcode = EPKG_FATAL;
+
			pkg_emit_missing_dep(pkg, dep);
+
			goto cleanup;
		}
	}

modified pkg/add.c
@@ -124,8 +124,15 @@ exec_add(int argc, char **argv)
			file = path;
		} else {
			file = argv[i];
-
			if (access(file, F_OK) != 0) {
-
				warn("%s",file);
+

+
			/* Special case: treat a filename of "-" as
+
			   meaning 'read from stdin.'  It doesn't make
+
			   sense to have a filename of "-" more than
+
			   once per command line, but we aren't
+
			   testing for that at the moment */
+

+
			if (strcmp(file, "-") != 0 && access(file, F_OK) != 0) {
+
				warn("%s", file);
				if (errno == ENOENT)
					warnx("Did you mean 'pkg install %s'?", file);
				sbuf_cat(failedpkgs, argv[i]);