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