2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
21 /*****************************************
22 * A simplified ftw(3), specific to GLiv *
23 *****************************************/
25 #include <sys/stat.h> /* struct stat, stat() */
26 #include <dirent.h> /* struct dirent, *dir() */
27 #include <stdio.h> /* perror() */
30 #include "foreach_file.h"
33 /* Push directories and handle files. */
34 static GSList
*process_dir(GSList
* stack
, const gchar
* dirname
,
35 foreach_file_func func
, gint
* res
)
38 struct dirent
*dir_ent
;
40 gchar
*name
, *fullname
;
41 gboolean is_dir
= FALSE
, is_dir_known
;
43 dir
= opendir(dirname
);
49 while ((dir_ent
= readdir(dir
)) != NULL
) {
50 name
= dir_ent
->d_name
;
53 (name
[1] == '\0' || (name
[1] == '.' && name
[2] == '\0')))
54 /* Skip "." and "..". */
57 fullname
= g_build_filename(dirname
, name
, NULL
);
60 #ifdef _DIRENT_HAVE_D_TYPE
61 switch (dir_ent
->d_type
) {
78 if (is_dir_known
== FALSE
&& !stat(fullname
, &st
)) {
79 is_dir
= S_ISDIR(st
.st_mode
);
86 stack
= g_slist_prepend(stack
, fullname
);
89 *res
+= (*func
) (fullname
);
100 * We know that func is add_file_to_list and
101 * we return the number of inserted files.
103 gint
foreach_file(const gchar
* path
, foreach_file_func func
)
105 GSList
*stack
= NULL
;
111 if (stat(path
, &st
) < 0) {
112 /* The path is not usable. */
117 if (S_ISDIR(st
.st_mode
) == FALSE
)
118 /* The path is a file, not a directory. */
119 return (*func
) (path
);
121 /* The path is a valid directory. */
123 stack
= g_slist_prepend(stack
, g_strdup(path
)); /* push */
128 current
= stack
->data
;
129 stack
= g_slist_remove_link(stack
, stack
); /* pop */
131 if (!stat(current
, &st
) && pathset_add(set
, current
))
132 /* Not already scanned. */
133 stack
= process_dir(stack
, current
, func
, &res
);