FOSSology  4.4.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 debsrcmimetypepk = 0;
170  int numrows;
171  int i;
172  char *uploadtree_tablename;
173 
174  struct rpmpkginfo *pi;
175  struct debpkginfo *dpi;
176 
177  pi = (struct rpmpkginfo *)malloc(sizeof(struct rpmpkginfo));
178  dpi = (struct debpkginfo *)malloc(sizeof(struct debpkginfo));
179 
180  rpmReadConfigFiles(NULL, NULL);
181 
182  /* "pkgagent" needs to know what? */
183 
184  /* "pkgagent" needs to know the mimetype for
185  * 'application/x-rpm' and 'application/x-debian-package' and 'application/x-debian-source'*/
186  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-rpm' LIMIT 1;");
187  result = PQexec(db_conn, sqlbuf);
188  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
189  {
190  free(pi);
191  free(dpi);
192  exit(-1);
193  }
194  mimetypepk = atoi(PQgetvalue(result, 0, 0));
195  PQclear(result);
196  if ( mimetypepk == 0 )
197  {
198  snprintf(sqlbuf, sizeof(sqlbuf), "INSERT INTO mimetype (mimetype_name) VALUES ('application/x-rpm');");
199  result = PQexec(db_conn, sqlbuf);
200  if (fo_checkPQcommand(db_conn, result, sqlbuf, __FILE__, __LINE__))
201  {
202  free(pi);
203  free(dpi);
204  exit(-1);
205  }
206  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-rpm' LIMIT 1;");
207  result = PQexec(db_conn, sqlbuf);
208  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
209  {
210  free(pi);
211  free(dpi);
212  exit(-1);
213  }
214  mimetypepk = atoi(PQgetvalue(result, 0, 0));
215  PQclear(result);
216  if ( mimetypepk == 0 )
217  {
218  LOG_ERROR("pkgagent rpm mimetype not installed!");
219  free(pi);
220  free(dpi);
221  return (-1);
222  }
223  }
224  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-debian-package' LIMIT 1;");
225  result = PQexec(db_conn, sqlbuf);
226  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
227  {
228  free(pi);
229  free(dpi);
230  exit(-1);
231  }
232  debmimetypepk = atoi(PQgetvalue(result, 0, 0));
233  PQclear(result);
234  if ( debmimetypepk == 0 )
235  {
236  snprintf(sqlbuf, sizeof(sqlbuf), "INSERT INTO mimetype (mimetype_name) VALUES ('application/x-debian-package');");
237  result = PQexec(db_conn, sqlbuf);
238  if (fo_checkPQcommand(db_conn, result, sqlbuf, __FILE__, __LINE__))
239  {
240  free(pi);
241  free(dpi);
242  exit(-1);
243  }
244  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-debian-package' LIMIT 1;");
245  result = PQexec(db_conn, sqlbuf);
246  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
247  {
248  free(pi);
249  free(dpi);
250  exit(-1);
251  }
252  debmimetypepk = atoi(PQgetvalue(result, 0, 0));
253  PQclear(result);
254  if ( debmimetypepk == 0 )
255  {
256  LOG_ERROR("pkgagent deb mimetype not installed!");
257  free(pi);
258  free(dpi);
259  return (-1);
260  }
261  }
262  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-debian-source' LIMIT 1;");
263  result = PQexec(db_conn, sqlbuf);
264  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
265  {
266  free(pi);
267  free(dpi);
268  exit(-1);
269  }
270  debsrcmimetypepk = atoi(PQgetvalue(result, 0, 0));
271  PQclear(result);
272  if ( debsrcmimetypepk == 0 )
273  {
274  snprintf(sqlbuf, sizeof(sqlbuf), "INSERT INTO mimetype (mimetype_name) VALUES ('application/x-debian-source');");
275  result = PQexec(db_conn, sqlbuf);
276  if (fo_checkPQcommand(db_conn, result, sqlbuf, __FILE__, __LINE__))
277  {
278  free(pi);
279  free(dpi);
280  exit(-1);
281  }
282  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT mimetype_pk FROM mimetype WHERE mimetype_name = 'application/x-debian-source' LIMIT 1;");
283  result = PQexec(db_conn, sqlbuf);
284  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
285  {
286  free(pi);
287  free(dpi);
288  exit(-1);
289  }
290  debsrcmimetypepk = atoi(PQgetvalue(result, 0, 0));
291  PQclear(result);
292  if ( debsrcmimetypepk == 0 )
293  {
294  LOG_ERROR("pkgagent deb source mimetype not installed!");
295  free(pi);
296  free(dpi);
297  return (-1);
298  }
299  }
300 
301  if (!upload_pk) // when upload_pk is empty
302  {
303  free(pi);
304  free(dpi);
305  return -1;
306  }
308  if (NULL == uploadtree_tablename) uploadtree_tablename = strdup("uploadtree_a");
309  /* retrieve the records to process */
310  snprintf(sqlbuf, sizeof(sqlbuf),
311  "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') 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);
312  result = PQexec(db_conn, sqlbuf);
313  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
314  {
315  free(pi);
316  free(dpi);
317  exit(-1);
318  }
319 
320  numrows = PQntuples(result);
321  for (i=0; i<numrows; i++)
322  {
323  char *repFile = NULL;
324 
325  memset(pi,0,sizeof(struct rpmpkginfo));
326  memset(dpi,0,sizeof(struct debpkginfo));
327 
328  strcpy(mimetype, PQgetvalue(result, i, 2));
329  /*
330  * if mimetype='application/x-rpm' process RPM packages
331  * if mimetype='application/x-debian-package' process DEBIAN packages
332  * if mimetype='application/x-debian-source' process DEBIAN source packages
333  * */
334  if (!strcasecmp(mimetype,"application/x-rpm")) {
335  pi->pFileFk = atoi(PQgetvalue(result, i, 0));
336  strncpy(pi->pFile, PQgetvalue(result, i, 1), sizeof(pi->pFile)-1);
337  pi->pFile[sizeof(pi->pFile)-1] = '\0';
338  repFile = fo_RepMkPath("files", pi->pFile);
339  if (!repFile) {
340  LOG_FATAL("pfile %ld PkgAgent unable to open file %s",
341  pi->pFileFk, pi->pFile);
342  return (-1);
343  }
344  if (GetMetadata(repFile,pi) != -1){
345  RecordMetadataRPM(pi);
346  }
347  /* free memory */
348  int i;
349  for(i=0; i< pi->req_size;i++)
350  free(pi->requires[i]);
351  free(pi->requires);
352  }
353  else if (!strcasecmp(mimetype, "application/x-debian-package")){
354  dpi->pFileFk = atoi(PQgetvalue(result, i, 0));
355  strncpy(dpi->pFile, PQgetvalue(result, i, 1), sizeof(dpi->pFile)-1);
356  dpi->pFile[sizeof(dpi->pFile)-1] = '\0';
357  if (GetMetadataDebBinary(upload_pk, dpi) != -1){
358  if (RecordMetadataDEB(dpi) != 0) continue;
359  }
360  /* free memory */
361  int i;
362  for(i=0; i< dpi->dep_size;i++)
363  free(dpi->depends[i]);
364  free(dpi->depends);
365  }
366  else if (!strcasecmp(mimetype, "application/x-debian-source")){
367  dpi->pFileFk = atoi(PQgetvalue(result, i, 0));
368  strncpy(dpi->pFile, PQgetvalue(result, i, 1), sizeof(dpi->pFile)-1);
369  dpi->pFile[sizeof(dpi->pFile)-1] = '\0';
370  repFile = fo_RepMkPath("files", dpi->pFile);
371  if (!repFile) {
372  LOG_FATAL("pfile %ld PkgAgent unable to open file %s\n",
373  dpi->pFileFk, dpi->pFile);
374  return (-1);
375  }
376  if (GetMetadataDebSource(repFile,dpi) != -1){
377  RecordMetadataDEB(dpi);
378  }
379  /* free memory */
380  int i;
381  for(i=0; i< dpi->dep_size;i++)
382  free(dpi->depends[i]);
383  free(dpi->depends);
384  } else {
385  printf("LOG: Not RPM and DEBIAN package!\n");
386  }
388  }
389  PQclear(result);
390  rpmFreeCrypto();
391  rpmFreeMacros(NULL);
392  free(pi);
393  free(dpi);
394  return (0);
395 }/*ProcessUpload (long upload_pk)*/
396 
402 void ReadHeaderInfo(Header header, struct rpmpkginfo *pi)
403 {
404  char fmt[128];
405  char * msgstr;
406  const char * errstr;
407  int i,j;
408  long *tp,t;
409  int header_status;
410 
411  struct rpmtd_s req;
412  rpm_count_t data_size;
413 
414  for (i = 0; i < 14; i++) {
415  memset(fmt, 0, sizeof(fmt));
416  strcat( fmt, "%{");
417  strcat( fmt, rpmTagGetName(tag[i]));
418  strcat( fmt, "}\n");
419 
420  msgstr = headerFormat(header, fmt, &errstr);
421  if (msgstr != NULL){
422  trim(msgstr);
423  printf("%s:%s\n",rpmTagGetName(tag[i]),msgstr);
424  switch (tag[i]) {
425  case RPMTAG_NAME:
426  EscapeString(msgstr, pi->pkgName, sizeof(pi->pkgName));
427  break;
428  case RPMTAG_EPOCH:
429  EscapeString(msgstr, pi->pkgAlias, sizeof(pi->pkgAlias));
430  break;
431  case RPMTAG_ARCH:
432  EscapeString(msgstr, pi->pkgArch, sizeof(pi->pkgArch));
433  break;
434  case RPMTAG_VERSION:
435  EscapeString(msgstr, pi->version, sizeof(pi->version));
436  break;
437  case RPMTAG_LICENSE:
438  EscapeString(msgstr, pi->license, sizeof(pi->license));
439  break;
440  case RPMTAG_GROUP:
441  EscapeString(msgstr, pi->group, sizeof(pi->group));
442  break;
443  case RPMTAG_PACKAGER:
444  EscapeString(msgstr, pi->packager, sizeof(pi->packager));
445  break;
446  case RPMTAG_RELEASE:
447  EscapeString(msgstr, pi->release, sizeof(pi->release));
448  break;
449  case RPMTAG_BUILDTIME:
450  t = atol(msgstr);
451  tp = &t;
452  strncpy(pi->buildDate,trim(asctime(gmtime((time_t*)tp))),sizeof(pi->buildDate)-1);
453  pi->buildDate[sizeof(pi->buildDate)-1] = '\0';
454  break;
455  case RPMTAG_VENDOR:
456  EscapeString(msgstr, pi->vendor, sizeof(pi->vendor));
457  break;
458  case RPMTAG_URL:
459  EscapeString(msgstr, pi->url, sizeof(pi->url));
460  break;
461  case RPMTAG_SOURCERPM:
462  EscapeString(msgstr, pi->sourceRPM,sizeof(pi->sourceRPM));
463  break;
464  case RPMTAG_SUMMARY:
465  EscapeString(msgstr, pi->summary, sizeof(pi->summary));
466  break;
467  case RPMTAG_DESCRIPTION:
468  EscapeString(msgstr, pi->description, sizeof(pi->description));
469  break;
470  default:
471  break;
472  }
473  }
474  free((void *)msgstr);
475  }
476  if (Verbose > 1) { printf("Name:%s\n",pi->pkgName);}
477  header_status = headerGet(header, tag[14], &req, HEADERGET_DEFAULT);
478  if (header_status) {
479  data_size = rpmtdCount(&req);
480  pi->requires = calloc(data_size, sizeof(char *));
481  for (j=0; j<(int)data_size;j++){
482  const char * temp = rpmtdNextString(&req);
483  pi->requires[j] = malloc(MAXCMD);
484  strcpy(pi->requires[j],temp);
485  }
486  pi->req_size = data_size;
487  rpmtdFreeData(&req);
488  }
489 
490  if (Verbose > 1) {
491  printf("Size:%d\n",pi->req_size);
492  for (j=0; j<pi->req_size;j++){
493  printf("REQ:%s\n",pi->requires[j]);
494  }
495  printf("Name:%s\n",pi->sourceRPM);
496  }
497 } /* ReadHeaderInfo(Header header, struct rpmpkginfo *pi) */
498 
505 int GetMetadata (char *pkg, struct rpmpkginfo *pi)
506 {
507  //rpmpi.pFileFk = 4234634;
508  //if (PKG_RPM)
509  //{
510  FD_t fd;
511  rpmRC rpmrc;
512  Header header;
513  rpmts ts;
514  rpmVSFlags vsflags;
515 
516  vsflags = RPMVSF_DEFAULT;
517  ts = (rpmts) rpmtsCreate();
518 
519  fd = Fopen(pkg,"r");
520  if ( fd == NULL ||Ferror(fd)){
521  rpmlog(RPMLOG_ERR, "open of %s failed: %s\n", pkg, Fstrerror(fd));
522  if (fd){
523  Fclose(fd);
524  }
525  return (-1);
526  }
527 
528  vsflags |= _RPMVSF_NOSIGNATURES;
529  vsflags |= _RPMVSF_NODIGESTS;
530  vsflags |= RPMVSF_NOHDRCHK;
531  vsflags |= RPMVSF_NEEDPAYLOAD;
532 
533  rpmtsSetVSFlags(ts, vsflags);
534 
535  //rpmReadConfigFiles(NULL, NULL);
536  rpmrc = rpmReadPackageFile(ts, fd, pkg,&header);
537  Fclose(fd);
538  ts = (rpmts) rpmtsFree(ts);
539 
540  switch (rpmrc) {
541  case RPMRC_OK:
542  case RPMRC_NOKEY:
543  case RPMRC_NOTTRUSTED:
544  break;
545  case RPMRC_NOTFOUND:
546  case RPMRC_FAIL:
547  default:
548  rpmlog(RPMLOG_ERR, "%s cannot be read or is not an RPM.\n", pkg);
549  return (-1);
550  }
551  ReadHeaderInfo(header, pi);
552  //rpmFreeMacros(NULL);
553  header = headerFree(header);
554  //}
555  return (0);
556 } /* GetMetadata(char *pkg, struct rpmpkginfo *pi) */
557 
564 {
565  char SQL[MAXCMD];
566  PGresult *result;
567  int pkg_pk;
568 
569  memset(SQL,0,sizeof(SQL));
570  snprintf(SQL,sizeof(SQL),"SELECT pfile_fk FROM pkg_rpm WHERE pfile_fk = %ld;",pi->pFileFk);
571  result = PQexec(db_conn, SQL);
572  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
573  if (PQntuples(result) <=0)
574  {
575  PQclear(result);
576  memset(SQL,0,sizeof(SQL));
577  result = PQexec(db_conn, "BEGIN;");
578  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
579  PQclear(result);
580 
581  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);",
582  trim(pi->pkgName),trim(pi->pkgAlias),trim(pi->pkgArch),trim(pi->version),
583  trim(pi->rpmFilename),trim(pi->license),trim(pi->group),trim(pi->packager),
584  trim(pi->release),pi->buildDate,trim(pi->vendor),trim(pi->url),trim(pi->sourceRPM),
585  trim(pi->summary),trim(pi->description),pi->pFileFk);
586  result = PQexec(db_conn, SQL);
587  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
588  {
589  PQexec(db_conn, "ROLLBACK;");
590  return (-1);
591  }
592  PQclear(result);
593 
594  result = PQexec(db_conn,"SELECT currval('pkg_rpm_pkg_pk_seq'::regclass);");
595  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
596  pkg_pk = atoi(PQgetvalue(result,0,0));
597  PQclear(result);
598 
599  if (Verbose) { printf("pkg_pk:%d\n",pkg_pk);}
600  int i;
601  for (i=0;i<pi->req_size;i++)
602  {
603  memset(SQL,0,sizeof(SQL));
604  snprintf(SQL,sizeof(SQL),"INSERT INTO pkg_rpm_req (pkg_fk,req_value) values (%d,E'%s');",pkg_pk,trim(pi->requires[i]));
605  result = PQexec(db_conn, SQL);
606  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
607  {
608  PQexec(db_conn, "ROLLBACK;");
609  return (-1);
610  }
611  PQclear(result);
612  }
613  result = PQexec(db_conn, "COMMIT;");
614  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
615  PQclear(result);
616  }
617  return (0);
618 } /* RecordMetadata(struct rpmpkginfo *pi) */
619 
620 
629 char * ParseDebFile(char *Sin, char *Field, char *Value)
630 {
631  int s,f,v;
632 
633  memset(Field,0,MAXCMD);
634  memset(Value,0,MAXCMD);
635 
636  f=0; v=0;
637  if(!isspace(Sin[0]))
638  {
639  for(s=0; (Sin[s] != '\0') && !isspace(Sin[s]) && (Sin[s] != ':'); s++)
640  {
641  Field[f++] = Sin[s];
642  }
643  while(isspace(Sin[s])) s++;
644  if (Sin[s] != ':')
645  {
646  return(Sin+s);
647  }
648  s++;
649  while(isspace(Sin[s])) s++;
650 
651  for( ; Sin[s] != '\0'; s++)
652  {
653  Value[v++]=Sin[s];
654  }
655  if (Verbose) { printf("Field is %s and Value is %s", Field, Value);}
656  return(Sin+s);
657  } else
658  {
659  if (Verbose) { printf("ExValue is %s", Sin);}
660  return(Sin);
661  }
662 } /* ParseDebFile(char *Sin, char *Field, char *Value) */
663 
671 {
672  char *repfile;
673  char *filename;
674  char SQL[MAXCMD];
675  PGresult *result;
676  unsigned long lft, rgt;
677 
678  FILE *fp;
679  char field[MAXCMD];
680  char value[MAXCMD];
681  char line[MAXCMD];
682  char *s = NULL;
683  char temp[MAXCMD];
684  char *uploadtree_tablename;
685 
686  if (!upload_pk) return -1; // when upload_pk is empty
688  if (NULL == uploadtree_tablename) uploadtree_tablename = strdup("uploadtree_a");
689  /* Get the debian control file's repository path */
690  /* First get the uploadtree bounds (lft,rgt) for the package */
691  snprintf(SQL,sizeof(SQL),"SELECT lft,rgt FROM %s WHERE upload_fk = %ld AND pfile_fk = %ld limit 1",
693  result = PQexec(db_conn, SQL);
694  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
695  if (PQntuples(result) == 0)
696  {
697  LOG_ERROR("Missing debian package (internal data inconsistancy). SQL: %s\n", SQL);
698  PQclear(result);
699  return (-1);
700  }
701  lft = strtoul(PQgetvalue(result,0,0), NULL, 10);
702  rgt = strtoul(PQgetvalue(result,0,1), NULL, 10);
703  PQclear(result);
704 
705  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')",
706  upload_pk, lft, rgt);
707  result = PQexec(db_conn, SQL);
708  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
709  if (PQntuples(result) > 0)
710  {
711  filename = PQgetvalue(result,0,0);
712  repfile = fo_RepMkPath("files", filename);
713  if (!repfile) {
714  LOG_FATAL("PkgAgent unable to open file %s\n",filename);
715  return (-1);
716  }
717  PQclear(result);
718  }
719  else
720  {
721  PQclear(result);
722  printf("LOG: Unable to find debian/control file! This file had wrong mimetype, ignore it!\n");
723  memset(SQL,0,sizeof(SQL));
724  snprintf(SQL,sizeof(SQL),"UPDATE pfile SET pfile_mimetypefk = NULL WHERE pfile_pk = %ld;", pi->pFileFk);
725  result = PQexec(db_conn, SQL);
726  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
727  PQclear(result);
728  return (-1);
729  }
730 
731  /* Parse the debian/control file to get every Field and Value */
732  if ((fp = fopen(repfile, "r")) == NULL){
733  LOG_FATAL("Unable to open debian/control file %s\n",repfile);
734  return (-1);
735  }
736 
737  while (fgets(line,MAXCMD,fp)!=NULL)
738  {
739  s = ParseDebFile(line,field,value);
740  trim(value);
741  if (!strcasecmp(field, "Description")) {
742  EscapeString(value, pi->summary, sizeof(pi->summary));
743  strcpy(temp, "");
744  }
745  if (s[0] != '\0') {
746  if ((strlen(temp) + strlen(s)) >= MAXCMD )
747  continue;
748  else
749  strcat(temp,s);
750  }
751  if (!strcasecmp(field, "Package")) {
752  EscapeString(value, pi->pkgName, sizeof(pi->pkgName));
753  }
754  if (!strcasecmp(field, "Version")) {
755  EscapeString(value, pi->version, sizeof(pi->version));
756  }
757  if (!strcasecmp(field, "Architecture")) {
758  EscapeString(value, pi->pkgArch, sizeof(pi->pkgArch));
759  }
760  if (!strcasecmp(field, "Maintainer")) {
761  EscapeString(value, pi->maintainer, sizeof(pi->maintainer));
762  }
763  if (!strcasecmp(field, "Installed-Size")) {
764  pi->installedSize=atol(value);
765  }
766  if (!strcasecmp(field, "Section")) {
767  EscapeString(value, pi->section, sizeof(pi->section));
768  }
769  if (!strcasecmp(field, "Priority")) {
770  EscapeString(value, pi->priority, sizeof(pi->priority));
771  }
772  if (!strcasecmp(field, "Homepage")) {
773  EscapeString(value, pi->homepage, sizeof(pi->homepage));
774  }
775  if (!strcasecmp(field, "Source")) {
776  EscapeString(value, pi->source, sizeof(pi->source));
777  }
778  if (!strcasecmp(field, "Depends")) {
779  char *depends = NULL;
780  char tempvalue[MAXCMD];
781  int size,i;
782  size_t length = MAXLENGTH;
783  size = 0;
784  if (value[0] != '\0'){
785  strncpy(tempvalue, value, sizeof(tempvalue));
786  depends = strtok(value, ",");
787  while (depends && (depends[0] != '\0')) {
788  if (strlen(depends) >= length)
789  length = strlen(depends) + 1;
790  depends = strtok(NULL, ",");
791  size++;
792  }
793  if (Verbose) { printf("SIZE:%d\n", size);}
794 
795  pi->depends = calloc(size, sizeof(char *));
796  pi->depends[0] = calloc(length, sizeof(char));
797  strcpy(pi->depends[0],strtok(tempvalue,","));
798  for (i=1;i<size;i++){
799  pi->depends[i] = calloc(length, sizeof(char));
800  strcpy(pi->depends[i],strtok(NULL, ","));
801  }
802  pi->dep_size = size;
803  }
804  }
805  }
806  EscapeString(temp, pi->description, sizeof(pi->description));
807 
808  fclose(fp);
809  free(repfile);
810  return (0);
811 }/* GetMetadataDebBinary(struct debpkginfo *pi) */
812 
819 {
820  char SQL[MAXCMD];
821  PGresult *result;
822  int pkg_pk;
823 
824  memset(SQL,0,sizeof(SQL));
825  snprintf(SQL,sizeof(SQL),"SELECT pfile_fk FROM pkg_deb WHERE pfile_fk = %ld;",pi->pFileFk);
826  result = PQexec(db_conn, SQL);
827  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
828  if (PQntuples(result) <=0)
829  {
830  PQclear(result);
831  memset(SQL,0,sizeof(SQL));
832  result = PQexec(db_conn, "BEGIN;");
833  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
834  PQclear(result);
835 
836  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);",
837  trim(pi->pkgName),trim(pi->pkgArch),trim(pi->version),trim(pi->maintainer),
838  pi->installedSize,trim(pi->section),trim(pi->priority),trim(pi->homepage),
839  trim(pi->source),trim(pi->summary),trim(pi->description),trim(pi->format),
840  trim(pi->uploaders),trim(pi->standardsVersion),pi->pFileFk);
841  result = PQexec(db_conn, SQL);
842  // ignore error
843  if ((result==0) || ((PQresultStatus(result) != PGRES_COMMAND_OK)))
844  {
845  LOG_FATAL("Error inserting, SQL is: %s, error code is:%s\n", SQL, PQresultErrorField(result, PG_DIAG_SQLSTATE));
846  PQexec(db_conn, "ROLLBACK;");
847  if (result) PQclear(result);
848  return (-1);
849  } else
850  {
851  PQclear(result);
852  }
853 
854  result = PQexec(db_conn,"SELECT currval('pkg_deb_pkg_pk_seq'::regclass);");
855  if (fo_checkPQresult(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
856  pkg_pk = atoi(PQgetvalue(result,0,0));
857  PQclear(result);
858 
859  if (Verbose) { printf("pkg_pk:%d\n",pkg_pk);}
860  int i;
861  for (i=0;i<pi->dep_size;i++)
862  {
863  memset(SQL,0,sizeof(SQL));
864  snprintf(SQL,sizeof(SQL),"INSERT INTO pkg_deb_req (pkg_fk,req_value) values (%d,E'%s');",pkg_pk,trim(pi->depends[i]));
865  if (Verbose) { printf("DEPENDS:%s\n",pi->depends[i]);}
866  result = PQexec(db_conn, SQL);
867  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__))
868  {
869  PQexec(db_conn, "ROLLBACK;");
870  return (-1);
871  }
872  PQclear(result);
873  }
874  result = PQexec(db_conn, "COMMIT;");
875  if (fo_checkPQcommand(db_conn, result, SQL, __FILE__, __LINE__)) exit(-1);
876  PQclear(result);
877  }
878  else
879  {
880  PQclear(result);
881  }
882  return (0);
883 }/* RecordMetadataDEB(struct debpkginfo *pi) */
884 
892 int GetMetadataDebSource (char *repFile, struct debpkginfo *pi)
893 {
894  FILE *fp;
895  char field[MAXCMD];
896  char value[MAXCMD];
897  char line[MAXCMD];
898 
899  /* Parse the debian .dsc file to get every Field and Value */
900  if ((fp = fopen(repFile, "r")) == NULL){
901  LOG_FATAL("Unable to open .dsc file %s\n",repFile);
902  return (-1);
903  }
904 
905  while (fgets(line,MAXCMD,fp)!=NULL)
906  {
907  ParseDebFile(line,field,value);
908 
909  trim(value);
910  if (!strcasecmp(field, "Format")) {
911  EscapeString(value, pi->format, sizeof(pi->format));
912  }
913  if (!strcasecmp(field, "Source")) {
914  EscapeString(value, pi->source, sizeof(pi->source));
915  }
916  if (!strcasecmp(field, "Source")) {
917  EscapeString(value, pi->pkgName, sizeof(pi->pkgName));
918  }
919  if (!strcasecmp(field, "Architecture")) {
920  EscapeString(value, pi->pkgArch, sizeof(pi->pkgArch));
921  }
922  if (!strcasecmp(field, "Version")) {
923  if (strlen(pi->version) == 0)
924  EscapeString(value, pi->version, sizeof(pi->version));
925  }
926  if (!strcasecmp(field, "Maintainer")) {
927  EscapeString(value, pi->maintainer, sizeof(pi->maintainer));
928  }
929  if (!strcasecmp(field, "Homepage")) {
930  EscapeString(value, pi->homepage, sizeof(pi->homepage));
931  }
932  if (!strcasecmp(field, "Uploaders")) {
933  EscapeString(value, pi->uploaders, sizeof(pi->uploaders));
934  }
935  if (!strcasecmp(field, "Standards-Version")) {
936  EscapeString(value, pi->standardsVersion, sizeof(pi->standardsVersion));
937  }
938  if (!strcasecmp(field, "Build-Depends")) {
939  char *depends = NULL;
940  char tempvalue[MAXCMD];
941  int size,i;
942  size = 0;
943  size_t length = MAXLENGTH;
944  if (value[0] != '\0'){
945  strncpy(tempvalue, value, sizeof(tempvalue));
946  depends = strtok(value, ",");
947  while (depends && (depends[0] != '\0')) {
948  if (strlen(depends) >= length)
949  length = strlen(depends) + 1;
950  depends = strtok(NULL, ",");
951  size++;
952  }
953  if (Verbose) { printf("SIZE:%d\n", size);}
954 
955  pi->depends = calloc(size, sizeof(char *));
956  pi->depends[0] = calloc(length, sizeof(char));
957  strcpy(pi->depends[0],strtok(tempvalue,","));
958  for (i=1;i<size;i++){
959  pi->depends[i] = calloc(length, sizeof(char));
960  strcpy(pi->depends[i],strtok(NULL, ","));
961  }
962  pi->dep_size = size;
963  }
964  }
965  }
966 
967  fclose(fp);
968  return (0);
969 }/* GetMetadataDebSource(char *repFile, struct debpkginfo *pi) */
970 
971 /***********************************************
972  Usage():
973  Command line options allow you to write the agent so it works
974  stand alone, in addition to working with the scheduler.
975  This simplifies code development and testing.
976  So if you have options, have a Usage().
977  Here are some suggested options (in addition to the program
978  specific options you may already have).
979  ***********************************************/
980 void Usage (char *Name)
981 {
982  printf("Usage: %s [options] [file [file [...]]\n",Name);
983  printf(" -i :: initialize the database, then exit.\n");
984  printf(" -v :: verbose (-vv = more verbose)\n");
985  printf(" -c :: Specify the directory for the system configuration.\n");
986  printf(" -C :: run from command line.\n");
987  printf(" file :: if files are rpm package listed, display their package information.\n");
988  printf(" no file :: process data from the scheduler.\n");
989  printf(" -V :: print the version info, then exit.\n");
990 } /* Usage() */
991 
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:629
void Usage(char *Name)
Say how to run this program.
Definition: pkgagent.c:980
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:505
int GetMetadataDebSource(char *repFile, struct debpkginfo *pi)
Get debian source package info from .dsc file.
Definition: pkgagent.c:892
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:818
int Verbose
Verbose level.
Definition: pkgagent.c:21
int RecordMetadataRPM(struct rpmpkginfo *pi)
Store rpm package info into database.
Definition: pkgagent.c:563
int GetMetadataDebBinary(long upload_pk, struct debpkginfo *pi)
Get debian binary package info.
Definition: pkgagent.c:670
void ReadHeaderInfo(Header header, struct rpmpkginfo *pi)
Get RPM package info from rpm file header use rpm library.
Definition: pkgagent.c:402
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:65
char section[MAXCMD]
Package section.
Definition: pkgagent.h:69
char priority[MAXCMD]
Package priority.
Definition: pkgagent.h:70
char standardsVersion[MAXCMD]
Package standards version.
Definition: pkgagent.h:83
long pFileFk
Package pfile in FOSSology.
Definition: pkgagent.h:77
char ** depends
Package dependency list.
Definition: pkgagent.h:79
char summary[MAXCMD]
Package summary.
Definition: pkgagent.h:75
char pFile[MAXCMD]
Package pfile hash.
Definition: pkgagent.h:78
char version[MAXCMD]
Package version.
Definition: pkgagent.h:68
char format[MAXCMD]
Package format.
Definition: pkgagent.h:82
char uploaders[MAXCMD]
Package contributors.
Definition: pkgagent.h:81
char maintainer[MAXCMD]
Package maintainer.
Definition: pkgagent.h:73
int installedSize
Size of package after install.
Definition: pkgagent.h:72
char pkgArch[MAXCMD]
Package architecture.
Definition: pkgagent.h:71
char description[MAXCMD]
Package description.
Definition: pkgagent.h:76
int dep_size
Package dependency list size.
Definition: pkgagent.h:80
char source[MAXCMD]
Package source.
Definition: pkgagent.h:67
char pkgName[MAXCMD]
Package name.
Definition: pkgagent.h:66
char homepage[MAXCMD]
Package link.
Definition: pkgagent.h:74
Holds meta info of rpm packages.
Definition: pkgagent.h:38
char buildDate[128]
Package build date.
Definition: pkgagent.h:48
char pFile[MAXCMD]
Package pfile hash.
Definition: pkgagent.h:55
char group[128]
Package group.
Definition: pkgagent.h:45
char version[64]
Package version.
Definition: pkgagent.h:42
char summary[MAXCMD]
Package summary.
Definition: pkgagent.h:52
char pkgName[256]
RPM package name.
Definition: pkgagent.h:39
char description[MAXCMD]
Package description.
Definition: pkgagent.h:53
char rpmFilename[256]
RPM file name.
Definition: pkgagent.h:43
char license[512]
RPM licenses.
Definition: pkgagent.h:44
char pkgArch[64]
Package architecture.
Definition: pkgagent.h:41
char sourceRPM[256]
Package source.
Definition: pkgagent.h:51
int req_size
Package dependency list size.
Definition: pkgagent.h:57
char pkgAlias[256]
Package alias.
Definition: pkgagent.h:40
char url[256]
Package link.
Definition: pkgagent.h:50
long pFileFk
Package pfile in FOSSology.
Definition: pkgagent.h:54
char release[64]
Package release.
Definition: pkgagent.h:47
char packager[1024]
Packager.
Definition: pkgagent.h:46
char ** requires
Package dependency list.
Definition: pkgagent.h:56
char vendor[128]
Package vendor.
Definition: pkgagent.h:49