]> git.tuebingen.mpg.de Git - dss.git/blob - fd.c
db0433fd180e522160b6592fc1fd573f8e1c267a
[dss.git] / fd.c
1 #include <unistd.h>
2 #include <assert.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <sys/types.h>
6 #include <dirent.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9
10
11 #include "gcc-compat.h"
12 #include "error.h"
13 #include "string.h"
14
15 /**
16  * Call a function for each subdirectory of the current working directory.
17  *
18  * \param dirname The directory to traverse.
19  * \param func The function to call for each subdirecrtory.
20  * \param private_data Pointer to an arbitrary data structure.
21  *
22  * For each top-level directory under \a dirname, the supplied function \a func is
23  * called.  The full path of the subdirectory and the \a private_data pointer
24  * are passed to \a func.
25  *
26  * \return This function returns immediately if \a func returned a negative
27  * value. In this case \a func must set error_txt and this negative value is
28  * returned to the caller. Otherwise the function returns when all
29  * subdirectories have been passed to \a func.
30  */
31
32 int for_each_subdir(int (*func)(const char *, void *), void *private_data)
33 {
34         struct dirent *entry;
35         int ret;
36         DIR *dir = opendir(".");
37
38         if (!dir) {
39                 ret = -ERRNO_TO_DSS_ERROR(errno);
40                 make_err_msg("opendir(\".\") failed");
41                 return ret;
42         }
43         while ((entry = readdir(dir))) {
44                 mode_t m;
45                 struct stat s;
46
47                 if (!strcmp(entry->d_name, "."))
48                         continue;
49                 if (!strcmp(entry->d_name, ".."))
50                         continue;
51                 ret = lstat(entry->d_name, &s) == -1;
52                 if (ret == -1) {
53                         ret = -ERRNO_TO_DSS_ERROR(errno);
54                         make_err_msg("lstat(\"%s\") failed", entry->d_name);
55                         goto out;
56                 }
57                 m = s.st_mode;
58                 if (!S_ISDIR(m))
59                         continue;
60                 ret = func(entry->d_name, private_data);
61                 if (ret < 0)
62                         goto out;
63         }
64         ret = 1;
65 out:
66         closedir(dir);
67         return ret;
68 }
69 /**
70  * Wrapper for chdir(2).
71  *
72  * \param path The specified directory.
73  *
74  * \return Standard.
75  */
76 int dss_chdir(const char *path)
77 {
78         int ret = chdir(path);
79
80         if (ret >= 0)
81                 return 1;
82         ret = -ERRNO_TO_DSS_ERROR(errno);
83         make_err_msg("chdir to %s failed", path);
84         return ret;
85 }
86
87 /**
88  * Set a file descriptor to non-blocking mode.
89  *
90  * \param fd The file descriptor.
91  *
92  * \return Standard.
93  */
94 __must_check int mark_fd_nonblocking(int fd)
95 {
96         int flags = fcntl(fd, F_GETFL);
97         if (flags < 0)
98                 return -ERRNO_TO_DSS_ERROR(errno);
99         flags = fcntl(fd, F_SETFL, ((long)flags) | O_NONBLOCK);
100         if (flags < 0)
101                 return -ERRNO_TO_DSS_ERROR(errno);
102         return 1;
103 }
104