Updated patch:
[PATCH 4/8] Use libarchive helper functions in explodeRPM()
Simplify the archive extraction loop in explodeRPM() by using the
unpack.c helper functions. Add a new parameter to explodeRPM, the
destination to unpack the archive to. This was previously handled
by dlabelUnpackRPMDir() directly, but it made more sense to me to
move it in to the libarchive unpack helper.
---
loader/driverdisk.c | 27 +-----------
loader/rpmextract.c | 110 ++++----------------------------------------------
loader/rpmextract.h | 3 +-
loader/unpack.c | 15 ++++++-
loader/unpack.h | 4 +-
5 files changed, 29 insertions(+), 130 deletions(-)
diff --git a/loader/driverdisk.c b/loader/driverdisk.c
index 2688c82..b689cc0 100644
--- a/loader/driverdisk.c
+++ b/loader/driverdisk.c
@@ -91,7 +91,8 @@ int dlabelFilter(const char* name, const struct stat *fstat, void *userptr)
logMessage(DEBUGLVL, "Unpacking %s", name);
/* we want firmware files */
- if (!strncmp("lib/firmware/", name, 13)) return 0;
+ if (strstr(name, "lib/firmware/") == NULL)
+ return 0;
if (l<3)
return 1;
@@ -145,24 +146,9 @@ int globErrFunc(const char *epath, int eerrno)
int dlabelUnpackRPMDir(char* rpmdir, char* destination, char *kernelver)
{
- char *oldcwd;
char *globpattern;
int rc = 0;
- /* get current working directory */
- oldcwd = getcwd(NULL, 0);
- if (!oldcwd) {
- logMessage(ERROR, "getcwd() failed: %m");
- return 1;
- }
-
- /* set the cwd to destination */
- if (chdir(destination)) {
- logMessage(ERROR, "We weren't able to CWD to \"%s\": %m", destination);
- free(oldcwd);
- return 1;
- }
-
checked_asprintf(&globpattern, "%s/*.rpm", rpmdir);
glob_t globres;
char** globitem;
@@ -170,7 +156,7 @@ int dlabelUnpackRPMDir(char* rpmdir, char* destination, char *kernelver)
/* iterate over all rpm files */
globitem = globres.gl_pathv;
while (globres.gl_pathc>0 && globitem != NULL && *globitem != NULL) {
- explodeRPM(*globitem, dlabelFilter, dlabelProvides, NULL, kernelver);
+ explodeRPM(*globitem, dlabelFilter, dlabelProvides, NULL, kernelver, destination);
globitem++;
}
globfree(&globres);
@@ -178,13 +164,6 @@ int dlabelUnpackRPMDir(char* rpmdir, char* destination, char *kernelver)
}
free(globpattern);
- /* restore CWD */
- if (chdir(oldcwd)) {
- logMessage(WARNING, "We weren't able to restore CWD to \"%s\": %m", oldcwd);
- }
-
- /* cleanup */
- free(oldcwd);
return rc;
}
diff --git a/loader/rpmextract.c b/loader/rpmextract.c
index de803b8..97e0c7b 100644
--- a/loader/rpmextract.c
+++ b/loader/rpmextract.c
@@ -38,6 +38,7 @@
#include "loader.h"
#include "rpmextract.h"
+#include "unpack.h"
#include "../pyanaconda/isys/log.h"
@@ -93,7 +94,8 @@ int explodeRPM(const char *source,
filterfunc filter,
dependencyfunc provides,
dependencyfunc deps,
- void* userptr)
+ void* userptr,
+ char *destination)
{
char buffer[BUFFERSIZE+1]; /* make space for trailing \0 */
FD_t fdi;
@@ -102,7 +104,6 @@ int explodeRPM(const char *source,
rpmRC rc;
FD_t gzdi;
struct archive *cpio;
- struct archive_entry *cpio_entry;
struct cpio_mydata cpio_mydata;
rpmts ts;
@@ -235,17 +236,15 @@ int explodeRPM(const char *source,
return EXIT_FAILURE;
}
+ cpio_mydata.gzdi = gzdi;
+ cpio_mydata.buffer = buffer;
+
/* initialize cpio decompressor */
- cpio = archive_read_new();
- if (cpio==NULL) {
+ if (unpack_init(&cpio) != ARCHIVE_OK) {
Fclose(gzdi);
return -1;
}
- cpio_mydata.gzdi = gzdi;
- cpio_mydata.buffer = buffer;
- archive_read_support_compression_all(cpio);
- archive_read_support_format_all(cpio);
rc = archive_read_open(cpio, &cpio_mydata, NULL, rpm_myread, rpm_myclose);
/* check the status of archive_open */
@@ -254,99 +253,8 @@ int explodeRPM(const char *source,
return -1;
}
- /* read all files in cpio archive */
- while ((rc = archive_read_next_header(cpio, &cpio_entry)) == ARCHIVE_OK){
- const struct stat *fstat;
- int64_t fsize;
- const char* filename;
- int needskip = 1; /* do we need to read the data to get to the next header? */
- int offset = 0;
- int towrite = 0;
-
- filename = archive_entry_pathname(cpio_entry);
- fstat = archive_entry_stat(cpio_entry);
- fsize = archive_entry_size(cpio_entry);
-
- /* Strip leading slashes */
- while (filename[offset] == '/')
- offset+=1;
-
- /* Strip leading ./ */
- while (filename[offset] == '.' && filename[offset+1] == '/')
- offset+=2;
-
- /* Other file type - we do not care except special cases */
- if (!S_ISREG(fstat->st_mode))
- towrite = 1;
- else
- towrite = 2;
-
- if (filter && filter(filename+offset, fstat, userptr)) {
- /* filter this file */
- towrite = 0;
- }
-
- /* Create directories */
- char* dirname = strdup(filename+offset);
-
- /* If the dup fails, let's hope the dirs already exist */
- if (dirname){
- char* dirptr = dirname;
- while (dirptr && *dirptr) {
- dirptr = strchr(dirptr, '/');
- if (dirptr) {
- *dirptr = 0;
- mkdir(dirname, 0700);
- *dirptr = '/';
- dirptr++;
- }
- }
- free(dirname);
- }
-
- /* Regular file */
- if (towrite>=2) {
- FILE *fdout = fopen(filename+offset, "w");
-
- if (fdout==NULL){
- rc = 33;
- break;
- }
-
- rc = archive_read_data_into_fd(cpio, fileno(fdout));
- if (rc!=ARCHIVE_OK) {
- /* XXX We didn't get the file.. well.. */
- needskip = 0;
- } else {
- needskip = 0;
- }
-
- fclose(fdout);
- }
-
- /* symlink, we assume that the path contained in symlink
- * is shorter than BUFFERSIZE */
- while (towrite && S_ISLNK(fstat->st_mode)) {
- char symlinkbuffer[BUFFERSIZE-1];
-
- needskip = 0;
- if ((rc = archive_read_data(cpio, symlinkbuffer, fsize))!=ARCHIVE_OK) {
- /* XXX We didn't get the file.. well.. */
- break;
- }
-
- if (symlink(buffer, filename+offset)) {
- logMessage(ERROR, "Failed to create symlink %s -> %s", filename+offset, buffer);
- }
-
- break;
- }
-
- if(needskip)
- archive_read_data_skip(cpio);
- }
-
- rc = archive_read_finish(cpio); /* Also closes the RPM stream using callback */
+ /* read all files in cpio archive and close */
+ rc = unpack_members_and_finish(cpio, destination, filter, userptr);
return rc != ARCHIVE_OK;
}
diff --git a/loader/rpmextract.h b/loader/rpmextract.h
index 20a5cc8..976047c 100644
--- a/loader/rpmextract.h
+++ b/loader/rpmextract.h
@@ -38,7 +38,8 @@ int explodeRPM(const char* file,
filterfunc filter,
dependencyfunc provides,
dependencyfunc deps,
- void* userptr);
+ void* userptr,
+ char *destination);
#endif
diff --git a/loader/unpack.c b/loader/unpack.c
index f3fa205..50c2ccf 100644
--- a/loader/unpack.c
+++ b/loader/unpack.c
@@ -26,6 +26,8 @@
#include <archive_entry.h>
#include <glib.h>
+#include "rpmextract.h"
+
#include "../pyanaconda/isys/log.h"
/*
@@ -55,7 +57,8 @@ int unpack_init(struct archive **a) {
* directory. If dest is not NULL and does not exist as a directory,
* create it first. Return ARCHIVE_OK on success, ARCHIVE_* otherwise.
*/
-int unpack_members_and_finish(struct archive *a, char *dest) {
+int unpack_members_and_finish(struct archive *a, char *dest,
+ filterfunc filter, void* userptr) {
int restore = 0;
char prevcwd[PATH_MAX];
struct archive_entry *e = NULL;
@@ -83,9 +86,15 @@ int unpack_members_and_finish(struct archive *a, char *dest) {
}
while (archive_read_next_header(a, &e) == ARCHIVE_OK) {
+ const char *pathname = archive_entry_pathname(e);
+ const struct stat *fstat = archive_entry_stat(e);
+
+ if (filter && filter(pathname, fstat, userptr))
+ continue;
+
if (archive_read_extract(a, e, 0) != ARCHIVE_OK) {
logMessage(ERROR, "error unpacking %s (%s:%d): %s",
- archive_entry_pathname(e), __func__, __LINE__,
+ pathname, __func__, __LINE__,
archive_error_string(a));
return ARCHIVE_FATAL;
}
@@ -138,5 +147,5 @@ int unpack_archive_file(char *filename, char *dest) {
return rc;
}
- return unpack_members_and_finish(a, dest);
+ return unpack_members_and_finish(a, dest, NULL, NULL);
}
diff --git a/loader/unpack.h b/loader/unpack.h
index 0ce1fac..6e6d130 100644
--- a/loader/unpack.h
+++ b/loader/unpack.h
@@ -23,9 +23,11 @@
#define UNPACK_H
#include <archive.h>
+#include "rpmextract.h"
int unpack_init(struct archive **);
-int unpack_members_and_finish(struct archive *, char *);
+int unpack_members_and_finish(struct archive *, char *,
+ filterfunc, void *);
int unpack_archive_file(char *, char *);
#endif
--
1.7.3.2
_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list