suricata
util-path.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2023 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  */
24 
25 #include "suricata-common.h"
26 #include "suricata.h"
27 #include "util-debug.h"
28 #include "util-path.h"
29 
30 #ifdef OS_WIN32
31 #include "win32-misc.h"
32 #define DIRECTORY_SEPARATOR '\\'
33 #else
34 #define DIRECTORY_SEPARATOR '/'
35 #endif
36 
37 /**
38  * \brief Check if a path is absolute
39  *
40  * \param path string with the path
41  *
42  * \retval 1 absolute
43  * \retval 0 not absolute
44  */
45 int PathIsAbsolute(const char *path)
46 {
47  if (strlen(path) > 1 && path[0] == '/') {
48  return 1;
49  }
50 
51 #if (defined OS_WIN32 || defined __CYGWIN__)
52  if (strlen(path) > 2) {
53  if (isalpha((unsigned char)path[0]) && path[1] == ':') {
54  return 1;
55  }
56  }
57 #endif
58 
59  return 0;
60 }
61 
62 /**
63  * \brief Check if a path is relative
64  *
65  * \param path string with the path
66  *
67  * \retval 1 relative
68  * \retval 0 not relative
69  */
70 int PathIsRelative(const char *path)
71 {
72  return PathIsAbsolute(path) ? 0 : 1;
73 }
74 
75 int PathMerge(char *out_buf, size_t buf_size, const char *const dir, const char *const fname)
76 {
77  char path[PATH_MAX];
78  if (dir == NULL || strlen(dir) == 0)
79  return -1;
80 
81  size_t r = strlcpy(path, dir, sizeof(path));
82  if (r >= sizeof(path)) {
83  return -1;
84  }
85 
86 #if defined OS_WIN32 || defined __CYGWIN__
87  if (path[strlen(path) - 1] != '\\')
88  r = strlcat(path, "\\\\", sizeof(path));
89 #else
90  if (path[strlen(path) - 1] != '/')
91  r = strlcat(path, "/", sizeof(path));
92 #endif
93  if (r >= sizeof(path)) {
94  return -1;
95  }
96  r = strlcat(path, fname, sizeof(path));
97  if (r >= sizeof(path)) {
98  return -1;
99  }
100  r = strlcpy(out_buf, path, buf_size);
101  if (r >= buf_size) {
102  return -1;
103  }
104 
105  return 0;
106 }
107 
108 char *PathMergeAlloc(const char *const dir, const char *const fname)
109 {
110  char path[PATH_MAX];
111  if (PathMerge(path, sizeof(path), dir, fname) != 0)
112  return NULL;
113 
114  char *ret = SCStrdup(path);
115  if (ret == NULL)
116  return NULL;
117 
118  return ret;
119 }
120 
121 /**
122  * \brief Wrapper around SCMkDir with default mode arguments.
123  */
124 int SCDefaultMkDir(const char *path)
125 {
126  return SCMkDir(path, S_IRWXU | S_IRGRP | S_IXGRP);
127 }
128 
129 /**
130  * \brief Recursively create a directory.
131  *
132  * \param path Path to create
133  * \param final true will create the final path component, false will not
134  *
135  * \retval 0 on success
136  * \retval -1 on error
137  */
138 int SCCreateDirectoryTree(const char *path, const bool final)
139 {
140  char pathbuf[PATH_MAX];
141  char *p;
142  size_t len = strlen(path);
143 
144  if (len > PATH_MAX - 1) {
145  return -1;
146  }
147 
148  strlcpy(pathbuf, path, sizeof(pathbuf));
149 
150  for (p = pathbuf + 1; *p; p++) {
151  if (*p == '/') {
152  /* Truncate, while creating directory */
153  *p = '\0';
154 
155  if (SCDefaultMkDir(pathbuf) != 0) {
156  if (errno != EEXIST) {
157  return -1;
158  }
159  }
160 
161  *p = '/';
162  }
163  }
164 
165  if (final) {
166  if (SCDefaultMkDir(pathbuf) != 0) {
167  if (errno != EEXIST) {
168  return -1;
169  }
170  }
171  }
172 
173  return 0;
174 }
175 
176 /**
177  * \brief Check if a path exists.
178  *
179  * \param Path to check for existence
180  *
181  * \retval true if path exists
182  * \retval false if path does not exist
183  */
184 bool SCPathExists(const char *path)
185 {
186  struct stat sb;
187  return stat(path, &sb) == 0;
188 }
189 
190 /**
191  * \brief OS independent wrapper for directory check
192  *
193  * \param dir_entry object to check
194  *
195  * \retval True if the object is a regular directory, otherwise false. This directory
196  * and parent directory will return false.
197  */
198 bool SCIsRegularDirectory(const struct dirent *const dir_entry)
199 {
200 #if !defined(OS_WIN32) && !defined(__sun)
201  if ((dir_entry->d_type == DT_DIR) &&
202  (strcmp(dir_entry->d_name, ".") != 0) &&
203  (strcmp(dir_entry->d_name, "..") != 0)) {
204  return true;
205  }
206 #endif
207  return false;
208 }
209 /**
210  * \brief OS independent to check for regular file
211  *
212  * \param dir_entry object to check
213  *
214  * \retval True if the object is a regular file. Otherwise false.
215  */
216 bool SCIsRegularFile(const struct dirent *const dir_entry)
217 {
218 #if defined(DT_REG)
219  return dir_entry->d_type == DT_REG;
220 #endif
221  return false;
222 }
223 
224 /**
225  * \brief OS independent wrapper for realpath
226  *
227  * \param path the path to resolve
228  * \param resolved_path the resolved path; if null, a buffer will be allocated
229  *
230  * \retval the resolved_path; or a pointer to a new resolved_path buffer
231  */
232 char *SCRealPath(const char *path, char *resolved_path)
233 {
234 #ifdef OS_WIN32
235  return _fullpath(resolved_path, path, PATH_MAX);
236 #else
237  return realpath(path, resolved_path);
238 #endif
239 }
240 
241 /*
242  * \brief Return the basename of the provided path.
243  * \param path The path on which to compute the basename
244  *
245  * \retval the basename of the path or NULL if the path lacks a non-leaf
246  */
247 const char *SCBasename(const char *path)
248 {
249  if (!path || strlen(path) == 0)
250  return NULL;
251 
252  const char *final = strrchr(path, DIRECTORY_SEPARATOR);
253  if (!final)
254  return path;
255 
256  if (*(final + 1) == '\0')
257  return NULL;
258 
259  return final + 1;
260 }
261 
262 /**
263  * \brief Check for directory traversal
264  *
265  * \param path The path string to check for traversal
266  *
267  * \retval true if directory traversal is found, otherwise false
268  */
269 bool SCPathContainsTraversal(const char *path)
270 {
271 #ifdef OS_WIN32
272  /* Win32 treats '/' and '\\' as equivalent directory separators */
273  return strstr(path, "../") != NULL || strstr(path, "..\\") != NULL;
274 #else
275  return strstr(path, "../") != NULL;
276 #endif
277 }
278 
279 /**
280  * \brief Open a text log file for append or truncate.
281  *
282  * On Windows, allows the file to be renamed or deleted while open so that
283  * external tools can rotate it. Only modes "a" and "w" are supported on
284  * all platforms; other modes fail with errno set to EINVAL.
285  *
286  * \param path The file path to open
287  * \param mode "a" to append or "w" to truncate
288  * \retval FILE* on success
289  * \retval NULL on error with errno set
290  */
291 FILE *SCFopenLogFile(const char *path, const char *mode)
292 {
293  if (strcmp(mode, "a") != 0 && strcmp(mode, "w") != 0) {
294  errno = EINVAL;
295  return NULL;
296  }
297 
298 #ifdef OS_WIN32
299  return SCWin32Fopen(path, mode);
300 #else
301  return fopen(path, mode);
302 #endif
303 }
304 
305 /**
306  * \brief Update access and modification time of an existing file to 'now'.
307  * \param path The file path to touch
308  * \retval 0 on success, -1 on failure
309  */
310 int SCTouchFile(const char *path)
311 {
312  if (path == NULL || path[0] == '\0') {
313  errno = EINVAL;
314  return -1;
315  }
316 #ifndef OS_WIN32
317  struct utimbuf ub;
318  ub.actime = ub.modtime = time(NULL);
319  if (utime(path, &ub) == 0)
320  return 0;
321 #endif
322  return -1;
323 }
win32-misc.h
len
uint8_t len
Definition: app-layer-dnp3.h:2
PathMergeAlloc
char * PathMergeAlloc(const char *const dir, const char *const fname)
Definition: util-path.c:108
PathMerge
int PathMerge(char *out_buf, size_t buf_size, const char *const dir, const char *const fname)
Definition: util-path.c:75
SCTouchFile
int SCTouchFile(const char *path)
Update access and modification time of an existing file to 'now'.
Definition: util-path.c:310
p
Packet * p
Definition: fuzz_dataset.c:30
SCDefaultMkDir
int SCDefaultMkDir(const char *path)
Wrapper around SCMkDir with default mode arguments.
Definition: util-path.c:124
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
SCPathContainsTraversal
bool SCPathContainsTraversal(const char *path)
Check for directory traversal.
Definition: util-path.c:269
util-debug.h
SCIsRegularDirectory
bool SCIsRegularDirectory(const struct dirent *const dir_entry)
OS independent wrapper for directory check.
Definition: util-path.c:198
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
DIRECTORY_SEPARATOR
#define DIRECTORY_SEPARATOR
Definition: util-path.c:34
SCBasename
const char * SCBasename(const char *path)
Definition: util-path.c:247
SCPathExists
bool SCPathExists(const char *path)
Check if a path exists.
Definition: util-path.c:184
SCFopenLogFile
FILE * SCFopenLogFile(const char *path, const char *mode)
Open a text log file for append or truncate.
Definition: util-path.c:291
suricata-common.h
util-path.h
PathIsAbsolute
int PathIsAbsolute(const char *path)
Check if a path is absolute.
Definition: util-path.c:45
SCMkDir
#define SCMkDir(a, b)
Definition: util-path.h:45
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
SCRealPath
char * SCRealPath(const char *path, char *resolved_path)
OS independent wrapper for realpath.
Definition: util-path.c:232
PathIsRelative
int PathIsRelative(const char *path)
Check if a path is relative.
Definition: util-path.c:70
SCWin32Fopen
FILE * SCWin32Fopen(const char *path, const char *mode)
suricata.h
SCIsRegularFile
bool SCIsRegularFile(const struct dirent *const dir_entry)
OS independent to check for regular file.
Definition: util-path.c:216
SCCreateDirectoryTree
int SCCreateDirectoryTree(const char *path, const bool final)
Recursively create a directory.
Definition: util-path.c:138