1 /* reqprov.c -- require/provide handling */
20 static StringBuf getOutputFrom(char *dir, char *argv[],
21 char *writePtr, int writeBytesLeft,
24 /*************************************************************/
26 /* Adding entries to the package reqprov list */
27 /* Handle duplicate entries */
29 /*************************************************************/
31 int addReqProv(struct PackageRec *p, int flags,
32 char *name, char *version)
37 /* Frist see if the same entry is already there */
40 if (rd->flags == flags) {
41 if (rd->version == version) {
43 } else if (!rd->version || !version) {
45 } else if (!strcmp(rd->version, version)) {
51 if (same && !strcmp(rd->name, name)) {
52 /* They are exacty the same */
60 rpmMessage(RPMMESS_DEBUG, "Already Got: %s\n", name);
64 rd = (struct ReqProv *)malloc(sizeof(*rd));
66 rd->name = strdup(name);
67 rd->version = version ? strdup(version) : NULL;
68 rd->next = p->reqprov;
71 if (flags & RPMSENSE_PROVIDES) {
72 rpmMessage(RPMMESS_DEBUG, "Adding provide: %s\n", name);
74 } else if (flags & RPMSENSE_CONFLICTS) {
75 rpmMessage(RPMMESS_DEBUG, "Adding conflict: %s\n", name);
78 rpmMessage(RPMMESS_DEBUG, "Adding require: %s\n", name);
85 /*************************************************************/
87 /* Add require/provides for the files in the header */
88 /* (adds to the package structure) */
90 /*************************************************************/
92 static StringBuf getOutputFrom(char *dir, char *argv[],
93 char *writePtr, int writeBytesLeft,
105 unsigned char buf[8193];
107 oldhandler = signal(SIGPIPE, SIG_IGN);
112 if (!(progPID = fork())) {
118 dup2(toProg[0], 0); /* Make stdin the in pipe */
119 dup2(fromProg[1], 1); /* Make stdout the out pipe */
126 execvp(argv[0], argv);
127 rpmError(RPMERR_EXEC, "Couldn't exec %s", argv[0]);
131 rpmError(RPMERR_FORK, "Couldn't fork %s", argv[0]);
138 /* Do not block reading or writing from/to prog. */
139 fcntl(fromProg[0], F_SETFL, O_NONBLOCK);
140 fcntl(toProg[1], F_SETFL, O_NONBLOCK);
142 readBuff = newStringBuf();
146 if (waitpid(progPID, &status, WNOHANG)) {
150 /* Write some stuff to the process if possible */
151 if (writeBytesLeft) {
153 write(toProg[1], writePtr,
154 (1024<writeBytesLeft) ? 1024 : writeBytesLeft)) < 0) {
155 if (errno != EAGAIN) {
156 perror("getOutputFrom()");
161 writeBytesLeft -= bytesWritten;
162 writePtr += bytesWritten;
167 /* Read any data from prog */
168 bytes = read(fromProg[0], buf, sizeof(buf)-1);
171 appendStringBuf(readBuff, buf);
172 bytes = read(fromProg[0], buf, sizeof(buf)-1);
175 /* terminate when prog dies */
180 signal(SIGPIPE, oldhandler);
182 if (writeBytesLeft) {
183 rpmError(RPMERR_EXEC, "failed to write all data to %s", argv[0]);
186 waitpid(progPID, &status, 0);
187 if (failNonZero && (!WIFEXITED(status) || WEXITSTATUS(status))) {
188 rpmError(RPMERR_EXEC, "%s failed", argv[0]);
195 int generateAutoReqProv(Header header, struct PackageRec *p)
197 char **f, **fsave, *s;
208 rpmMessage(RPMMESS_VERBOSE, "Finding dependencies...\n");
210 /*** Get root directory ***/
212 if (rpmGetVar(RPMVAR_ROOT)) {
213 strcpy(dir, rpmGetVar(RPMVAR_ROOT));
218 /*** Generate File List ***/
220 if (!headerGetEntry(header, RPMTAG_FILENAMES, NULL, (void **) &f, &count)) {
227 headerGetEntry(header, RPMTAG_FILEMODES, NULL, (void **) &modes, NULL);
229 writeBuff = newStringBuf();
233 /* We skip the leading "/" (already normalized) */
234 writeBytes += strlen(s);
235 appendLineStringBuf(writeBuff, s + 1);
240 writePtr = getStringBuf(writeBuff);
242 /*** Do Provides ***/
244 argv[0] = "find-provides";
246 readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 1);
248 rpmError(RPMERR_EXEC, "Failed to find provides");
252 s = getStringBuf(readBuff);
253 f = fsave = splitString(s, strlen(s), '\n');
254 freeStringBuf(readBuff);
257 addReqProv(p, RPMSENSE_PROVIDES, *f, NULL);
263 /*** Do Requires ***/
265 argv[0] = "find-requires";
267 readBuff = getOutputFrom(dir, argv, writePtr, writeBytes, 0);
269 rpmError(RPMERR_EXEC, "Failed to find requires");
273 s = getStringBuf(readBuff);
274 f = fsave = splitString(s, strlen(s), '\n');
275 freeStringBuf(readBuff);
278 addReqProv(p, RPMSENSE_ANY, *f, NULL);
286 freeStringBuf(writeBuff);
291 /*************************************************************/
293 /* Generate and add header entry from package record */
295 /*************************************************************/
297 int processReqProv(Header h, struct PackageRec *p)
300 char **nameArray, **namePtr;
301 char **versionArray, **versionPtr;
302 int_32 *flagArray, *flagPtr;
307 nameArray = namePtr = malloc(p->numProv * sizeof(*nameArray));
308 rpmMessage(RPMMESS_VERBOSE, "Provides (%d):", p->numProv);
310 if (rd->flags & RPMSENSE_PROVIDES) {
311 rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
312 *namePtr++ = rd->name;
316 rpmMessage(RPMMESS_VERBOSE, "\n");
318 headerAddEntry(h, RPMTAG_PROVIDES, RPM_STRING_ARRAY_TYPE, nameArray, p->numProv);
322 if (p->numConflict) {
324 nameArray = namePtr = malloc(p->numConflict * sizeof(*nameArray));
325 versionArray = versionPtr =
326 malloc(p->numConflict * sizeof(*versionArray));
327 flagArray = flagPtr = malloc(p->numConflict * sizeof(*flagArray));
328 rpmMessage(RPMMESS_VERBOSE, "Conflicts (%d):", p->numConflict);
330 if (rd->flags & RPMSENSE_CONFLICTS) {
331 rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
332 *namePtr++ = rd->name;
333 *versionPtr++ = rd->version ? rd->version : "";
334 *flagPtr++ = rd->flags & RPMSENSE_SENSEMASK;
338 rpmMessage(RPMMESS_VERBOSE, "\n");
340 headerAddEntry(h, RPMTAG_CONFLICTNAME, RPM_STRING_ARRAY_TYPE,
341 nameArray, p->numConflict);
342 headerAddEntry(h, RPMTAG_CONFLICTVERSION, RPM_STRING_ARRAY_TYPE,
343 versionArray, p->numConflict);
344 headerAddEntry(h, RPMTAG_CONFLICTFLAGS, RPM_INT32_TYPE,
345 flagArray, p->numConflict);
354 nameArray = namePtr = malloc(p->numReq * sizeof(*nameArray));
355 versionArray = versionPtr = malloc(p->numReq * sizeof(*versionArray));
356 flagArray = flagPtr = malloc(p->numReq * sizeof(*flagArray));
357 rpmMessage(RPMMESS_VERBOSE, "Requires (%d):", p->numReq);
359 if (! ((rd->flags & RPMSENSE_PROVIDES) ||
360 (rd->flags & RPMSENSE_CONFLICTS))) {
361 rpmMessage(RPMMESS_VERBOSE, " %s", rd->name);
362 *namePtr++ = rd->name;
363 *versionPtr++ = rd->version ? rd->version : "";
364 *flagPtr++ = rd->flags & RPMSENSE_SENSEMASK;
368 rpmMessage(RPMMESS_VERBOSE, "\n");
370 headerAddEntry(h, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE,
371 nameArray, p->numReq);
372 headerAddEntry(h, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE,
373 versionArray, p->numReq);
374 headerAddEntry(h, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE,
375 flagArray, p->numReq);