FOSSology  4.7.0-rc1
Open Source License Compliance by Open Source Software
pkgagent.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2011-2014 Hewlett-Packard Development Company, L.P.
3 
4  SPDX-License-Identifier: GPL-2.0-only
5 */
19 #include "pkgagent.h"
20 
21 int Verbose = 0;
22 PGconn* db_conn = NULL;
23 
25 int tag[15] = { RPMTAG_NAME,
26  RPMTAG_EPOCH,
27  RPMTAG_ARCH,
28  RPMTAG_VERSION,
29  RPMTAG_LICENSE,
30  RPMTAG_GROUP,
31  RPMTAG_PACKAGER,
32  RPMTAG_RELEASE,
33  RPMTAG_BUILDTIME,
34  RPMTAG_VENDOR,
35  RPMTAG_URL,
36  RPMTAG_SOURCERPM,
37  RPMTAG_SUMMARY,
38  RPMTAG_DESCRIPTION,
39  RPMTAG_REQUIRENAME
40 };
41 
51 void EscapeString (char *sourceString, char *escString, int esclen)
52 {
53  int len;
54  int error;
55 
56  /* remove any backslashes from the string as they don't escape properly
57  * for example, "don\'t" in the input will cause an insert error
58  */
59  char *cp = (char *)sourceString;
60  while(*cp)
61  {
62  if (*cp == '\\') *cp = ' ';
63  cp++;
64  }
65 
66  /* Revert changes of revision 3721
67  * If the size of input string larger than destination buffer,
68  * will cut of the input string with destination buffer
69  */
70  len = strlen(sourceString);
71  if ( len > esclen/2 )
72  len = esclen/2 - 1;
73 
74  /* check the size of the destination buffer */
75  /* comment this changes, will revisit later */
76  /*
77  if((len = strlen(sourceString)) > esclen/2) {
78  printf("ERROR %s.%d: length of input string is too large\n", __FILE__, __LINE__);
79  printf("ERROR length of string was %d, max length is %d\n", len, esclen/2);
80  return;
81  }
82  */
83  //printf("TEST:esclen---%d,sourcelen---%d\n",esclen,len);
84  PQescapeStringConn(db_conn, escString, sourceString, len, &error);
85  if (error)
86  printf("WARNING: %s line %d: Error escaping string with multibype character set?\n",__FILE__, __LINE__ );
87 }
88 
101 char * GetFieldValue (char *Sin, char *Field, int FieldMax,
102  char *Value, int ValueMax, char Separator)
103 {
104  int s,f,v;
105  int GotQuote;
106 
107  memset(Field,0,FieldMax);
108  memset(Value,0,ValueMax);
109 
110  while(isspace(Sin[0])) Sin++; /* skip initial spaces */
111  if (Sin[0]=='\0') return(NULL);
112  f=0; v=0;
113 
114  for(s=0; (Sin[s] != '\0') && !isspace(Sin[s]) && (Sin[s] != '='); s++)
115  {
116  Field[f++] = Sin[s];
117  }
118  while(isspace(Sin[s])) s++; /* skip spaces after field name */
119  if (Sin[s] != Separator) /* if it is not a field, then just return it. */
120  {
121  return(Sin+s);
122  }
123  if (Sin[s]=='\0') return(NULL);
124  s++; /* skip '=' */
125  while(isspace(Sin[s])) s++; /* skip spaces after '=' */
126  if (Sin[s]=='\0') return(NULL);
127 
128  GotQuote='\0';
129  if ((Sin[s]=='\'') || (Sin[s]=='"'))
130  {
131  GotQuote = Sin[s];
132  s++; /* skip quote */
133  if (Sin[s]=='\0') return(NULL);
134  }
135  if (GotQuote)
136  {
137  for( ; (Sin[s] != '\0') && (Sin[s] != GotQuote); s++)
138  {
139  if (Sin[s]=='\\') Value[v++]=Sin[++s];
140  else Value[v++]=Sin[s];
141  }
142  }
143  else
144  {
145  /* if it gets here, then there is no quote */
146  for( ; (Sin[s] != '\0') && !isspace(Sin[s]); s++)
147  {
148  if (Sin[s]=='\\') Value[v++]=Sin[++s];
149  else Value[v++]=Sin[s];
150  }
151  }
152  while(isspace(Sin[s])) s++; /* skip spaces */
153  return(Sin+s);
154 } /* GetFieldValue() */
155 
156 
163 {
164  char mimetype[128];
165  char sqlbuf[1024];
166  PGresult *result;
167  int mimetypepk = 0;
168  int debmimetypepk = 0;
169  int debmodernmimetypepk = 0;
170  int debsrcmimetypepk = 0;
171  int numrows;
172  int i;
173  char *uploadtree_tablename;
174 
175  struct rpmpkginfo *pi;
176  struct debpkginfo *dpi;
177 
178  pi = (struct rpmpkginfo *)malloc(sizeof(struct rpmpkginfo));
179  dpi = (struct debpkginfo *)malloc(sizeof(struct debpkginfo));
180 
181  rpmReadConfigFiles(NULL, NULL);
182 
183  /* "pkgagent" needs to know what? */
184 
185  /* "pkgagent" needs to know the mimetype for
186  * 'application/x-rpm' and 'application/x-debian-package' and 'application/x-debian-source'*/
187  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-rpm' LIMIT 1;");
188  result = PQexec(db_conn, sqlbuf);
189  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
190  {
191  free(pi);
192  free(dpi);
193  exit(-1);
194  }
195  mimetypepk = atoi(PQgetvalue(result, 0, 0));
196  PQclear(result);
197  if ( mimetypepk == 0 )
198  {
199  snprintf(sqlbuf, sizeof(sqlbuf), "INSERT INTO mimetype (mimetype_name) VALUES ('application/x-rpm');");
200  result = PQexec(db_conn, sqlbuf);
201  if (fo_checkPQcommand(db_conn, result, sqlbuf, __FILE__, __LINE__))
202  {
203  free(pi);
204  free(dpi);
205  exit(-1);
206  }
207  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-rpm' LIMIT 1;");
208  result = PQexec(db_conn, sqlbuf);
209  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
210  {
211  free(pi);
212  free(dpi);
213  exit(-1);
214  }
215  mimetypepk = atoi(PQgetvalue(result, 0, 0));
216  PQclear(result);
217  if ( mimetypepk == 0 )
218  {
219  LOG_ERROR("pkgagent rpm mimetype not installed!");
220  free(pi);
221  free(dpi);
222  return (-1);
223  }
224  }
225  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-debian-package' LIMIT 1;");
226  result = PQexec(db_conn, sqlbuf);
227  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
228  {
229  free(pi);
230  free(dpi);
231  exit(-1);
232  }
233  debmimetypepk = atoi(PQgetvalue(result, 0, 0));
234  PQclear(result);
235  if ( debmimetypepk == 0 )
236  {
237  snprintf(sqlbuf, sizeof(sqlbuf), "INSERT INTO mimetype (mimetype_name) VALUES ('application/x-debian-package');");
238  result = PQexec(db_conn, sqlbuf);
239  if (fo_checkPQcommand(db_conn, result, sqlbuf, __FILE__, __LINE__))
240  {
241  free(pi);
242  free(dpi);
243  exit(-1);
244  }
245  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-debian-package' LIMIT 1;");
246  result = PQexec(db_conn, sqlbuf);
247  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
248  {
249  free(pi);
250  free(dpi);
251  exit(-1);
252  }
253  debmimetypepk = atoi(PQgetvalue(result, 0, 0));
254  PQclear(result);
255  if ( debmimetypepk == 0 )
256  {
257  LOG_ERROR("pkgagent deb mimetype not installed!");
258  free(pi);
259  free(dpi);
260  return (-1);
261  }
262  }
263  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/vnd.debian.binary-package' LIMIT 1;");
264  result = PQexec(db_conn, sqlbuf);
265  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
266  {
267  free(pi);
268  free(dpi);
269  exit(-1);
270  }
271  debmodernmimetypepk = atoi(PQgetvalue(result, 0, 0));
272  PQclear(result);
273  if ( debmodernmimetypepk == 0 )
274  {
275  snprintf(sqlbuf, sizeof(sqlbuf), "INSERT INTO mimetype (mimetype_name) VALUES ('application/vnd.debian.binary-package');");
276  result = PQexec(db_conn, sqlbuf);
277  if (fo_checkPQcommand(db_conn, result, sqlbuf, __FILE__, __LINE__))
278  {
279  printf("ERROR: unable to insert modern debian mimetype %s\n", sqlbuf);
280  free(pi);
281  free(dpi);
282  exit(-1);
283  }
284  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/vnd.debian.binary-package' LIMIT 1;");
285  result = PQexec(db_conn, sqlbuf);
286  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
287  {
288  free(pi);
289  free(dpi);
290  exit(-1);
291  }
292  debmodernmimetypepk = atoi(PQgetvalue(result, 0, 0));
293  PQclear(result);
294  if ( debmodernmimetypepk == 0 )
295  {
296  LOG_ERROR("pkgagent modern debian mimetype not installed!");
297  free(pi);
298  free(dpi);
299  return (-1);
300  }
301  }
302  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-debian-source' LIMIT 1;");
303  result = PQexec(db_conn, sqlbuf);
304  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
305  {
306  free(pi);
307  free(dpi);
308  exit(-1);
309  }
310  debsrcmimetypepk = atoi(PQgetvalue(result, 0, 0));
311  PQclear(result);
312  if ( debsrcmimetypepk == 0 )
313  {
314  snprintf(sqlbuf, sizeof(sqlbuf), "INSERT INTO mimetype (mimetype_name) VALUES ('application/x-debian-source');");
315  result = PQexec(db_conn, sqlbuf);
316  if (fo_checkPQcommand(db_conn, result, sqlbuf, __FILE__, __LINE__))
317  {
318  free(pi);
319  free(dpi);
320  exit(-1);
321  }
322  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-debian-source' LIMIT 1;");
323  result = PQexec(db_conn, sqlbuf);
324  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
325  {
326  free(pi);
327  free(dpi);
328  exit(-1);
329  }
330  debsrcmimetypepk = atoi(PQgetvalue(result, 0, 0));
331  PQclear(result);
332  if ( debsrcmimetypepk == 0 )
333  {
334  LOG_ERROR("pkgagent deb source mimetype not installed!");
335  free(pi);
336  free(dpi);
337  return (-1);
338  }
339  }
340 
341  if (!upload_pk) // when upload_pk is empty
342  {
343  free(pi);
344  free(dpi);
345  return -1;
346  }
348  if (NULL == uploadtree_tablename) uploadtree_tablename = strdup("uploadtree_a");
349  /* retrieve the records to process */
350  snprintf(sqlbuf, sizeof(sqlbuf),
351  "SELECT pfile_pk as pfile_pk, pfile_sha1 || '.' || pfile_md5 || '.' || pfile_size AS pfilename, mimetype_name as mimetype from pfile, mimetype, (SELECT distinct(pfile_fk) as PF from %s where upload_fk='%ld') as SS where PF=pfile_pk and (pfile_mimetypefk='%d' or pfile_mimetypefk='%d' OR pfile_mimetypefk='%d' OR pfile_mimetypefk='%d') and mimetype_pk=pfile_mimetypefk and (not exists (SELECT 1 from pkg_rpm where pkg_rpm.pfile_fk = pfile_pk)) and (not exists (SELECT 1 from pkg_deb where pkg_deb.pfile_fk = pfile_pk))", uploadtree_tablename, upload_pk, mimetypepk, debmimetypepk, debsrcmimetypepk, debmodernmimetypepk);
352  result = PQexec(db_conn, sqlbuf);
353  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
354  {
355  free(pi);
356  free(dpi);
357  exit(-1);
358  }
359 
360  numrows = PQntuples(result);
361  for (i=0; i<numrows; i++)
362  {
363  char *repFile = NULL;
364 
365  memset(pi,0,sizeof(struct rpmpkginfo));
366  memset(dpi,0,sizeof(struct debpkginfo));
367 
368  strcpy(mimetype, PQgetvalue(result, i, 2));
369  /*
370  * if mimetype='application/x-rpm' process RPM packages
371  * if mimetype='application/x-debian-package' process DEBIAN packages
372  * if mimetype='application/x-debian-source' process DEBIAN source packages
373  * */
374  if (!strcasecmp(mimetype,"application/x-rpm")) {
375  pi->pFileFk = atoi(PQgetvalue(result, i, 0));
376  strncpy(pi->pFile, PQgetvalue(result, i, 1), sizeof(pi->pFile)-1);
377  pi->pFile[sizeof(pi->pFile)-1] = '\0';
378  repFile = fo_RepMkPath("files", pi->pFile);
379  if (!repFile) {
380  LOG_FATAL("pfile %ld PkgAgent unable to open file %s",
381  pi->pFileFk, pi->pFile);
382  return (-1);
383  }
384  if (GetMetadata(repFile,pi) != -1){
385  RecordMetadataRPM(pi);
386  }
387  /* free memory */
388  int i;
389  for(i=0; i< pi->req_size;i++)
390  free(pi->requires[i]);
391  free(pi->requires);
392  }
393  else if (!strcasecmp(mimetype, "application/x-debian-package") ||
394  !strcasecmp(mimetype, "application/vnd.debian.binary-package")){
395  dpi->pFileFk = atoi(PQgetvalue(result, i, 0));
396  strncpy(dpi->pFile, PQgetvalue(result, i, 1), sizeof(dpi->pFile)-1);
397  dpi->pFile[sizeof(dpi->pFile)-1] = '\0';
398  if (GetMetadataDebBinary(upload_pk, dpi) != -1){
399  if (RecordMetadataDEB(dpi) != 0) continue;
400  }
401  /* free memory */
402  if (dpi->depends) {
403  int i;
404  for(i=0; i< dpi->dep_size;i++)
405  free(dpi->depends[i]);
406  free(dpi->depends);
407  dpi->depends = NULL;
408  dpi->dep_size = 0;
409  }
410  }
411  else if (!strcasecmp(mimetype, "application/x-debian-source")){
412  dpi->pFileFk = atoi(PQgetvalue(result, i, 0));
413  strncpy(dpi->pFile, PQgetvalue(result, i, 1), sizeof(dpi->pFile)-1);
414  dpi->pFile[sizeof(dpi->pFile)-1] = '\0';
415  repFile = fo_RepMkPath("files", dpi->pFile);
416  if (!repFile) {
417  LOG_FATAL("pfile %ld PkgAgent unable to open file %s\n",
418  dpi->pFileFk, dpi->pFile);
419  return (-1);
420  }
421  if (GetMetadataDebSource(repFile,dpi) != -1){
422  RecordMetadataDEB(dpi);
423  }
424  /* free memory */
425  if (dpi->depends) {
426  int i;
427  for(i=0; i< dpi->dep_size;i++)
428  free(dpi->depends[i]);
429  free(dpi->depends);
430  dpi->depends = NULL;
431  dpi->dep_size = 0;
432  }
433  } else {
434  printf("LOG: Not RPM and DEBIAN package!\n");
435  }
437  }
438  PQclear(result);
439  rpmFreeCrypto();
440  rpmFreeMacros(NULL);
441  free(pi);
442  free(dpi);
443  return (0);
444 }/*ProcessUpload (long upload_pk)*/
445 
451 void ReadHeaderInfo(Header header, struct rpmpkginfo *pi)
452 {
453  char fmt[128];
454  char * msgstr;
455  const char * errstr;
456  int i,j;
457  long *tp,t;
458  int header_status;
459 
460  struct rpmtd_s req;
461  rpm_count_t data_size;
462 
463  for (i = 0; i < 14; i++) {
464  memset(fmt, 0, sizeof(fmt));
465  strcat( fmt, "%{");
466  strcat( fmt, rpmTagGetName(tag[i]));
467  strcat( fmt, "}\n");
468 
469  msgstr = headerFormat(header, fmt, &errstr);
470  if (msgstr != NULL){
471  trim(msgstr);
472  printf("%s:%s\n",rpmTagGetName(tag[i]),msgstr);
473  switch (tag[i]) {
474  case RPMTAG_NAME:
475  EscapeString(msgstr, pi->pkgName, sizeof(pi->pkgName));
476  break;
477  case RPMTAG_EPOCH:
478  EscapeString(msgstr, pi->pkgAlias, sizeof(pi->pkgAlias));
479  break;
480  case RPMTAG_ARCH:
481  EscapeString(msgstr, pi->pkgArch, sizeof(pi->pkgArch));
482  break;
483  case RPMTAG_VERSION:
484  EscapeString(msgstr, pi->version, sizeof(pi->version));
485  break;
486  case RPMTAG_LICENSE:
487  EscapeString(msgstr, pi->license, sizeof(pi->license));
488  break;
489  case RPMTAG_GROUP:
490  EscapeString(msgstr, pi->group, sizeof(pi->group));
491  break;
492  case RPMTAG_PACKAGER:
493  EscapeString(msgstr, pi->packager, sizeof(pi->packager));
494  break;
495  case RPMTAG_RELEASE:
496  EscapeString(msgstr, pi->release, sizeof(pi->release));
497  break;
498  case RPMTAG_BUILDTIME:
499  t = atol(msgstr);
500  tp = &t;
501  strncpy(pi->buildDate,trim(asctime(gmtime((time_t*)tp))),sizeof(pi->buildDate)-1);
502  pi->buildDate[sizeof(pi->buildDate)-1] = '\0';
503  break;
504  case RPMTAG_VENDOR:
505  EscapeString(msgstr, pi->vendor, sizeof(pi->vendor));
506  break;
507  case RPMTAG_URL:
508  EscapeString(msgstr, pi->url, sizeof(pi->url));
509  break;
510  case RPMTAG_SOURCERPM:
511  EscapeString(msgstr, pi->sourceRPM,sizeof(pi->sourceRPM));
512  break;
513  case RPMTAG_SUMMARY:
514  EscapeString(msgstr, pi->summary, sizeof(pi->summary));
515  break;
516  case RPMTAG_DESCRIPTION:
517  EscapeString(msgstr, pi->description, sizeof(pi->description));
518  break;
519  default:
520  break;
521  }
522  }
523  free((void *)msgstr);
524  }
525  if (Verbose > 1) { printf("Name:%s\n",pi->pkgName);}
526  header_status = headerGet(header, tag[14], &req, HEADERGET_DEFAULT);
527  if (header_status) {
528  data_size = rpmtdCount(&req);
529  pi->requires = calloc(data_size, sizeof(char *));
530  for (j=0; j<(int)data_size;j++){
531  const char * temp = rpmtdNextString(&req);
532  pi->requires[j] = malloc(MAXCMD);
533  strncpy(pi->requires[j], temp, MAXCMD - 1);
534  pi->requires[j][MAXCMD - 1] = '\0';
535  }
536  pi->req_size = data_size;
537  rpmtdFreeData(&req);
538  }
539 
540  if (Verbose > 1) {
541  printf("Size:%d\n",pi->req_size);
542  for (j=0; j<pi->req_size;j++){
543  printf("REQ:%s\n",pi->requires[j]);
544  }
545  printf("Name:%s\n",pi->sourceRPM);
546  }
547 } /* ReadHeaderInfo(Header header, struct rpmpkginfo *pi) */
548 
555 int GetMetadata (char *pkg, struct rpmpkginfo *pi)
556 {
557  //rpmpi.pFileFk = 4234634;
558  //if (PKG_RPM)
559  //{
560  FD_t fd;
561  rpmRC rpmrc;
562  Header header;
563  rpmts ts;
564  rpmVSFlags vsflags;
565 
566  vsflags = RPMVSF_DEFAULT;
567  ts = (rpmts) rpmtsCreate();
568 
569  fd = Fopen(pkg,"r");
570  if ( fd == NULL ||Ferror(fd)){
571  rpmlog(RPMLOG_ERR, "open of %s failed: %s\n", pkg, Fstrerror(fd));
572  if (fd){
573  Fclose(fd);
574  }
575  return (-1);
576  }
577 
578  vsflags |= _RPMVSF_NOSIGNATURES;
579  vsflags |= _RPMVSF_NODIGESTS;
580  vsflags |= RPMVSF_NOHDRCHK;
581  vsflags |= RPMVSF_NEEDPAYLOAD;
582 
583  rpmtsSetVSFlags(ts, vsflags);
584 
585  //rpmReadConfigFiles(NULL, NULL);
586  rpmrc = rpmReadPackageFile(ts, fd, pkg,&header);
587  Fclose(fd);
588  ts = (rpmts) rpmtsFree(ts);
589 
590  switch (rpmrc) {
591  case RPMRC_OK:
592  case RPMRC_NOKEY:
593  case RPMRC_NOTTRUSTED:
594  break;
595  case RPMRC_NOTFOUND:
596  case RPMRC_FAIL:
597  default:
598  rpmlog(RPMLOG_ERR, "%s cannot be read or is not an RPM.\n", pkg);
599  return (-1);
600  }
601  ReadHeaderInfo(header, pi);
602  //rpmFreeMacros(NULL);
603  header = headerFree(header);
604  //}
605  return (0);
606 } /* GetMetadata(char *pkg, struct rpmpkginfo *pi) */
607 
614 {
615  char SQL[MAXCMD];
616  PGresult *result;
617  int pkg_pk;
618 
619  memset(SQL,0,sizeof(SQL));
620  snprintf(SQL,sizeof(SQL),"SELECT pfile_fk FROM pkg_rpm WHERE pfile_fk = %ld;",pi->pFileFk);
621  result = PQexec(db_conn, SQL);
622  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
623  if (PQntuples(result) <=0)
624  {
625  PQclear(result);
626  memset(SQL,0,sizeof(SQL));
627  result = PQexec(db_conn, "BEGIN;");
628  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
629  PQclear(result);
630 
631  snprintf(SQL,sizeof(SQL),"INSERT INTO pkg_rpm (pkg_name,pkg_alias,pkg_arch,version,rpm_filename,license,pkg_group,packager,release,build_date,vendor,url,source_rpm,summary,description,pfile_fk) values (E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',%ld);",
632  trim(pi->pkgName),trim(pi->pkgAlias),trim(pi->pkgArch),trim(pi->version),
633  trim(pi->rpmFilename),trim(pi->license),trim(pi->group),trim(pi->packager),
634  trim(pi->release),pi->buildDate,trim(pi->vendor),trim(pi->url),trim(pi->sourceRPM),
635  trim(pi->summary),trim(pi->description),pi->pFileFk);
636  result = PQexec(db_conn, SQL);
637  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
638  {
639  PQexec(db_conn, "ROLLBACK;");
640  return (-1);
641  }
642  PQclear(result);
643 
644  result = PQexec(db_conn,"SELECT currval('pkg_rpm_pkg_pk_seq'::regclass);");
645  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
646  pkg_pk = atoi(PQgetvalue(result,0,0));
647  PQclear(result);
648 
649  if (Verbose) { printf("pkg_pk:%d\n",pkg_pk);}
650  int i;
651  for (i=0;i<pi->req_size;i++)
652  {
653  memset(SQL,0,sizeof(SQL));
654  snprintf(SQL,sizeof(SQL),"INSERT INTO pkg_rpm_req (pkg_fk,req_value) values (%d,E'%s');",pkg_pk,trim(pi->requires[i]));
655  result = PQexec(db_conn, SQL);
656  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
657  {
658  PQexec(db_conn, "ROLLBACK;");
659  return (-1);
660  }
661  PQclear(result);
662  }
663  result = PQexec(db_conn, "COMMIT;");
664  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
665  PQclear(result);
666  }
667  return (0);
668 } /* RecordMetadata(struct rpmpkginfo *pi) */
669 
670 
679 char * ParseDebFile(char *Sin, char *Field, char *Value)
680 {
681  int s,f,v;
682 
683  memset(Field,0,MAXCMD);
684  memset(Value,0,MAXCMD);
685 
686  f=0; v=0;
687  if(!isspace(Sin[0]))
688  {
689  for(s=0; (Sin[s] != '\0') && !isspace(Sin[s]) && (Sin[s] != ':'); s++)
690  {
691  Field[f++] = Sin[s];
692  }
693  while(isspace(Sin[s])) s++;
694  if (Sin[s] != ':')
695  {
696  return(Sin+s);
697  }
698  s++;
699  while(isspace(Sin[s])) s++;
700 
701  for( ; Sin[s] != '\0'; s++)
702  {
703  Value[v++]=Sin[s];
704  }
705  if (Verbose) { printf("Field is %s and Value is %s", Field, Value);}
706  return(Sin+s);
707  } else
708  {
709  if (Verbose) { printf("ExValue is %s", Sin);}
710  return(Sin);
711  }
712 } /* ParseDebFile(char *Sin, char *Field, char *Value) */
713 
721 {
722  char *repfile;
723  char *filename;
724  char SQL[MAXCMD];
725  PGresult *result;
726  unsigned long lft, rgt;
727 
728  FILE *fp;
729  char field[MAXCMD];
730  char value[MAXCMD];
731  char line[MAXCMD];
732  char *s = NULL;
733  char temp[MAXCMD];
734  char *uploadtree_tablename;
735 
736  if (!upload_pk) return -1; // when upload_pk is empty
738  if (NULL == uploadtree_tablename) uploadtree_tablename = strdup("uploadtree_a");
739  /* Get the debian control file's repository path */
740  /* First get the uploadtree bounds (lft,rgt) for the package */
741  snprintf(SQL,sizeof(SQL),"SELECT lft,rgt FROM %s WHERE upload_fk = %ld AND pfile_fk = %ld limit 1",
743  result = PQexec(db_conn, SQL);
744  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
745  if (PQntuples(result) == 0)
746  {
747  LOG_ERROR("Missing debian package (internal data inconsistancy). SQL: %s\n", SQL);
748  PQclear(result);
749  return (-1);
750  }
751  lft = strtoul(PQgetvalue(result,0,0), NULL, 10);
752  rgt = strtoul(PQgetvalue(result,0,1), NULL, 10);
753  PQclear(result);
754 
755  snprintf(SQL,sizeof(SQL),"SELECT pfile_sha1 || '.' || pfile_md5 || '.' || pfile_size FROM pfile, uploadtree where (pfile_pk=pfile_fk) and (upload_fk = %ld) AND (lft > %ld) AND (rgt < %ld) AND (ufile_name = 'control')",
756  upload_pk, lft, rgt);
757  result = PQexec(db_conn, SQL);
758  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
759  if (PQntuples(result) > 0)
760  {
761  filename = PQgetvalue(result,0,0);
762  repfile = fo_RepMkPath("files", filename);
763  if (!repfile) {
764  LOG_FATAL("PkgAgent unable to open file %s\n",filename);
765  return (-1);
766  }
767  PQclear(result);
768  }
769  else
770  {
771  PQclear(result);
772  printf("LOG: Unable to find debian/control file! This file had wrong mimetype, ignore it!\n");
773  memset(SQL,0,sizeof(SQL));
774  snprintf(SQL,sizeof(SQL),"UPDATE pfile SET pfile_mimetypefk = NULL WHERE pfile_pk = %ld;", pi->pFileFk);
775  result = PQexec(db_conn, SQL);
776  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
777  PQclear(result);
778  return (-1);
779  }
780 
781  /* Parse the debian/control file to get every Field and Value */
782  if ((fp = fopen(repfile, "r")) == NULL){
783  LOG_FATAL("Unable to open debian/control file %s\n",repfile);
784  return (-1);
785  }
786 
787  while (fgets(line,MAXCMD,fp)!=NULL)
788  {
789  s = ParseDebFile(line,field,value);
790  trim(value);
791  if (!strcasecmp(field, "Description")) {
792  EscapeString(value, pi->summary, sizeof(pi->summary));
793  strcpy(temp, "");
794  }
795  if (s[0] != '\0') {
796  if ((strlen(temp) + strlen(s)) >= MAXCMD )
797  continue;
798  else
799  strcat(temp,s);
800  }
801  if (!strcasecmp(field, "Package")) {
802  EscapeString(value, pi->pkgName, sizeof(pi->pkgName));
803  }
804  if (!strcasecmp(field, "Version")) {
805  EscapeString(value, pi->version, sizeof(pi->version));
806  }
807  if (!strcasecmp(field, "Architecture")) {
808  EscapeString(value, pi->pkgArch, sizeof(pi->pkgArch));
809  }
810  if (!strcasecmp(field, "Maintainer")) {
811  EscapeString(value, pi->maintainer, sizeof(pi->maintainer));
812  }
813  if (!strcasecmp(field, "Installed-Size")) {
814  pi->installedSize=atol(value);
815  }
816  if (!strcasecmp(field, "Section")) {
817  EscapeString(value, pi->section, sizeof(pi->section));
818  }
819  if (!strcasecmp(field, "Priority")) {
820  EscapeString(value, pi->priority, sizeof(pi->priority));
821  }
822  if (!strcasecmp(field, "Homepage")) {
823  EscapeString(value, pi->homepage, sizeof(pi->homepage));
824  }
825  if (!strcasecmp(field, "Source")) {
826  EscapeString(value, pi->source, sizeof(pi->source));
827  }
828  if (!strcasecmp(field, "Depends")) {
829  char *depends = NULL;
830  char countcopy[MAXCMD];
831  char splitcopy[MAXCMD];
832  int size,i;
833  size_t length = MAXLENGTH;
834  size = 0;
835  if (value[0] != '\0'){
836  strncpy(countcopy, value, sizeof(countcopy)-1);
837  countcopy[sizeof(countcopy)-1] = '\0';
838  depends = strtok(countcopy, ",");
839  while (depends && (depends[0] != '\0')) {
840  if (strlen(depends) >= length)
841  length = strlen(depends) + 1;
842  depends = strtok(NULL, ",");
843  size++;
844  }
845  if (Verbose) { printf("SIZE:%d\n", size);}
846 
847  strncpy(splitcopy, value, sizeof(splitcopy)-1);
848  splitcopy[sizeof(splitcopy)-1] = '\0';
849  pi->depends = calloc(size, sizeof(char *));
850  depends = strtok(splitcopy, ",");
851  for (i=0; i<size; i++){
852  pi->depends[i] = calloc(length, sizeof(char));
853  if (depends) {
854  strncpy(pi->depends[i], depends, length - 1);
855  pi->depends[i][length - 1] = '\0';
856  depends = strtok(NULL, ",");
857  }
858  }
859  pi->dep_size = size;
860  }
861  }
862  }
863  EscapeString(temp, pi->description, sizeof(pi->description));
864 
865  fclose(fp);
866  free(repfile);
867  return (0);
868 }/* GetMetadataDebBinary(struct debpkginfo *pi) */
869 
876 {
877  char SQL[MAXCMD];
878  PGresult *result;
879  int pkg_pk;
880 
881  memset(SQL,0,sizeof(SQL));
882  snprintf(SQL,sizeof(SQL),"SELECT pfile_fk FROM pkg_deb WHERE pfile_fk = %ld;",pi->pFileFk);
883  result = PQexec(db_conn, SQL);
884  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
885  if (PQntuples(result) <=0)
886  {
887  PQclear(result);
888  memset(SQL,0,sizeof(SQL));
889  result = PQexec(db_conn, "BEGIN;");
890  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
891  PQclear(result);
892 
893  snprintf(SQL,sizeof(SQL),"INSERT INTO pkg_deb (pkg_name,pkg_arch,version,maintainer,installed_size,section,priority,homepage,source,summary,description,format,uploaders,standards_version,pfile_fk) values (E'%s',E'%s',E'%s',E'%s',%d,E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',E'%s',%ld);",
894  trim(pi->pkgName),trim(pi->pkgArch),trim(pi->version),trim(pi->maintainer),
895  pi->installedSize,trim(pi->section),trim(pi->priority),trim(pi->homepage),
896  trim(pi->source),trim(pi->summary),trim(pi->description),trim(pi->format),
897  trim(pi->uploaders),trim(pi->standardsVersion),pi->pFileFk);
898  result = PQexec(db_conn, SQL);
899  // ignore error
900  if ((result==0) || ((PQresultStatus(result) != PGRES_COMMAND_OK)))
901  {
902  LOG_FATAL("Error inserting, SQL is: %s, error code is:%s\n", SQL, PQresultErrorField(result, PG_DIAG_SQLSTATE));
903  PQexec(db_conn, "ROLLBACK;");
904  if (result) PQclear(result);
905  return (-1);
906  } else
907  {
908  PQclear(result);
909  }
910 
911  result = PQexec(db_conn,"SELECT currval('pkg_deb_pkg_pk_seq'::regclass);");
912  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
913  pkg_pk = atoi(PQgetvalue(result,0,0));
914  PQclear(result);
915 
916  if (Verbose) { printf("pkg_pk:%d\n",pkg_pk);}
917  int i;
918  for (i=0;i<pi->dep_size;i++)
919  {
920  memset(SQL,0,sizeof(SQL));
921  snprintf(SQL,sizeof(SQL),"INSERT INTO pkg_deb_req (pkg_fk,req_value) values (%d,E'%s');",pkg_pk,trim(pi->depends[i]));
922  if (Verbose) { printf("DEPENDS:%s\n",pi->depends[i]);}
923  result = PQexec(db_conn, SQL);
924  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
925  {
926  PQexec(db_conn, "ROLLBACK;");
927  return (-1);
928  }
929  PQclear(result);
930  }
931  result = PQexec(db_conn, "COMMIT;");
932  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
933  PQclear(result);
934  }
935  else
936  {
937  PQclear(result);
938  }
939  return (0);
940 }/* RecordMetadataDEB(struct debpkginfo *pi) */
941 
949 int GetMetadataDebSource (char *repFile, struct debpkginfo *pi)
950 {
951  FILE *fp;
952  char field[MAXCMD];
953  char value[MAXCMD];
954  char line[MAXCMD];
955 
956  /* Parse the debian .dsc file to get every Field and Value */
957  if ((fp = fopen(repFile, "r")) == NULL){
958  LOG_FATAL("Unable to open .dsc file %s\n",repFile);
959  return (-1);
960  }
961 
962  while (fgets(line,MAXCMD,fp)!=NULL)
963  {
964  ParseDebFile(line,field,value);
965 
966  trim(value);
967  if (!strcasecmp(field, "Format")) {
968  EscapeString(value, pi->format, sizeof(pi->format));
969  }
970  if (!strcasecmp(field, "Source")) {
971  EscapeString(value, pi->source, sizeof(pi->source));
972  }
973  if (!strcasecmp(field, "Binary")) {
974  EscapeString(value, pi->pkgName, sizeof(pi->pkgName));
975  }
976  if (!strcasecmp(field, "Architecture")) {
977  EscapeString(value, pi->pkgArch, sizeof(pi->pkgArch));
978  }
979  if (!strcasecmp(field, "Version")) {
980  if (strlen(pi->version) == 0)
981  EscapeString(value, pi->version, sizeof(pi->version));
982  }
983  if (!strcasecmp(field, "Maintainer")) {
984  EscapeString(value, pi->maintainer, sizeof(pi->maintainer));
985  }
986  if (!strcasecmp(field, "Homepage")) {
987  EscapeString(value, pi->homepage, sizeof(pi->homepage));
988  }
989  if (!strcasecmp(field, "Uploaders")) {
990  EscapeString(value, pi->uploaders, sizeof(pi->uploaders));
991  }
992  if (!strcasecmp(field, "Standards-Version")) {
993  EscapeString(value, pi->standardsVersion, sizeof(pi->standardsVersion));
994  }
995  if (!strcasecmp(field, "Build-Depends")) {
996  char *depends = NULL;
997  char countcopy[MAXCMD];
998  char splitcopy[MAXCMD];
999  int size,i;
1000  size = 0;
1001  size_t length = MAXLENGTH;
1002  if (value[0] != '\0'){
1003  strncpy(countcopy, value, sizeof(countcopy)-1);
1004  countcopy[sizeof(countcopy)-1] = '\0';
1005  depends = strtok(countcopy, ",");
1006  while (depends && (depends[0] != '\0')) {
1007  if (strlen(depends) >= length)
1008  length = strlen(depends) + 1;
1009  depends = strtok(NULL, ",");
1010  size++;
1011  }
1012  if (Verbose) { printf("SIZE:%d\n", size);}
1013 
1014  strncpy(splitcopy, value, sizeof(splitcopy)-1);
1015  splitcopy[sizeof(splitcopy)-1] = '\0';
1016  pi->depends = calloc(size, sizeof(char *));
1017  depends = strtok(splitcopy, ",");
1018  for (i=0; i<size; i++){
1019  pi->depends[i] = calloc(length, sizeof(char));
1020  if (depends) {
1021  strncpy(pi->depends[i], depends, length - 1);
1022  pi->depends[i][length - 1] = '\0';
1023  depends = strtok(NULL, ",");
1024  }
1025  }
1026  pi->dep_size = size;
1027  }
1028  }
1029  }
1030 
1031  fclose(fp);
1032  return (0);
1033 }/* GetMetadataDebSource(char *repFile, struct debpkginfo *pi) */
1034 
1035 /***********************************************
1036  Usage():
1037  Command line options allow you to write the agent so it works
1038  stand alone, in addition to working with the scheduler.
1039  This simplifies code development and testing.
1040  So if you have options, have a Usage().
1041  Here are some suggested options (in addition to the program
1042  specific options you may already have).
1043  ***********************************************/
1044 void Usage (char *Name)
1045 {
1046  printf("Usage: %s [options] [file [file [...]]\n",Name);
1047  printf(" -i :: initialize the database, then exit.\n");
1048  printf(" -v :: verbose (-vv = more verbose)\n");
1049  printf(" -c :: Specify the directory for the system configuration.\n");
1050  printf(" -C :: run from command line.\n");
1051  printf(" file :: if files are rpm package listed, display their package information.\n");
1052  printf(" no file :: process data from the scheduler.\n");
1053  printf(" -V :: print the version info, then exit.\n");
1054 } /* Usage() */
1055 
char SQL[256]
SQL query to execute.
Definition: adj2nest.c:78
char * uploadtree_tablename
upload.uploadtree_tablename
Definition: adj2nest.c:100
int s
The socket that the CLI will use to communicate.
Definition: fo_cli.c:37
char * trim(char *ptext)
Trimming whitespace.
Definition: fossconfig.c:690
FUNCTION char * GetUploadtreeTableName(PGconn *pgConn, int upload_pk)
Get the uploadtree table name for this upload_pk If upload_pk does not exist, return "uploadtree".
Definition: libfossagent.c:414
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 fo_checkPQcommand(PGconn *pgConn, PGresult *result, char *sql, char *FileID, int LineNumb)
Check the result status of a postgres commands (not select) If an error occured, write the error to s...
Definition: libfossdb.c:204
char * fo_RepMkPath(const char *Type, char *Filename)
Given a filename, construct the full path to the file.
Definition: libfossrepo.c:352
void fo_scheduler_heart(int i)
This function must be called by agents to let the scheduler know they are alive and how many items th...
#define MAXLENGTH
Buffer length.
Definition: util.c:23
char * ParseDebFile(char *Sin, char *Field, char *Value)
Parse Debian binary control file with Field/Value pairs.
Definition: pkgagent.c:679
void Usage(char *Name)
Say how to run this program.
Definition: pkgagent.c:1044
char * GetFieldValue(char *Sin, char *Field, int FieldMax, char *Value, int ValueMax, char Separator)
Given a string that contains field='value' pairs, save the items.
Definition: pkgagent.c:101
int GetMetadata(char *pkg, struct rpmpkginfo *pi)
Get RPM package info.
Definition: pkgagent.c:555
int GetMetadataDebSource(char *repFile, struct debpkginfo *pi)
Get debian source package info from .dsc file.
Definition: pkgagent.c:949
void EscapeString(char *sourceString, char *escString, int esclen)
Escaping special characters(single quote)
Definition: pkgagent.c:51
int ProcessUpload(long upload_pk)
Get all pfile need to processed use upload_pk.
Definition: pkgagent.c:162
PGconn * db_conn
The connection to Database.
Definition: pkgagent.c:22
int RecordMetadataDEB(struct debpkginfo *pi)
Store debian package info into database.
Definition: pkgagent.c:875
int Verbose
Verbose level.
Definition: pkgagent.c:21
int RecordMetadataRPM(struct rpmpkginfo *pi)
Store rpm package info into database.
Definition: pkgagent.c:613
int GetMetadataDebBinary(long upload_pk, struct debpkginfo *pi)
Get debian binary package info.
Definition: pkgagent.c:720
void ReadHeaderInfo(Header header, struct rpmpkginfo *pi)
Get RPM package info from rpm file header use rpm library.
Definition: pkgagent.c:451
int tag[15]
Definition: pkgagent.c:25
pkgagent header
const char * upload_pk
Definition: sqlstatements.h:82
Holds meta info of Debian packages.
Definition: pkgagent.h:68
char section[MAXCMD]
Package section.
Definition: pkgagent.h:72
char priority[MAXCMD]
Package priority.
Definition: pkgagent.h:73
char standardsVersion[MAXCMD]
Package standards version.
Definition: pkgagent.h:86
long pFileFk
Package pfile in FOSSology.
Definition: pkgagent.h:80
char ** depends
Package dependency list.
Definition: pkgagent.h:82
char summary[MAXCMD]
Package summary.
Definition: pkgagent.h:78
char pFile[MAXCMD]
Package pfile hash.
Definition: pkgagent.h:81
char version[MAXCMD]
Package version.
Definition: pkgagent.h:71
char format[MAXCMD]
Package format.
Definition: pkgagent.h:85
char uploaders[MAXCMD]
Package contributors.
Definition: pkgagent.h:84
char maintainer[MAXCMD]
Package maintainer.
Definition: pkgagent.h:76
int installedSize
Size of package after install.
Definition: pkgagent.h:75
char pkgArch[MAXCMD]
Package architecture.
Definition: pkgagent.h:74
char description[MAXCMD]
Package description.
Definition: pkgagent.h:79
int dep_size
Package dependency list size.
Definition: pkgagent.h:83
char source[MAXCMD]
Package source.
Definition: pkgagent.h:70
char pkgName[MAXCMD]
Package name.
Definition: pkgagent.h:69
char homepage[MAXCMD]
Package link.
Definition: pkgagent.h:77
Holds meta info of rpm packages.
Definition: pkgagent.h:41
char buildDate[128]
Package build date.
Definition: pkgagent.h:51
char pFile[MAXCMD]
Package pfile hash.
Definition: pkgagent.h:58
char group[128]
Package group.
Definition: pkgagent.h:48
char version[64]
Package version.
Definition: pkgagent.h:45
char summary[MAXCMD]
Package summary.
Definition: pkgagent.h:55
char pkgName[256]
RPM package name.
Definition: pkgagent.h:42
char description[MAXCMD]
Package description.
Definition: pkgagent.h:56
char rpmFilename[256]
RPM file name.
Definition: pkgagent.h:46
char license[512]
RPM licenses.
Definition: pkgagent.h:47
char pkgArch[64]
Package architecture.
Definition: pkgagent.h:44
char sourceRPM[256]
Package source.
Definition: pkgagent.h:54
int req_size
Package dependency list size.
Definition: pkgagent.h:60
char pkgAlias[256]
Package alias.
Definition: pkgagent.h:43
char url[256]
Package link.
Definition: pkgagent.h:53
long pFileFk
Package pfile in FOSSology.
Definition: pkgagent.h:57
char release[64]
Package release.
Definition: pkgagent.h:50
char packager[1024]
Packager.
Definition: pkgagent.h:49
char ** requires
Package dependency list.
Definition: pkgagent.h:59
char vendor[128]
Package vendor.
Definition: pkgagent.h:52