home *** CD-ROM | disk | FTP | other *** search
- /* reqprov.c -- require/provide handling */
-
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <signal.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <sys/time.h>
- #include <sys/resource.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <sys/stat.h>
- #include <errno.h>
-
- #include "specP.h"
- #include "reqprov.h"
- #include "messages.h"
- #include "rpmlib.h"
- #include "misc.h"
-
- static StringBuf getOutputFrom(char *dir, char *argv[],
- char *writePtr, int writeBytesLeft,
- int failNonZero);
-
- /*************************************************************/
- /* */
- /* Adding entries to the package reqprov list */
- /* Handle duplicate entries */
- /* */
- /*************************************************************/
-
- int addReqProv(struct PackageRec *p, int flags,
- char *name, char *version)
- {
- struct ReqProv *rd;
- int same;
-
- /* Frist see if the same entry is already there */
- rd = p->reqprov;
- while (rd) {
- if (rd->flags == flags) {
- if (rd->version == version) {
- same = 1;
- } else if (!rd->version || !version) {
- same = 0;
- } else if (!strcmp(rd->version, version)) {
- same = 1;
- } else {
- same = 0;
- }
-
- if (same && !strcmp(rd->name, name)) {
- /* They are exacty the same */
- break;
- }
- }
- rd = rd->next;
- }
- if (rd) {
- /* already there */
- rpmMessage(RPMMESS_DEBUG, "Already Got: %s\n", name);
- return 0;
- }
-
- rd = (struct ReqProv *)malloc(sizeof(*rd));
- rd->flags = flags;
- rd->name = strdup(name);
- rd->version = version ? strdup(version) : NULL;
- rd->next = p->reqprov;
- p->reqprov = rd;
-
- if (flags & RPMSENSE_PROVIDES) {
- rpmMessage(RPMMESS_DEBUG, "Adding provide: %s\n", name);
- p->numProv++;
- } else if (flags & RPMSENSE_CONFLICTS) {
- rpmMessage(RPMMESS_DEBUG, "Adding conflict: %s\n", name);
- p->numConflict++;
- } else if (flags & RPMSENSE_PREREQ) {
- rpmMessage(RPMMESS_DEBUG, "Adding prereq: %s\n", name);
- p->numPreReq++;
- } else if (flags & RPMSENSE_OBSOLETES) {
- rpmMessage(RPMMESS_DEBUG, "Adding obsoletes: %s\n", name);
- p->numObsoletes++;
- } else {
- rpmMessage(RPMMESS_DEBUG, "Adding require: %s\n", name);
- p->numReq++;
- }
-
- return 0;
- }
-
- /*************************************************************/
- /* */
- /* Add require/provides for the files in the header */
- /* (adds to the package structure) */
- /* */
- /*************************************************************/
-
- static StringBuf getOutputFrom(char *dir, char *argv[],
- char *writePtr, int writeBytesLeft,
- int failNonZero)
- {
- int progPID;
- int progDead;
- int toProg[2];
- int fromProg[2];
- int status;
- void *oldhandler;
- int bytesWritten;
- StringBuf readBuff;
- int bytes;
- unsigned char buf[8193];
-
- oldhandler = signal(SIGPIPE, SIG_IGN);
-
- pipe(toProg);
- pipe(fromProg);
-
- if (!(progPID = fork())) {
- close(toProg[1]);
- close(fromProg[0]);
-
- dup2(toProg[0], 0); /* Make stdin the in pipe */
- dup2(fromProg[1], 1); /* Make stdout the out pipe */
-
- close(toProg[0]);
- close(fromProg[1]);
-
- chdir(dir);
-
- execvp(argv[0], argv);
- rpmError(RPMERR_EXEC, "Couldn't exec %s", argv[0]);
- _exit(RPMERR_EXEC);
- }
- if (progPID < 0) {
- rpmError(RPMERR_FORK, "Couldn't fork %s", argv[0]);
- return NULL;
- }
-
- close(toProg[0]);
- close(fromProg[1]);
-
- /* Do not block reading or writing from/to prog. */
- fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
- fcntl(toProg[1], F_SETFL, O_NONBLOCK);
-
- readBuff = newStringBuf();
-
- progDead = 0;
- do {
- if (waitpid(progPID, &status, WNOHANG)) {
- progDead = 1;
- }
-
- /* Write some stuff to the process if possible */
- if (writeBytesLeft) {
- if ((bytesWritten =
- write(toProg[1], writePtr,
- (1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
- if (errno != EAGAIN) {
- perror("getOutputFrom()");
- exit(1);
- }
- bytesWritten = 0;
- }
- writeBytesLeft -= bytesWritten;
- writePtr += bytesWritten;
- } else {
- close(toProg[1]);
- }
-
- /* Read any data from prog */
- bytes = read(fromProg[0], buf, sizeof(buf)-1);
- while (bytes > 0) {
- buf[bytes] = '\0';
- appendStringBuf(readBuff, buf);
- bytes = read(fromProg[0], buf, sizeof(buf)-1);
- }
-
- /* terminate when prog dies */
- } while (!progDead);
-
- close(toProg[1]);
- close(fromProg[0]);
- signal(SIGPIPE, oldhandler);
-
- if (writeBytesLeft) {
- rpmError(RPMERR_EXEC, "failed to write all data to %s", argv[0]);
- return NULL;
- }
- waitpid(progPID, &status, 0);
- if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
- rpmError(RPMERR_EXEC, "%s failed", argv[0]);
- return NULL;
- }
-
- return readBuff;
- }
-
- int generateAutoReqProv(Header header, struct PackageRec *p)
- {
- char **f, **fsave, *s;
- int count;
- int_16 *modes;
-
- StringBuf writeBuff;
- StringBuf readBuff;
- char *writePtr;
- int writeBytes;
- char dir[1024];
- char *argv[8];
-
- rpmMessage(RPMMESS_VERBOSE, "Finding dependencies...\n");
-
- /*** Get root directory ***/
-
- if (rpmGetVar(RPMVAR_ROOT)) {
- strcpy(dir, rpmGetVar(RPMVAR_ROOT));
- } else {
- strcpy(dir, "/");
- }
-
- /*** Generate File List ***/
-
- if (!headerGetEntry(header, RPMTAG_FILENAMES, NULL, (void **) &f, &count)) {
- return 0;
- }
- if (!count) {
- return 0;
- }
- fsave = f;
- headerGetEntry(header, RPMTAG_FILEMODES, NULL, (void **) &modes, NULL);
-
- writeBuff = newStringBuf();
- writeBytes = 0;
- while (count--) {
- s = *f++;
- /* We skip the leading "/" (already normalized) */
- writeBytes += strlen(s);
- appendLineStringBuf(writeBuff, s + 1);
- }
- if (fsave) {
- free(fsave);
- }
- writePtr = getStringBuf(writeBuff);
-
- /*** Do Provides ***/
-
- argv[0] = "find-provides";
- argv[1] = NULL;
- readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 1);
- if (!readBuff) {
- rpmError(RPMERR_EXEC, "Failed to find provides");
- exit(1);
- }
-
- s = getStringBuf(readBuff);
- f = fsave = splitString(s, strlen(s), '\n');
- freeStringBuf(readBuff);
- while (*f) {
- if (**f) {
- addReqProv(p, RPMSENSE_PROVIDES, *f, NULL);
- }
- f++;
- }
- free(fsave);
-
- /*** Do Requires ***/
-
- argv[0] = "find-requires";
- argv[1] = NULL;
- readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 0);
- if (!readBuff) {
- rpmError(RPMERR_EXEC, "Failed to find requires");
- exit(1);
- }
-
- s = getStringBuf(readBuff);
- f = fsave = splitString(s, strlen(s), '\n');
- freeStringBuf(readBuff);
- while (*f) {
- if (**f) {
- addReqProv(p, RPMSENSE_ANY, *f, NULL);
- }
- f++;
- }
- free(fsave);
-
- /*** Clean Up ***/
-
- freeStringBuf(writeBuff);
-
- return 0;
- }
-
- /*************************************************************/
- /* */
- /* Generate and add header entry from package record */
- /* */
- /*************************************************************/
-
- int processReqProv(Header h, struct PackageRec *p)
- {
- struct ReqProv *rd;
- char **nameArray, **namePtr;
- char **versionArray, **versionPtr;
- int_32 *flagArray, *flagPtr;
- int x;
-
- if (p->numProv) {
- rd = p->reqprov;
- nameArray = namePtr = malloc(p->numProv * sizeof(*nameArray));
- rpmMessage(RPMMESS_VERBOSE, "Provides (%d):", p->numProv);
- while (rd) {
- if (rd->flags & RPMSENSE_PROVIDES) {
- rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
- *namePtr++ = rd->name;
- }
- rd = rd->next;
- }
- rpmMessage(RPMMESS_VERBOSE, "\n");
-
- headerAddEntry(h, RPMTAG_PROVIDES, RPM_STRING_ARRAY_TYPE, nameArray, p->numProv);
- free(nameArray);
- }
-
- if (p->numObsoletes) {
- rd = p->reqprov;
- nameArray = namePtr = malloc(p->numProv * sizeof(*nameArray));
- rpmMessage(RPMMESS_VERBOSE, "Obsoletes (%d):", p->numObsoletes);
- while (rd) {
- if (rd->flags & RPMSENSE_OBSOLETES) {
- rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
- *namePtr++ = rd->name;
- }
- rd = rd->next;
- }
- rpmMessage(RPMMESS_VERBOSE, "\n");
-
- headerAddEntry(h, RPMTAG_OBSOLETES, RPM_STRING_ARRAY_TYPE, nameArray, p->numObsoletes);
- free(nameArray);
- }
-
- if (p->numConflict) {
- rd = p->reqprov;
- nameArray = namePtr = malloc(p->numConflict * sizeof(*nameArray));
- versionArray = versionPtr =
- malloc(p->numConflict * sizeof(*versionArray));
- flagArray = flagPtr = malloc(p->numConflict * sizeof(*flagArray));
- rpmMessage(RPMMESS_VERBOSE, "Conflicts (%d):", p->numConflict);
- while (rd) {
- if (rd->flags & RPMSENSE_CONFLICTS) {
- rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
- *namePtr++ = rd->name;
- *versionPtr++ = rd->version ? rd->version : "";
- *flagPtr++ = rd->flags & RPMSENSE_SENSEMASK;
- }
- rd = rd->next;
- }
- rpmMessage(RPMMESS_VERBOSE, "\n");
-
- headerAddEntry(h, RPMTAG_CONFLICTNAME, RPM_STRING_ARRAY_TYPE,
- nameArray, p->numConflict);
- headerAddEntry(h, RPMTAG_CONFLICTVERSION, RPM_STRING_ARRAY_TYPE,
- versionArray, p->numConflict);
- headerAddEntry(h, RPMTAG_CONFLICTFLAGS, RPM_INT32_TYPE,
- flagArray, p->numConflict);
-
- free(nameArray);
- free(versionArray);
- free(flagArray);
- }
-
- x = p->numReq + p->numPreReq;
- if (x) {
- rd = p->reqprov;
- nameArray = namePtr = malloc(x * sizeof(*nameArray));
- versionArray = versionPtr = malloc(x * sizeof(*versionArray));
- flagArray = flagPtr = malloc(x * sizeof(*flagArray));
- rpmMessage(RPMMESS_VERBOSE, "[Pre]Requires (%d):", x);
- while (rd) {
- if (! ((rd->flags & RPMSENSE_PROVIDES) ||
- (rd->flags & RPMSENSE_OBSOLETES) ||
- (rd->flags & RPMSENSE_CONFLICTS))) {
- if (rd->flags & RPMSENSE_PREREQ) {
- rpmMessage(RPMMESS_VERBOSE, " [%s]", rd->name);
- } else {
- rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
- }
- *namePtr++ = rd->name;
- *versionPtr++ = rd->version ? rd->version : "";
- *flagPtr++ = (rd->flags & RPMSENSE_SENSEMASK) |
- (rd->flags & RPMSENSE_PREREQ);
- }
- rd = rd->next;
- }
- rpmMessage(RPMMESS_VERBOSE, "\n");
-
- headerAddEntry(h, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE,
- nameArray, x);
- headerAddEntry(h, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE,
- versionArray, x);
- headerAddEntry(h, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE,
- flagArray, x);
-
- free(nameArray);
- free(versionArray);
- free(flagArray);
- }
-
- return 0;
- }
-