home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / rpm / build / reqprov.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-17  |  10.4 KB  |  414 lines

  1. /* reqprov.c -- require/provide handling */
  2.  
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <signal.h>
  7. #include <fcntl.h>
  8. #include <ctype.h>
  9. #include <sys/time.h>
  10. #include <sys/resource.h>
  11. #include <sys/types.h>
  12. #include <sys/wait.h>
  13. #include <sys/stat.h>
  14. #include <errno.h>
  15.  
  16. #include "specP.h"
  17. #include "reqprov.h"
  18. #include "messages.h"
  19. #include "rpmlib.h"
  20. #include "misc.h"
  21.  
  22. static StringBuf getOutputFrom(char *dir, char *argv[],
  23.                    char *writePtr, int writeBytesLeft,
  24.                    int failNonZero);
  25.  
  26. /*************************************************************/
  27. /*                                                           */
  28. /* Adding entries to the package reqprov list                */
  29. /* Handle duplicate entries                                  */
  30. /*                                                           */
  31. /*************************************************************/
  32.  
  33. int addReqProv(struct PackageRec *p, int flags,
  34.            char *name, char *version)
  35. {
  36.     struct ReqProv *rd;
  37.     int same;
  38.  
  39.     /* Frist see if the same entry is already there */
  40.     rd = p->reqprov;
  41.     while (rd) {
  42.     if (rd->flags == flags) {
  43.         if (rd->version == version) {
  44.         same = 1;
  45.         } else if (!rd->version || !version) {
  46.         same = 0;
  47.         } else if (!strcmp(rd->version, version)) {
  48.         same = 1;
  49.         } else {
  50.         same = 0;
  51.         }
  52.  
  53.         if (same && !strcmp(rd->name, name)) {
  54.         /* They are exacty the same */
  55.         break;
  56.         }
  57.     }
  58.     rd = rd->next;
  59.     }
  60.     if (rd) {
  61.     /* already there */
  62.     rpmMessage(RPMMESS_DEBUG, "Already Got: %s\n", name);
  63.     return 0;
  64.     }
  65.     
  66.     rd = (struct ReqProv *)malloc(sizeof(*rd));
  67.     rd->flags = flags;
  68.     rd->name = strdup(name);
  69.     rd->version = version ? strdup(version) : NULL;
  70.     rd->next = p->reqprov;
  71.     p->reqprov = rd;
  72.  
  73.     if (flags & RPMSENSE_PROVIDES) {
  74.     rpmMessage(RPMMESS_DEBUG, "Adding provide: %s\n", name);
  75.     p->numProv++;
  76.     } else if (flags & RPMSENSE_CONFLICTS) {
  77.     rpmMessage(RPMMESS_DEBUG, "Adding conflict: %s\n", name);
  78.     p->numConflict++;
  79.     } else if (flags & RPMSENSE_PREREQ) {
  80.     rpmMessage(RPMMESS_DEBUG, "Adding prereq: %s\n", name);
  81.     p->numPreReq++;
  82.     } else if (flags & RPMSENSE_OBSOLETES) {
  83.     rpmMessage(RPMMESS_DEBUG, "Adding obsoletes: %s\n", name);
  84.     p->numObsoletes++;
  85.     } else {    
  86.     rpmMessage(RPMMESS_DEBUG, "Adding require: %s\n", name);
  87.     p->numReq++;
  88.     }
  89.  
  90.     return 0;
  91. }
  92.  
  93. /*************************************************************/
  94. /*                                                           */
  95. /* Add require/provides for the files in the header          */
  96. /*  (adds to the package structure)                          */
  97. /*                                                           */
  98. /*************************************************************/
  99.  
  100. static StringBuf getOutputFrom(char *dir, char *argv[],
  101.                    char *writePtr, int writeBytesLeft,
  102.                    int failNonZero)
  103. {
  104.     int progPID;
  105.     int progDead;
  106.     int toProg[2];
  107.     int fromProg[2];
  108.     int status;
  109.     void *oldhandler;
  110.     int bytesWritten;
  111.     StringBuf readBuff;
  112.     int bytes;
  113.     unsigned char buf[8193];
  114.  
  115.     oldhandler = signal(SIGPIPE, SIG_IGN);
  116.  
  117.     pipe(toProg);
  118.     pipe(fromProg);
  119.     
  120.     if (!(progPID = fork())) {
  121.     close(toProg[1]);
  122.     close(fromProg[0]);
  123.     
  124.     dup2(toProg[0], 0);   /* Make stdin the in pipe */
  125.     dup2(fromProg[1], 1); /* Make stdout the out pipe */
  126.  
  127.     close(toProg[0]);
  128.     close(fromProg[1]);
  129.  
  130.     chdir(dir);
  131.     
  132.     execvp(argv[0], argv);
  133.     rpmError(RPMERR_EXEC, "Couldn't exec %s", argv[0]);
  134.     _exit(RPMERR_EXEC);
  135.     }
  136.     if (progPID < 0) {
  137.     rpmError(RPMERR_FORK, "Couldn't fork %s", argv[0]);
  138.     return NULL;
  139.     }
  140.  
  141.     close(toProg[0]);
  142.     close(fromProg[1]);
  143.  
  144.     /* Do not block reading or writing from/to prog. */
  145.     fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
  146.     fcntl(toProg[1], F_SETFL, O_NONBLOCK);
  147.     
  148.     readBuff = newStringBuf();
  149.  
  150.     progDead = 0;
  151.     do {
  152.     if (waitpid(progPID, &status, WNOHANG)) {
  153.         progDead = 1;
  154.     }
  155.  
  156.     /* Write some stuff to the process if possible */
  157.         if (writeBytesLeft) {
  158.         if ((bytesWritten =
  159.           write(toProg[1], writePtr,
  160.             (1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
  161.             if (errno != EAGAIN) {
  162.             perror("getOutputFrom()");
  163.                 exit(1);
  164.         }
  165.             bytesWritten = 0;
  166.         }
  167.         writeBytesLeft -= bytesWritten;
  168.         writePtr += bytesWritten;
  169.     } else {
  170.         close(toProg[1]);
  171.     }
  172.     
  173.     /* Read any data from prog */
  174.     bytes = read(fromProg[0], buf, sizeof(buf)-1);
  175.     while (bytes > 0) {
  176.         buf[bytes] = '\0';
  177.         appendStringBuf(readBuff, buf);
  178.         bytes = read(fromProg[0], buf, sizeof(buf)-1);
  179.     }
  180.  
  181.     /* terminate when prog dies */
  182.     } while (!progDead);
  183.  
  184.     close(toProg[1]);
  185.     close(fromProg[0]);
  186.     signal(SIGPIPE, oldhandler);
  187.  
  188.     if (writeBytesLeft) {
  189.     rpmError(RPMERR_EXEC, "failed to write all data to %s", argv[0]);
  190.     return NULL;
  191.     }
  192.     waitpid(progPID, &status, 0);
  193.     if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
  194.     rpmError(RPMERR_EXEC, "%s failed", argv[0]);
  195.     return NULL;
  196.     }
  197.  
  198.     return readBuff;
  199. }
  200.  
  201. int generateAutoReqProv(Header header, struct PackageRec *p)
  202. {
  203.     char **f, **fsave, *s;
  204.     int count;
  205.     int_16 *modes;
  206.  
  207.     StringBuf writeBuff;
  208.     StringBuf readBuff;
  209.     char *writePtr;
  210.     int writeBytes;
  211.     char dir[1024];
  212.     char *argv[8];
  213.  
  214.     rpmMessage(RPMMESS_VERBOSE, "Finding dependencies...\n");
  215.  
  216.     /*** Get root directory ***/
  217.     
  218.     if (rpmGetVar(RPMVAR_ROOT)) {
  219.     strcpy(dir, rpmGetVar(RPMVAR_ROOT));
  220.     } else {
  221.     strcpy(dir, "/");
  222.     }
  223.  
  224.     /*** Generate File List ***/
  225.     
  226.     if (!headerGetEntry(header, RPMTAG_FILENAMES, NULL, (void **) &f, &count)) {
  227.     return 0;
  228.     }
  229.     if (!count) {
  230.     return 0;
  231.     }
  232.     fsave = f;
  233.     headerGetEntry(header, RPMTAG_FILEMODES, NULL, (void **) &modes, NULL);
  234.  
  235.     writeBuff = newStringBuf();
  236.     writeBytes = 0;
  237.     while (count--) {
  238.         s = *f++;
  239.     /* We skip the leading "/" (already normalized) */
  240.     writeBytes += strlen(s);
  241.     appendLineStringBuf(writeBuff, s + 1);
  242.     }
  243.     if (fsave) {
  244.     free(fsave);
  245.     }
  246.     writePtr = getStringBuf(writeBuff);
  247.  
  248.     /*** Do Provides ***/
  249.     
  250.     argv[0] = "find-provides";
  251.     argv[1] = NULL;
  252.     readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 1);
  253.     if (!readBuff) {
  254.     rpmError(RPMERR_EXEC, "Failed to find provides");
  255.     exit(1);
  256.     }
  257.     
  258.     s = getStringBuf(readBuff);
  259.     f = fsave = splitString(s, strlen(s), '\n');
  260.     freeStringBuf(readBuff);
  261.     while (*f) {
  262.     if (**f) {
  263.         addReqProv(p, RPMSENSE_PROVIDES, *f, NULL);
  264.     }
  265.     f++;
  266.     }
  267.     free(fsave);
  268.  
  269.     /*** Do Requires ***/
  270.     
  271.     argv[0] = "find-requires";
  272.     argv[1] = NULL;
  273.     readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 0);
  274.     if (!readBuff) {
  275.     rpmError(RPMERR_EXEC, "Failed to find requires");
  276.     exit(1);
  277.     }
  278.  
  279.     s = getStringBuf(readBuff);
  280.     f = fsave = splitString(s, strlen(s), '\n');
  281.     freeStringBuf(readBuff);
  282.     while (*f) {
  283.     if (**f) {
  284.         addReqProv(p, RPMSENSE_ANY, *f, NULL);
  285.     }
  286.     f++;
  287.     }
  288.     free(fsave);
  289.  
  290.     /*** Clean Up ***/
  291.  
  292.     freeStringBuf(writeBuff);
  293.  
  294.     return 0;
  295. }
  296.  
  297. /*************************************************************/
  298. /*                                                           */
  299. /* Generate and add header entry from package record         */
  300. /*                                                           */
  301. /*************************************************************/
  302.  
  303. int processReqProv(Header h, struct PackageRec *p)
  304. {
  305.     struct ReqProv *rd;
  306.     char **nameArray, **namePtr;
  307.     char **versionArray, **versionPtr;
  308.     int_32 *flagArray, *flagPtr;
  309.     int x;
  310.  
  311.     if (p->numProv) {
  312.     rd = p->reqprov;
  313.     nameArray = namePtr = malloc(p->numProv * sizeof(*nameArray));
  314.     rpmMessage(RPMMESS_VERBOSE, "Provides (%d):", p->numProv);
  315.     while (rd) {
  316.         if (rd->flags & RPMSENSE_PROVIDES) {
  317.         rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
  318.         *namePtr++ = rd->name;
  319.         }
  320.         rd = rd->next;
  321.     }
  322.     rpmMessage(RPMMESS_VERBOSE, "\n");
  323.  
  324.     headerAddEntry(h, RPMTAG_PROVIDES, RPM_STRING_ARRAY_TYPE, nameArray, p->numProv);
  325.     free(nameArray);
  326.     }
  327.  
  328.     if (p->numObsoletes) {
  329.     rd = p->reqprov;
  330.     nameArray = namePtr = malloc(p->numProv * sizeof(*nameArray));
  331.     rpmMessage(RPMMESS_VERBOSE, "Obsoletes (%d):", p->numObsoletes);
  332.     while (rd) {
  333.         if (rd->flags & RPMSENSE_OBSOLETES) {
  334.         rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
  335.         *namePtr++ = rd->name;
  336.         }
  337.         rd = rd->next;
  338.     }
  339.     rpmMessage(RPMMESS_VERBOSE, "\n");
  340.  
  341.     headerAddEntry(h, RPMTAG_OBSOLETES, RPM_STRING_ARRAY_TYPE, nameArray, p->numObsoletes);
  342.     free(nameArray);
  343.     }
  344.  
  345.     if (p->numConflict) {
  346.     rd = p->reqprov;
  347.     nameArray = namePtr = malloc(p->numConflict * sizeof(*nameArray));
  348.     versionArray = versionPtr =
  349.         malloc(p->numConflict * sizeof(*versionArray));
  350.     flagArray = flagPtr = malloc(p->numConflict * sizeof(*flagArray));
  351.     rpmMessage(RPMMESS_VERBOSE, "Conflicts (%d):", p->numConflict);
  352.     while (rd) {
  353.         if (rd->flags & RPMSENSE_CONFLICTS) {
  354.         rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
  355.         *namePtr++ = rd->name;
  356.         *versionPtr++ = rd->version ? rd->version : "";
  357.         *flagPtr++ = rd->flags & RPMSENSE_SENSEMASK;
  358.         }
  359.         rd = rd->next;
  360.     }
  361.     rpmMessage(RPMMESS_VERBOSE, "\n");
  362.  
  363.     headerAddEntry(h, RPMTAG_CONFLICTNAME, RPM_STRING_ARRAY_TYPE,
  364.          nameArray, p->numConflict);
  365.     headerAddEntry(h, RPMTAG_CONFLICTVERSION, RPM_STRING_ARRAY_TYPE,
  366.          versionArray, p->numConflict);
  367.     headerAddEntry(h, RPMTAG_CONFLICTFLAGS, RPM_INT32_TYPE,
  368.          flagArray, p->numConflict);
  369.  
  370.     free(nameArray);
  371.     free(versionArray);
  372.     free(flagArray);
  373.     }
  374.  
  375.     x = p->numReq + p->numPreReq;
  376.     if (x) {
  377.     rd = p->reqprov;
  378.     nameArray = namePtr = malloc(x * sizeof(*nameArray));
  379.     versionArray = versionPtr = malloc(x * sizeof(*versionArray));
  380.     flagArray = flagPtr = malloc(x * sizeof(*flagArray));
  381.     rpmMessage(RPMMESS_VERBOSE, "[Pre]Requires (%d):", x);
  382.     while (rd) {
  383.         if (! ((rd->flags & RPMSENSE_PROVIDES) ||
  384.            (rd->flags & RPMSENSE_OBSOLETES) ||
  385.            (rd->flags & RPMSENSE_CONFLICTS))) {
  386.         if (rd->flags & RPMSENSE_PREREQ) {
  387.             rpmMessage(RPMMESS_VERBOSE, " [%s]", rd->name);
  388.         } else {
  389.             rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
  390.         }
  391.         *namePtr++ = rd->name;
  392.         *versionPtr++ = rd->version ? rd->version : "";
  393.         *flagPtr++ = (rd->flags & RPMSENSE_SENSEMASK) |
  394.             (rd->flags & RPMSENSE_PREREQ);
  395.         }
  396.         rd = rd->next;
  397.     }
  398.     rpmMessage(RPMMESS_VERBOSE, "\n");
  399.  
  400.     headerAddEntry(h, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE,
  401.          nameArray, x);
  402.     headerAddEntry(h, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE,
  403.          versionArray, x);
  404.     headerAddEntry(h, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE,
  405.          flagArray, x);
  406.  
  407.     free(nameArray);
  408.     free(versionArray);
  409.     free(flagArray);
  410.     }
  411.  
  412.     return 0;
  413. }
  414.