Mercurial > molko
annotate libmlk-util/mlk/util/dir.c @ 570:aaf518c87628
util: introduce dir module
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 09 Mar 2023 20:30:00 +0100 |
parents | |
children | cba66f7d8a53 |
rev | line source |
---|---|
570
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
1 /* |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
2 * dir.c -- portable directory iterator |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
3 * |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
4 * Copyright (c) 2020-2023 David Demelier <markand@malikania.fr> |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
5 * |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
6 * Permission to use, copy, modify, and/or distribute this software for any |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
7 * purpose with or without fee is hereby granted, provided that the above |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
8 * copyright notice and this permission notice appear in all copies. |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
9 * |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
17 */ |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
18 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
19 #include <assert.h> |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
20 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
21 #include "dir.h" |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
22 #include "sysconfig.h" |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
23 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
24 #if defined(MLK_HAVE_DIRENT_H) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
25 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
26 /* {{{ Generic dirent.h support. */ |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
27 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
28 #include <dirent.h> |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
29 #include <stdio.h> |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
30 #include <stdlib.h> |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
31 #include <string.h> |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
32 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
33 struct self { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
34 DIR *dp; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
35 struct dirent *entry; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
36 }; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
37 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
38 static inline int |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
39 skip(const struct self *self) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
40 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
41 return strcmp(self->entry->d_name, ".") == 0 || |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
42 strcmp(self->entry->d_name, "..") == 0; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
43 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
44 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
45 static void |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
46 handle_finish(struct mlk_dir_iter *iter) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
47 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
48 struct self *self = iter->handle; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
49 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
50 if (self) { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
51 closedir(self->dp); |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
52 free(self); |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
53 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
54 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
55 iter->entry = NULL; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
56 iter->handle = NULL; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
57 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
58 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
59 static int |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
60 handle_open(struct mlk_dir_iter *iter, const char *path) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
61 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
62 struct self *self; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
63 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
64 if (!(self = calloc(1, sizeof (*self)))) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
65 return -1; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
66 if (!(self->dp = opendir(path))) { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
67 free(self); |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
68 return -1; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
69 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
70 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
71 iter->handle = self; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
72 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
73 return 0; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
74 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
75 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
76 static int |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
77 handle_next(struct mlk_dir_iter *iter) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
78 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
79 struct self *self = iter->handle; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
80 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
81 /* Skip . and .. which are barely useful. */ |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
82 while ((self->entry = readdir(self->dp)) && skip(self)) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
83 continue; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
84 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
85 /* End of directory, free all and indicate EOF to the user. */ |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
86 if (!self->entry) { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
87 handle_finish(iter); |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
88 return 0; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
89 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
90 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
91 iter->entry = self->entry->d_name; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
92 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
93 return 1; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
94 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
95 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
96 /* }}} */ |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
97 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
98 #else |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
99 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
100 /* {{{ No-op implementation */ |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
101 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
102 #include <stddef.h> |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
103 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
104 int |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
105 handle_open(struct mlk_dir_iter *iter, const char *path) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
106 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
107 (void)path; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
108 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
109 iter->entry = NULL; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
110 iter->handle = NULL; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
111 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
112 return -1; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
113 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
114 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
115 int |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
116 handle_next(struct mlk_dir_iter *iter) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
117 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
118 (void)iter; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
119 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
120 return 0; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
121 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
122 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
123 void |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
124 handle_finish(struct mlk_dir_iter *iter) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
125 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
126 (void)iter; |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
127 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
128 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
129 /* }}} */ |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
130 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
131 #endif |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
132 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
133 int |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
134 mlk_dir_open(struct mlk_dir_iter *iter, const char *path) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
135 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
136 assert(path); |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
137 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
138 return handle_open(iter, path); |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
139 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
140 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
141 int |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
142 mlk_dir_next(struct mlk_dir_iter *iter) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
143 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
144 assert(iter); |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
145 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
146 return handle_next(iter); |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
147 } |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
148 |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
149 void |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
150 mlk_dir_finish(struct mlk_dir_iter *iter) |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
151 { |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
152 return handle_finish(iter); |
aaf518c87628
util: introduce dir module
David Demelier <markand@malikania.fr>
parents:
diff
changeset
|
153 } |