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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 }