source: mainline/uspace/lib/fmgt/src/walk.c@ 1ec732a

Last change on this file since 1ec732a was 1ec732a, checked in by Jiri Svoboda <jiri@…>, 3 weeks ago

Verify file - navigator operation and command-line utility.

  • Property mode set to 100644
File size: 5.1 KB
RevLine 
[1ec732a]1/*
2 * Copyright (c) 2025 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup fmgt
30 * @{
31 */
32/** @file File system tree walker.
33 */
34
35#include <adt/list.h>
36#include <dirent.h>
37#include <errno.h>
38#include <mem.h>
39#include <stdbool.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <str.h>
43#include <vfs/vfs.h>
44
45#include "fmgt.h"
46#include "fmgt/walk.h"
47
48static errno_t fmgt_walk_subtree(fmgt_walk_params_t *, const char *);
49
50/** Initialize walk parameters.
51 *
52 * Every walk parameters structure must be initialized first using this
53 * function.
54 *
55 * @param params Pointer to walk parameters structure.
56 */
57void fmgt_walk_params_init(fmgt_walk_params_t *params)
58{
59 memset(params, 0, sizeof(fmgt_walk_params_t));
60}
61
62/** Walk file (invoke file callback).
63 *
64 * @param params Walk parameters
65 * @param fname File path
66 *
67 * @return EOK on success or an error code
68 */
69static errno_t fmgt_walk_file(fmgt_walk_params_t *params, const char *fname)
70{
71 if (params->cb->file != NULL)
72 return params->cb->file(params->arg, fname);
73 else
74 return EOK;
75}
76
77/** Enter directory (invoke directory entry callback).
78 *
79 * @param params Walk parameters
80 * @param dname Directory path
81 * @return EOK on success or an error code
82 */
83static errno_t fmgt_walk_dir_enter(fmgt_walk_params_t *params,
84 const char *dname)
85{
86 if (params->cb->dir_enter != NULL)
87 return params->cb->dir_enter(params->arg, dname);
88 else
89 return EOK;
90}
91
92/** Leave directory (invoke directory exit callback).
93 *
94 * @param params Walk parameters
95 * @param dname Directory path
96 * @return EOK on success or an error code
97 */
98static errno_t fmgt_walk_dir_leave(fmgt_walk_params_t *params,
99 const char *dname)
100{
101 if (params->cb->dir_enter != NULL)
102 return params->cb->dir_leave(params->arg, dname);
103 else
104 return EOK;
105}
106
107/** Walk directory.
108 *
109 * @param params Walk parameters
110 * @param dname Directory name
111 * @return EOK on success or an error code
112 */
113static errno_t fmgt_walk_dir(fmgt_walk_params_t *params, const char *dname)
114{
115 DIR *dir = NULL;
116 struct dirent *de;
117 errno_t rc;
118 char *pathname = NULL;
119 int rv;
120
121 rc = fmgt_walk_dir_enter(params, dname);
122 if (rc != EOK)
123 goto error;
124
125 dir = opendir(dname);
126 if (dir == NULL) {
127 rc = EIO;
128 goto error;
129 }
130
131 de = readdir(dir);
132 while (de != NULL) {
133 rv = asprintf(&pathname, "%s/%s", dname, de->d_name);
134 if (rv < 0) {
135 rc = ENOMEM;
136 goto error;
137 }
138
139 rc = fmgt_walk_subtree(params, pathname);
140 if (rc != EOK) {
141 free(pathname);
142 goto error;
143 }
144
145 free(pathname);
146 de = readdir(dir);
147 }
148
149 rc = fmgt_walk_dir_leave(params, dname);
150 if (rc != EOK)
151 return rc;
152
153 closedir(dir);
154 return EOK;
155error:
156 if (dir != NULL)
157 closedir(dir);
158 return rc;
159}
160
161/** Walk subtree.
162 *
163 * @params params Walk parameters.
164 * @params fname Subtree path.
165 *
166 * @return EOK on success or an error code.
167 */
168static errno_t fmgt_walk_subtree(fmgt_walk_params_t *params, const char *fname)
169{
170 vfs_stat_t stat;
171 errno_t rc;
172
173 rc = vfs_stat_path(fname, &stat);
174 if (rc != EOK)
175 return rc;
176
177 if (stat.is_directory) {
178 /* Directory */
179 rc = fmgt_walk_dir(params, fname);
180 if (rc != EOK)
181 return rc;
182 } else {
183 /* Not a directory */
184 rc = fmgt_walk_file(params, fname);
185 if (rc != EOK)
186 return rc;
187 }
188
189 return EOK;
190}
191
192/** Perform a file system walk.
193 *
194 * Walks the list of files/directories in @a params->flist. Directories
195 * are walked recursively. Callbacks are involved for each file, directory,
196 * if defined.in @a params->cb, the callback argument is @a params->arg.
197 *
198 * @param params Walk parameters
199 * @return EOK on success or an error code.
200 */
201errno_t fmgt_walk(fmgt_walk_params_t *params)
202{
203 fmgt_flist_entry_t *entry;
204 errno_t rc;
205
206 entry = fmgt_flist_first(params->flist);
207 while (entry != NULL) {
208 rc = fmgt_walk_subtree(params, entry->fname);
209 if (rc != EOK)
210 return rc;
211
212 entry = fmgt_flist_next(entry);
213 }
214
215 return EOK;
216}
217
218/** @}
219 */
Note: See TracBrowser for help on using the repository browser.