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
|
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "gcc-compat.h"
#include "err.h"
#include "str.h"
#include "file.h"
/*
* Call a function for each subdirectory of the current working directory.
*
* For each top-level directory under dirname, the supplied callback function
* is called, passing the full path to the subdirectory and the private_data
* pointer.
*
* If the callback returns a negative error value, the loop is terminated and
* that negative value is returned to the caller. If the iteration completes
* with no errors, the function returns non-negative.
*/
int for_each_subdir(int (*func)(const char *, void *), void *private_data)
{
struct dirent *entry;
int ret;
DIR *dir = opendir(".");
if (!dir)
return -ERRNO_TO_DSS_ERROR(errno);
while ((entry = readdir(dir))) {
mode_t m;
struct stat s;
if (!strcmp(entry->d_name, "."))
continue;
if (!strcmp(entry->d_name, ".."))
continue;
ret = lstat(entry->d_name, &s) == -1;
if (ret == -1) {
ret = -ERRNO_TO_DSS_ERROR(errno);
goto out;
}
m = s.st_mode;
if (!S_ISDIR(m))
continue;
ret = func(entry->d_name, private_data);
if (ret < 0)
goto out;
}
ret = 1;
out:
closedir(dir);
return ret;
}
/* Set a file descriptor to non-blocking mode. */
__must_check int mark_fd_nonblocking(int fd)
{
int flags = fcntl(fd, F_GETFL);
if (flags < 0)
return -ERRNO_TO_DSS_ERROR(errno);
flags = fcntl(fd, F_SETFL, ((long)flags) | O_NONBLOCK);
if (flags < 0)
return -ERRNO_TO_DSS_ERROR(errno);
return 1;
}
/*
* Call select(2) with no exceptfds and start over if the call was interrupted
* by a signal. All arguments are passed verbatim to select(2). Returns the
* return value of the underlying select call on success, a negative error code
* on error.
*/
int dss_select(int n, fd_set *readfds, fd_set *writefds,
struct timeval *timeout_tv)
{
int ret, err;
do {
ret = select(n, readfds, writefds, NULL, timeout_tv);
err = errno;
} while (ret < 0 && err == EINTR);
if (ret < 0)
return -ERRNO_TO_DSS_ERROR(errno);
return ret;
}
|