OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include <sys/types.h> | |
12 #include <dirent.h> | |
13 #include <errno.h> | |
14 #include <stdlib.h> | |
15 #include <string.h> | |
16 | |
17 #include "webrtc/base/linuxfdwalk.h" | |
18 | |
19 // Parses a file descriptor number in base 10, requiring the strict format used | |
20 // in /proc/*/fd. Returns the value, or -1 if not a valid string. | |
21 static int parse_fd(const char *s) { | |
22 if (!*s) { | |
23 // Empty string is invalid. | |
24 return -1; | |
25 } | |
26 int val = 0; | |
27 do { | |
28 if (*s < '0' || *s > '9') { | |
29 // Non-numeric characters anywhere are invalid. | |
30 return -1; | |
31 } | |
32 int digit = *s++ - '0'; | |
33 val = val * 10 + digit; | |
34 } while (*s); | |
35 return val; | |
36 } | |
37 | |
38 int fdwalk(void (*func)(void *, int), void *opaque) { | |
39 DIR *dir = opendir("/proc/self/fd"); | |
40 if (!dir) { | |
41 return -1; | |
42 } | |
43 int opendirfd = dirfd(dir); | |
44 int parse_errors = 0; | |
45 struct dirent *ent; | |
46 // Have to clear errno to distinguish readdir() completion from failure. | |
47 while (errno = 0, (ent = readdir(dir)) != NULL) { | |
48 if (strcmp(ent->d_name, ".") == 0 || | |
49 strcmp(ent->d_name, "..") == 0) { | |
50 continue; | |
51 } | |
52 // We avoid atoi or strtol because those are part of libc and they involve | |
53 // locale stuff, which is probably not safe from a post-fork context in a | |
54 // multi-threaded app. | |
55 int fd = parse_fd(ent->d_name); | |
56 if (fd < 0) { | |
57 parse_errors = 1; | |
58 continue; | |
59 } | |
60 if (fd != opendirfd) { | |
61 (*func)(opaque, fd); | |
62 } | |
63 } | |
64 int saved_errno = errno; | |
65 if (closedir(dir) < 0) { | |
66 if (!saved_errno) { | |
67 // Return the closedir error. | |
68 return -1; | |
69 } | |
70 // Else ignore it because we have a more relevant error to return. | |
71 } | |
72 if (saved_errno) { | |
73 errno = saved_errno; | |
74 return -1; | |
75 } else if (parse_errors) { | |
76 errno = EBADF; | |
77 return -1; | |
78 } else { | |
79 return 0; | |
80 } | |
81 } | |
OLD | NEW |