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 tempvalue[MAXCMD];
822  int size,i;
823  size_t length = MAXLENGTH;
824  size = 0;
825  if (value[0] != '\0'){
826  strncpy(tempvalue, value, sizeof(tempvalue));
827  depends = strtok(value, ",");
828  while (depends && (depends[0] != '\0')) {
829  if (strlen(depends) >= length)
830  length = strlen(depends) + 1;
831  depends = strtok(NULL, ",");
832  size++;
833  }
834  if (Verbose) { printf("SIZE:%d\n", size);}
835 
836  pi->depends = calloc(size, sizeof(char *));
837  pi->depends[0] = calloc(length, sizeof(char));
838  strcpy(pi->depends[0],strtok(tempvalue,","));
839  for (i=1;i<size;i++){
840  pi->depends[i] = calloc(length, sizeof(char));
841  strcpy(pi->depends[i],strtok(NULL, ","));
842  }
843  pi->dep_size = size;
844  }
845  }
846  }
847  EscapeString(temp, pi->description, sizeof(pi->description));
848 
849  fclose(fp);
850  free(repfile);
851  return (0);
852 }/* GetMetadataDebBinary(struct debpkginfo *pi) */
853 
860 {
861  char SQL[MAXCMD];
862  PGresult *result;
863  int pkg_pk;
864 
865  memset(SQL,0,sizeof(SQL));
866  snprintf(SQL,sizeof(SQL),"SELECT pfile_fk FROM pkg_deb WHERE pfile_fk = %ld;",pi->pFileFk);
867  result = PQexec(db_conn, SQL);
868  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
869  if (PQntuples(result) <=0)
870  {
871  PQclear(result);
872  memset(SQL,0,sizeof(SQL));
873  result = PQexec(db_conn, "BEGIN;");
874  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
875  PQclear(result);
876 
877  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);",
878  trim(pi->pkgName),trim(pi->pkgArch),trim(pi->version),trim(pi->maintainer),
879  pi->installedSize,trim(pi->section),trim(pi->priority),trim(pi->homepage),
880  trim(pi->source),trim(pi->summary),trim(pi->description),trim(pi->format),
881  trim(pi->uploaders),trim(pi->standardsVersion),pi->pFileFk);
882  result = PQexec(db_conn, SQL);
883  // ignore error
884  if ((result==0) || ((PQresultStatus(result) != PGRES_COMMAND_OK)))
885  {
886  LOG_FATAL("Error inserting, SQL is: %s, error code is:%s\n", SQL, PQresultErrorField(result, PG_DIAG_SQLSTATE));
887  PQexec(db_conn, "ROLLBACK;");
888  if (result) PQclear(result);
889  return (-1);
890  } else
891  {
892  PQclear(result);
893  }
894 
895  result = PQexec(db_conn,"SELECT currval('pkg_deb_pkg_pk_seq'::regclass);");
896  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
897  pkg_pk = atoi(PQgetvalue(result,0,0));
898  PQclear(result);
899 
900  if (Verbose) { printf("pkg_pk:%d\n",pkg_pk);}
901  int i;
902  for (i=0;i<pi->dep_size;i++)
903  {
904  memset(SQL,0,sizeof(SQL));
905  snprintf(SQL,sizeof(SQL),"INSERT INTO pkg_deb_req (pkg_fk,req_value) values (%d,E'%s');",pkg_pk,trim(pi->depends[i]));
906  if (Verbose) { printf("DEPENDS:%s\n",pi->depends[i]);}
907  result = PQexec(db_conn, SQL);
908  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
909  {
910  PQexec(db_conn, "ROLLBACK;");
911  return (-1);
912  }
913  PQclear(result);
914  }
915  result = PQexec(db_conn, "COMMIT;");
916  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
917  PQclear(result);
918  }
919  else
920  {
921  PQclear(result);
922  }
923  return (0);
924 }/* RecordMetadataDEB(struct debpkginfo *pi) */
925 
933 int GetMetadataDebSource (char *repFile, struct debpkginfo *pi)
934 {
935  FILE *fp;
936  char field[MAXCMD];
937  char value[MAXCMD];
938  char line[MAXCMD];
939 
940  /* Parse the debian .dsc file to get every Field and Value */
941  if ((fp = fopen(repFile, "r")) == NULL){
942  LOG_FATAL("Unable to open .dsc file %s\n",repFile);
943  return (-1);
944  }
945 
946  while (fgets(line,MAXCMD,fp)!=NULL)
947  {
948  ParseDebFile(line,field,value);
949 
950  trim(value);
951  if (!strcasecmp(field, "Format")) {
952  EscapeString(value, pi->format, sizeof(pi->format));
953  }
954  if (!strcasecmp(field, "Source")) {
955  EscapeString(value, pi->source, sizeof(pi->source));
956  }
957  if (!strcasecmp(field, "Source")) {
958  EscapeString(value, pi->pkgName, sizeof(pi->pkgName));
959  }
960  if (!strcasecmp(field, "Architecture")) {
961  EscapeString(value, pi->pkgArch, sizeof(pi->pkgArch));
962  }
963  if (!strcasecmp(field, "Version")) {
964  if (strlen(pi->version) == 0)
965  EscapeString(value, pi->version, sizeof(pi->version));
966  }
967  if (!strcasecmp(field, "Maintainer")) {
968  EscapeString(value, pi->maintainer, sizeof(pi->maintainer));
969  }
970  if (!strcasecmp(field, "Homepage")) {
971  EscapeString(value, pi->homepage, sizeof(pi->homepage));
972  }
973  if (!strcasecmp(field, "Uploaders")) {
974  EscapeString(value, pi->uploaders, sizeof(pi->uploaders));
975  }
976  if (!strcasecmp(field, "Standards-Version")) {
977  EscapeString(value, pi->standardsVersion, sizeof(pi->standardsVersion));
978  }
979  if (!strcasecmp(field, "Build-Depends")) {
980  char *depends = NULL;
981  char tempvalue[MAXCMD];
982  int size,i;
983  size = 0;
984  size_t length = MAXLENGTH;
985  if (value[0] != '\0'){
986  strncpy(tempvalue, value, sizeof(tempvalue));
987  depends = strtok(value, ",");
988  while (depends && (depends[0] != '\0')) {
989  if (strlen(depends) >= length)
990  length = strlen(depends) + 1;
991  depends = strtok(NULL, ",");
992  size++;
993  }
994  if (Verbose) { printf("SIZE:%d\n", size);}
995 
996  pi->depends = calloc(size, sizeof(char *));
997  pi->depends[0] = calloc(length, sizeof(char));
998  strcpy(pi->depends[0],strtok(tempvalue,","));
999  for (i=1;i<size;i++){
1000  pi->depends[i] = calloc(length, sizeof(char));
1001  strcpy(pi->depends[i],strtok(NULL, ","));
1002  }
1003  pi->dep_size = size;
1004  }
1005  }
1006  }
1007 
1008  fclose(fp);
1009  return (0);
1010 }/* GetMetadataDebSource(char *repFile, struct debpkginfo *pi) */
1011 
1012 /***********************************************
1013  Usage():
1014  Command line options allow you to write the agent so it works
1015  stand alone, in addition to working with the scheduler.
1016  This simplifies code development and testing.
1017  So if you have options, have a Usage().
1018  Here are some suggested options (in addition to the program
1019  specific options you may already have).
1020  ***********************************************/
1021 void Usage (char *Name)
1022 {
1023  printf("Usage: %s [options] [file [file [...]]\n",Name);
1024  printf(" -i :: initialize the database, then exit.\n");
1025  printf(" -v :: verbose (-vv = more verbose)\n");
1026  printf(" -c :: Specify the directory for the system configuration.\n");
1027  printf(" -C :: run from command line.\n");
1028  printf(" file :: if files are rpm package listed, display their package information.\n");
1029  printf(" no file :: process data from the scheduler.\n");
1030  printf(" -V :: print the version info, then exit.\n");
1031 } /* Usage() */
1032 
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:1021
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:933
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:859
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