FOSSology  4.4.0
Open Source License Compliance by Open Source Software
snippet_scan.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-only
26 #define _GNU_SOURCE
27 #include "snippet_scan.h"
28 #include <stdio.h>
29 #include <errno.h>
30 
31 extern void logme(char *msg);
32 
33 extern char *baseTMP;
34 int Verbose = 0;
35 PGconn *db_conn = NULL;
36 extern int Agent_pk;
37 extern char ApiUrl[200];
38 extern char accToken[100];
39 
40 
41 
42 /***************************************************************************/
43 
44 int splitLine(char *lineToSplit, char *separator, char **fields){
45 int i=0;
46 
47 
48  char *token;
49 
50  char* strSplit = lineToSplit;
51  while ((token = strtok_r(strSplit , separator, &strSplit)))
52  sprintf(fields[i++],"%s",token);
53 return i;
54  }
55 
56 void extract_csv(char *out, char *in, int n, long limit,char sep)
57 {
58  char seps[3];
59  char line[2048];
60  sprintf(line,"%s",in);
61  sprintf(seps,"%c",sep);
62  char * token = strtok(line, seps);
63  // loop through the string to extract all other tokens
64  int count=0;
65  while( token != NULL ) {
66  count++;// printf( " %s\n", token ); //printing each token
67  if (count==n){
68  sprintf(out,"%s",token);
69  break;
70 
71  }
72  token = strtok(NULL, seps);
73 
74  }
75 }
76 
82 FILE *openFileByKey(long pFileKey)
83 {
84  char sqlbuf[200];
85  PGresult *result;
86  sprintf(sqlbuf, "SELECT pfile_sha1 || '.' || pfile_md5 || '.' || pfile_size AS pfile_path FROM pfile WHERE pfile_pk = %ld;", pFileKey);
87  result = PQexec(db_conn, sqlbuf);
88  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
89  {
90 
91  exit(-1);
92  }
93  char path[500];
94  sprintf(path, "%s", PQgetvalue(result, 0, 0));
95  return fo_RepFread("files", path);
96 }
97 
98 
102 int getLicenseId(unsigned char *name)
103 {
104  PGresult *result;
105  char sqlbuf[500];
106  sprintf(sqlbuf, "select lr.rf_pk from license_ref lr where lr.rf_shortname like '%s';", name);
107  result = PQexec(db_conn, sqlbuf);
108 
109  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
110  {
111  return 0;
112  }
113 
114  if (PQgetvalue(result, 0, 0) != NULL)
115  {
116  return atoi(PQgetvalue(result, 0, 0));
117  }
118  else
119  return 0;
120 }
121 
122 
129 void dumpToFile(const char *path, unsigned char *content, long size)
130 {
131  FILE *fptr;
132  fptr = fopen(path, "w");
133 
134  if (fptr == NULL)
135  {
136  LOG_ERROR("Snippet scan: Could not create temp file")
137  }
138  else
139  {
140  fwrite(content, size, 1, fptr);
141  fclose(fptr);
142  }
143 }
144 
145 void RestoreTempFile(char * uploadFolder, long key, long realParent, char *realName)
146 {
147  char dstName[256];
148  FILE *f = openFileByKey(key); /* Open the file from the repository by its key */
149  sprintf(dstName, "%s/%ld_%ld_%s", uploadFolder,realParent,key,realName); /* Create a name for the temp file, including the temp folder */
150  if (f != NULL)
151  {
152  fseek(f, 0, SEEK_END); /* Read the file and dump the content into the temp file*/
153  int size = ftell(f);
154  unsigned char *contents = calloc(1, size);
155  memset(contents, '\0', size);
156  rewind(f);
157  size_t readSize = fread(contents, size, 1, f);
158  fo_RepFclose(f);
159  if(readSize==0)
160  return;
161  dumpToFile(dstName, contents, size);
162  }
163 }
164 
165 
166  /*1 inventory_id,
167  2 path,
168  3 detected_usage,
169  4 detected_component,
170  5 detected_license,
171  6 detected_version,
172  7 detected_latest,
173  8 detected_purls,
174  9 detected_url,
175  10 detected_match,
176  11 detected_lines,
177  12 detected_oss_lines,
178  13 detected_path
179 */
185 void ParseResults(char *folder){
186  PGresult *result;
187  char Cmd[100];
188  char auxSql[MAXCMD*4];
189 
190  char detectedUsage[MAXCMD];
191  char detPurls[MAXCMD];
192  char detLicenses[MAXCMD];
193  char path[MAXCMD];
194  char detMatch[MAXCMD];
195  char detLines[MAXCMD];
196  char detPath[MAXCMD];
197  char detUrl[MAXCMD];
198 
199  sprintf(Cmd, "%s/results.csv", folder);
200  FILE* file = fopen(Cmd, "r");
201 
202  char line[MAXCMD*10];
203  int resCount=0;
204  if(file==NULL) {
205  LOG_ERROR("Error while opening the file");
206  return;
207  }
208  while (fgets(line, sizeof(line), file)) {
209  if (resCount==0) { resCount++;continue;} //Skip header
210  if (line[0]!=0 && line[0]!=' '){
211  long parent;
212  long key;
213  char srcName[MAXCMD];
214  extract_csv(path, line, 2,MAXCMD,',');
215  if( path!=NULL) {
216  sscanf(path,"%ld_%ld_%s",&parent,&key,srcName);
217  } else {return;}
218 
219  int lenLine=strlen(line);
220  extract_csv(detectedUsage, line, 3,lenLine,',');
221  extract_csv(detPurls, line, 8,lenLine,',');
222  extract_csv(detLicenses, line, 5,lenLine,',');
223  extract_csv(detUrl, line, 9,lenLine,',');
224 
225  extract_csv(detMatch, line, 10,lenLine,',');
226  extract_csv(detLines, line, 12,lenLine,',');
227  extract_csv(detPath, line, 13,lenLine,',');
228 
229  // License store
230 
231  for (int i=1;i<5;i++){
232  char aux[100];
233  extract_csv(aux, detLicenses, i,strlen(detLicenses),';');
234  if (aux==NULL) break;
235  else {
236  int detLic= getLicenseId((unsigned char *) aux); /* ... from name, get the key of license that matches short_name at license_ref */
237  if(detLic!=0){
238  sprintf(auxSql,"INSERT INTO license_file(rf_fk, agent_fk, rf_timestamp, pfile_fk) VALUES(%d,%d, now(), %ld);",detLic,Agent_pk,key);
239  result = PQexec(db_conn,auxSql);
240  } else {
242  }
243  }
244  }
245 
246 
247  //File info store
248  if(strcmp((char *)detectedUsage,"none") && (!(strcmp((char *)detectedUsage,"file"))||!(strcmp((char *)detectedUsage,"snippet")) )){
249  char *auxSQL;
250  asprintf(&auxSQL,"INSERT INTO scanoss_fileinfo (pfile_fk, matchtype, lineranges, purl,filepath,url) VALUES(%ld, '%s', '%s', '%s','%s','%s');", key,detectedUsage,detLines,detPurls,detPath,detUrl);//,url,filePath);
251  result = PQexec(db_conn,auxSQL);
252  free(auxSQL);
253  if (PQntuples(result) == 0)
254  {
255  PQclear(result);
256  }
257  }
258  resCount++;
259  } else {break;}
260  }
261 }
262 
263 
269 int ScanFolder(char *folder)
270 {
271 
272  FILE *Fin;
273  char Cmd[MAXCMD];
274  memset(Cmd, '\0', MAXCMD);
275 
276  unsigned char apiurl[400];
277  unsigned char key[110];
278 
279  if(ApiUrl[0]!='\0') {
280  sprintf((char *) apiurl,"--apiurl %s",ApiUrl);
281  }
282  else
283  memset(apiurl,0,sizeof(apiurl));
284 
285  if(accToken[0]!='\0' && accToken[0]!=' ') {
286  sprintf((char *)key,"--key %s",accToken);
287  }
288  else
289  memset(key,0,sizeof(key));
290 
291  char *user;
292  asprintf(&user,"%s",fo_config_get(sysconfig, "DIRECTORIES", "PROJECTUSER", NULL));
293 
294  sprintf(Cmd,"PYTHONPATH='/home/%s/pythondeps/' /home/%s/pythondeps/bin/scanoss-py scan %s --format=csv -o %s/results.csv %s %s", user,user,folder, folder,apiurl,key); /* Create the command to run */
295  logme(Cmd);
296  free(user);
297  Fin = popen(Cmd, "r"); /* Run the command */
298  if (!Fin) {
299  LOG_ERROR("Snippet scan: failed to start scan %s",strerror(errno));
300  pclose(Fin);
301  return -1;
302  } else {
303  pclose(Fin);
304  }
305 return 0;
306 }
307 
308 
309 int RebuildUpload(long upload_pk,char *tempFolder)
310 {
311 
312  char sqlbuf[1024];
313  PGresult *result;
314  int numrows;
315  int i;
316  char *uploadtree_tablename;
317 
318  if (!upload_pk) // when upload_pk is empty
319  {
320  LOG_ERROR("Snippet scan: Missing upload key");
321  return -1;
322  }
323 
325  if (NULL == uploadtree_tablename)
326  uploadtree_tablename = strdup("uploadtree_a");
327  /* retrieve the records to process */
328  snprintf(sqlbuf, sizeof(sqlbuf),
329  "SELECT * from uploadtree_a, upload where upload_fk = upload_pk and upload_pk = '%ld' ", upload_pk);
330  result = PQexec(db_conn, sqlbuf);
331  if (fo_checkPQresult(db_conn, result, sqlbuf, __FILE__, __LINE__))
332  {
333  LOG_ERROR("Snippet scan: Error retrieving jobs");
334  exit(-1);
335  }
336 
337  numrows = PQntuples(result);
338  long parent = 0;
339  long realParent = 0;
340  long fileMode = 0;
341  long pFileFK = 0;
342  char *realName;
343  /* for each record, get it name and real parent */
344  for (i = 0; i < numrows; i++)
345  { //fo_scheduler_heart(1);
346 
347  parent = atoi(PQgetvalue(result, i, 1));
348  realParent = atoi(PQgetvalue(result, i, 2));
349  fileMode = atol(PQgetvalue(result, i, 5));
350  asprintf(&realName,"%s",PQgetvalue(result, i, 8)); //8 fileName
351  for(int j=0;j<strlen(realName);j++){
352  if(( realName[j]>='A' && realName[j]<='Z' ) ||
353  ( realName[j]>='a' && realName[j]<='z' ) ||
354  ( realName[j]>='0' && realName[j]<='9' ) || realName[j]=='.');
355  else realName[j]='_';
356 
357  }
358  //Nothing to be done on folders entries
359  if (parent != realParent && (fileMode == ((1<<28)|(1<<13)|(1<<9)))){
360 
361  } else {
362  // Ensure that it is a real file
363  //fileMode & ((1<<28)|(1<<13)|(1<<9)) == 0
364  if (fileMode != ((1<<28)|(1<<13)|(1<<9))) {
365  pFileFK = atoi(PQgetvalue(result, i, 4));
366  if (pFileFK != 0){
367  RestoreTempFile(tempFolder, pFileFK,parent,realName);
368 
369  }
370 
371  }
372  }
373  free(realName);
374  }
375  PQclear(result);
376 
377 
378  return (0);
379 }
380 
381 
382 
383 
384 
385 
386 /***********************************************
387  Usage():
388  Command line options allow you to write the agent so it works
389  stand alone, in addition to working with the scheduler.
390  This simplifies code development and testing.
391  So if you have options, have a Usage().
392  Here are some suggested options (in addition to the program
393  specific options you may already have).
394  ***********************************************/
395 void Usage(char *Name)
396 {
397  printf("Usage: %s [file|folder]\n", Name);
398  printf(" -i :: initialize the database, then exit.\n");
399  printf(" -v :: verbose (-vv = more verbose)\n");
400  printf(" -c :: Specify the directory for the system configuration.\n");
401  printf(" -C <file path/folder path> :: run from command line.\n");
402  printf(" -V :: print the version info, then exit.\n");
403 } /* Usage() */
404 
char * uploadtree_tablename
upload.uploadtree_tablename
Definition: adj2nest.c:100
char * fo_config_get(fo_conf *conf, const char *group, const char *key, GError **error)
Gets an element based on its group name and key name. If the group or key is not found,...
Definition: fossconfig.c:336
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_RepFclose(FILE *F)
Perform an fclose.
Definition: libfossrepo.c:601
FILE * fo_RepFread(char *Type, char *Filename)
Perform an fopen for reading only.
Definition: libfossrepo.c:613
fo_conf * sysconfig
void Usage(char *Name)
Say how to run this program.
Definition: snippet_scan.c:395
void dumpToFile(const char *path, unsigned char *content, long size)
Dumps the content of a file in the repository to a temporary file.
Definition: snippet_scan.c:129
PGconn * db_conn
The connection to Database.
Definition: snippet_scan.c:35
void ParseResults(char *folder)
Parse results from a temporary file and store results on database.
Definition: snippet_scan.c:185
int ScanFolder(char *folder)
Scans a Temporary folder.
Definition: snippet_scan.c:269
int Verbose
Verbose level.
Definition: snippet_scan.c:34
FILE * openFileByKey(long pFileKey)
Open a file of the repository given its primary key.
Definition: snippet_scan.c:82
int Agent_pk
agent identifier
Definition: finder.c:19
int getLicenseId(unsigned char *name)
Retrieves the license id (license_ref.rf_pk) given its short name.
Definition: snippet_scan.c:102
scanoss header
const char * upload_pk
Definition: sqlstatements.h:82