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 <booh@altern.org>
21 /*******************************************************
22 * FTW implementation that your system shouldn't lack. *
23 *******************************************************/
25 /* No #include <...> as this file is #included in loading.c */
37 typedef int (*ftw_func
) (const char *name
, const struct stat
* st
, int unused
);
39 int ftw(const char *filename
, ftw_func func
, int unused
);
40 static void ftw_rec(const char *filename
, ftw_func func
);
42 static int list_length
;
43 static mini_stat
*list
;
45 static void append_to_list(dev_t dev
, ino_t ino
)
48 list
= realloc(list
, list_length
* sizeof(mini_stat
));
49 list
[list_length
- 1].st_dev
= dev
;
50 list
[list_length
- 1].st_ino
= ino
;
53 static int is_in_list(dev_t dev
, ino_t ino
)
57 for (i
= 0; i
< list_length
; i
++) {
58 if (list
[i
].st_ino
== ino
&& list
[i
].st_dev
== dev
)
64 /* Returns 0 if path is neither ".." nor "." to avoid infinite recursion. */
65 static int path_ok(const char *path
)
70 if ((path
[1] == '\0') || (path
[1] == '.' && path
[2] == '\0'))
76 static void ftw_dir(const char *dirname
, ftw_func func
)
78 struct dirent
*dir_ent
;
85 append_to_list(st
.st_dev
, st
.st_ino
);
87 /* 2 = (1 for '/') + (1 for '\0') */
88 dir_len
= strlen(dirname
) + 2;
90 dir
= opendir(dirname
);
92 (*func
) (dirname
, &st
, FTW_DNR
);
96 dir_ent
= readdir(dir
);
98 while (dir_ent
!= NULL
) {
99 if (path_ok(dir_ent
->d_name
) == 0) {
100 name
= malloc((dir_len
+ strlen(dir_ent
->d_name
)) * sizeof(char));
101 sprintf(name
, "%s/%s", dirname
, dir_ent
->d_name
);
105 dir_ent
= readdir(dir
);
110 static void ftw_rec(const char *filename
, ftw_func func
)
114 lstat(filename
, &st
);
115 if (S_ISLNK(st
.st_mode
)) {
116 /* We have a symbolic link. */
118 if (S_ISDIR(st
.st_mode
) && is_in_list(st
.st_dev
, st
.st_ino
)) {
120 * We already traversed this directory so
121 * adding it may cause infinite recursion.
127 if (S_ISDIR(st
.st_mode
)) {
128 ftw_dir(filename
, func
);
129 (*func
) (filename
, &st
, FTW_D
);
131 (*func
) (filename
, &st
, FTW_F
);
134 int ftw(const char *filename
, ftw_func func
, int unused
)
138 if (lstat(filename
, &st
) == -1) {
139 (*func
) (filename
, &st
, FTW_NS
);
146 ftw_rec(filename
, func
);