GCC Code Coverage Report


Directory: ./
File: common/src/dir.c
Date: 2026-11-08 20:01:15
Exec Total Coverage
Lines: 94 100 94.0%
Functions: 8 8 100.0%
Branches: 52 58 89.7%

Line Branch Exec Source
1 /*
2 * Common code for working with directory trees.
3 * Copyright © 2007-2026, albinoloverats ~ Software Development
4 * email: stegfs@albinoloverats.net
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include <fcntl.h>
26 #include <dirent.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29
30 #include "non-gnu.h"
31 #include "common.h"
32 #include "error.h"
33 #include "mem.h"
34 #include "dir.h"
35 #include "list.h"
36
37 431 extern char *dir_get_name_aux(const char * const path, const char ext)
38 {
39 431 const char *file = strrchr(path, DIR_SEPARATOR_CHAR);
40
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 2 times.
431 if (file)
41 429 file++;
42 else
43 2 file = path;
44 431 const char *pass = strrchr(path, ext);
45
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 165 times.
431 if (!pass)
46 266 pass = strchr(file, '\0');
47 431 return m_strndup(file, pass - file);
48 }
49
50 966 extern uint16_t dir_get_deep(const char * const path)
51 {
52 1 uint16_t d = 0;
53 1 char *ptr = (char *)path;
54
2/2
✓ Branch 0 taken 1010 times.
✓ Branch 1 taken 966 times.
1976 while ((ptr = strchr(ptr, DIR_SEPARATOR_CHAR)))
55 {
56 1010 d++;
57 1010 ptr++;
58 }
59 966 return d;
60 }
61
62 45 extern char *dir_get_part(const char * const path, const uint16_t index)
63 {
64
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 44 times.
45 if (!index)
65 1 return m_strdup(DIR_SEPARATOR);
66 2 char *ptr = (char *)path;
67
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 43 times.
101 for (uint16_t i = 0; i < index; i++)
68 {
69 58 char *separator = strchr(ptr, DIR_SEPARATOR_CHAR);
70
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 57 times.
58 if (!separator)
71 {
72 1 ptr += strlen(ptr);
73 1 break;
74 }
75 57 ptr = separator + 1;
76 }
77 44 return m_strndup(ptr, strchrnul(ptr, DIR_SEPARATOR_CHAR) - ptr);
78 }
79
80 102 extern char *dir_get_pass(const char * const restrict path)
81 {
82
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 101 times.
102 if (!strrchr(path, ':'))
83 1 return m_strdup("");
84 101 return m_strdup(strrchr(path, ':') + 1);
85 }
86
87 47 extern char *dir_get_path(const char * const restrict path)
88 {
89 47 const char *s = strrchr(path, DIR_SEPARATOR_CHAR);
90
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 46 times.
47 if (!s)
91 1 return m_strdup("");
92 46 char *p = strndup(path, s - path);
93
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 6 times.
46 if (strlen(p))
94 1 return p;
95 40 free(p);
96 40 return m_strdup(DIR_SEPARATOR);
97 }
98
99 /*
100 * Taken from http://nion.modprobe.de/tmp/mkdir.c
101 */
102 3 extern void dir_mk_recursive(const char *path, mode_t mode)
103 {
104 #ifdef _WIN32
105 (void)mode;
106 #endif
107 3 char *opath = m_strdup(path);
108 3 size_t len = strlen(opath);
109
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!len)
110 {
111 1 free(opath);
112 1 return;
113 }
114
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 if (len > 1 && opath[len - 1] == '/')
115 1 opath[len - 1] = '\0';
116
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 2 times.
56 for (char *p = opath; *p; p++)
117
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 46 times.
54 if (*p == '/')
118 {
119 8 *p = '\0';
120
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
8 if (access(opath, F_OK))
121 3 mkdir(opath, mode);
122 8 *p = '/';
123 }
124
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (access(opath, F_OK)) /* if path is not terminated with / */
125 1 mkdir(opath, mode);
126 2 free(opath);
127 2 return;
128 }
129
130 33 static void get_tree(list_t l, const char *path, dir_type_e type)
131 {
132
7/8
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 98 times.
✓ Branch 4 taken 33 times.
✓ Branch 5 taken 33 times.
✓ Branch 6 taken 65 times.
✓ Branch 8 taken 131 times.
✓ Branch 9 taken 33 times.
164 DIR_SCAN_TOP;
133
134 65 bool add = false;
135 65 bool dir = false;
136 /*
137 * eps[i]->d_type doesn't always give a proper
138 * answer, so we've gotta stat
139 */
140 struct stat s;
141
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
65 if (lstat(file, &s))
142 {
143 ✗ free(file);
144 ✗ continue;
145 }
146
6/8
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
65 switch (s.st_mode & S_IFMT)
147 {
148 24 case S_IFDIR:
149 24 add = type & DIR_FOLDER;
150 24 dir = true;
151 24 break;
152 7 case S_IFCHR:
153 7 add = type & DIR_CHAR;
154 7 break;
155 ✗ case S_IFBLK:
156 ✗ add = type & DIR_BLOCK;
157 ✗ break;
158 7 case S_IFREG:
159 7 add = type & DIR_FILE;
160 7 break;
161 #ifndef _WIN32
162 13 case S_IFLNK:
163 13 add = type & DIR_LINK;
164 13 break;
165 7 case S_IFSOCK:
166 7 add = type & DIR_SOCKET;
167 7 break;
168 #endif
169 7 case S_IFIFO:
170 7 add = type & DIR_PIPE;
171 7 break;
172 }
173
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 44 times.
65 if (add)
174 {
175 21 char *f = m_strdup(file);
176
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if (!list_add(l, f))
177 ✗ free(f);
178 }
179
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 41 times.
65 if (dir)
180 24 get_tree(l, file, type);
181
182
2/2
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 33 times.
229 DIR_SCAN_END;
183
184 33 return;
185 }
186
187 9 extern list_t dir_get_tree(const char *path, dir_type_e type)
188 {
189 9 list_t l = list_string();
190 9 get_tree(l, path, type);
191 9 return l;
192 }
193