[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[PATCH 6/7] Add the cpio routine and interface to librpm



- adds the code to unpack RPMs which provide specific Provide:
- adds the code to unpack cpio directly from the RPM
- adds the dependency on librpm
---
 anaconda.spec.in    |    1 +
 loader/Makefile.am  |    6 +-
 loader/cpio.c       |  192 +++++++++++++++++++++++++++++++++++++++++++
 loader/cpio.h       |  116 ++++++++++++++++++++++++++
 loader/rpmextract.c |  227 +++++++++++++++++++++++++++++++++++++++++++++++++++
 loader/rpmextract.h |   47 +++++++++++
 6 files changed, 587 insertions(+), 2 deletions(-)
 create mode 100644 loader/cpio.c
 create mode 100644 loader/cpio.h
 create mode 100644 loader/rpmextract.c
 create mode 100644 loader/rpmextract.h

diff --git a/anaconda.spec.in b/anaconda.spec.in
index 862e306..8344105 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -69,6 +69,7 @@ BuildRequires: pango-devel
 BuildRequires: pykickstart >= %{pykickstartver}
 BuildRequires: python-devel
 BuildRequires: python-urlgrabber
+BuildRequires: rpm-devel
 BuildRequires: rpm-python >= %{rpmpythonver}
 BuildRequires: slang-devel >= %{slangver}
 BuildRequires: xmlto
diff --git a/loader/Makefile.am b/loader/Makefile.am
index e5d1b7f..2d3b39b 100644
--- a/loader/Makefile.am
+++ b/loader/Makefile.am
@@ -45,13 +45,15 @@ loader_CFLAGS      = $(COMMON_CFLAGS) $(GLIB_CFLAGS) $(LIBNM_GLIB_CFLAGS) \
 loader_LDADD       = $(NEWT_LIBS) $(GLIB_LIBS) $(LIBNL_LIBS) \
                      $(LIBNM_GLIB_LIBS) $(CHECKISOMD5_LIBS) \
                      $(LIBCURL_LIBS) \
-                     $(ISCSI_LIBS) $(top_srcdir)/isys/libisys.la
+                     $(ISCSI_LIBS) $(top_srcdir)/isys/libisys.la \
+		     -lrpm -lrpmio
 loader_SOURCES     = loader.c copy.c log.c moduleinfo.c loadermisc.c \
                      modules.c windows.c lang.c kbd.c driverdisk.c \
                      selinux.c mediacheck.c kickstart.c driverselect.c \
                      getparts.c dirbrowser.c fwloader.c ibft.c hardware.c \
                      method.c cdinstall.c hdinstall.c nfsinstall.c \
-                     urlinstall.c net.c urls.c telnet.c telnetd.c
+                     urlinstall.c net.c urls.c telnet.c telnetd.c \
+		     cpio.c rpmextract.c
 
 init_CFLAGS        = $(COMMON_CFLAGS)
 init_SOURCES       = init.c undomounts.c shutdown.c copy.c
diff --git a/loader/cpio.c b/loader/cpio.c
new file mode 100644
index 0000000..36335fc
--- /dev/null
+++ b/loader/cpio.c
@@ -0,0 +1,192 @@
+/** \ingroup payload
+ * \file lib/cpio.c
+ *  Handle cpio payloads within rpm packages.
+ *
+ * \warning FIXME: We don't translate between cpio and system mode bits! These
+ * should both be the same, but really odd things are going to happen if
+ * that's not true!
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <rpm/rpmio.h>
+#include <rpm/rpmlog.h>
+#include <rpm/header.h>
+
+#include "cpio.h"
+
+
+const char * headerGetString(Header h, rpmTag tag)
+{
+    const char *res = NULL;
+    struct rpmtd_s td;
+
+    if (headerGet(h, tag, &td, HEADERGET_MINMEM)) {
+        if (rpmtdCount(&td) == 1) {
+            res = rpmtdGetString(&td);
+        }
+        rpmtdFreeData(&td);
+    }
+    return res;
+}
+
+/**
+ * Convert string to unsigned integer (with buffer size check).
+ * @param str           input string
+ * @retval endptr       address of 1st character not processed
+ * @param base          numerical conversion base
+ * @param num           max no. of bytes to read
+ * @return              converted integer
+ */
+static unsigned long strntoul(const char *str,char **endptr, int base, size_t num)
+{
+    char buf[num+1], * end;
+    unsigned long ret;
+
+    strncpy(buf, str, num);
+    buf[num] = '\0';
+
+    ret = strtoul(buf, &end, base);
+    if (*end != '\0')
+        *endptr = ((char *)str) + (end - buf);  /* XXX discards const */
+    else
+        *endptr = ((char *)str) + strlen(buf);
+
+    return ret;
+}
+
+#define GET_NUM_FIELD(phys, log) \
+        \
+        log = strntoul(phys, &end, 16, sizeof(phys)); \
+        \
+        if ( (end - phys) != sizeof(phys) ) return CPIOERR_BAD_HEADER;
+#define SET_NUM_FIELD(phys, val, space) \
+        sprintf(space, "%8.8lx", (unsigned long) (val)); \
+        \
+        memcpy(phys, space, 8) \
+
+int cpioReadFileHdr(FD_t fd, struct stat * st, char** name)
+{
+    struct cpioCrcPhysicalHeader hdr;
+    int nameSize;
+    char * end;
+    unsigned int major, minor;
+    int rc = 0;
+    char paddingBuffer[4];
+
+    rc = Fread(&hdr, PHYS_HDR_SIZE, 1, fd);
+    if(rc!=1) return CPIOERR_BAD_HEADER;
+
+    if (strncmp(CPIO_CRC_MAGIC, hdr.magic, sizeof(CPIO_CRC_MAGIC)-1) &&
+        strncmp(CPIO_NEWC_MAGIC, hdr.magic, sizeof(CPIO_NEWC_MAGIC)-1))
+        return CPIOERR_BAD_MAGIC;
+
+    GET_NUM_FIELD(hdr.inode, st->st_ino);
+    GET_NUM_FIELD(hdr.mode, st->st_mode);
+    GET_NUM_FIELD(hdr.uid, st->st_uid);
+    GET_NUM_FIELD(hdr.gid, st->st_gid);
+    GET_NUM_FIELD(hdr.nlink, st->st_nlink);
+    GET_NUM_FIELD(hdr.mtime, st->st_mtime);
+    GET_NUM_FIELD(hdr.filesize, st->st_size);
+
+    GET_NUM_FIELD(hdr.devMajor, major);
+    GET_NUM_FIELD(hdr.devMinor, minor);
+    st->st_dev = makedev(major, minor);
+
+    GET_NUM_FIELD(hdr.rdevMajor, major);
+    GET_NUM_FIELD(hdr.rdevMinor, minor);
+    st->st_rdev = makedev(major, minor);
+
+    GET_NUM_FIELD(hdr.namesize, nameSize);
+    //if (nameSize >= fsm->wrsize)
+    //  return CPIOERR_BAD_HEADER;
+    
+    long padding = (nameSize+PHYS_HDR_SIZE)%4;
+    if(padding>0) padding = 4-padding;
+
+    {   char * t = malloc(nameSize + 1);
+        rc = Fread(t, nameSize, 1, fd);
+        if (rc != 1) {
+            free(t);
+            return CPIOERR_BAD_HEADER;
+        }
+        t[nameSize] = '\0';
+        *name = t;
+    }
+
+    if(padding){
+      rc = Fread(paddingBuffer, padding, 1, fd);
+      if (rc != 1) {
+        free(*name);
+        return CPIOERR_BAD_HEADER;
+      }
+    }
+
+    return (st->st_ino == 0 && st->st_size == 0 && st->st_mode == 0)?CPIOERR_HDR_TRAILER:0;
+}
+
+const char * cpioStrerror(int rc)
+{
+    static char msg[256];
+    const char *s;
+    int myerrno = errno;
+    size_t l;
+
+    strcpy(msg, "cpio: ");
+    switch (rc) {
+    default: {
+        char *t = msg + strlen(msg);
+        sprintf(t, "(error 0x%x)", (unsigned)rc);
+        s = NULL;
+        break;
+    }
+    case CPIOERR_BAD_MAGIC:     s = "Bad magic";                break;
+    case CPIOERR_BAD_HEADER:    s = "Bad/unreadable  header";break;
+
+    case CPIOERR_OPEN_FAILED:   s = "open";     break;
+    case CPIOERR_CHMOD_FAILED:  s = "chmod";    break;
+    case CPIOERR_CHOWN_FAILED:  s = "chown";    break;
+    case CPIOERR_WRITE_FAILED:  s = "write";    break;
+    case CPIOERR_UTIME_FAILED:  s = "utime";    break;
+    case CPIOERR_UNLINK_FAILED: s = "unlink";   break;
+    case CPIOERR_RENAME_FAILED: s = "rename";   break;
+    case CPIOERR_SYMLINK_FAILED: s = "symlink"; break;
+    case CPIOERR_STAT_FAILED:   s = "stat";     break;
+    case CPIOERR_LSTAT_FAILED:  s = "lstat";    break;
+    case CPIOERR_MKDIR_FAILED:  s = "mkdir";    break;
+    case CPIOERR_RMDIR_FAILED:  s = "rmdir";    break;
+    case CPIOERR_MKNOD_FAILED:  s = "mknod";    break;
+    case CPIOERR_MKFIFO_FAILED: s = "mkfifo";   break;
+    case CPIOERR_LINK_FAILED:   s = "link";     break;
+    case CPIOERR_READLINK_FAILED: s = "readlink";       break;
+    case CPIOERR_READ_FAILED:   s = "read";     break;
+    case CPIOERR_COPY_FAILED:   s = "copy";     break;
+    case CPIOERR_LSETFCON_FAILED: s = "lsetfilecon";    break;
+    case CPIOERR_SETCAP_FAILED: s = "cap_set_file";     break;
+
+    case CPIOERR_HDR_SIZE:      s = "Header size too big";      break;
+    case CPIOERR_UNKNOWN_FILETYPE: s = "Unknown file type";     break;
+    case CPIOERR_MISSING_HARDLINK: s = "Missing hard link(s)"; break;
+    case CPIOERR_DIGEST_MISMATCH: s = "Digest mismatch";        break;
+    case CPIOERR_INTERNAL:      s = "Internal error";   break;
+    case CPIOERR_UNMAPPED_FILE: s = "Archive file not in header"; break;
+    case CPIOERR_ENOENT:        s = strerror(ENOENT); break;
+    case CPIOERR_ENOTEMPTY:     s = strerror(ENOTEMPTY); break;
+    }
+
+    l = sizeof(msg) - strlen(msg) - 1;
+    if (s != NULL) {
+        if (l > 0) strncat(msg, s, l);
+        l -= strlen(s);
+    }
+    if ((rc & CPIOERR_CHECK_ERRNO) && myerrno) {
+        s = " failed - ";
+        if (l > 0) strncat(msg, s, l);
+        l -= strlen(s);
+        if (l > 0) strncat(msg, strerror(myerrno), l);
+    }
+    return msg;
+}
diff --git a/loader/cpio.h b/loader/cpio.h
new file mode 100644
index 0000000..7e70cce
--- /dev/null
+++ b/loader/cpio.h
@@ -0,0 +1,116 @@
+#ifndef H_CPIO
+#define H_CPIO
+
+/** \ingroup payload
+ * \file lib/cpio.h
+ *  Structures used to handle cpio payloads within rpm packages.
+ *
+ *  @warning Rpm's cpio implementation may be different than standard cpio.
+ *  The implementation is pretty close, but it has some behaviors which are
+ *  more to RPM's liking. I tried to document the differing behavior in cpio.c,
+ *  but I may have missed some (ewt).
+ *
+ */
+
+/** \ingroup payload
+ * @note CPIO_CHECK_ERRNO bit is set only if errno is valid.
+ */
+#define CPIOERR_CHECK_ERRNO	0x00008000
+
+/** \ingroup payload
+ */
+enum cpioErrorReturns {
+        CPIOERR_BAD_MAGIC       = 2,
+        CPIOERR_BAD_HEADER      = 3,
+        CPIOERR_OPEN_FAILED     = 4     | CPIOERR_CHECK_ERRNO,
+        CPIOERR_CHMOD_FAILED    = 5     | CPIOERR_CHECK_ERRNO,
+        CPIOERR_CHOWN_FAILED    = 6     | CPIOERR_CHECK_ERRNO,
+        CPIOERR_WRITE_FAILED    = 7     | CPIOERR_CHECK_ERRNO,
+        CPIOERR_UTIME_FAILED    = 8     | CPIOERR_CHECK_ERRNO,
+        CPIOERR_UNLINK_FAILED   = 9     | CPIOERR_CHECK_ERRNO,
+        CPIOERR_RENAME_FAILED   = 10    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_SYMLINK_FAILED  = 11    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_STAT_FAILED     = 12    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_LSTAT_FAILED    = 13    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_MKDIR_FAILED    = 14    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_RMDIR_FAILED    = 15    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_MKNOD_FAILED    = 16    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_MKFIFO_FAILED   = 17    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_LINK_FAILED     = 18    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_READLINK_FAILED = 19    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_READ_FAILED     = 20    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_COPY_FAILED     = 21    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_LSETFCON_FAILED = 22    | CPIOERR_CHECK_ERRNO,
+        CPIOERR_HDR_SIZE        = 23,
+        CPIOERR_HDR_TRAILER     = 24,
+        CPIOERR_UNKNOWN_FILETYPE= 25,
+        CPIOERR_MISSING_HARDLINK= 26,
+        CPIOERR_DIGEST_MISMATCH = 27,
+        CPIOERR_INTERNAL        = 28,
+        CPIOERR_UNMAPPED_FILE   = 29,
+        CPIOERR_ENOENT          = 30,
+        CPIOERR_ENOTEMPTY       = 31,
+        CPIOERR_SETCAP_FAILED   = 32    | CPIOERR_CHECK_ERRNO,
+};
+
+/*
+ * Size limit for individual files in "new ascii format" cpio archives.
+ * The max size of the entire archive is unlimited from cpio POV,
+ * but subject to filesystem limitations.
+ */
+#define CPIO_FILESIZE_MAX UINT32_MAX
+
+#define CPIO_NEWC_MAGIC "070701"
+#define CPIO_CRC_MAGIC  "070702"
+#define CPIO_TRAILER    "TRAILER!!!"
+
+/** \ingroup payload
+ * Cpio archive header information.
+ */
+struct cpioCrcPhysicalHeader {
+    char magic[6];
+    char inode[8];
+    char mode[8];
+    char uid[8];
+    char gid[8];
+    char nlink[8];
+    char mtime[8];
+    char filesize[8];
+    char devMajor[8];
+    char devMinor[8];
+    char rdevMajor[8];
+    char rdevMinor[8];
+    char namesize[8];
+    char checksum[8];                   /* ignored !! */
+};
+
+#define PHYS_HDR_SIZE   110             /* Don't depend on sizeof(struct) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const char * headerGetString(Header h, rpmTag tag);
+
+/**
+ * Read cpio header.
+ * @retval fsm          file path and stat info
+ * @retval st
+ * @return              0 on success
+ */
+RPM_GNUC_INTERNAL
+int cpioReadFileHdr(FD_t fd, struct stat * st, char** name);
+
+/** \ingroup payload
+ * Return formatted error message on payload handling failure.
+ * @param rc            error code
+ * @return              formatted error string
+ */
+/* XXX should be RPM_GNUC_INTERNAL too but build/pack.c uses */
+const char * cpioStrerror(int rc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* H_CPIO */
diff --git a/loader/rpmextract.c b/loader/rpmextract.c
new file mode 100644
index 0000000..ca741ad
--- /dev/null
+++ b/loader/rpmextract.c
@@ -0,0 +1,227 @@
+/* rpm2dir: unpack the payload of RPM package to the current directory*/
+/* Based on rpm2cpio */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rpm/rpmlib.h>		/* rpmReadPackageFile .. */
+#include <rpm/rpmtag.h>
+#include <rpm/rpmio.h>
+#include <rpm/rpmpgp.h>
+
+#include <rpm/rpmts.h>
+
+#include <stdio.h>
+
+#include "cpio.h"
+#include "rpmextract.h"
+
+/*
+ * explode source RPM into the current directory
+ * use filters to skip packages and files we do not need
+ */
+int explodeRPM(const char *source,
+               filterfunc filter,
+               dependencyfunc provides,
+               dependencyfunc deps,
+               void* userptr)
+{
+    char buffer[BUFFERSIZE+1]; /* make space for trailing \0 */
+    FD_t fdi;
+    Header h;
+    char * rpmio_flags = NULL;
+    rpmRC rc;
+    FD_t gzdi;
+    
+    if (strcmp(source, "-") == 0)
+        fdi = fdDup(STDIN_FILENO);
+    else
+        fdi = Fopen(source, "r.ufdio");
+
+    if (Ferror(fdi)) {
+        logMessage(ERROR, "%s: %s\n", (strcmp(source, "-") == 0 ? "<stdin>" : source), Fstrerror(fdi));
+        return EXIT_FAILURE;
+    }
+    rpmReadConfigFiles(NULL, NULL);
+
+    {   rpmts ts = rpmtsCreate();
+        rpmVSFlags vsflags = 0;
+
+        /* XXX retain the ageless behavior of rpm2cpio */
+        vsflags |= _RPMVSF_NODIGESTS;
+        vsflags |= _RPMVSF_NOSIGNATURES;
+        vsflags |= RPMVSF_NOHDRCHK;
+        (void) rpmtsSetVSFlags(ts, vsflags);
+
+        rc = rpmReadPackageFile(ts, fdi, "rpm2dir", &h);
+
+        ts = rpmtsFree(ts);
+    }
+
+    switch (rc) {
+    case RPMRC_OK:
+    case RPMRC_NOKEY:
+    case RPMRC_NOTTRUSTED:
+        break;
+    case RPMRC_NOTFOUND:
+        logMessage(ERROR, "argument is not an RPM package\n");
+        return EXIT_FAILURE;
+        break;
+    case RPMRC_FAIL:
+    default:
+        logMessage(ERROR, "error reading header from package\n");
+        return EXIT_FAILURE;
+        break;
+    }
+
+    /* Retrieve all dependencies and run them through deps function */
+    while(deps){
+        struct rpmtd_s td;
+        const char *depname;
+
+        if (!headerGet(h, RPMTAG_REQUIRENAME, &td, HEADERGET_MINMEM))
+          break;
+
+        /* iterator */
+        while ((depname = rpmtdNextString(&td))) {
+          if(deps(depname, userptr)){
+            Fclose(fdi);
+            return EXIT_BADDEPS;
+          }
+        }
+        rpmtdFreeData(&td);
+        break;
+    }
+
+    /* Retrieve all provides and run them through provides function */
+    while(provides){
+        struct rpmtd_s td;
+        const char *depname;
+        int found = 0;
+
+        if (!headerGet(h, RPMTAG_PROVIDES, &td, HEADERGET_MINMEM))
+          break;
+
+        /* iterator */
+        while ((depname = rpmtdNextString(&td))) {
+          if(!provides(depname, userptr)){
+            found++;
+          }
+        }
+        rpmtdFreeData(&td);
+        if(found<=0)
+            return EXIT_BADDEPS;
+        break;
+    }
+
+    /* Retrieve type of payload compression. */
+    {   
+        const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
+        if(compr && strcmp(compr, "gzip")) rpmio_flags = rstrscat(NULL, "r.", compr, "dio", NULL);
+        else rpmio_flags = rstrscat(NULL, "r.", "gzdio", NULL);
+    }
+
+    gzdi = Fdopen(fdi, rpmio_flags);    /* XXX gzdi == fdi */
+    free(rpmio_flags);
+
+    if (gzdi == NULL) {
+        logMessage(ERROR, "cannot re-open payload: %s\n", Fstrerror(gzdi));
+        return EXIT_FAILURE;
+    }
+
+    while(!rc){
+      char *filename = NULL;
+      struct stat fstat;
+      int offset = 0;
+      int towrite = 1;
+
+      rc = cpioReadFileHdr(gzdi, &fstat, &filename);
+      if(rc == CPIOERR_HDR_TRAILER){
+        rc = 0;
+        break;
+      } else if(rc != 0){
+        break;
+      }
+
+      /* 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);
+      char* dirptr = dirname;
+      while(dirptr!=NULL && *dirptr!=0){
+        dirptr = strchr(dirptr, '/');
+        if(dirptr){
+          *dirptr = 0;
+          mkdir(dirname, 0700);
+          *dirptr = '/';
+          dirptr++;
+        }
+      }
+      free(dirname);
+      
+      /* Regular file */
+      long readbytes = 0;
+      long padding = fstat.st_size%4;
+      FILE *fdout = NULL;
+      if(padding>0) padding = 4-padding;
+
+      if(towrite>=2){
+        fdout = fopen(filename+offset, "w");
+
+        if(fdout==NULL){
+          free(filename);
+          rc = 33;
+          break;
+        }
+      }
+
+      while(1){
+        long toread = (BUFFERSIZE>fstat.st_size) ? fstat.st_size : BUFFERSIZE;
+        if(toread<=0) break;
+        readbytes = Fread(buffer, toread, 1, gzdi);
+        if(readbytes<=0){
+          rc = 34; //truncated archive? set error flag...
+          break;
+        }
+        else{
+          fstat.st_size-=toread;
+          if(towrite>=2)
+            if(fwrite(buffer, toread, 1, fdout)!=1){
+              /* TODO: error handling */
+            }
+          buffer[toread] = 0;
+        }
+      }
+
+      /* symlink, we assume that the path comtained in symlink
+       * is shorter than BUFFERSIZE */
+      if(towrite && !rc && S_ISLNK(fstat.st_mode)){
+        if(symlink(buffer, filename+offset)){
+          /* TODO: error handling */
+        }
+      }
+
+      free(filename);
+      if(towrite>=2) fclose(fdout);
+
+      if(padding) readbytes = Fread(buffer, padding, 1, gzdi);
+    }
+
+
+    Fclose(gzdi);       /* XXX gzdi == fdi */
+
+    return rc;
+}
diff --git a/loader/rpmextract.h b/loader/rpmextract.h
new file mode 100644
index 0000000..0348b49
--- /dev/null
+++ b/loader/rpmextract.h
@@ -0,0 +1,47 @@
+/*
+   File name: rpmextract.h
+   Date:      2009/09/16
+   Author:    msivak
+
+   Copyright (C) 2009 msivak
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   in a file called COPYING along with this program; if not, write to
+   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+   02139, USA.
+*/
+
+
+#ifndef __RPMEXTRACT_H__
+#define __RPMEXTRACT_H__
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define EXIT_BADDEPS 4
+#define BUFFERSIZE 1024
+
+/* both filter functions return 0 - match, 1 - match not found */
+typedef int (*filterfunc)(const char* name, struct stat *fstat, void *userptr);
+typedef int (*dependencyfunc)(const char* depends, void *userptr);
+
+int explodeRPM(const char* file,
+               filterfunc filter,
+               dependencyfunc provides,
+               dependencyfunc deps,
+               void* userptr);
+
+#endif
+
+/* end of rpmextract.h */
-- 
1.6.4.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]