• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jasonish / suricata / 23105300094

15 Mar 2026 06:48AM UTC coverage: 75.784% (-0.7%) from 76.495%
23105300094

push

github

jasonish
github-ci: ubuntu minimal build fixups

- Don't run on the GitHub provided VM, it contains a newer Rust than
  stock Ubuntu does.

252836 of 333628 relevant lines covered (75.78%)

1978514.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.16
/src/util-path.c
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
{
6,938✔
46
    if (strlen(path) > 1 && path[0] == '/') {
6,938✔
47
        return 1;
33✔
48
    }
33✔
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;
6,905✔
59
}
6,938✔
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
{
122✔
71
    return PathIsAbsolute(path) ? 0 : 1;
122✔
72
}
122✔
73

74
int PathMerge(char *out_buf, size_t buf_size, const char *const dir, const char *const fname)
75
{
13,379✔
76
    char path[PATH_MAX];
13,379✔
77
    if (dir == NULL || strlen(dir) == 0)
13,379✔
78
        return -1;
×
79

80
    size_t r = strlcpy(path, dir, sizeof(path));
13,379✔
81
    if (r >= sizeof(path)) {
13,379✔
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] != '/')
13,379✔
90
        r = strlcat(path, "/", sizeof(path));
13,379✔
91
#endif
13,379✔
92
    if (r >= sizeof(path)) {
13,379✔
93
        return -1;
×
94
    }
×
95
    r = strlcat(path, fname, sizeof(path));
13,379✔
96
    if (r >= sizeof(path)) {
13,379✔
97
        return -1;
×
98
    }
×
99
    r = strlcpy(out_buf, path, buf_size);
13,379✔
100
    if (r >= buf_size) {
13,379✔
101
        return -1;
×
102
    }
×
103

104
    return 0;
13,379✔
105
}
13,379✔
106

107
char *PathMergeAlloc(const char *const dir, const char *const fname)
108
{
64✔
109
    char path[PATH_MAX];
64✔
110
    if (PathMerge(path, sizeof(path), dir, fname) != 0)
64✔
111
        return NULL;
×
112

113
    char *ret = SCStrdup(path);
64✔
114
    if (ret == NULL)
64✔
115
        return NULL;
×
116

117
    return ret;
64✔
118
}
64✔
119

120
/**
121
 * \brief Wrapper around SCMkDir with default mode arguments.
122
 */
123
int SCDefaultMkDir(const char *path)
124
{
50,175✔
125
    return SCMkDir(path, S_IRWXU | S_IRGRP | S_IXGRP);
50,175✔
126
}
50,175✔
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
{
5,109✔
139
    char pathbuf[PATH_MAX];
5,109✔
140
    char *p;
5,109✔
141
    size_t len = strlen(path);
5,109✔
142

143
    if (len > PATH_MAX - 1) {
5,109✔
144
        return -1;
×
145
    }
×
146

147
    strlcpy(pathbuf, path, sizeof(pathbuf));
5,109✔
148

149
    for (p = pathbuf + 1; *p; p++) {
433,541✔
150
        if (*p == '/') {
428,432✔
151
            /* Truncate, while creating directory */
152
            *p = '\0';
38,564✔
153

154
            if (SCDefaultMkDir(pathbuf) != 0) {
38,564✔
155
                if (errno != EEXIST) {
38,560✔
156
                    return -1;
×
157
                }
×
158
            }
38,560✔
159

160
            *p = '/';
38,564✔
161
        }
38,564✔
162
    }
428,432✔
163

164
    if (final) {
5,109✔
165
        if (SCDefaultMkDir(pathbuf) != 0) {
46✔
166
            if (errno != EEXIST) {
×
167
                return -1;
×
168
            }
×
169
        }
×
170
    }
46✔
171

172
    return 0;
5,109✔
173
}
5,109✔
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
{
11,724✔
185
    struct stat sb;
11,724✔
186
    if (stat(path, &sb) == 0) {
11,724✔
187
        return true;
52✔
188
    }
52✔
189
    return false;
11,672✔
190
}
11,724✔
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
{
16✔
273
#ifdef OS_WIN32
274
    const char *pattern = "..\\";
275
#else
276
    const char *pattern = "../";
16✔
277
#endif
16✔
278
    return strstr(path, pattern) != NULL;
16✔
279
}
16✔
280

281
/**
282
 * \brief Update access and modification time of an existing file to 'now'.
283
 * \param path The file path to touch
284
 * \retval 0 on success, -1 on failure
285
 */
286
int SCTouchFile(const char *path)
287
{
×
288
    if (path == NULL || path[0] == '\0') {
×
289
        errno = EINVAL;
×
290
        return -1;
×
291
    }
×
292
#ifndef OS_WIN32
×
293
    struct utimbuf ub;
×
294
    ub.actime = ub.modtime = time(NULL);
×
295
    if (utime(path, &ub) == 0)
×
296
        return 0;
×
297
#endif
×
298
    return -1;
×
299
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc