dir.c
4.02 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* dir.c: This is the home of the posix-style get_dir_first, get_dir_next.
* Right now, those function only return non-directory filenames.
* (This is because thats what i wanted for checkout_files.)
*
* Copyright (C) 2006 Georg Steffers
*
* Author: Georg Steffers [GST] <georg.steffers@aschendorff.de>
* Developer:
*
* Changes (for this file only):
* (2006-06-12) [GST] Started this changelog...well the program is
* ready since some weeks right now.
*/
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <scot/dir.h>
#include <scot/exception.h>
/*
* within the get_dir_... functions one can decide if one wants to follow
* symlinks or not. To achive this i use different stat functions to
* identify files. A variable of this type is capable of holding those
* stat functions.
*/
typedef int (*stat_func_t) (const char *, struct stat *);
/*
* This functions tries an opendir on the given path and uses the
* get_dir_next function to retrieve the first file within that directory.
*
* parameters:
* path: The path to the directory that should be read.
* file: A pointer to a structure that holds further information to the
* found file. (e.g. the path to the file)
* fsym: fsym==0 => don't follow symlinks, fsym!=0 => follow symlinks
*
* returns:
* NULL if an error occures or an handle to the opened directory on
* success. This handle should be closed later in the program.
* There should be a function that does this, but as this program
* actually exits anyway after directory reading i have not done it
* right now.
*/
DIR_HANDLE
get_dir_first (const char * path, FILE_DATA * file, int fsym)
{
DIR * dir;
dir = opendir (path); /* !!!FIXME!!! Do error handling here */
/* opendir could fail for various reasons, most likely are two.
* The given string does not reflect any file, or is no directory */
if (NULL == dir)
/* errno is set by opendir */
return NULL;
if (get_dir_next (dir, path, file, fsym) != GET_DIRENT_OK)
return NULL;
return dir;
}
/*
* This functions retrieves the next file within the given dir.
*
* parameters:
* dir: Handle to a directory opened with get_dir_first previously.
* path: The path to the directory that is read.
* (hmmm, this seems not that ideal to me...why should this
* function construct the full path to the found file.
* The filename is more that enough i think, as the caller knows
* the path already.)
* file: A pointer to a structure that holds further information to the
* found file. (e.g. the path to the file)
* fsym: fsym==0 => don't follow symlinks, fsym!=0 => follow symlinks
*
* returns:
* This function returns always one of the following:
* GET_DIRENT_ERR: if an error occured...errno might or might not be set.
* NO_FILES_LEFT: if the last entry of the directory was read.
* GET_DIRENT_OK: if the next directory entry was read successfully.
*/
int
get_dir_next (DIR_HANDLE dir, const char * path, FILE_DATA * file, int fsym)
{
stat_func_t my_stat_f;
/* first look if we should use a symlink following stat */
switch (fsym)
{
case DONT_FOLLOW_SYM: my_stat_f = lstat; break;
case FOLLOW_SYM:
default: my_stat_f = stat;;
}
strncpy (file->path, path, MAX_PATH);
/* add a / to path but don't write more than MAX_PATH */
if (strlen (file->path) < MAX_PATH &&
file->path [strlen (file->path)-1] != '/')
{
file->path [strlen (file->path) + 1] = '\0';
file->path [strlen (file->path)] = '/';
}
/* now fill the given struct dirent_stat */
errno = 0;
file->file = readdir (dir);
if (NULL == file->file)
{
if (NULL != dir)
closedir (dir);
if (errno != EBADF)
return NO_FILES_LEFT;
return GET_DIRENT_ERR;
}
strncpy (
file->path+strlen (file->path),
file->file->d_name,
MAX_PATH-strlen (file->path));
if (my_stat_f (file->path, &(file->stat)) == -1)
{
/* errno is filled by the stat function */
return GET_DIRENT_ERR;
}
return GET_DIRENT_OK;
}