-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfiles.c
145 lines (111 loc) · 2.73 KB
/
files.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* author: Aleksei Kozadaev (2019)
*/
#include <errno.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <assert.h>
#include "log.h"
#include "files.h"
#define ALLOC 64
#define MAXPATH 1024
static void add_file(const char *file);
static int is_directory(const char *fname);
static int is_ignored(const char *name);
static int walk_dir(const char *dir);
char **fstore = NULL;
size_t fsize = 0;
size_t fcap = ALLOC;
const char *ignored[] = { "/.git", "/.hg", NULL };
char **files_parse(const char **args, size_t *nfiles) {
assert(!fstore);
fstore = malloc(sizeof(*fstore) * fcap);
if (!fstore) {
LOG_PERROR("malloc");
abort();
}
while (*args != NULL) {
const char *fname = *args++;
if (is_directory(fname) && walk_dir(fname) == -1) {
abort();
}
add_file(fname);
}
*nfiles = fsize;
return fstore;
}
void files_free(void) {
for (int i = 0; i < fsize; i++) {
free(fstore[i]);
}
free(fstore);
}
void add_file(const char *file) {
if (fsize == fcap) {
fcap *= 2;
fstore = realloc(fstore, sizeof(*fstore) * fcap);
if (!fstore) {
LOG_PERROR("realloc");
abort();
}
}
fstore[fsize++] = strdup(file);
}
int is_directory(const char *fname) {
struct stat stbuf;
if (stat(fname, &stbuf) == -1) {
LOG_PERROR_VA("%s", fname);
return 0;
}
return S_ISDIR(stbuf.st_mode);
}
int is_ignored(const char *name) {
for (int i = 0; ignored[i] != NULL; i++) {
if (strstr(name, ignored[i]) != NULL) {
return 1;
}
}
return 0;
}
/* got to the directory, make necessary checks and call (handle_files) to
* handle the contents */
int walk_dir(const char *dir) {
char name[MAXPATH];
struct dirent *dp;
DIR *dfd;
size_t dirlen;
if ((dfd = opendir(dir)) == NULL) {
// not a folder - nothing to do.
return 0;
}
dirlen = strlen(dir);
while ((dp = readdir(dfd)) != NULL) {
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
continue;
}
if ((dirlen + strlen(dp->d_name) + 2) > MAXPATH) {
LOG_ERROR("directory name is too long");
goto error;
}
if (dp->d_type == DT_DIR) {
sprintf(name, "%s/%s", dir, dp->d_name);
if (is_ignored(name)) {
continue;
}
add_file(name);
if (walk_dir(name) == -1) {
goto error;
}
}
/* ignore everything else */
}
closedir(dfd);
return 0;
error:
if (dfd) {
closedir(dfd);
}
return -1;
}