FOSSology  4.7.1
Open Source License Compliance by Open Source Software
utils.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2013 Hewlett-Packard Development Company, L.P.
3  SPDX-FileCopyrightText: © 2019 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
12 #include "maintagent.h"
13 
14 /* monotonic time helper */
15 double now_monotonic_seconds(void)
16 {
17  struct timespec ts;
18  #if defined(CLOCK_MONOTONIC)
19  clock_gettime(CLOCK_MONOTONIC, &ts);
20  #else
21  clock_gettime(CLOCK_REALTIME, &ts);
22  #endif
23  return ts.tv_sec + ts.tv_nsec / 1e9;
24 }
25 
26 /* log start marker; always a NOTICE, extra detail only when agent_verbose >= 3 */
27 void log_action_start(const char* action)
28 {
29  time_t t = time(NULL);
30  /* format ISO8601 time */
31  char timestr[64];
32  struct tm tm;
33  if (localtime_r(&t, &tm)) {
34  strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S%z", &tm);
35  } else {
36  snprintf(timestr, sizeof(timestr), "%ld", (long)t);
37  }
38 
39  /* shorten file path to start from "maintagent/" if present */
40  const char *fullpath = __FILE__;
41  const char *shortpath = strstr(fullpath, "maintagent/");
42  if (!shortpath) shortpath = fullpath;
43 
44  LOG_NOTICE("START %s %ld", action, (long)t);
45 
46  if (agent_verbose >= 3) {
47  LOG_NOTICE("%s %s Action %s started at %ld", timestr, shortpath, action, (long)t);
48  }
49 }
50 
51 /* log end marker and duration; always a NOTICE, extra detail only when agent_verbose >= 3 */
52 void log_action_end(const char* action, double start)
53 {
54  double end = now_monotonic_seconds();
55  double dur = end - start;
56  time_t t = time(NULL);
57  /* format ISO8601 time */
58  char timestr[64];
59  struct tm tm;
60  if (localtime_r(&t, &tm)) {
61  strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S%z", &tm);
62  } else {
63  snprintf(timestr, sizeof(timestr), "%ld", (long)t);
64  }
65 
66  /* shorten file path to start from "maintagent/" if present */
67  const char *fullpath = __FILE__;
68  const char *shortpath = strstr(fullpath, "maintagent/");
69  if (!shortpath) shortpath = fullpath;
70 
71  LOG_NOTICE("END %s %ld duration=%.3f", action, (long)t, dur);
72 
73  if (agent_verbose >= 3) {
74  LOG_NOTICE("%s %s Action %s ended at %ld (duration=%.3f s)", timestr, shortpath, action, (long)t, dur);
75  }
76 }
77 
85 FUNCTION void exitNow(int exitVal)
86 {
87  if (pgConn) PQfinish(pgConn);
89 
90  if (exitVal) LOG_ERROR("Exiting with status %d", exitVal);
91 
92  fo_scheduler_disconnect(exitVal);
93  exit(exitVal);
94 } /* ExitNow() */
95 
103 FUNCTION char* strtoupper(char* s)
104 {
105  char* p = s;
106  while ((*p = toupper(*p)))
107  p++;
108  return s;
109 }
110 
131 FUNCTION void recurseDir(const char* type, char* path, int level)
132 {
133  DIR* dir;
134  struct dirent* entry;
135  dir = opendir(path);
136  if (dir == NULL)
137  {
138  LOG_ERROR("Unable to open dir: '%s'", path);
139  LOG_ERROR("Error: %s", strerror(errno));
140  return;
141  }
142  while ((entry = readdir(dir)) != NULL)
143  {
144  if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
145  {
146  char nextpath[myBUFSIZ];
147  if (level > 0)
148  {
149  // Have not reached to file yet
150  strncpy(nextpath, path, myBUFSIZ - 1);
151  strncat(nextpath, "/", myBUFSIZ - 1);
152  strncat(nextpath, entry->d_name, myBUFSIZ - 1);
153 
154  recurseDir(type, nextpath, level - 1);
155  }
156  else
157  {
158  // entry is a file
159  char delim[] = ".";
160  char sha1[41];
161  char md5[33];
162  long fsize;
163  char* ptr;
164 
165  memset(sha1, '\0', 41);
166  memset(md5, '\0', 33);
167  strncpy(nextpath, entry->d_name, myBUFSIZ - 1);
168  ptr = strtok(nextpath, delim);
169  if (ptr == NULL)
170  {
171  LOG_FATAL("Unable to split path '%s' for pfile.", nextpath);
172  exitNow(-105);
173  }
174  strncpy(sha1, ptr, 40);
175  ptr = strtok(NULL, delim);
176  strncpy(md5, ptr, 32);
177  ptr = strtok(NULL, delim);
178  fsize = atol(ptr);
179  checkPFileExists(sha1, md5, fsize, type);
180  }
181  }
182  }
183  closedir(dir);
184 }
185 
194 FUNCTION void checkPFileExists(char* sha1, char* md5, long fsize,
195  const char* type)
196 {
197  PGresult* result;
198  int countTuples;
199  fo_dbManager_PreparedStatement* existsStatement;
200  char sql[] =
201  "WITH pf AS ("
202  "SELECT pfile_pk FROM pfile "
203  "WHERE pfile_md5 = $1 AND pfile_sha1 = $2 AND pfile_size = $3) "
204  "SELECT 1 AS exists FROM uploadtree INNER JOIN pf "
205  "ON pf.pfile_pk = pfile_fk "
206  "UNION ALL "
207  "SELECT 1 AS exists FROM upload INNER JOIN pf "
208  "ON pf.pfile_pk = pfile_fk;";
209 
210  existsStatement = fo_dbManager_PrepareStamement(dbManager, "checkPfileExists",
211  sql, char*, char*, long);
212  result = fo_dbManager_ExecPrepared(existsStatement, strtoupper(md5),
213  strtoupper(sha1), fsize);
214  if (fo_checkPQresult(pgConn, result, sql, __FILE__, __LINE__))
215  {
216  exitNow(-140);
217  }
218 
219  countTuples = PQntuples(result);
220  if (countTuples < 1)
221  {
222  deleteRepoFile(sha1, md5, fsize, type);
224  }
225  else
226  {
228  }
229  PQclear(result);
230 }
231 
241 FUNCTION void deleteRepoFile(char* sha1, char* md5, long fsize,
242  const char* type)
243 {
244  char filename[myBUFSIZ];
245  char* goldFilePath;
246 
247  snprintf(filename, myBUFSIZ, "%s.%s.%ld", sha1, md5, fsize);
248  goldFilePath = fo_RepMkPath(type, filename);
249  unlink(goldFilePath);
250  free(goldFilePath);
251 }
PGconn * pgConn
Database connection.
Definition: adj2nest.c:86
int s
The socket that the CLI will use to communicate.
Definition: fo_cli.c:37
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
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_disconnect(int retcode)
Disconnect the scheduler connection.
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...
int agent_verbose
Common verbose flags for the agents, this is used so that the scheduler can change the verbose level ...
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16
FUNCTION char * strtoupper(char *s)
Helper function to upper case a string.
Definition: utils.c:103
FUNCTION void exitNow(int exitVal)
Exit function. This does all cleanup and should be used instead of calling exit() or main() return.
Definition: utils.c:85
FUNCTION void checkPFileExists(char *sha1, char *md5, long fsize, const char *type)
Check if given checksums exists in DB, if not call deleteRepoFile()
Definition: utils.c:194
FUNCTION void deleteRepoFile(char *sha1, char *md5, long fsize, const char *type)
Take a file checksum, generate repo path and call unlink()
Definition: utils.c:241
FUNCTION void recurseDir(const char *type, char *path, int level)
Recursively read directory till level is 0.
Definition: utils.c:131
PGresult * fo_dbManager_ExecPrepared(fo_dbManager_PreparedStatement *preparedStatement,...)
Execute a prepared statement.
Definition: standalone.c:37
void fo_dbManager_free(fo_dbManager *dbManager)
Un-allocate the memory from a DB manager.
Definition: standalone.c:35
start($application)
start the application Assumes application is restartable via /etc/init.d/<script>....
Definition: pkgConfig.php:1214