FileSystemIndexer v0.1.2-beta
File System Indexer - An API to index files from your system
Loading...
Searching...
No Matches
FSI_dirUtils_posix.h
Go to the documentation of this file.
1#ifndef INCLUDE_INTERFACES_FSI_DIRUTILS_POSIX_H_
2#define INCLUDE_INTERFACES_FSI_DIRUTILS_POSIX_H_
3
4#ifdef __cplusplus
5# define __FSI_DIRUTILS_POSIX_CPP_OPEN extern "C" {
6# define __FSI_DIRUTILS_POSIX_CPP_CLOSE }
7#else
8# define __FSI_DIRUTILS_POSIX_CPP_OPEN
9# define __FSI_DIRUTILS_POSIX_CPP_CLOSE
10#endif // __cplusplus
11
13
14#include "../../FSIpredefines.h"
15
16#ifndef FSI_OS_WIN32
17
18#include "../FSI_dirUtils.h"
19
20#include "cstr/cstr.h"
21
22#include <dirent.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <fcntl.h>
26
27typedef struct FSI_DirData_POSIX
28{
29 DIR *dir;
30 CSTR path;
31
32 int dirfd;
34
35typedef struct FSI_Visited_POSIX
36{
37 dev_t dev;
38 ino_t ino;
40
41/**
42 * @brief Open directory as read only
43 * @param d Directory data
44 * @param path Path to open dir
45 * @return Status (1 if worked, 0 if failed)
46 */
47int fsi_openDir(FSI_DirData *d, const char *path);
48
49/**
50 * @brief Read directory from reading the `FSI_DirData` information
51 * @param d Directory data
52 * @param out Entry data to set the information
53 * @return Status (1 if worked, 0 if failed)
54 */
56
57/**
58 * @brief Get the directory data to deallocate memory
59 * @param d Object to deallocate
60 */
62
63/**
64 * @brief Get the entry type of the dirfd from the FSI_DirData_POSIX
65 * * Get if: Directory, File, Symlink or other
66 * @param dirfd Entry type to get from the syscall
67 * @param e Get dirent type quickly from the `e` ptr with its corresponding `dirent` data
68 * @return Return the FSI_EntryType
69 */
70static inline FSI_EntryType fsi_getEntryType(int dirfd, struct dirent *e)
71{
72 switch (e->d_type)
73 {
74 case DT_REG: return FSI_FILE;
75 case DT_DIR: return FSI_DIR;
76 case DT_LNK: return FSI_SYMLINK;
77 case DT_UNKNOWN:
78 default:
79 {
80 struct stat st;
81
82 if (fstatat(dirfd, e->d_name, &st, AT_SYMLINK_NOFOLLOW) == 0)
83 {
84 if (S_ISREG(st.st_mode)) return FSI_FILE;
85 if (S_ISDIR(st.st_mode)) return FSI_DIR;
86 if (S_ISDIR(st.st_mode)) return FSI_SYMLINK;
87 }
88
89 return FSI_OTHER;
90 }
91 }
92}
93
94static inline FSI_EntryType fsi_getEntryTypeFromDirent(int dirfd, struct dirent *e, struct stat *stOut)
95{
96 switch (e->d_type)
97 {
98 case DT_REG:
99 return FSI_FILE;
100
101 case DT_DIR:
102 if (fstatat(dirfd, e->d_name, stOut, AT_SYMLINK_NOFOLLOW) == 0)
103 return FSI_DIR;
104
105 return FSI_OTHER;
106
107 case DT_LNK: return FSI_SYMLINK;
108
109 default:
110 if (fstatat(dirfd, e->d_name, stOut, AT_SYMLINK_NOFOLLOW) == 0)
111 {
112 if (S_ISDIR(stOut->st_mode)) return FSI_DIR;
113 if (S_ISREG(stOut->st_mode)) return FSI_FILE;
114 }
115
116 return FSI_OTHER;
117 }
118}
119
120static inline int fsi_visitedHas(CVEC *v, dev_t dev, ino_t ino)
121{
122 for (size_t i = 0 ; i < v->size ; i++)
123 {
124 FSI_Visited_POSIX *e = (FSI_Visited_POSIX*)cvec_get(v, i);
125
126 if (!e) continue;
127
128 if (e->dev == dev && e->ino == ino)
129 return 1;
130 }
131
132 return 0;
133}
134
135static inline void fsi_visitedAdd(CVEC *v, dev_t dev, ino_t ino)
136{
137 FSI_Visited_POSIX e = {0};
138
139 e.dev = dev;
140 e.ino = ino;
141
142 cvec_push(v, FSI_Visited_POSIX, e);
143}
144
145static inline void __fsi_walk(
146 CVEC *out,
147 CVEC *visited,
148
149 const char *path
150)
151{
152 int fd = open(path, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
153 if (fd < 0) return;
154
155 DIR *dir = fdopendir(fd);
156 if (!dir)
157 {
158 close(fd);
159 return;
160 }
161
162 struct stat dirSt;
163
164 if (fstat(fd, &dirSt) != 0)
165 {
166 closedir(dir);
167 return;
168 }
169
170 if (fsi_visitedHas(visited, dirSt.st_dev, dirSt.st_ino))
171 {
172 closedir(dir);
173 return;
174 }
175
176 fsi_visitedAdd(visited, dirSt.st_dev, dirSt.st_ino);
177
178 struct dirent *e;
179 CSTR tmp = cstr_init();
180
181 while ((e = readdir(dir)))
182 {
183 if (e->d_name[0] == '.' &&
184 (e->d_name[1] == '\0' || (e->d_name[1] == '.' && e->d_name[2] == '\0')))
185 continue;
186
187 struct stat st;
188
189 int type = fsi_getEntryTypeFromDirent(fd, e, &st);
190
191 cstr_set(&tmp, path);
192 cstr_add(&tmp, "/");
193 cstr_add(&tmp, e->d_name);
194
195 cvec_push(out, const char*, CVEC_sys_strdup(tmp.data));
196
197 if (type == FSI_DIR)
198 __fsi_walk(out, visited, tmp.data);
199 }
200
201 cstr_destroy(&tmp);
202
203 closedir(dir);
204}
205
206#endif // FSI_OS_WIN32
207
209
210#undef __FSI_DIRUTILS_POSIX_CPP_OPEN
211#undef __FSI_DIRUTILS_POSIX_CPP_CLOSE
212
213#endif // INCLUDE_CORE_FSI_DIRUTILS_H_
FSI_EntryType
@ FSI_SYMLINK
@ FSI_DIR
@ FSI_OTHER
@ FSI_FILE
void fsi_closeDir(FSI_DirData *d)
Get the directory data to deallocate memory.
int fsi_openDir(FSI_DirData *d, const char *path)
Open directory as read only.
static void __fsi_walk(CVEC *out, CVEC *visited, const char *path)
static FSI_EntryType fsi_getEntryTypeFromDirent(int dirfd, struct dirent *e, struct stat *stOut)
static int fsi_visitedHas(CVEC *v, dev_t dev, ino_t ino)
#define __FSI_DIRUTILS_POSIX_CPP_CLOSE
static void fsi_visitedAdd(CVEC *v, dev_t dev, ino_t ino)
static FSI_EntryType fsi_getEntryType(int dirfd, struct dirent *e)
Get the entry type of the dirfd from the FSI_DirData_POSIX.
int fsi_readDir(FSI_DirData *d, FSI_EntryData *out)
Read directory from reading the FSI_DirData information.
#define __FSI_DIRUTILS_POSIX_CPP_OPEN