cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

files_names.c
Go to the documentation of this file.
1 /*
2  Copyright 2019 Northern.tech AS
3 
4  This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the
8  Free Software Foundation; version 3.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 
19  To the extent this program is licensed as part of the Enterprise
20  versions of CFEngine, the applicable Commercial Open Source License
21  (COSL) may apply to this file if you as a licensee so wish it. See
22  included file COSL.txt.
23 */
24 
25 #include <files_names.h>
26 
27 #include <policy.h>
28 #include <promises.h>
29 #include <cf3.defs.h>
30 #include <dir.h>
31 #include <item_lib.h>
32 #include <files_interfaces.h>
33 #include <string_lib.h>
34 #include <known_dirs.h>
35 #include <conversion.h>
36 
37 #include <cf-windows-functions.h>
38 
39 /*********************************************************************/
40 
41 bool IsNewerFileTree(const char *dir, time_t reftime)
42 {
43  const struct dirent *dirp;
44  Dir *dirh;
45  struct stat sb;
46 
47 // Assumes that race conditions on the file path are unlikely and unimportant
48 
49  if (lstat(dir, &sb) == -1)
50  {
51  Log(LOG_LEVEL_ERR, "Unable to stat directory '%s' in IsNewerFileTree. (stat: %s)", dir, GetErrorStr());
52  // return true to provoke update
53  return true;
54  }
55 
56  if (S_ISDIR(sb.st_mode))
57  {
58  if (sb.st_mtime > reftime)
59  {
60  Log(LOG_LEVEL_VERBOSE, " >> Detected change in %s", dir);
61  return true;
62  }
63  }
64 
65  if ((dirh = DirOpen(dir)) == NULL)
66  {
67  Log(LOG_LEVEL_ERR, "Unable to open directory '%s' in IsNewerFileTree. (opendir: %s)", dir, GetErrorStr());
68  return false;
69  }
70  else
71  {
72  for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh))
73  {
74  if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, ".."))
75  {
76  continue;
77  }
78 
79  char path[CF_BUFSIZE];
80  size_t ret = (size_t) snprintf(path, sizeof(path), "%s%c%s",
81  dir, FILE_SEPARATOR, dirp->d_name);
82 
83  if (ret >= sizeof(path))
84  {
86  "Internal limit reached in IsNewerFileTree(),"
87  " path too long: '%s' + '%s'",
88  dir, dirp->d_name);
89  DirClose(dirh);
90  return false;
91  }
92 
93  if (lstat(path, &sb) == -1)
94  {
95  Log(LOG_LEVEL_ERR, "Unable to stat directory '%s' in IsNewerFileTree. (lstat: %s)", path, GetErrorStr());
96  DirClose(dirh);
97  // return true to provoke update
98  return true;
99  }
100 
101  if (S_ISDIR(sb.st_mode))
102  {
103  if (sb.st_mtime > reftime)
104  {
105  Log(LOG_LEVEL_VERBOSE, " >> Detected change in %s", path);
106  DirClose(dirh);
107  return true;
108  }
109  else
110  {
111  if (IsNewerFileTree(path, reftime))
112  {
113  DirClose(dirh);
114  return true;
115  }
116  }
117  }
118  }
119  }
120 
121  DirClose(dirh);
122  return false;
123 }
124 
125 /*********************************************************************/
126 
127 bool IsDir(const char *path)
128 /*
129 Checks if the object pointed to by path exists and is a directory.
130 Returns true if so, false otherwise.
131 */
132 {
133 #ifdef __MINGW32__
134  return NovaWin_IsDir(path);
135 #else
136  struct stat sb;
137 
138  if (stat(path, &sb) != -1)
139  {
140  if (S_ISDIR(sb.st_mode))
141  {
142  return true;
143  }
144  }
145 
146  return false;
147 #endif /* !__MINGW32__ */
148 }
149 
150 /*********************************************************************/
151 
152 char *JoinSuffix(char *path, size_t path_size, const char *leaf)
153 {
154  int len = strlen(leaf);
155 
156  if (Chop(path, path_size) == -1)
157  {
158  Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator");
159  }
160  DeleteSlash(path);
161 
162  if (strlen(path) + len + 1 > path_size)
163  {
164  Log(LOG_LEVEL_ERR, "JoinSuffix: Internal limit reached. Tried to add %s to %s",
165  leaf, path);
166  return NULL;
167  }
168 
169  strlcat(path, leaf, path_size);
170  return path;
171 }
172 
173 /**
174  * Just like the JoinSuffix() above, but makes sure there's a FILE_SEPARATOR
175  * between @path and @leaf_path. The only exception is the case where @path is
176  * "" and @leaf_path doesn't start with a FILE_SEPARATOR. In that case:
177  * JoinPaths("", PATH_MAX, "some_path") -> "some_path"
178  *
179  * This function is similar to Python's os.path.join() except that unlike the
180  * Python function this one actually joins @path and @leaf_path even if
181  * @leaf_path starts with a FILE_SEPARATOR.
182  */
183 char *JoinPaths(char *path, size_t path_size, const char *leaf_path)
184 {
185  size_t len = strlen(leaf_path);
186  size_t path_len = strnlen(path, path_size);
187 
188  if (Chop(path, path_size - 1) == -1)
189  {
190  Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator");
191  return NULL;
192  }
193 
194  if (path_len + len + 1 > path_size)
195  {
196  Log(LOG_LEVEL_ERR, "JoinPaths: Internal limit reached. Tried to add %s to %s",
197  leaf_path, path);
198  return NULL;
199  }
200 
201  /* make sure there's a FILE_SEPARATOR between path and leaf_path */
202  if ((path_len > 0 && !IsFileSep(path[path_len - 1])) && !IsFileSep(leaf_path[0]))
203  {
204  strlcat(path, FILE_SEPARATOR_STR, path_size);
205  }
206  else if ((path_len > 0 && IsFileSep(path[path_len - 1])) && IsFileSep(leaf_path[0]))
207  {
208  leaf_path += 1;
209  }
210  strlcat(path, leaf_path, path_size);
211  return path;
212 }
213 
214 bool IsAbsPath(const char *path)
215 {
216  if (IsFileSep(*path))
217  {
218  return true;
219  }
220  else
221  {
222  return false;
223  }
224 }
225 
226 /**
227  * Append a slash, of the kind that the string already has, only if the string
228  * doesn't end in one.
229  */
230 void AddSlash(char *str)
231 {
232  char *sp, *sep = FILE_SEPARATOR_STR;
233  int f = false, b = false;
234 
235  if (str == NULL)
236  {
237  return;
238  }
239 
240  if (strlen(str) == 0)
241  {
242  strcpy(str, sep);
243  return;
244  }
245 
246 /* Try to see what convention is being used for filenames
247  in case this is a cross-system copy from Win/Unix */
248 
249  for (sp = str; *sp != '\0'; sp++)
250  {
251  switch (*sp)
252  {
253  case '/':
254  f = true;
255  break;
256  case '\\':
257  b = true;
258  break;
259  default:
260  break;
261  }
262  }
263 
264  if (f && (!b))
265  {
266  sep = "/";
267  }
268  else if (b && (!f))
269  {
270  sep = "\\";
271  }
272 
273  if (!IsFileSep(str[strlen(str) - 1]))
274  {
275  strcat(str, sep);
276  }
277 }
278 
279 /*********************************************************************/
280 
281 char *GetParentDirectoryCopy(const char *path)
282 /**
283  * WARNING: Remember to free return value.
284  **/
285 {
286  assert(path);
287  assert(strlen(path) > 0);
288 
289  char *path_copy = xstrdup(path);
290 
291  if(strcmp(path_copy, "/") == 0)
292  {
293  return path_copy;
294  }
295 
296  char *sp = (char *)LastFileSeparator(path_copy);
297 
298  if(!sp)
299  {
300  Log(LOG_LEVEL_ERR, "Path %s does not contain file separators (GetParentDirectory())", path_copy);
301  free(path_copy);
302  return NULL;
303  }
304 
305  if(sp == FirstFileSeparator(path_copy)) // don't chop off first path separator
306  {
307  *(sp + 1) = '\0';
308  }
309  else
310  {
311  *sp = '\0';
312  }
313 
314  return path_copy;
315 }
316 
317 /*********************************************************************/
318 
319 // Can remove several slashes if they are redundant.
320 void DeleteSlash(char *str)
321 {
322  int size = strlen(str);
323  if ((size == 0) || (str == NULL))
324  {
325  return;
326  }
327 
328  int root = RootDirLength(str);
329  while (IsFileSep(str[size - 1]) && size - 1 > root)
330  {
331  size--;
332  }
333  str[size] = '\0'; /* no-op if we didn't change size */
334 }
335 
336 /*********************************************************************/
337 
338 void DeleteRedundantSlashes(char *str)
339 {
340  int move_from;
341  // Invariant: newpos <= oldpos
342  int oldpos = RootDirLength(str);
343  int newpos = oldpos;
344  while (str[oldpos] != '\0')
345  {
346  // Skip over subsequent separators.
347  while (IsFileSep(str[oldpos]))
348  {
349  oldpos++;
350  }
351  move_from = oldpos;
352 
353  // And then skip over the next path component.
354  while (str[oldpos] != '\0' && !IsFileSep(str[oldpos]))
355  {
356  oldpos++;
357  }
358 
359  // If next character is file separator, move past it, since we want to keep one.
360  if (IsFileSep(str[oldpos]))
361  {
362  oldpos++;
363  }
364 
365  int move_len = oldpos - move_from;
366  memmove(&str[newpos], &str[move_from], move_len);
367  newpos += move_len;
368  }
369 
370  str[newpos] = '\0';
371 }
372 
373 /*********************************************************************/
374 
375 const char *FirstFileSeparator(const char *str)
376 {
377  assert(str);
378  assert(strlen(str) > 0);
379 
380  if(strncmp(str, "\\\\", 2) == 0) // windows share
381  {
382  return str + 1;
383  }
384 
385  for(const char *pos = str; *pos != '\0'; pos++)
386  {
387  if(IsFileSep(*pos))
388  {
389  return pos;
390  }
391  }
392 
393  return NULL;
394 }
395 
396 /*********************************************************************/
397 
398 const char *LastFileSeparator(const char *str)
399  /* Return pointer to last file separator in string, or NULL if
400  string does not contains any file separtors */
401 {
402  const char *sp;
403 
404 /* Walk through string backwards */
405 
406  sp = str + strlen(str) - 1;
407 
408  while (sp >= str)
409  {
410  if (IsFileSep(*sp))
411  {
412  return sp;
413  }
414  sp--;
415  }
416 
417  return NULL;
418 }
419 
420 /*********************************************************************/
421 
422 bool ChopLastNode(char *str)
423  /* Chop off trailing node name (possible blank) starting from
424  last character and removing up to the first / encountered
425  e.g. /a/b/c -> /a/b
426  /a/b/ -> /a/b
427  Will also collapse redundant/repeating path separators.
428  */
429 {
430  char *sp;
431  bool ret;
432 
434 
435 /* Here cast is necessary and harmless, str is modifiable */
436  if ((sp = (char *) LastFileSeparator(str)) == NULL)
437  {
438  int pos = RootDirLength(str);
439  if (str[pos] == '\0')
440  {
441  ret = false;
442  }
443  else
444  {
445  str[pos] = '.';
446  str[pos + 1] = '\0';
447  ret = true;
448  }
449  }
450  else
451  {
452  // Don't chop the root slash in an absolute path.
453  if (IsAbsoluteFileName(str) && FirstFileSeparator(str) == sp)
454  {
455  *(++sp) = '\0';
456  }
457  else
458  {
459  *sp = '\0';
460  }
461  ret = true;
462  }
463 
464  return ret;
465 }
466 
467 /*********************************************************************/
468 
469 void TransformNameInPlace(char *s, char from, char to)
470 {
471  for (; *s != '\0'; s++)
472  {
473  if (*s == from)
474  {
475  *s = to;
476  }
477  }
478 }
479 
480 /*********************************************************************/
481 
482 /* TODO remove, kill, burn this function! Replace with BufferCanonify or CanonifyNameInPlace */
483 char *CanonifyName(const char *str)
484 {
485  static char buffer[CF_BUFSIZE]; /* GLOBAL_R, no initialization needed */
486 
487  strlcpy(buffer, str, CF_BUFSIZE);
488  CanonifyNameInPlace(buffer);
489  return buffer;
490 }
491 
492 /*********************************************************************/
493 
494 char *CanonifyChar(const char *str, char ch)
495 {
496  static char buffer[CF_BUFSIZE]; /* GLOBAL_R, no initialization needed */
497  char *sp;
498 
499  strlcpy(buffer, str, CF_BUFSIZE);
500 
501  for (sp = buffer; *sp != '\0'; sp++)
502  {
503  if (*sp == ch)
504  {
505  *sp = '_';
506  }
507  }
508 
509  return buffer;
510 }
511 
512 /*********************************************************************/
513 
514 int CompareCSVName(const char *s1, const char *s2)
515 {
516  const char *sp1, *sp2;
517  char ch1, ch2;
518 
519  for (sp1 = s1, sp2 = s2; (*sp1 != '\0') || (*sp2 != '\0'); sp1++, sp2++)
520  {
521  ch1 = (*sp1 == ',') ? '_' : *sp1;
522  ch2 = (*sp2 == ',') ? '_' : *sp2;
523 
524  if (ch1 > ch2)
525  {
526  return 1;
527  }
528  else if (ch1 < ch2)
529  {
530  return -1;
531  }
532  }
533 
534  return 0;
535 }
536 
537 /*********************************************************************/
538 
539 const char *ReadLastNode(const char *str)
540 /* Return the last node of a pathname string */
541 {
542  const char *sp;
543 
544  if ((sp = LastFileSeparator(str)) == NULL)
545  {
546  return str;
547  }
548  else
549  {
550  return sp + 1;
551  }
552 }
553 
554 /*********************************************************************/
555 
556 bool CompressPath(char *dest, size_t dest_size, const char *src)
557 {
558  char node[CF_BUFSIZE];
559  int nodelen;
560  int rootlen;
561 
562  memset(dest, 0, dest_size);
563 
564  rootlen = RootDirLength(src);
565 
566  if(rootlen >= dest_size)
567  {
569  "Internal limit reached in CompressPath(),"
570  "src path too long (%d bytes): '%s'",
571  rootlen, src);
572  return false;
573  }
574 
575  memcpy(dest, src, rootlen);
576 
577  for (const char *sp = src + rootlen; *sp != '\0'; sp++)
578  {
579  if (IsFileSep(*sp))
580  {
581  continue;
582  }
583 
584  for (nodelen = 0; (sp[nodelen] != '\0') && (!IsFileSep(sp[nodelen])); nodelen++)
585  {
586  if (nodelen > CF_MAXLINKSIZE)
587  {
588  Log(LOG_LEVEL_ERR, "Link in path suspiciously large");
589  return false;
590  }
591  }
592 
593  strncpy(node, sp, nodelen);
594  node[nodelen] = '\0';
595 
596  sp += nodelen - 1;
597 
598  if (strcmp(node, ".") == 0)
599  {
600  continue;
601  }
602 
603  if (strcmp(node, "..") == 0)
604  {
605  if (!ChopLastNode(dest))
606  {
607  Log(LOG_LEVEL_DEBUG, "used .. beyond top of filesystem!");
608  return false;
609  }
610 
611  continue;
612  }
613 
614  AddSlash(dest);
615 
616  size_t ret = strlcat(dest, node, dest_size);
617 
618  if (ret >= CF_BUFSIZE)
619  {
621  "Internal limit reached in CompressPath(),"
622  " path too long: '%s' + '%s'",
623  dest, node);
624  return false;
625  }
626  }
627 
628  return true;
629 }
630 
631 /*********************************************************************/
632 
633 /**
634  * Get absolute path of @path. If @path is already an absolute path this
635  * function just returns a compressed (see CompressPath()) copy of it. Otherwise
636  * this function prepends the curent working directory before @path and returns
637  * the result compressed with CompressPath(). If anything goes wrong, an empty
638  * string is returned.
639  *
640  * WARNING: Remember to free return value.
641  **/
642 char *GetAbsolutePath(const char *path)
643 {
644  if (NULL_OR_EMPTY(path))
645  {
646  return NULL;
647  }
648  char abs_path[PATH_MAX] = { 0 };
649  if (IsAbsoluteFileName(path))
650  {
651  CompressPath(abs_path, PATH_MAX, path);
652  return xstrdup(abs_path);
653  }
654  else
655  {
656  /* the full_path can potentially be long (with many '../' parts)*/
657  char full_path[2 * PATH_MAX] = { 0 };
658  if (getcwd(full_path, PATH_MAX) == NULL)
659  {
661  "Could not determine current directory (getcwd: %s)",
662  GetErrorStr());
663  }
664  JoinPaths(full_path, 2 * PATH_MAX, path);
665  CompressPath(abs_path, PATH_MAX, full_path);
666  return xstrdup(abs_path);
667  }
668 }
669 
670 char *GetRealPath(const char *const path)
671 {
672  if (NULL_OR_EMPTY(path))
673  {
674  return NULL;
675  }
676  char *const abs_path = GetAbsolutePath(path);
677  if (NULL_OR_EMPTY(abs_path))
678  {
679  free(abs_path);
680  return NULL;
681  }
682 
683 #ifdef __linux__ // POSIX 2008 - could add newer versions of BSD / solaris
684  char *real_path = realpath(abs_path, NULL);
685  if (NOT_NULL_AND_EMPTY(real_path))
686  {
687  free(real_path);
688  real_path = NULL;
689  }
690 #else // Pre POSIX 2008 - realpath arg cannot be NULL
691  char *const path_buf = xcalloc(1, PATH_MAX);
692  char *real_path = realpath(abs_path, path_buf);
693  if (NULL_OR_EMPTY(real_path))
694  {
695  free(path_buf);
696  real_path = NULL;
697  }
698 #endif
699 
700  free(abs_path);
701  return real_path;
702 }
703 
704 /*********************************************************************/
705 
706 FilePathType FilePathGetType(const char *file_path)
707 {
708  if (IsAbsoluteFileName(file_path))
709  {
711  }
712  else if (*file_path == '.')
713  {
715  }
716  else
717  {
719  }
720 }
721 
723 {
724  return !StringStartsWith(f, GetInputDir());
725 }
726 
727 /*******************************************************************/
728 
729 static int UnixRootDirLength(const char *f)
730 {
731  if (IsFileSep(*f))
732  {
733  return 1;
734  }
735 
736  return 0;
737 }
738 
739 #ifdef _WIN32
740 static int NTRootDirLength(const char *f)
741 {
742  int len;
743 
744  if (f[0] == '\\' && f[1] == '\\')
745  {
746  /* UNC style path */
747 
748  /* Skip over host name */
749  for (len = 2; f[len] != '\\'; len++)
750  {
751  if (f[len] == '\0')
752  {
753  return len;
754  }
755  }
756 
757  /* Skip over share name */
758 
759  for (len++; f[len] != '\\'; len++)
760  {
761  if (f[len] == '\0')
762  {
763  return len;
764  }
765  }
766 
767  /* Skip over file separator */
768  len++;
769 
770  return len;
771  }
772 
773  if (isalpha(f[0]) && f[1] == ':')
774  {
775  if (IsFileSep(f[2]))
776  {
777  return 3;
778  }
779 
780  return 2;
781  }
782 
783  return UnixRootDirLength(f);
784 }
785 #endif
786 
787 int RootDirLength(const char *f)
788  /* Return length of Initial directory in path - */
789 {
790 #ifdef _WIN32
791  return NTRootDirLength(f);
792 #else
793  return UnixRootDirLength(f);
794 #endif
795 }
796 
797 /* Buffer should be at least CF_MAXVARSIZE large */
798 const char *GetSoftwareCacheFilename(char *buffer)
799 {
800  snprintf(buffer, CF_MAXVARSIZE, "%s/%s", GetStateDir(), SOFTWARE_PACKAGES_CACHE);
801  MapName(buffer);
802  return buffer;
803 }
804 
805 /* Buffer should be at least CF_MAXVARSIZE large */
806 const char *GetSoftwarePatchesFilename(char *buffer)
807 {
808  snprintf(buffer, CF_MAXVARSIZE, "%s/%s", GetStateDir(), SOFTWARE_PATCHES_CACHE);
809  MapName(buffer);
810  return buffer;
811 }
812 
813 const char *RealPackageManager(const char *manager)
814 {
815  assert(manager);
816 
817  const char *pos = strchr(manager, ' ');
818  if (strncmp(manager, "env ", 4) != 0
819  && (!pos || pos - manager < 4 || strncmp(pos - 4, "/env", 4) != 0))
820  {
821  return CommandArg0(manager);
822  }
823 
824  // Look for variable assignments.
825  const char *last_pos;
826  bool eq_sign_found = false;
827  while (true)
828  {
829  if (eq_sign_found)
830  {
831  last_pos = pos + 1;
832  }
833  else
834  {
835  last_pos = pos + strspn(pos, " "); // Skip over consecutive spaces.
836  }
837  pos = strpbrk(last_pos, "= ");
838  if (!pos)
839  {
840  break;
841  }
842  if (*pos == '=')
843  {
844  eq_sign_found = true;
845  }
846  else if (eq_sign_found)
847  {
848  eq_sign_found = false;
849  }
850  else
851  {
852  return CommandArg0(last_pos);
853  }
854  }
855 
856  // Reached the end? Weird. Must be env command with no real command.
857  return CommandArg0(manager);
858 }
void * xcalloc(size_t nmemb, size_t size)
Definition: alloc-mini.c:51
char * xstrdup(const char *str)
Definition: alloc-mini.c:56
#define SOFTWARE_PACKAGES_CACHE
Definition: cf3.defs.h:594
#define CF_MAXLINKSIZE
Definition: cf3.defs.h:56
#define SOFTWARE_PATCHES_CACHE
Definition: cf3.defs.h:595
void free(void *)
const char * CommandArg0(const char *execstr)
Definition: conversion.c:882
#define CF_BUFSIZE
Definition: definitions.h:50
#define CF_MAXVARSIZE
Definition: definitions.h:36
const struct dirent * DirRead(Dir *dir)
Definition: unix_dir.c:92
void DirClose(Dir *dir)
Definition: unix_dir.c:118
Dir * DirOpen(const char *dirname)
Definition: unix_dir.c:41
bool IsAbsoluteFileName(const char *f)
Definition: file_lib.c:333
char * MapName(char *s)
Definition: file_lib.c:441
#define IsFileSep(c)
Definition: file_lib.h:101
#define FILE_SEPARATOR_STR
Definition: file_lib.h:103
#define FILE_SEPARATOR
Definition: file_lib.h:102
char * CanonifyChar(const char *str, char ch)
Definition: files_names.c:494
int CompareCSVName(const char *s1, const char *s2)
Definition: files_names.c:514
bool IsAbsPath(const char *path)
Definition: files_names.c:214
const char * GetSoftwarePatchesFilename(char *buffer)
Definition: files_names.c:806
bool CompressPath(char *dest, size_t dest_size, const char *src)
Definition: files_names.c:556
bool ChopLastNode(char *str)
Definition: files_names.c:422
char * CanonifyName(const char *str)
Definition: files_names.c:483
const char * FirstFileSeparator(const char *str)
Definition: files_names.c:375
bool IsFileOutsideDefaultRepository(const char *f)
Definition: files_names.c:722
char * JoinSuffix(char *path, size_t path_size, const char *leaf)
Definition: files_names.c:152
void AddSlash(char *str)
Definition: files_names.c:230
char * GetRealPath(const char *const path)
Definition: files_names.c:670
FilePathType FilePathGetType(const char *file_path)
Definition: files_names.c:706
char * GetAbsolutePath(const char *path)
Definition: files_names.c:642
const char * ReadLastNode(const char *str)
Definition: files_names.c:539
void DeleteSlash(char *str)
Definition: files_names.c:320
int RootDirLength(const char *f)
Definition: files_names.c:787
static int UnixRootDirLength(const char *f)
Definition: files_names.c:729
bool IsNewerFileTree(const char *dir, time_t reftime)
Definition: files_names.c:41
bool IsDir(const char *path)
Definition: files_names.c:127
char * GetParentDirectoryCopy(const char *path)
Definition: files_names.c:281
const char * RealPackageManager(const char *manager)
Definition: files_names.c:813
void DeleteRedundantSlashes(char *str)
Definition: files_names.c:338
const char * GetSoftwareCacheFilename(char *buffer)
Definition: files_names.c:798
char * JoinPaths(char *path, size_t path_size, const char *leaf_path)
Definition: files_names.c:183
void TransformNameInPlace(char *s, char from, char to)
Definition: files_names.c:469
const char * LastFileSeparator(const char *str)
Definition: files_names.c:398
FilePathType
Definition: files_names.h:31
@ FILE_PATH_TYPE_RELATIVE
Definition: files_names.h:33
@ FILE_PATH_TYPE_NON_ANCHORED
Definition: files_names.h:34
@ FILE_PATH_TYPE_ABSOLUTE
Definition: files_names.h:32
#define NULL
Definition: getopt1.c:56
const char * GetInputDir(void)
Definition: known_dirs.c:182
const char * GetStateDir(void)
Definition: known_dirs.c:186
const char * GetErrorStr(void)
Definition: logging.c:275
void Log(LogLevel level, const char *fmt,...)
Definition: logging.c:409
@ LOG_LEVEL_ERR
Definition: logging.h:42
@ LOG_LEVEL_DEBUG
Definition: logging.h:47
@ LOG_LEVEL_WARNING
Definition: logging.h:43
@ LOG_LEVEL_VERBOSE
Definition: logging.h:46
int lstat(const char *file_name, struct stat *buf)
#define S_ISDIR(m)
Definition: platform.h:916
#define dirent
Definition: platform.h:160
#define PATH_MAX
Definition: platform.h:176
bool StringStartsWith(const char *str, const char *prefix)
Check if a string starts with the given prefix.
Definition: string_lib.c:1335
int Chop(char *str, size_t max_length)
Remove trailing spaces.
Definition: string_lib.c:1174
void CanonifyNameInPlace(char *s)
Definition: string_lib.c:1574
#define NULL_OR_EMPTY(str)
Definition: string_lib.h:43
#define NOT_NULL_AND_EMPTY(str)
Definition: string_lib.h:46
size_t strlcat(char *dst, const char *src, size_t siz)
Definition: strlcat.c:36
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:34
size_t strnlen(const char *str, size_t maxlen)
Definition: strnlen.c:32
Definition: unix_dir.c:33