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
51
52#if defined(__APPLE__) || defined(__FreeBSD__)
53
54#include <sys/mount.h>
55
56struct mtab_list *xgetmountlist(char *path)
57{
58 struct mtab_list *mtlist = 0, *mt;
59 struct statfs *entries;
60 int i, count;
61
62 if (path) error_exit("xgetmountlist");
63 if ((count = getmntinfo(&entries, 0)) == 0) perror_exit("getmntinfo");
64
65
66
67
68
69 for (i = 0; i < count; ++i) {
70 struct statfs *me = &entries[i];
71
72 mt = xzalloc(sizeof(struct mtab_list) + strlen(me->f_fstypename) +
73 strlen(me->f_mntonname) + strlen(me->f_mntfromname) + strlen("") + 4);
74 dlist_add_nomalloc((void *)&mtlist, (void *)mt);
75
76
77
78 stat(me->f_mntonname, &(mt->stat));
79 statvfs(me->f_mntonname, &(mt->statvfs));
80
81
82 mt->dir = stpcpy(mt->type, me->f_fstypename)+1;
83 mt->device = stpcpy(mt->dir, me->f_mntonname)+1;
84 mt->opts = stpcpy(mt->device, me->f_mntfromname)+1;
85 strcpy(mt->opts, "");
86 }
87
88 return mtlist;
89}
90
91#else
92
93#include <mntent.h>
94
95static void octal_deslash(char *s)
96{
97 char *o = s;
98
99 while (*s) {
100 if (*s == '\\') {
101 int i, oct = 0;
102
103 for (i = 1; i < 4; i++) {
104 if (!isdigit(s[i])) break;
105 oct = (oct<<3)+s[i]-'0';
106 }
107 if (i == 4) {
108 *o++ = oct;
109 s += i;
110 continue;
111 }
112 }
113 *o++ = *s++;
114 }
115
116 *o = 0;
117}
118
119
120
121
122int mountlist_istype(struct mtab_list *ml, char *typelist)
123{
124 int len, skip;
125 char *t;
126
127 if (!typelist) return 1;
128
129 skip = strncmp(typelist, "no", 2);
130
131 for (;;) {
132 if (!(t = comma_iterate(&typelist, &len))) break;
133 if (!skip) {
134
135 if (strncmp(t, "no", 2)) error_exit("bad typelist");
136 if (!strncmp(t+2, ml->type, len-2)) {
137 skip = 1;
138 break;
139 }
140 } else if (!strncmp(t, ml->type, len) && !ml->type[len]) {
141 skip = 0;
142 break;
143 }
144 }
145
146 return !skip;
147}
148
149struct mtab_list *xgetmountlist(char *path)
150{
151 struct mtab_list *mtlist = 0, *mt;
152 struct mntent *me;
153 FILE *fp;
154 char *p = path ? path : "/proc/mounts";
155
156 if (!(fp = setmntent(p, "r"))) perror_exit("bad %s", p);
157
158
159
160
161
162 while ((me = getmntent(fp))) {
163 mt = xzalloc(sizeof(struct mtab_list) + strlen(me->mnt_fsname) +
164 strlen(me->mnt_dir) + strlen(me->mnt_type) + strlen(me->mnt_opts) + 4);
165 dlist_add_nomalloc((void *)&mtlist, (void *)mt);
166
167
168
169 if (!path) {
170 stat(me->mnt_dir, &(mt->stat));
171 statvfs(me->mnt_dir, &(mt->statvfs));
172 }
173
174
175 mt->dir = stpcpy(mt->type, me->mnt_type)+1;
176 mt->device = stpcpy(mt->dir, me->mnt_dir)+1;
177 mt->opts = stpcpy(mt->device, me->mnt_fsname)+1;
178 strcpy(mt->opts, me->mnt_opts);
179
180 octal_deslash(mt->dir);
181 octal_deslash(mt->device);
182 }
183 endmntent(fp);
184
185 return mtlist;
186}
187
188#endif
189
190#ifdef __APPLE__
191
192#include <sys/event.h>
193
194struct xnotify *xnotify_init(int max)
195{
196 struct xnotify *not = xzalloc(sizeof(struct xnotify));
197
198 not->max = max;
199 if ((not->kq = kqueue()) == -1) perror_exit("kqueue");
200 not->paths = xmalloc(max * sizeof(char *));
201 not->fds = xmalloc(max * sizeof(int));
202
203 return not;
204}
205
206int xnotify_add(struct xnotify *not, int fd, char *path)
207{
208 struct kevent event;
209
210 if (not->count == not->max) error_exit("xnotify_add overflow");
211 EV_SET(&event, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE, 0, NULL);
212 if (kevent(not->kq, &event, 1, NULL, 0, NULL) == -1 || event.flags & EV_ERROR)
213 return -1;
214 not->paths[not->count] = path;
215 not->fds[not->count++] = fd;
216
217 return 0;
218}
219
220int xnotify_wait(struct xnotify *not, char **path)
221{
222 struct kevent event;
223 int i;
224
225 for (;;) {
226 if (kevent(not->kq, NULL, 0, &event, 1, NULL) != -1) {
227
228 for (i = 0; i<not->count; i++) if (not->fds[i]==event.ident) {
229 *path = not->paths[i];
230
231 return event.ident;
232 }
233 }
234 }
235}
236
237#else
238
239#include <sys/inotify.h>
240
241struct xnotify *xnotify_init(int max)
242{
243 struct xnotify *not = xzalloc(sizeof(struct xnotify));
244
245 not->max = max;
246 if ((not->kq = inotify_init()) < 0) perror_exit("inotify_init");
247 not->paths = xmalloc(max * sizeof(char *));
248 not->fds = xmalloc(max * 2 * sizeof(int));
249
250 return not;
251}
252
253int xnotify_add(struct xnotify *not, int fd, char *path)
254{
255 int i = 2*not->count;
256
257 if (not->max == not->count) error_exit("xnotify_add overflow");
258 if ((not->fds[i] = inotify_add_watch(not->kq, path, IN_MODIFY))==-1)
259 return -1;
260 not->fds[i+1] = fd;
261 not->paths[not->count++] = path;
262
263 return 0;
264}
265
266int xnotify_wait(struct xnotify *not, char **path)
267{
268 struct inotify_event ev;
269 int i;
270
271 for (;;) {
272 if (sizeof(ev)!=read(not->kq, &ev, sizeof(ev))) perror_exit("inotify");
273
274 for (i = 0; i<not->count; i++) if (ev.wd==not->fds[2*i]) {
275 *path = not->paths[i];
276
277 return not->fds[2*i+1];
278 }
279 }
280}
281
282#endif
283
284#ifdef __APPLE__
285
286ssize_t xattr_get(const char *path, const char *name, void *value, size_t size)
287{
288 return getxattr(path, name, value, size, 0, 0);
289}
290
291ssize_t xattr_lget(const char *path, const char *name, void *value, size_t size)
292{
293 return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
294}
295
296ssize_t xattr_fget(int fd, const char *name, void *value, size_t size)
297{
298 return fgetxattr(fd, name, value, size, 0, 0);
299}
300
301ssize_t xattr_list(const char *path, char *list, size_t size)
302{
303 return listxattr(path, list, size, 0);
304}
305
306ssize_t xattr_llist(const char *path, char *list, size_t size)
307{
308 return listxattr(path, list, size, XATTR_NOFOLLOW);
309}
310
311ssize_t xattr_flist(int fd, char *list, size_t size)
312{
313 return flistxattr(fd, list, size, 0);
314}
315
316ssize_t xattr_set(const char* path, const char* name,
317 const void* value, size_t size, int flags)
318{
319 return setxattr(path, name, value, size, 0, flags);
320}
321
322ssize_t xattr_lset(const char* path, const char* name,
323 const void* value, size_t size, int flags)
324{
325 return setxattr(path, name, value, size, 0, flags | XATTR_NOFOLLOW);
326}
327
328ssize_t xattr_fset(int fd, const char* name,
329 const void* value, size_t size, int flags)
330{
331 return fsetxattr(fd, name, value, size, 0, flags);
332}
333
334#else
335
336ssize_t xattr_get(const char *path, const char *name, void *value, size_t size)
337{
338 return getxattr(path, name, value, size);
339}
340
341ssize_t xattr_lget(const char *path, const char *name, void *value, size_t size)
342{
343 return lgetxattr(path, name, value, size);
344}
345
346ssize_t xattr_fget(int fd, const char *name, void *value, size_t size)
347{
348 return fgetxattr(fd, name, value, size);
349}
350
351ssize_t xattr_list(const char *path, char *list, size_t size)
352{
353 return listxattr(path, list, size);
354}
355
356ssize_t xattr_llist(const char *path, char *list, size_t size)
357{
358 return llistxattr(path, list, size);
359}
360
361ssize_t xattr_flist(int fd, char *list, size_t size)
362{
363 return flistxattr(fd, list, size);
364}
365
366ssize_t xattr_set(const char* path, const char* name,
367 const void* value, size_t size, int flags)
368{
369 return setxattr(path, name, value, size, flags);
370}
371
372ssize_t xattr_lset(const char* path, const char* name,
373 const void* value, size_t size, int flags)
374{
375 return lsetxattr(path, name, value, size, flags);
376}
377
378ssize_t xattr_fset(int fd, const char* name,
379 const void* value, size_t size, int flags)
380{
381 return fsetxattr(fd, name, value, size, flags);
382}
383
384
385#endif
386
387#ifdef __APPLE__
388
389
390int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev)
391{
392 int old_dirfd = open(".", O_RDONLY), result;
393
394 if (old_dirfd == -1 || fchdir(dirfd) == -1) return -1;
395 result = mknod(path, mode, dev);
396 if (fchdir(old_dirfd) == -1) perror_exit("mknodat couldn't return");
397 return result;
398}
399#endif
400
401
402
403
404#define SIGNIFY(x) {SIG##x, #x}
405
406static const struct signame signames[] = {
407
408 SIGNIFY(ABRT), SIGNIFY(ALRM), SIGNIFY(BUS),
409 SIGNIFY(FPE), SIGNIFY(HUP), SIGNIFY(ILL), SIGNIFY(INT), SIGNIFY(KILL),
410 SIGNIFY(PIPE), SIGNIFY(QUIT), SIGNIFY(SEGV), SIGNIFY(TERM),
411 SIGNIFY(USR1), SIGNIFY(USR2), SIGNIFY(SYS), SIGNIFY(TRAP),
412 SIGNIFY(VTALRM), SIGNIFY(XCPU), SIGNIFY(XFSZ),
413
414 SIGNIFY(PROF), SIGNIFY(IO),
415#ifdef __linux__
416 SIGNIFY(STKFLT), SIGNIFY(POLL), SIGNIFY(PWR),
417#elif defined(__APPLE__)
418 SIGNIFY(EMT), SIGNIFY(INFO),
419#endif
420
421
422
423
424
425 SIGNIFY(CHLD), SIGNIFY(CONT), SIGNIFY(STOP), SIGNIFY(TSTP),
426 SIGNIFY(TTIN), SIGNIFY(TTOU), SIGNIFY(URG),
427
428 SIGNIFY(WINCH),
429};
430int signames_len = ARRAY_LEN(signames);
431
432#undef SIGNIFY
433
434void xsignal_all_killers(void *handler)
435{
436 int i;
437
438 for (i=0; signames[i].num != SIGCHLD; i++)
439 if (signames[i].num != SIGKILL)
440 xsignal(signames[i].num, handler ? exit_signal : SIG_DFL);
441}
442
443
444int sig_to_num(char *sigstr)
445{
446 int i, offset;
447 char *s;
448
449
450 i = estrtol(sigstr, &s, 10);
451 if (!errno && !*s) return i;
452
453
454 strcasestart(&sigstr, "sig");
455
456
457 for (i=0; i<ARRAY_LEN(signames); i++)
458 if (!strcasecmp(sigstr, signames[i].name)) return signames[i].num;
459
460
461#ifdef SIGRTMIN
462 if (strcasestart(&sigstr, "rtmin")) i = SIGRTMIN;
463 else if (strcasestart(&sigstr, "rtmax")) i = SIGRTMAX;
464 else return -1;
465
466
467 if (!*sigstr) return i;
468
469
470
471 offset = estrtol(sigstr, &s, 10);
472 if (errno || *s) return -1;
473 i += offset;
474 if (i >= SIGRTMIN && i <= SIGRTMAX) return i;
475#endif
476
477 return -1;
478}
479
480char *num_to_sig(int sig)
481{
482 int i;
483
484
485 for (i=0; i<signames_len; i++)
486 if (signames[i].num == sig) return signames[i].name;
487
488
489#ifdef SIGRTMIN
490 if (sig == SIGRTMIN) return "RTMIN";
491 if (sig == SIGRTMAX) return "RTMAX";
492 if (sig > SIGRTMIN && sig < SIGRTMAX) {
493 if (sig-SIGRTMIN <= SIGRTMAX-sig) sprintf(libbuf, "RTMIN+%d", sig-SIGRTMIN);
494 else sprintf(libbuf, "RTMAX-%d", SIGRTMAX-sig);
495 return libbuf;
496 }
497#endif
498
499 return NULL;
500}
501