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 #define DIRECTORY_SEPARATOR '\\'
32 #else
33 #define DIRECTORY_SEPARATOR '/'
34 #endif
35 
36 /**
37  * \brief Check if a path is absolute
38  *
39  * \param path string with the path
40  *
41  * \retval 1 absolute
42  * \retval 0 not absolute
43  */
44 int PathIsAbsolute(const char *path)
45 {
46  if (strlen(path) > 1 && path[0] == '/') {
47  return 1;
48  }
49 
50 #if (defined OS_WIN32 || defined __CYGWIN__)
51  if (strlen(path) > 2) {
52  if (isalpha((unsigned char)path[0]) && path[1] == ':') {
53  return 1;
54  }
55  }
56 #endif
57 
58  return 0;
59 }
60 
61 /**
62  * \brief Check if a path is relative
63  *
64  * \param path string with the path
65  *
66  * \retval 1 relative
67  * \retval 0 not relative
68  */
69 int PathIsRelative(const char *path)
70 {
71  return PathIsAbsolute(path) ? 0 : 1;
72 }
73 
74 int PathMerge(char *out_buf, size_t buf_size, const char *const dir, const char *const fname)
75 {
76  char path[PATH_MAX];
77  if (dir == NULL || strlen(dir) == 0)
78  return -1;
79 
80  size_t r = strlcpy(path, dir, sizeof(path));
81  if (r >= sizeof(path)) {
82  return -1;
83  }
84 
85 #if defined OS_WIN32 || defined __CYGWIN__
86  if (path[strlen(path) - 1] != '\\')
87  r = strlcat(path, "\\\\", sizeof(path));
88 #else
89  if (path[strlen(path) - 1] != '/')
90  r = strlcat(path, "/", sizeof(path));
91 #endif
92  if (r >= sizeof(path)) {
93  return -1;
94  }
95  r = strlcat(path, fname, sizeof(path));
96  if (r >= sizeof(path)) {
97  return -1;
98  }
99  r = strlcpy(out_buf, path, buf_size);
100  if (r >= buf_size) {
101  return -1;
102  }
103 
104  return 0;
105 }
106 
107 char *PathMergeAlloc(const char *const dir, const char *const fname)
108 {
109  char path[PATH_MAX];
110  if (PathMerge(path, sizeof(path), dir, fname) != 0)
111  return NULL;
112 
113  char *ret = SCStrdup(path);
114  if (ret == NULL)
115  return NULL;
116 
117  return ret;
118 }
119 
120 /**
121  * \brief Wrapper around SCMkDir with default mode arguments.
122  */
123 int SCDefaultMkDir(const char *path)
124 {
125  return SCMkDir(path, S_IRWXU | S_IRGRP | S_IXGRP);
126 }
127 
128 /**
129  * \brief Recursively create a directory.
130  *
131  * \param path Path to create
132  * \param final true will create the final path component, false will not
133  *
134  * \retval 0 on success
135  * \retval -1 on error
136  */
137 int SCCreateDirectoryTree(const char *path, const bool final)
138 {
139  char pathbuf[PATH_MAX];
140  char *p;
141  size_t len = strlen(path);
142 
143  if (len > PATH_MAX - 1) {
144  return -1;
145  }
146 
147  strlcpy(pathbuf, path, sizeof(pathbuf));
148 
149  for (p = pathbuf + 1; *p; p++) {
150  if (*p == '/') {
151  /* Truncate, while creating directory */
152  *p = '\0';
153 
154  if (SCDefaultMkDir(pathbuf) != 0) {
155  if (errno != EEXIST) {
156  return -1;
157  }
158  }
159 
160  *p = '/';
161  }
162  }
163 
164  if (final) {
165  if (SCDefaultMkDir(pathbuf) != 0) {
166  if (errno != EEXIST) {
167  return -1;
168  }
169  }
170  }
171 
172  return 0;
173 }
174 
175 /**
176  * \brief Check if a path exists.
177  *
178  * \param Path to check for existence
179  *
180  * \retval true if path exists
181  * \retval false if path does not exist
182  */
183 bool SCPathExists(const char *path)
184 {
185  struct stat sb;
186  if (stat(path, &sb) == 0) {
187  return true;
188  }
189  return false;
190 }
191 
192 /**
193  * \brief OS independent wrapper for directory check
194  *
195  * \param dir_entry object to check
196  *
197  * \retval True if the object is a regular directory, otherwise false. This directory
198  * and parent directory will return false.
199  */
200 bool SCIsRegularDirectory(const struct dirent *const dir_entry)
201 {
202 #ifndef OS_WIN32
203  if ((dir_entry->d_type == DT_DIR) &&
204  (strcmp(dir_entry->d_name, ".") != 0) &&
205  (strcmp(dir_entry->d_name, "..") != 0)) {
206  return true;
207  }
208 #endif
209  return false;
210 }
211 /**
212  * \brief OS independent to check for regular file
213  *
214  * \param dir_entry object to check
215  *
216  * \retval True if the object is a regular file. Otherwise false.
217  */
218 bool SCIsRegularFile(const struct dirent *const dir_entry)
219 {
220 #ifndef OS_WIN32
221  return dir_entry->d_type == DT_REG;
222 #endif
223  return false;
224 }
225 
226 /**
227  * \brief OS independent wrapper for realpath
228  *
229  * \param path the path to resolve
230  * \param resolved_path the resolved path; if null, a buffer will be allocated
231  *
232  * \retval the resolved_path; or a pointer to a new resolved_path buffer
233  */
234 char *SCRealPath(const char *path, char *resolved_path)
235 {
236 #ifdef OS_WIN32
237  return _fullpath(resolved_path, path, PATH_MAX);
238 #else
239  return realpath(path, resolved_path);
240 #endif
241 }
242 
243 /*
244  * \brief Return the basename of the provided path.
245  * \param path The path on which to compute the basename
246  *
247  * \retval the basename of the path or NULL if the path lacks a non-leaf
248  */
249 const char *SCBasename(const char *path)
250 {
251  if (!path || strlen(path) == 0)
252  return NULL;
253 
254  char *final = strrchr(path, DIRECTORY_SEPARATOR);
255  if (!final)
256  return path;
257 
258  if (*(final + 1) == '\0')
259  return NULL;
260 
261  return final + 1;
262 }
263 
264 /**
265  * \brief Check for directory traversal
266  *
267  * \param path The path string to check for traversal
268  *
269  * \retval true if directory traversal is found, otherwise false
270  */
271 bool SCPathContainsTraversal(const char *path)
272 {
273 #ifdef OS_WIN32
274  const char *pattern = "..\\";
275 #else
276  const char *pattern = "../";
277 #endif
278  return strstr(path, pattern) != NULL;
279 }
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:107
PathMerge
int PathMerge(char *out_buf, size_t buf_size, const char *const dir, const char *const fname)
Definition: util-path.c:74
SCDefaultMkDir
int SCDefaultMkDir(const char *path)
Wrapper around SCMkDir with default mode arguments.
Definition: util-path.c:123
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:271
util-debug.h
SCIsRegularDirectory
bool SCIsRegularDirectory(const struct dirent *const dir_entry)
OS independent wrapper for directory check.
Definition: util-path.c:200
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:33
SCBasename
const char * SCBasename(const char *path)
Definition: util-path.c:249
SCPathExists
bool SCPathExists(const char *path)
Check if a path exists.
Definition: util-path.c:183
suricata-common.h
util-path.h
PathIsAbsolute
int PathIsAbsolute(const char *path)
Check if a path is absolute.
Definition: util-path.c:44
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:234
PathIsRelative
int PathIsRelative(const char *path)
Check if a path is relative.
Definition: util-path.c:69
suricata.h
SCIsRegularFile
bool SCIsRegularFile(const struct dirent *const dir_entry)
OS independent to check for regular file.
Definition: util-path.c:218
SCCreateDirectoryTree
int SCCreateDirectoryTree(const char *path, const bool final)
Recursively create a directory.
Definition: util-path.c:137