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