File: ftw.c

package info (click to toggle)
libprelude 0.9.7.2-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 15,112 kB
  • ctags: 14,426
  • sloc: ansic: 131,701; xml: 27,964; sh: 9,465; makefile: 390; awk: 342; yacc: 207; lex: 141; python: 9; perl: 2
file content (113 lines) | stat: -rw-r--r-- 3,232 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* Copyright (C) 2005 Free Software Foundation, Inc.
 * Written by Yoann Vandoorselaere <yoann@prelude-ids.org>
 *
 * The file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This file is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this file; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

#ifdef HAVE_CONFIG_H
 #include <config.h>
#endif

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

#include "ftw_.h"
#include "pathmax.h"


static int get_path_infos(const char *path, struct stat *st, int *flag)
{
        int ret;
        
        ret = stat(path, st);
        if ( ret < 0 ) {
                *flag = FTW_NS;
                return -1;
        }
        
        if ( S_ISREG(st->st_mode) )
                *flag = FTW_F;
                
        else if ( S_ISDIR(st->st_mode) )
                *flag = FTW_D;
        
        else if ( S_ISLNK(st->st_mode) )
                *flag = FTW_SL;

        return ret;
}



int ftw(const char *dir,
        int (*fn)(const char *file, const struct stat *sb, int flag), int nopenfd) 
{
        DIR *d;
        size_t len;
        struct stat st;
        struct dirent *de;
        int flag, ret = 0;
        char filename[PATH_MAX];

        ret = get_path_infos(dir, &st, &flag);
        if ( ret < 0 )
                return -1;
                        
        d = opendir(dir);
        if ( ! d )
                return (errno == EACCES) ? fn(dir, &st, FTW_DNR) : -1;

        ret = fn(dir, &st, flag);
        if ( ret < 0 ) {
                closedir(d);
                return ret;
        }
        
        while ( (de = readdir(d)) ) {          

                len = snprintf(filename, sizeof(filename), "%s/%s", dir, de->d_name);
                if ( len < 0 || len >= sizeof(filename) ) {
                        errno = ENAMETOOLONG;
                        return -1;
                }
                
                ret = get_path_infos(filename, &st, &flag);
                if ( ret < 0 )
                        break;
                                
                if ( flag == FTW_D ) {
                        if ( strcmp(de->d_name, "..") == 0 || strcmp(de->d_name, ".") == 0 )
                                continue;

                        ret = ftw(filename, fn, nopenfd);
                        if ( ret < 0 )
                                break;
                        
                        continue;
                }
                
                ret = fn(filename, (flag == FTW_NS) ? NULL : &st, flag);
                if ( ret < 0 )
                        break;
        }

        closedir(d);

        return ret;
}