1
2
3
4
5
6
7#include "toys.h"
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#if CFG_TOYBOX_FORK
23pid_t xfork(void)
24{
25 pid_t pid = fork();
26
27 if (pid < 0) perror_exit("fork");
28
29 return pid;
30}
31#endif
32
33int xgetrandom(void *buf, unsigned buflen, unsigned flags)
34{
35 int fd;
36
37#if CFG_TOYBOX_GETRANDOM
38 if (buflen == getrandom(buf, buflen, flags&~WARN_ONLY)) return 1;
39 if (errno!=ENOSYS && !(flags&WARN_ONLY)) perror_exit("getrandom");
40#endif
41 fd = xopen(flags ? "/dev/random" : "/dev/urandom",O_RDONLY|(flags&WARN_ONLY));
42 if (fd == -1) return 0;
43 xreadall(fd, buf, buflen);
44 close(fd);
45
46 return 1;
47}
48
49
50#if defined(__APPLE__) || defined(__FreeBSD__)
51
52
53
54
55#else
56
57#include <mntent.h>
58
59static void octal_deslash(char *s)
60{
61 char *o = s;
62
63 while (*s) {
64 if (*s == '\\') {
65 int i, oct = 0;
66
67 for (i = 1; i < 4; i++) {
68 if (!isdigit(s[i])) break;
69 oct = (oct<<3)+s[i]-'0';
70 }
71 if (i == 4) {
72 *o++ = oct;
73 s += i;
74 continue;
75 }
76 }
77 *o++ = *s++;
78 }
79
80 *o = 0;
81}
82
83
84
85
86int mountlist_istype(struct mtab_list *ml, char *typelist)
87{
88 int len, skip;
89 char *t;
90
91 if (!typelist) return 1;
92
93 skip = strncmp(typelist, "no", 2);
94
95 for (;;) {
96 if (!(t = comma_iterate(&typelist, &len))) break;
97 if (!skip) {
98
99 if (strncmp(t, "no", 2)) error_exit("bad typelist");
100 if (!strncmp(t+2, ml->type, len-2)) {
101 skip = 1;
102 break;
103 }
104 } else if (!strncmp(t, ml->type, len) && !ml->type[len]) {
105 skip = 0;
106 break;
107 }
108 }
109
110 return !skip;
111}
112
113
114
115
116struct mtab_list *xgetmountlist(char *path)
117{
118 struct mtab_list *mtlist = 0, *mt;
119 struct mntent *me;
120 FILE *fp;
121 char *p = path ? path : "/proc/mounts";
122
123 if (!(fp = setmntent(p, "r"))) perror_exit("bad %s", p);
124
125
126
127
128
129 while ((me = getmntent(fp))) {
130 mt = xzalloc(sizeof(struct mtab_list) + strlen(me->mnt_fsname) +
131 strlen(me->mnt_dir) + strlen(me->mnt_type) + strlen(me->mnt_opts) + 4);
132 dlist_add_nomalloc((void *)&mtlist, (void *)mt);
133
134
135
136 if (!path) {
137 stat(me->mnt_dir, &(mt->stat));
138 statvfs(me->mnt_dir, &(mt->statvfs));
139 }
140
141
142 mt->dir = stpcpy(mt->type, me->mnt_type)+1;
143 mt->device = stpcpy(mt->dir, me->mnt_dir)+1;
144 mt->opts = stpcpy(mt->device, me->mnt_fsname)+1;
145 strcpy(mt->opts, me->mnt_opts);
146
147 octal_deslash(mt->dir);
148 octal_deslash(mt->device);
149 }
150 endmntent(fp);
151
152 return mtlist;
153}
154
155#endif
156
157#ifdef __APPLE__
158
159#include <sys/event.h>
160
161struct xnotify *xnotify_init(int max)
162{
163 struct xnotify *not = xzalloc(sizeof(struct xnotify));
164
165 not->max = max;
166 if ((not->kq = kqueue()) == -1) perror_exit("kqueue");
167 not->paths = xmalloc(max * sizeof(char *));
168 not->fds = xmalloc(max * sizeof(int));
169
170 return not;
171}
172
173int xnotify_add(struct xnotify *not, int fd, char *path)
174{
175 struct kevent event;
176
177 if (not->count == not->max) error_exit("xnotify_add overflow");
178 EV_SET(&event, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE, 0, NULL);
179 if (kevent(not->kq, &event, 1, NULL, 0, NULL) == -1 || event.flags & EV_ERROR)
180 return -1;
181 not->paths[not->count] = path;
182 not->fds[not->count++] = fd;
183
184 return 0;
185}
186
187int xnotify_wait(struct xnotify *not, char **path)
188{
189 struct kevent event;
190 int i;
191
192 for (;;) {
193 if (kevent(not->kq, NULL, 0, &event, 1, NULL) != -1) {
194
195 for (i = 0; i<not->count; i++) if (not->fds[i]==event.ident) {
196 *path = paths[i];
197
198 return event.ident;
199 }
200 }
201 }
202}
203
204#else
205
206#include <sys/inotify.h>
207
208struct xnotify *xnotify_init(int max)
209{
210 struct xnotify *not = xzalloc(sizeof(struct xnotify));
211
212 not->max = max;
213 if ((not->kq = inotify_init()) < 0) perror_exit("inotify_init");
214 not->paths = xmalloc(max * sizeof(char *));
215 not->fds = xmalloc(max * 2 * sizeof(int));
216
217 return not;
218}
219
220int xnotify_add(struct xnotify *not, int fd, char *path)
221{
222 int i = 2*not->count;
223
224 if (not->max == not->count) error_exit("xnotify_add overflow");
225 if ((not->fds[i] = inotify_add_watch(not->kq, path, IN_MODIFY))==-1)
226 return -1;
227 not->fds[i+1] = fd;
228 not->paths[not->count++] = path;
229
230 return 0;
231}
232
233int xnotify_wait(struct xnotify *not, char **path)
234{
235 struct inotify_event ev;
236 int i;
237
238 for (;;) {
239 if (sizeof(ev)!=read(not->kq, &ev, sizeof(ev))) perror_exit("inotify");
240
241 for (i = 0; i<not->count; i++) if (ev.wd==not->fds[2*i]) {
242 *path = not->paths[i];
243
244 return not->fds[2*i+1];
245 }
246 }
247}
248
249#endif
250