FOSSology  4.6.0
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  int i;
403  for(i=0; i< dpi->dep_size;i++)
404  free(dpi->depends[i]);
405  free(dpi->depends);
406  }
407  else if (!strcasecmp(mimetype, "application/x-debian-source")){
408  dpi->pFileFk = atoi(PQgetvalue(result, i, 0));
409  strncpy(dpi->pFile, PQgetvalue(result, i, 1), sizeof(dpi->pFile)-1);
410  dpi->pFile[sizeof(dpi->pFile)-1] = '\0';
411  repFile = fo_RepMkPath("files", dpi->pFile);
412  if (!repFile) {
413  LOG_FATAL("pfile %ld PkgAgent unable to open file %s\n",
414  dpi->pFileFk, dpi->pFile);
415  return (-1);
416  }
417  if (GetMetadataDebSource(repFile,dpi) != -1){
418  RecordMetadataDEB(dpi);
419  }
420  /* free memory */
421  int i;
422  for(i=0; i< dpi->dep_size;i++)
423  free(dpi->depends[i]);
424  free(dpi->depends);
425  } else {
426  printf("LOG: Not RPM and DEBIAN package!\n");
427  }
429  }
430  PQclear(result);
431  rpmFreeCrypto();
432  rpmFreeMacros(NULL);
433  free(pi);
434  free(dpi);
435  return (0);
436 }/*ProcessUpload (long upload_pk)*/
437 
443 void ReadHeaderInfo(Header header, struct rpmpkginfo *pi)
444 {
445  char fmt[128];
446  char * msgstr;
447  const char * errstr;
448  int i,j;
449  long *tp,t;
450  int header_status;
451 
452  struct rpmtd_s req;
453  rpm_count_t data_size;
454 
455  for (i = 0; i < 14; i++) {
456  memset(fmt, 0, sizeof(fmt));
457  strcat( fmt, "%{");
458  strcat( fmt, rpmTagGetName(tag[i]));
459  strcat( fmt, "}\n");
460 
461  msgstr = headerFormat(header, fmt, &errstr);
462  if (msgstr != NULL){
463  trim(msgstr);
464  printf("%s:%s\n",rpmTagGetName(tag[i]),msgstr);
465  switch (tag[i]) {
466  case RPMTAG_NAME:
467  EscapeString(msgstr, pi->pkgName, sizeof(pi->pkgName));
468  break;
469  case RPMTAG_EPOCH:
470  EscapeString(msgstr, pi->pkgAlias, sizeof(pi->pkgAlias));
471  break;
472  case RPMTAG_ARCH:
473  EscapeString(msgstr, pi->pkgArch, sizeof(pi->pkgArch));
474  break;
475  case RPMTAG_VERSION:
476  EscapeString(msgstr, pi->version, sizeof(pi->version));
477  break;
478  case RPMTAG_LICENSE:
479  EscapeString(msgstr, pi->license, sizeof(pi->license));
480  break;
481  case RPMTAG_GROUP:
482  EscapeString(msgstr, pi->group, sizeof(pi->group));
483  break;
484  case RPMTAG_PACKAGER:
485  EscapeString(msgstr, pi->packager, sizeof(pi->packager));
486  break;
487  case RPMTAG_RELEASE:
488  EscapeString(msgstr, pi->release, sizeof(pi->release));
489  break;
490  case RPMTAG_BUILDTIME:
491  t = atol(msgstr);
492  tp = &t;
493  strncpy(pi->buildDate,trim(asctime(gmtime((time_t*)tp))),sizeof(pi->buildDate)-1);
494  pi->buildDate[sizeof(pi->buildDate)-1] = '\0';
495  break;
496  case RPMTAG_VENDOR:
497  EscapeString(msgstr, pi->vendor, sizeof(pi->vendor));
498  break;
499  case RPMTAG_URL:
500  EscapeString(msgstr, pi->url, sizeof(pi->url));
501  break;
502  case RPMTAG_SOURCERPM:
503  EscapeString(msgstr, pi->sourceRPM,sizeof(pi->sourceRPM));
504  break;
505  case RPMTAG_SUMMARY:
506  EscapeString(msgstr, pi->summary, sizeof(pi->summary));
507  break;
508  case RPMTAG_DESCRIPTION:
509  EscapeString(msgstr, pi->description, sizeof(pi->description));
510  break;
511  default:
512  break;
513  }
514  }
515  free((void *)msgstr);
516  }
517  if (Verbose > 1) { printf("Name:%s\n",pi->pkgName);}
518  header_status = headerGet(header, tag[14], &req, HEADERGET_DEFAULT);
519  if (header_status) {
520  data_size = rpmtdCount(&req);
521  pi->requires = calloc(data_size, sizeof(char *));
522  for (j=0; j<(int)data_size;j++){
523  const char * temp = rpmtdNextString(&req);
524  pi->requires[j] = malloc(MAXCMD);
525  strcpy(pi->requires[j],temp);
526  }
527  pi->req_size = data_size;
528  rpmtdFreeData(&req);
529  }
530 
531  if (Verbose > 1) {
532  printf("Size:%d\n",pi->req_size);
533  for (j=0; j<pi->req_size;j++){
534  printf("REQ:%s\n",pi->requires[j]);
535  }
536  printf("Name:%s\n",pi->sourceRPM);
537  }
538 } /* ReadHeaderInfo(Header header, struct rpmpkginfo *pi) */
539 
546 int GetMetadata (char *pkg, struct rpmpkginfo *pi)
547 {
548  //rpmpi.pFileFk = 4234634;
549  //if (PKG_RPM)
550  //{
551  FD_t fd;
552  rpmRC rpmrc;
553  Header header;
554  rpmts ts;
555  rpmVSFlags vsflags;
556 
557  vsflags = RPMVSF_DEFAULT;
558  ts = (rpmts) rpmtsCreate();
559 
560  fd = Fopen(pkg,"r");
561  if ( fd == NULL ||Ferror(fd)){
562  rpmlog(RPMLOG_ERR, "open of %s failed: %s\n", pkg, Fstrerror(fd));
563  if (fd){
564  Fclose(fd);
565  }
566  return (-1);
567  }
568 
569  vsflags |= _RPMVSF_NOSIGNATURES;
570  vsflags |= _RPMVSF_NODIGESTS;
571  vsflags |= RPMVSF_NOHDRCHK;
572  vsflags |= RPMVSF_NEEDPAYLOAD;
573 
574  rpmtsSetVSFlags(ts, vsflags);
575 
576  //rpmReadConfigFiles(NULL, NULL);
577  rpmrc = rpmReadPackageFile(ts, fd, pkg,&header);
578  Fclose(fd);
579  ts = (rpmts) rpmtsFree(ts);
580 
581  switch (rpmrc) {
582  case RPMRC_OK:
583  case RPMRC_NOKEY:
584  case RPMRC_NOTTRUSTED:
585  break;
586  case RPMRC_NOTFOUND:
587  case RPMRC_FAIL:
588  default:
589  rpmlog(RPMLOG_ERR, "%s cannot be read or is not an RPM.\n", pkg);
590  return (-1);
591  }
592  ReadHeaderInfo(header, pi);
593  //rpmFreeMacros(NULL);
594  header = headerFree(header);
595  //}
596  return (0);
597 } /* GetMetadata(char *pkg, struct rpmpkginfo *pi) */
598 
605 {
606  char SQL[MAXCMD];
607  PGresult *result;
608  int pkg_pk;
609 
610  memset(SQL,0,sizeof(SQL));
611  snprintf(SQL,sizeof(SQL),"SELECT pfile_fk FROM pkg_rpm WHERE pfile_fk = %ld;",pi->pFileFk);
612  result = PQexec(db_conn, SQL);
613  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
614  if (PQntuples(result) <=0)
615  {
616  PQclear(result);
617  memset(SQL,0,sizeof(SQL));
618  result = PQexec(db_conn, "BEGIN;");
619  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
620  PQclear(result);
621 
622  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);",
623  trim(pi->pkgName),trim(pi->pkgAlias),trim(pi->pkgArch),trim(pi->version),
624  trim(pi->rpmFilename),trim(pi->license),trim(pi->group),trim(pi->packager),
625  trim(pi->release),pi->buildDate,trim(pi->vendor),trim(pi->url),trim(pi->sourceRPM),
626  trim(pi->summary),trim(pi->description),pi->pFileFk);
627  result = PQexec(db_conn, SQL);
628  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
629  {
630  PQexec(db_conn, "ROLLBACK;");
631  return (-1);
632  }
633  PQclear(result);
634 
635  result = PQexec(db_conn,"SELECT currval('pkg_rpm_pkg_pk_seq'::regclass);");
636  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
637  pkg_pk = atoi(PQgetvalue(result,0,0));
638  PQclear(result);
639 
640  if (Verbose) { printf("pkg_pk:%d\n",pkg_pk);}
641  int i;
642  for (i=0;i<pi->req_size;i++)
643  {
644  memset(SQL,0,sizeof(SQL));
645  snprintf(SQL,sizeof(SQL),"INSERT INTO pkg_rpm_req (pkg_fk,req_value) values (%d,E'%s');",pkg_pk,trim(pi->requires[i]));
646  result = PQexec(db_conn, SQL);
647  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
648  {
649  PQexec(db_conn, "ROLLBACK;");
650  return (-1);
651  }
652  PQclear(result);
653  }
654  result = PQexec(db_conn, "COMMIT;");
655  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
656  PQclear(result);
657  }
658  return (0);
659 } /* RecordMetadata(struct rpmpkginfo *pi) */
660 
661 
670 char * ParseDebFile(char *Sin, char *Field, char *Value)
671 {
672  int s,f,v;
673 
674  memset(Field,0,MAXCMD);
675  memset(Value,0,MAXCMD);
676 
677  f=0; v=0;
678  if(!isspace(Sin[0]))
679  {
680  for(s=0; (Sin[s] != '\0') && !isspace(Sin[s]) && (Sin[s] != ':'); s++)
681  {
682  Field[f++] = Sin[s];
683  }
684  while(isspace(Sin[s])) s++;
685  if (Sin[s] != ':')
686  {
687  return(Sin+s);
688  }
689  s++;
690  while(isspace(Sin[s])) s++;
691 
692  for( ; Sin[s] != '\0'; s++)
693  {
694  Value[v++]=Sin[s];
695  }
696  if (Verbose) { printf("Field is %s and Value is %s", Field, Value);}
697  return(Sin+s);
698  } else
699  {
700  if (Verbose) { printf("ExValue is %s", Sin);}
701  return(Sin);
702  }
703 } /* ParseDebFile(char *Sin, char *Field, char *Value) */
704 
712 {
713  char *repfile;
714  char *filename;
715  char SQL[MAXCMD];
716  PGresult *result;
717  unsigned long lft, rgt;
718 
719  FILE *fp;
720  char field[MAXCMD];
721  char value[MAXCMD];
722  char line[MAXCMD];
723  char *s = NULL;
724  char temp[MAXCMD];
725  char *uploadtree_tablename;
726 
727  if (!upload_pk) return -1; // when upload_pk is empty
729  if (NULL == uploadtree_tablename) uploadtree_tablename = strdup("uploadtree_a");
730  /* Get the debian control file's repository path */
731  /* First get the uploadtree bounds (lft,rgt) for the package */
732  snprintf(SQL,sizeof(SQL),"SELECT lft,rgt FROM %s WHERE upload_fk = %ld AND pfile_fk = %ld limit 1",
734  result = PQexec(db_conn, SQL);
735  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
736  if (PQntuples(result) == 0)
737  {
738  LOG_ERROR("Missing debian package (internal data inconsistancy). SQL: %s\n", SQL);
739  PQclear(result);
740  return (-1);
741  }
742  lft = strtoul(PQgetvalue(result,0,0), NULL, 10);
743  rgt = strtoul(PQgetvalue(result,0,1), NULL, 10);
744  PQclear(result);
745 
746  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')",
747  upload_pk, lft, rgt);
748  result = PQexec(db_conn, SQL);
749  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
750  if (PQntuples(result) > 0)
751  {
752  filename = PQgetvalue(result,0,0);
753  repfile = fo_RepMkPath("files", filename);
754  if (!repfile) {
755  LOG_FATAL("PkgAgent unable to open file %s\n",filename);
756  return (-1);
757  }
758  PQclear(result);
759  }
760  else
761  {
762  PQclear(result);
763  printf("LOG: Unable to find debian/control file! This file had wrong mimetype, ignore it!\n");
764  memset(SQL,0,sizeof(SQL));
765  snprintf(SQL,sizeof(SQL),"UPDATE pfile SET pfile_mimetypefk = NULL WHERE pfile_pk = %ld;", pi->pFileFk);
766  result = PQexec(db_conn, SQL);
767  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
768  PQclear(result);
769  return (-1);
770  }
771 
772  /* Parse the debian/control file to get every Field and Value */
773  if ((fp = fopen(repfile, "r")) == NULL){
774  LOG_FATAL("Unable to open debian/control file %s\n",repfile);
775  return (-1);
776  }
777 
778  while (fgets(line,MAXCMD,fp)!=NULL)
779  {
780  s = ParseDebFile(line,field,value);
781  trim(value);
782  if (!strcasecmp(field, "Description")) {
783  EscapeString(value, pi->summary, sizeof(pi->summary));
784  strcpy(temp, "");
785  }
786  if (s[0] != '\0') {
787  if ((strlen(temp) + strlen(s)) >= MAXCMD )
788  continue;
789  else
790  strcat(temp,s);
791  }
792  if (!strcasecmp(field, "Package")) {
793  EscapeString(value, pi->pkgName, sizeof(pi->pkgName));
794  }
795  if (!strcasecmp(field, "Version")) {
796  EscapeString(value, pi->version, sizeof(pi->version));
797  }
798  if (!strcasecmp(field, "Architecture")) {
799  EscapeString(value, pi->pkgArch, sizeof(pi->pkgArch));
800  }
801  if (!strcasecmp(field, "Maintainer")) {
802  EscapeString(value, pi->maintainer, sizeof(pi->maintainer));
803  }
804  if (!strcasecmp(field, "Installed-Size")) {
805  pi->installedSize=atol(value);
806  }
807  if (!strcasecmp(field, "Section")) {
808  EscapeString(value, pi->section, sizeof(pi->section));
809  }
810  if (!strcasecmp(field, "Priority")) {
811  EscapeString(value, pi->priority, sizeof(pi->priority));
812  }
813  if (!strcasecmp(field, "Homepage")) {
814  EscapeString(value, pi->homepage, sizeof(pi->homepage));
815  }
816  if (!strcasecmp(field, "Source")) {
817  EscapeString(value, pi->source, sizeof(pi->source));
818  }
819  if (!strcasecmp(field, "Depends")) {
820  char *depends = NULL;
821  char countcopy[MAXCMD];
822  char splitcopy[MAXCMD];
823  int size,i;
824  size_t length = MAXLENGTH;
825  size = 0;
826  if (value[0] != '\0'){
827  strncpy(countcopy, value, sizeof(countcopy)-1);
828  countcopy[sizeof(countcopy)-1] = '\0';
829  depends = strtok(countcopy, ",");
830  while (depends && (depends[0] != '\0')) {
831  if (strlen(depends) >= length)
832  length = strlen(depends) + 1;
833  depends = strtok(NULL, ",");
834  size++;
835  }
836  if (Verbose) { printf("SIZE:%d\n", size);}
837 
838  strncpy(splitcopy, value, sizeof(splitcopy)-1);
839  splitcopy[sizeof(splitcopy)-1] = '\0';
840  pi->depends = calloc(size, sizeof(char *));
841  depends = strtok(splitcopy, ",");
842  for (i=0; i<size; i++){
843  pi->depends[i] = calloc(length, sizeof(char));
844  if (depends) {
845  strcpy(pi->depends[i], depends);
846  depends = strtok(NULL, ",");
847  }
848  }
849  pi->dep_size = size;
850  }
851  }
852  }
853  EscapeString(temp, pi->description, sizeof(pi->description));
854 
855  fclose(fp);
856  free(repfile);
857  return (0);
858 }/* GetMetadataDebBinary(struct debpkginfo *pi) */
859 
866 {
867  char SQL[MAXCMD];
868  PGresult *result;
869  int pkg_pk;
870 
871  memset(SQL,0,sizeof(SQL));
872  snprintf(SQL,sizeof(SQL),"SELECT pfile_fk FROM pkg_deb WHERE pfile_fk = %ld;",pi->pFileFk);
873  result = PQexec(db_conn, SQL);
874  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
875  if (PQntuples(result) <=0)
876  {
877  PQclear(result);
878  memset(SQL,0,sizeof(SQL));
879  result = PQexec(db_conn, "BEGIN;");
880  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
881  PQclear(result);
882 
883  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);",
884  trim(pi->pkgName),trim(pi->pkgArch),trim(pi->version),trim(pi->maintainer),
885  pi->installedSize,trim(pi->section),trim(pi->priority),trim(pi->homepage),
886  trim(pi->source),trim(pi->summary),trim(pi->description),trim(pi->format),
887  trim(pi->uploaders),trim(pi->standardsVersion),pi->pFileFk);
888  result = PQexec(db_conn, SQL);
889  // ignore error
890  if ((result==0) || ((PQresultStatus(result) != PGRES_COMMAND_OK)))
891  {
892  LOG_FATAL("Error inserting, SQL is: %s, error code is:%s\n", SQL, PQresultErrorField(result, PG_DIAG_SQLSTATE));
893  PQexec(db_conn, "ROLLBACK;");
894  if (result) PQclear(result);
895  return (-1);
896  } else
897  {
898  PQclear(result);
899  }
900 
901  result = PQexec(db_conn,"SELECT currval('pkg_deb_pkg_pk_seq'::regclass);");
902  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
903  pkg_pk = atoi(PQgetvalue(result,0,0));
904  PQclear(result);
905 
906  if (Verbose) { printf("pkg_pk:%d\n",pkg_pk);}
907  int i;
908  for (i=0;i<pi->dep_size;i++)
909  {
910  memset(SQL,0,sizeof(SQL));
911  snprintf(SQL,sizeof(SQL),"INSERT INTO pkg_deb_req (pkg_fk,req_value) values (%d,E'%s');",pkg_pk,trim(pi->depends[i]));
912  if (Verbose) { printf("DEPENDS:%s\n",pi->depends[i]);}
913  result = PQexec(db_conn, SQL);
914  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
915  {
916  PQexec(db_conn, "ROLLBACK;");
917  return (-1);
918  }
919  PQclear(result);
920  }
921  result = PQexec(db_conn, "COMMIT;");
922  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
923  PQclear(result);
924  }
925  else
926  {
927  PQclear(result);
928  }
929  return (0);
930 }/* RecordMetadataDEB(struct debpkginfo *pi) */
931 
939 int GetMetadataDebSource (char *repFile, struct debpkginfo *pi)
940 {
941  FILE *fp;
942  char field[MAXCMD];
943  char value[MAXCMD];
944  char line[MAXCMD];
945 
946  /* Parse the debian .dsc file to get every Field and Value */
947  if ((fp = fopen(repFile, "r")) == NULL){
948  LOG_FATAL("Unable to open .dsc file %s\n",repFile);
949  return (-1);
950  }
951 
952  while (fgets(line,MAXCMD,fp)!=NULL)
953  {
954  ParseDebFile(line,field,value);
955 
956  trim(value);
957  if (!strcasecmp(field, "Format")) {
958  EscapeString(value, pi->format, sizeof(pi->format));
959  }
960  if (!strcasecmp(field, "Source")) {
961  EscapeString(value, pi->source, sizeof(pi->source));
962  }
963  if (!strcasecmp(field, "Source")) {
964  EscapeString(value, pi->pkgName, sizeof(pi->pkgName));
965  }
966  if (!strcasecmp(field, "Architecture")) {
967  EscapeString(value, pi->pkgArch, sizeof(pi->pkgArch));
968  }
969  if (!strcasecmp(field, "Version")) {
970  if (strlen(pi->version) == 0)
971  EscapeString(value, pi->version, sizeof(pi->version));
972  }
973  if (!strcasecmp(field, "Maintainer")) {
974  EscapeString(value, pi->maintainer, sizeof(pi->maintainer));
975  }
976  if (!strcasecmp(field, "Homepage")) {
977  EscapeString(value, pi->homepage, sizeof(pi->homepage));
978  }
979  if (!strcasecmp(field, "Uploaders")) {
980  EscapeString(value, pi->uploaders, sizeof(pi->uploaders));
981  }
982  if (!strcasecmp(field, "Standards-Version")) {
983  EscapeString(value, pi->standardsVersion, sizeof(pi->standardsVersion));
984  }
985  if (!strcasecmp(field, "Build-Depends")) {
986  char *depends = NULL;
987  char countcopy[MAXCMD];
988  char splitcopy[MAXCMD];
989  int size,i;
990  size = 0;
991  size_t length = MAXLENGTH;
992  if (value[0] != '\0'){
993  strncpy(countcopy, value, sizeof(countcopy)-1);
994  countcopy[sizeof(countcopy)-1] = '\0';
995  depends = strtok(countcopy, ",");
996  while (depends && (depends[0] != '\0')) {
997  if (strlen(depends) >= length)
998  length = strlen(depends) + 1;
999  depends = strtok(NULL, ",");
1000  size++;
1001  }
1002  if (Verbose) { printf("SIZE:%d\n", size);}
1003 
1004  strncpy(splitcopy, value, sizeof(splitcopy)-1);
1005  splitcopy[sizeof(splitcopy)-1] = '\0';
1006  pi->depends = calloc(size, sizeof(char *));
1007  depends = strtok(splitcopy, ",");
1008  for (i=0; i<size; i++){
1009  pi->depends[i] = calloc(length, sizeof(char));
1010  if (depends) {
1011  strcpy(pi->depends[i], depends);
1012  depends = strtok(NULL, ",");
1013  }
1014  }
1015  pi->dep_size = size;
1016  }
1017  }
1018  }
1019 
1020  fclose(fp);
1021  return (0);
1022 }/* GetMetadataDebSource(char *repFile, struct debpkginfo *pi) */
1023 
1024 /***********************************************
1025  Usage():
1026  Command line options allow you to write the agent so it works
1027  stand alone, in addition to working with the scheduler.
1028  This simplifies code development and testing.
1029  So if you have options, have a Usage().
1030  Here are some suggested options (in addition to the program
1031  specific options you may already have).
1032  ***********************************************/
1033 void Usage (char *Name)
1034 {
1035  printf("Usage: %s [options] [file [file [...]]\n",Name);
1036  printf(" -i :: initialize the database, then exit.\n");
1037  printf(" -v :: verbose (-vv = more verbose)\n");
1038  printf(" -c :: Specify the directory for the system configuration.\n");
1039  printf(" -C :: run from command line.\n");
1040  printf(" file :: if files are rpm package listed, display their package information.\n");
1041  printf(" no file :: process data from the scheduler.\n");
1042  printf(" -V :: print the version info, then exit.\n");
1043 } /* Usage() */
1044 
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:670
void Usage(char *Name)
Say how to run this program.
Definition: pkgagent.c:1033
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:546
int GetMetadataDebSource(char *repFile, struct debpkginfo *pi)
Get debian source package info from .dsc file.
Definition: pkgagent.c:939
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:865
int Verbose
Verbose level.
Definition: pkgagent.c:21
int RecordMetadataRPM(struct rpmpkginfo *pi)
Store rpm package info into database.
Definition: pkgagent.c:604
int GetMetadataDebBinary(long upload_pk, struct debpkginfo *pi)
Get debian binary package info.
Definition: pkgagent.c:711
void ReadHeaderInfo(Header header, struct rpmpkginfo *pi)
Get RPM package info from rpm file header use rpm library.
Definition: pkgagent.c:443
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