FOSSology  4.4.0
Open Source License Compliance by Open Source Software
leaf.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2010-2013 Hewlett-Packard Development Company, L.P.
3 
4  SPDX-License-Identifier: GPL-2.0-only
5 */
6 
11 #include "buckets.h"
12 
13 extern int debug;
14 extern int DEB_SOURCE;
15 extern int DEB_BINARY;
16 
17 
30 FUNCTION int processLeaf(PGconn *pgConn, pbucketdef_t bucketDefArray,
31  puploadtree_t puploadtree, ppackage_t ppackage,
32  int agent_pk, int hasPrules)
33 {
34  int rv = 0;
35  int *bucketList;
36 
37  bucketList = getLeafBuckets(pgConn, bucketDefArray, puploadtree, ppackage, hasPrules);
38  if (bucketList)
39  {
40  if (debug)
41  {
42  printf(" buckets for pfile %d:",puploadtree->pfile_fk);
43  for (rv=0;bucketList[rv];rv++) printf("%d ",bucketList[rv]);
44  printf("\n");
45  }
46  rv = writeBuckets(pgConn, puploadtree->pfile_fk, puploadtree->uploadtree_pk,
47  bucketList, agent_pk,
48  bucketDefArray->nomos_agent_pk, bucketDefArray->bucketpool_pk);
49  }
50  else
51  rv = -1;
52 
53  free(bucketList);
54  return rv;
55 }
56 
57 
68 FUNCTION int *getLeafBuckets(PGconn *pgConn, pbucketdef_t in_bucketDefArray,
69  puploadtree_t puploadtree, ppackage_t ppackage,
70  int hasPrules)
71 {
72  char *fcnName = "getLeafBuckets";
73  int *bucket_pk_list = 0;
74  int *bucket_pk_list_start;
75  char filepath[512];
76  char sql[1024];
77  PGresult *result;
78  PGresult *resultmime;
79  int mimetype;
80  int numLics, licNumb;
81  int numBucketDefs = 0;
82  int match = 0; // bucket match
83  int foundmatch, foundmatch2;
84  int *pmatch_array;
85  int **ppmatch_array;
86  int *pfile_rfpks;
87  int rv;
88  int isPkg = 0;
89  int envnum;
90  pbucketdef_t bucketDefArray;
91  regex_file_t *regex_row;
92  char *argv[2];
93  char *envp[11];
94  char envbuf[4096];
95  char pkgtype=0;
96  pid_t pid;
97 
98  if (debug) printf("debug: %s pfile: %d\n", fcnName, puploadtree->pfile_fk);
99  /*** count how many elements are in in_bucketDefArray ***/
100  for (bucketDefArray = in_bucketDefArray; bucketDefArray->bucket_pk; bucketDefArray++)
101  numBucketDefs++;
102 
103  /* allocate return array to hold max number of bucket_pk's + 1 for null terminator */
104  bucket_pk_list_start = calloc(numBucketDefs+1, sizeof(int));
105  if (bucket_pk_list_start == 0)
106  {
107  printf("FATAL: out of memory allocating int array of %d elements\n", numBucketDefs+1);
108  return 0;
109  }
110  bucket_pk_list = bucket_pk_list_start;
111 
112  /*** select all the licenses for uploadtree_pk and children and agent_pk ***/
113  bucketDefArray = in_bucketDefArray;
114 // snprintf(sql, sizeof(sql),
115 // "select rf_shortname, rf_pk from license_file, license_ref where agent_fk=%d and pfile_fk=%d and rf_fk=rf_pk",
116 // bucketDefArray->nomos_agent_pk, puploadtree->pfile_fk);
117  snprintf(sql, sizeof(sql),
118  "SELECT distinct(rf_shortname) as rf_shortname, rf_pk \
119  from license_ref,license_file,\
120  (SELECT distinct(pfile_fk) as PF from uploadtree \
121  where upload_fk=%d \
122  and uploadtree.lft BETWEEN %d and %d) as SS \
123  where PF=pfile_fk and agent_fk=%d and rf_fk=rf_pk",
124  puploadtree->upload_fk, puploadtree->lft, puploadtree->rgt,
125  bucketDefArray->nomos_agent_pk);
126 
127  result = PQexec(pgConn, sql);
128  if (fo_checkPQresult(pgConn, result, sql, fcnName, __LINE__)) return 0;
129  numLics = PQntuples(result);
130 
131  /* make int array of rf_pk's for this pfile */
132  pfile_rfpks = calloc(numLics+1, sizeof(int));
133  if (pfile_rfpks == 0)
134  {
135  printf("FATAL: out of memory allocating int array of %d rf_pk elements\n", numLics+1);
136  return 0;
137  }
138  for (licNumb=0; licNumb < numLics; licNumb++)
139  pfile_rfpks[licNumb] = atoi(PQgetvalue(result, licNumb, 1));
140 
141 
142 #ifdef BOBG
143 printf("bobg: fileName: %s\n", puploadtree->ufile_name);
144 #endif
145  isPkg = (ppackage->pkgname[0]) ? 1 : 0;
146  /* loop through all the bucket defs in this pool */
147  for (bucketDefArray = in_bucketDefArray; bucketDefArray->bucket_pk; bucketDefArray++)
148  {
149  /* if this def is restricted to package (applies_to='p'),
150  then skip if this is not a package.
151  NOTE DEPENDENCY ON PKG ANALYSIS!
152  */
153  if (bucketDefArray->applies_to == 'p')
154  {
155  if (!isPkg) continue;
156  }
157  else
158  {
159  /* If this is a container, see if any of its children are in
160  this bucket. If so, then the container is in this bucket.
161  */
162  if ((!isPkg) && (IsContainer(puploadtree->ufile_mode)))
163  {
164  rv = childInBucket(pgConn, bucketDefArray, puploadtree);
165  if (rv == 1)
166  {
167  *bucket_pk_list = bucketDefArray->bucket_pk;
168  bucket_pk_list++;
169  match++;
170  }
171  else if (rv == -1) return 0; //error
172  continue;
173  }
174  }
175 
176 #ifdef BOBG
177 printf("bobg: check bucket_pk: %d\n", bucketDefArray->bucket_pk);
178 #endif
179  switch (bucketDefArray->bucket_type)
180  {
181  /*** 1 MATCH_EVERY ***/
182  case 1:
183  ppmatch_array = bucketDefArray->match_every;
184  if (!ppmatch_array) break;
185  while (*ppmatch_array)
186  {
187  /* is match_array contained in pfile_rfpks? */
188  if (arrayAinB(*ppmatch_array, pfile_rfpks))
189  {
190  *bucket_pk_list = bucketDefArray->bucket_pk;
191  bucket_pk_list++;
192  match++;
193  break;
194  }
195  ++ppmatch_array;
196  }
197  break;
198 
199  /*** 2 MATCH_ONLY ***/
200  case 2:
201  if (numLics == 0) break;
202  foundmatch = 1;
203  /* loop through pfile licenses to see if they are all found in the match_only list */
204  for (licNumb=0; licNumb < numLics; licNumb++)
205  {
206  /* if rf_pk doesn't match any value in match_only,
207  then pfile is not in this bucket */
208  pmatch_array = bucketDefArray->match_only;
209  while (*pmatch_array)
210  {
211  if (pfile_rfpks[licNumb] == *pmatch_array) break;
212  pmatch_array++;
213  }
214  if (!*pmatch_array)
215  {
216  /* no match, so pfile is not in this bucket */
217  foundmatch = 0;
218  break; /* break out of for loop */
219  }
220  }
221  if (foundmatch)
222  {
223  *bucket_pk_list = bucketDefArray->bucket_pk;
224  bucket_pk_list++;
225  match++;
226  }
227  break;
228 
229  /*** 3 REGEX ***/
230  case 3: /* does this regex match any license names for this pfile */
231  if (matchAnyLic(result, numLics, &bucketDefArray->compRegex))
232  {
233  /* regex matched! */
234  *bucket_pk_list = bucketDefArray->bucket_pk;
235  bucket_pk_list++;
236  match++;
237  }
238  break;
239 
240  /*** 4 EXEC ***/
241  case 4:
242  /* file to exec bucketDefArray->dataFilename
243  * Exec'd file returns 0 on true (file is in bucket).
244  * When a file is exec'd it can expect the following
245  * environment variables:
246  * FILENAME: name of file being checked
247  * LICENSES: pipe seperated list of licenses for this file.
248  * PKGVERS: Package version from pkg header
249  * VENDOR: Vendor from pkg header
250  * PKGNAME: simple package name (e.g. "cup", "mozilla-mail", ...)
251  of file being checked. Only applies to packages.
252  * SRCPKGNAME: Source package name
253  * UPLOADTREE_PK: uploadtree_pk
254  * PFILE_PK: pfile_pk
255  * PKGTYPE: 's' if source, 'b' if binary package, '' if not a package
256  */
257  /* put together complete file path to file */
258  snprintf(filepath, sizeof(filepath), "%s/bucketpools/%d/%s",
259  PROJECTSTATEDIR, bucketDefArray->bucketpool_pk, bucketDefArray->dataFilename);
260  if ((pid = fork()) < 0)
261  {
262  printf("FATAL: fork failure, %s\n", strerror(errno));
263  }
264  else
265  if (pid == 0) /* in child */
266  {
267  /* use TMPDIR for working directory
268  */
269  if ((rv = chdir("/tmp")))
270  {
271  printf("FATAL: exec bucket couldn't cd to /tmp\n");
272  exit(1);
273  }
274 
275  /* set up environment variables */
276  envnum = 0;
277  argv[0] = strdup(bucketDefArray->dataFilename);
278  argv[1] = 0;
279  sprintf(envbuf, "FILENAME=%s", puploadtree->ufile_name);
280  envp[envnum++] = strdup(envbuf);
281  /* create pipe seperated list of licenses */
282  strcpy(envbuf, "LICENSES=");
283  for (licNumb=0; licNumb < numLics; licNumb++)
284  {
285  if (envbuf[9]) strcat(envbuf, "|");
286  strcat(envbuf, PQgetvalue(result, licNumb, 0));
287  }
288  envp[envnum++] = strdup(envbuf);
289  sprintf(envbuf, "PKGVERS=%s", ppackage->pkgvers);
290  envp[envnum++] = strdup(envbuf);
291  sprintf(envbuf, "VENDOR=%s", ppackage->vendor);
292  envp[envnum++] =strdup(envbuf);
293  sprintf(envbuf, "PKGNAME=%s", ppackage->pkgname);
294  envp[envnum++] =strdup(envbuf);
295  sprintf(envbuf, "SRCPKGNAME=%s", ppackage->srcpkgname);
296  envp[envnum++] =strdup(envbuf);
297  sprintf(envbuf, "UPLOADTREE_PK=%d", puploadtree->uploadtree_pk);
298  envp[envnum++] =strdup(envbuf);
299  sprintf(envbuf, "PFILE_PK=%d", puploadtree->pfile_fk);
300  envp[envnum++] =strdup(envbuf);
301 
302  /* Only figure out PKGTYPE if this is a pkg
303  For Debian packages, check mimetype:
304  application/x-debian-package -- binary
305  application/x-debian-source -- source
306  For RPM's,
307  if srcpkgname is not null,
308  then this is a binary package
309  else this is a source package
310  */
311  pkgtype = 0;
312  if (isPkg)
313  {
314  if ((strstr(ppackage->srcpkgname,"none")==0)
315  || (ppackage->srcpkgname[0]==0)) pkgtype='b';
316  else
317  {
318  snprintf(sql, sizeof(sql),
319  "select pfile_mimetypefk from pfile where pfile_pk=%d",
320  puploadtree->pfile_fk);
321  resultmime = PQexec(pgConn, sql);
322  if (fo_checkPQresult(pgConn, resultmime, sql, fcnName, __LINE__)) return 0;
323  mimetype = *(PQgetvalue(resultmime, 0, 0));
324  PQclear(resultmime);
325  if (mimetype == DEB_SOURCE) pkgtype = 's';
326  else if (mimetype == DEB_BINARY) pkgtype = 'b';
327  else pkgtype = 's';
328  }
329  }
330  sprintf(envbuf, "PKGTYPE=%c", pkgtype);
331  envp[envnum++] =strdup(envbuf);
332 
333  envp[envnum++] = 0;
334  execve(filepath, argv, envp);
335  printf("FATAL: buckets execve (%s) failed, %s\n", filepath, strerror(errno));
336  exit(1);
337  }
338 
339  /* wait for exit */
340  if (waitpid(pid, &rv, 0) < 0)
341  {
342  printf("FATAL: waitpid, %s\n", strerror(errno));
343  return 0;
344  }
345  if (WIFSIGNALED(rv))
346  {
347  printf("FATAL: child %d died from signal %d", pid, WTERMSIG(rv));
348  return 0;
349  }
350  else
351  if (WIFSTOPPED(rv))
352  {
353  printf("FATAL: child %d stopped, signal %d", pid, WSTOPSIG(rv));
354  return 0;
355  }
356  else
357  if (WIFEXITED(rv))
358  {
359  if (WEXITSTATUS(rv) == 0)
360  {
361  *bucket_pk_list = bucketDefArray->bucket_pk;
362  bucket_pk_list++;
363  match++;
364  }
365  }
366  break;
367 
368  /*** 5 REGEX-FILE ***/
369  /* File format is:
370  {filetype1} {regex1} {op} {filetype2} {regex2}
371  filetype == 1 is filename
372  filetype == 2 is license
373  op to end of line is optional.
374  e.g. filename COPYRIGHT and license BSD.*clause
375  */
376  case 5:
377  regex_row = bucketDefArray->regex_row;
378  foundmatch = 0;
379  foundmatch2 = 0;
380  /* loop through each regex_row */
381  while (regex_row->ftype1)
382  {
383  /* switches do not have a default since values have already been validated
384  see init.c
385  */
386  switch (regex_row->ftype1)
387  {
388  case 1: // check regex against filename
389  foundmatch = !regexec(&regex_row->compRegex1, puploadtree->ufile_name, 0, 0, 0);
390  break;
391  case 2: // check regex against licenses
392  foundmatch = matchAnyLic(result, numLics, &regex_row->compRegex1);
393  break;
394  }
395 
396  /* no sense in evaluating last half if first have is a match and
397  op is an OR
398  */
399  if ((regex_row->op == 2) || !foundmatch)
400  if (regex_row->op)
401  {
402  switch (regex_row->ftype2)
403  {
404  case 1: // check regex against filename
405  foundmatch2 = !regexec(&regex_row->compRegex2, puploadtree->ufile_name, 0, 0, 0);
406  break;
407  case 2: // check regex against licenses
408  foundmatch2 = matchAnyLic(result, numLics, &regex_row->compRegex2);
409  break;
410  }
411  }
412 
413  switch (regex_row->op)
414  {
415  case 1: // AND
416  foundmatch = (foundmatch && foundmatch2) ? 1 : 0;
417  break;
418  case 2: // OR
419  foundmatch = (foundmatch || foundmatch2) ? 1 : 0;
420  break;
421  case 3: // Not
422  foundmatch = (foundmatch && !foundmatch2) ? 1 : 0;
423  break;
424  }
425 
426  if (foundmatch)
427  {
428  *bucket_pk_list = bucketDefArray->bucket_pk;
429  bucket_pk_list++;
430  match++;
431  }
432  regex_row++;
433  }
434  break;
435 
436  /*** 99 DEFAULT bucket. aka not in any other bucket ***/
437  case 99:
438  if (!match)
439  {
440  *bucket_pk_list = bucketDefArray->bucket_pk;
441  bucket_pk_list++;
442  match++;
443  }
444  break;
445 
446  /*** UNKNOWN BUCKET TYPE ***/
447  default:
448  printf("FATAL: Unknown bucket type %d, exiting...\n",
449  bucketDefArray->bucket_type);
450  exit(-1);
451  }
452 #ifdef BOBG
453 printf("bobg match: %d\n", match);
454 #endif
455  if (match && bucketDefArray->stopon == 'Y') break;
456  }
457 
458 #ifdef BOBG
459  printf("bobg exit GetLeafBuckets()\n");
460 #endif
461  free(pfile_rfpks);
462  PQclear(result);
463  return bucket_pk_list_start;
464 }
PGconn * pgConn
Database connection.
Definition: adj2nest.c:86
int agent_pk
Definition: agent.h:74
FUNCTION int matchAnyLic(PGresult *result, int numLics, regex_t *compRegex)
Does this regex match any license name for this pfile?
Definition: match.c:24
FUNCTION int childInBucket(PGconn *pgConn, pbucketdef_t bucketDef, puploadtree_t puploadtree)
Given a container uploadtree_pk and bucketdef, determine if any child is in this bucket.
Definition: child.c:26
int DEB_SOURCE
Definition: buckets.c:60
FUNCTION int processLeaf(PGconn *pgConn, pbucketdef_t bucketDefArray, puploadtree_t puploadtree, ppackage_t ppackage, int agent_pk, int hasPrules)
Determine which bucket(s) a leaf node is in and write results.
Definition: leaf.c:30
int DEB_BINARY
Definition: buckets.c:62
int debug
Definition: buckets.c:57
FUNCTION int * getLeafBuckets(PGconn *pgConn, pbucketdef_t in_bucketDefArray, puploadtree_t puploadtree, ppackage_t ppackage, int hasPrules)
Determine what buckets the pfile is in.
Definition: leaf.c:68
int fo_checkPQresult(PGconn *pgConn, PGresult *result, char *sql, char *FileID, int LineNumb)
Check the result status of a postgres SELECT.
Definition: libfossdb.c:170
int ** match_every
Definition: buckets.h:66
int nomos_agent_pk
Definition: buckets.h:70
char applies_to
Definition: buckets.h:69
regex_file_t * regex_row
Definition: buckets.h:67
regex_t compRegex
Definition: buckets.h:63
char * dataFilename
Definition: buckets.h:64
int * match_only
Definition: buckets.h:65
Store the results of a regex match.
Definition: scanners.hpp:28
char vendor[256]
Definition: buckets.h:119
char pkgname[256]
Definition: buckets.h:117
char srcpkgname[256]
Definition: buckets.h:120
char pkgvers[256]
Definition: buckets.h:118
REGEX-FILE bucket type.
Definition: buckets.h:42
char * ufile_name
Definition: buckets.h:102
FUNCTION int arrayAinB(int *arrayA, int *arrayB)
Verify that all the values in array A are also in B.
Definition: validate.c:24
FUNCTION int writeBuckets(PGconn *pgConn, int pfile_pk, int uploadtree_pk, int *bucketList, int agent_pk, int nomosagent_pk, int bucketpool_pk)
Write bucket results to either db (bucket_file, bucket_container) or stdout.
Definition: write.c:29