PERFORCE change 179000 for review
Garrett Cooper
gcooper at FreeBSD.org
Mon May 31 03:44:57 UTC 2010
http://p4web.freebsd.org/@@179000?ac=10
Change 179000 by gcooper at gcooper-bayonetta on 2010/05/31 03:44:51
Make sure that unpack_to_buffer never lets data hit the disk by using
archive_read_data(3).
Affected files ...
.. //depot/projects/soc2007/gcooper-pkg_install-enhancements-simplified/lib/libpkg/file.c#19 edit
Differences ...
==== //depot/projects/soc2007/gcooper-pkg_install-enhancements-simplified/lib/libpkg/file.c#19 (text+ko) ====
@@ -335,10 +335,8 @@
ARCHIVE_EXTRACT_FFLAGS|ARCHIVE_EXTRACT_XATTR)
/*
- * Unpack a single file, denoted by file, to a buffer; this call uses
- * unpack_to_fd to first open the file, and once that has been completed
- * it opens the file and proceeds to read it into the buffer which will
- * need to be freed by the user at a later date.
+ * Unpack a single file, denoted by file, to a buffer. It proceeds to read it
+ * into the buffer which will need to be freed by the user at a later date.
*
* Returns an address to a buffer with the contents of *file if successful, or
* returns NULL on failure.
@@ -347,39 +345,98 @@
unpack_to_buffer(const char *pkg, const char *file)
{
- struct stat sb;
+ struct archive *archive;
+ struct archive_entry *archive_entry;
+ Boolean found_match = FALSE;
+
+ int64_t buf_size;
+
char *buf = NULL;
- int fd;
- int serrno;
+ const char *entry_pathname = NULL;
+ const char *error = NULL;
+ int archive_fd = -1;
+ int r;
+
+ errno = 0;
+
+ if ((archive = archive_read_new()) != NULL) {
+
+ if (archive_read_support_compression_all(archive)
+ != ARCHIVE_OK ||
+ archive_read_support_format_tar(archive) != ARCHIVE_OK)
+ error = archive_error_string(archive);
+ /*
+ * Avoid potential race conditions with
+ * archive_read_open_filename(3), by opening the file
+ * beforehand.
+ */
+ else if (pkg == NULL)
+ archive_fd = fileno(stdin);
+ else
+ archive_fd = open(pkg, O_RDONLY);
+
+ }
+
+ /* The initial open failed or archive(3) failed to open the file. */
+ if (archive_fd == -1 || archive == NULL) ;
+ /* archive(3) failed to open the file descriptor. */
+ else if (archive_read_open_fd(archive, archive_fd,
+ ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK)
+ error = archive_error_string(archive);
+ else
+ while (error == NULL && found_match == FALSE &&
+ (r = archive_read_next_header(archive, &archive_entry)) ==
+ ARCHIVE_OK) {
+
+ entry_pathname = archive_entry_pathname(archive_entry);
+
+ if (strncmp(file, entry_pathname, PATH_MAX) == 0) {
+
+ /*
+ * Regardless of whether or not extract passes,
+ * we found our target file so let's exit
+ * quickly because the underlying issue is most
+ * likely unrecoverable.
+ */
+ found_match = TRUE;
+
+ buf_size = archive_entry_size(archive_entry);
+
+ if (buf_size == 0)
+ errno = EINVAL;
+ else {
+
+ buf = malloc(sizeof(char)*buf_size);
+
+ if (buf == NULL)
+ error = strerror(errno);
+ else {
- if ((fd = unpack_to_fd(pkg, file)) != -1) {
+ r = archive_read_data(archive,
+ buf, buf_size);
- if (fstat(fd, &sb) == 0) {
+ if (r != ARCHIVE_OK)
+ error = archive_error_string(archive);
- /*
- * User either passed in a non-NULL value or we need
- * to malloc on the fly and let the user deal with it
- * later.
- */
- buf = malloc(sb.st_size);
- if (buf != NULL) {
+ }
- if (read(fd, buf, sb.st_size) != sb.st_size) {
- free(buf);
- buf = NULL;
}
}
}
- }
+
+#if 0
+ /*
+ * This should be stored in a global buffer or something similar that's
+ * retrievable via pkg_error or something of that flavor.
+ */
+ if (errno != 0)
+ error = strerror(errno);
+#endif
- if (0 <= fd) {
- serrno = errno;
- close(fd);
- if (serrno != 0)
- errno = serrno;
- }
+ if (archive != NULL)
+ archive_read_finish(archive);
return (buf);
@@ -402,7 +459,8 @@
Boolean extract_whole_archive = FALSE;
const char *entry_pathname = NULL;
const char *error = NULL;
- int archive_fd = -1, r;
+ int archive_fd = -1;
+ int r;
errno = 0;
@@ -490,9 +548,8 @@
const char *entry_pathname = NULL;
const char *error = NULL;
+ int archive_fd = -1, r;
int fd = -1;
- /* int fd = -1; */
- int archive_fd = -1, r;
errno = 0;
More information about the p4-projects
mailing list