1*cf5a6c84SAndroid Build Coastguard Worker /* portability.c - code to workaround the deficiencies of various platforms.
2*cf5a6c84SAndroid Build Coastguard Worker *
3*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2012 Rob Landley <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker * Copyright 2012 Georgi Chorbadzhiyski <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker */
6*cf5a6c84SAndroid Build Coastguard Worker
7*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
8*cf5a6c84SAndroid Build Coastguard Worker
9*cf5a6c84SAndroid Build Coastguard Worker // We can't fork() on nommu systems, and vfork() requires an exec() or exit()
10*cf5a6c84SAndroid Build Coastguard Worker // before resuming the parent (because they share a heap until then). And no,
11*cf5a6c84SAndroid Build Coastguard Worker // we can't implement our own clone() call that does the equivalent of fork()
12*cf5a6c84SAndroid Build Coastguard Worker // because nommu heaps use physical addresses so if we copy the heap all our
13*cf5a6c84SAndroid Build Coastguard Worker // pointers are wrong. (You need an mmu in order to map two heaps to the same
14*cf5a6c84SAndroid Build Coastguard Worker // address range without interfering with each other.) In the absence of
15*cf5a6c84SAndroid Build Coastguard Worker // a portable way to tell malloc() to start a new heap without freeing the old
16*cf5a6c84SAndroid Build Coastguard Worker // one, you pretty much need the exec().)
17*cf5a6c84SAndroid Build Coastguard Worker
18*cf5a6c84SAndroid Build Coastguard Worker // So we exec ourselves (via /proc/self/exe, if anybody knows a way to
19*cf5a6c84SAndroid Build Coastguard Worker // re-exec self without depending on the filesystem, I'm all ears),
20*cf5a6c84SAndroid Build Coastguard Worker // and use the arguments to signal reentry.
21*cf5a6c84SAndroid Build Coastguard Worker
22*cf5a6c84SAndroid Build Coastguard Worker #if CFG_TOYBOX_FORK
xfork(void)23*cf5a6c84SAndroid Build Coastguard Worker pid_t xfork(void)
24*cf5a6c84SAndroid Build Coastguard Worker {
25*cf5a6c84SAndroid Build Coastguard Worker pid_t pid = fork();
26*cf5a6c84SAndroid Build Coastguard Worker
27*cf5a6c84SAndroid Build Coastguard Worker if (pid < 0) perror_exit("fork");
28*cf5a6c84SAndroid Build Coastguard Worker
29*cf5a6c84SAndroid Build Coastguard Worker return pid;
30*cf5a6c84SAndroid Build Coastguard Worker }
31*cf5a6c84SAndroid Build Coastguard Worker #endif
32*cf5a6c84SAndroid Build Coastguard Worker
xgetrandom(void * buf,unsigned buflen)33*cf5a6c84SAndroid Build Coastguard Worker void xgetrandom(void *buf, unsigned buflen)
34*cf5a6c84SAndroid Build Coastguard Worker {
35*cf5a6c84SAndroid Build Coastguard Worker int fd;
36*cf5a6c84SAndroid Build Coastguard Worker
37*cf5a6c84SAndroid Build Coastguard Worker // Linux keeps getrandom() in <sys/random.h> and getentropy() in <unistd.h>
38*cf5a6c84SAndroid Build Coastguard Worker // BSD/macOS only has getentropy(), but it's in <sys/random.h> (to be fair,
39*cf5a6c84SAndroid Build Coastguard Worker // they were there first). getrandom() and getentropy() both went into glibc
40*cf5a6c84SAndroid Build Coastguard Worker // in the same release (2.25 in 2017), so this test still works.
41*cf5a6c84SAndroid Build Coastguard Worker #if __has_include(<sys/random.h>)
42*cf5a6c84SAndroid Build Coastguard Worker while (buflen) {
43*cf5a6c84SAndroid Build Coastguard Worker if (getentropy(buf, fd = buflen>256 ? 256 : buflen)) break;
44*cf5a6c84SAndroid Build Coastguard Worker buflen -= fd;
45*cf5a6c84SAndroid Build Coastguard Worker buf += fd;
46*cf5a6c84SAndroid Build Coastguard Worker }
47*cf5a6c84SAndroid Build Coastguard Worker if (!buflen) return;
48*cf5a6c84SAndroid Build Coastguard Worker if (errno!=ENOSYS) perror_exit("getrandom");
49*cf5a6c84SAndroid Build Coastguard Worker #endif
50*cf5a6c84SAndroid Build Coastguard Worker xreadall(fd = xopen("/dev/urandom", O_RDONLY), buf, buflen);
51*cf5a6c84SAndroid Build Coastguard Worker close(fd);
52*cf5a6c84SAndroid Build Coastguard Worker }
53*cf5a6c84SAndroid Build Coastguard Worker
54*cf5a6c84SAndroid Build Coastguard Worker // Get list of mounted filesystems, including stat and statvfs info.
55*cf5a6c84SAndroid Build Coastguard Worker // Returns a reversed list, which is good for finding overmounts and such.
56*cf5a6c84SAndroid Build Coastguard Worker
57*cf5a6c84SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
58*cf5a6c84SAndroid Build Coastguard Worker
59*cf5a6c84SAndroid Build Coastguard Worker #include <sys/mount.h>
60*cf5a6c84SAndroid Build Coastguard Worker
xgetmountlist(char * path)61*cf5a6c84SAndroid Build Coastguard Worker struct mtab_list *xgetmountlist(char *path)
62*cf5a6c84SAndroid Build Coastguard Worker {
63*cf5a6c84SAndroid Build Coastguard Worker struct mtab_list *mtlist = 0, *mt;
64*cf5a6c84SAndroid Build Coastguard Worker struct statfs *entries;
65*cf5a6c84SAndroid Build Coastguard Worker int i, count;
66*cf5a6c84SAndroid Build Coastguard Worker
67*cf5a6c84SAndroid Build Coastguard Worker if (path) error_exit("xgetmountlist");
68*cf5a6c84SAndroid Build Coastguard Worker if (!(count = getmntinfo(&entries, MNT_WAIT))) perror_exit("getmntinfo");
69*cf5a6c84SAndroid Build Coastguard Worker
70*cf5a6c84SAndroid Build Coastguard Worker // The "test" part of the loop is done before the first time through and
71*cf5a6c84SAndroid Build Coastguard Worker // again after each "increment", so putting the actual load there avoids
72*cf5a6c84SAndroid Build Coastguard Worker // duplicating it. If the load was NULL, the loop stops.
73*cf5a6c84SAndroid Build Coastguard Worker
74*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i < count; ++i) {
75*cf5a6c84SAndroid Build Coastguard Worker struct statfs *me = &entries[i];
76*cf5a6c84SAndroid Build Coastguard Worker
77*cf5a6c84SAndroid Build Coastguard Worker mt = xzalloc(sizeof(struct mtab_list) + strlen(me->f_fstypename) +
78*cf5a6c84SAndroid Build Coastguard Worker strlen(me->f_mntonname) + strlen(me->f_mntfromname) + strlen("") + 4);
79*cf5a6c84SAndroid Build Coastguard Worker dlist_add_nomalloc((void *)&mtlist, (void *)mt);
80*cf5a6c84SAndroid Build Coastguard Worker
81*cf5a6c84SAndroid Build Coastguard Worker // Collect details about mounted filesystem.
82*cf5a6c84SAndroid Build Coastguard Worker // Don't report errors, just leave data zeroed.
83*cf5a6c84SAndroid Build Coastguard Worker stat(me->f_mntonname, &(mt->stat));
84*cf5a6c84SAndroid Build Coastguard Worker statvfs(me->f_mntonname, &(mt->statvfs));
85*cf5a6c84SAndroid Build Coastguard Worker
86*cf5a6c84SAndroid Build Coastguard Worker // Remember information from struct statfs.
87*cf5a6c84SAndroid Build Coastguard Worker mt->dir = stpcpy(mt->type, me->f_fstypename)+1;
88*cf5a6c84SAndroid Build Coastguard Worker mt->device = stpcpy(mt->dir, me->f_mntonname)+1;
89*cf5a6c84SAndroid Build Coastguard Worker mt->opts = stpcpy(mt->device, me->f_mntfromname)+1;
90*cf5a6c84SAndroid Build Coastguard Worker strcpy(mt->opts, ""); /* TODO: reverse from f_flags? */
91*cf5a6c84SAndroid Build Coastguard Worker }
92*cf5a6c84SAndroid Build Coastguard Worker
93*cf5a6c84SAndroid Build Coastguard Worker return mtlist;
94*cf5a6c84SAndroid Build Coastguard Worker }
95*cf5a6c84SAndroid Build Coastguard Worker
96*cf5a6c84SAndroid Build Coastguard Worker #else
97*cf5a6c84SAndroid Build Coastguard Worker
98*cf5a6c84SAndroid Build Coastguard Worker #include <mntent.h>
99*cf5a6c84SAndroid Build Coastguard Worker
100*cf5a6c84SAndroid Build Coastguard Worker // Check if this type matches list.
101*cf5a6c84SAndroid Build Coastguard Worker // Odd syntax: typelist all yes = if any, typelist all no = if none.
102*cf5a6c84SAndroid Build Coastguard Worker
mountlist_istype(struct mtab_list * ml,char * typelist)103*cf5a6c84SAndroid Build Coastguard Worker int mountlist_istype(struct mtab_list *ml, char *typelist)
104*cf5a6c84SAndroid Build Coastguard Worker {
105*cf5a6c84SAndroid Build Coastguard Worker int len, skip;
106*cf5a6c84SAndroid Build Coastguard Worker char *t;
107*cf5a6c84SAndroid Build Coastguard Worker
108*cf5a6c84SAndroid Build Coastguard Worker if (!typelist) return 1;
109*cf5a6c84SAndroid Build Coastguard Worker
110*cf5a6c84SAndroid Build Coastguard Worker // leading "no" indicates whether entire list is inverted
111*cf5a6c84SAndroid Build Coastguard Worker skip = strncmp(typelist, "no", 2);
112*cf5a6c84SAndroid Build Coastguard Worker
113*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
114*cf5a6c84SAndroid Build Coastguard Worker if (!(t = comma_iterate(&typelist, &len))) break;
115*cf5a6c84SAndroid Build Coastguard Worker if (!skip) {
116*cf5a6c84SAndroid Build Coastguard Worker // later "no" after first are ignored
117*cf5a6c84SAndroid Build Coastguard Worker strstart(&t, "no");
118*cf5a6c84SAndroid Build Coastguard Worker if (!strncmp(t, ml->type, len-2)) {
119*cf5a6c84SAndroid Build Coastguard Worker skip = 1;
120*cf5a6c84SAndroid Build Coastguard Worker break;
121*cf5a6c84SAndroid Build Coastguard Worker }
122*cf5a6c84SAndroid Build Coastguard Worker } else if (!strncmp(t, ml->type, len) && !ml->type[len]) {
123*cf5a6c84SAndroid Build Coastguard Worker skip = 0;
124*cf5a6c84SAndroid Build Coastguard Worker break;
125*cf5a6c84SAndroid Build Coastguard Worker }
126*cf5a6c84SAndroid Build Coastguard Worker }
127*cf5a6c84SAndroid Build Coastguard Worker
128*cf5a6c84SAndroid Build Coastguard Worker return !skip;
129*cf5a6c84SAndroid Build Coastguard Worker }
130*cf5a6c84SAndroid Build Coastguard Worker
xgetmountlist(char * path)131*cf5a6c84SAndroid Build Coastguard Worker struct mtab_list *xgetmountlist(char *path)
132*cf5a6c84SAndroid Build Coastguard Worker {
133*cf5a6c84SAndroid Build Coastguard Worker struct mtab_list *mtlist = 0, *mt;
134*cf5a6c84SAndroid Build Coastguard Worker struct mntent *me;
135*cf5a6c84SAndroid Build Coastguard Worker FILE *fp;
136*cf5a6c84SAndroid Build Coastguard Worker char *p = path ? path : "/proc/mounts";
137*cf5a6c84SAndroid Build Coastguard Worker
138*cf5a6c84SAndroid Build Coastguard Worker if (!(fp = setmntent(p, "r"))) perror_exit("bad %s", p);
139*cf5a6c84SAndroid Build Coastguard Worker
140*cf5a6c84SAndroid Build Coastguard Worker // The "test" part of the loop is done before the first time through and
141*cf5a6c84SAndroid Build Coastguard Worker // again after each "increment", so putting the actual load there avoids
142*cf5a6c84SAndroid Build Coastguard Worker // duplicating it. If the load was NULL, the loop stops.
143*cf5a6c84SAndroid Build Coastguard Worker
144*cf5a6c84SAndroid Build Coastguard Worker while ((me = getmntent(fp))) {
145*cf5a6c84SAndroid Build Coastguard Worker mt = xzalloc(sizeof(struct mtab_list) + strlen(me->mnt_fsname) +
146*cf5a6c84SAndroid Build Coastguard Worker strlen(me->mnt_dir) + strlen(me->mnt_type) + strlen(me->mnt_opts) + 4);
147*cf5a6c84SAndroid Build Coastguard Worker dlist_add_nomalloc((void *)&mtlist, (void *)mt);
148*cf5a6c84SAndroid Build Coastguard Worker
149*cf5a6c84SAndroid Build Coastguard Worker // Collect details about mounted filesystem
150*cf5a6c84SAndroid Build Coastguard Worker // Don't report errors, just leave data zeroed
151*cf5a6c84SAndroid Build Coastguard Worker if (!path) {
152*cf5a6c84SAndroid Build Coastguard Worker stat(me->mnt_dir, &(mt->stat));
153*cf5a6c84SAndroid Build Coastguard Worker statvfs(me->mnt_dir, &(mt->statvfs));
154*cf5a6c84SAndroid Build Coastguard Worker }
155*cf5a6c84SAndroid Build Coastguard Worker
156*cf5a6c84SAndroid Build Coastguard Worker // Remember information from /proc/mounts
157*cf5a6c84SAndroid Build Coastguard Worker mt->dir = stpcpy(mt->type, me->mnt_type)+1;
158*cf5a6c84SAndroid Build Coastguard Worker mt->device = stpcpy(mt->dir, me->mnt_dir)+1;
159*cf5a6c84SAndroid Build Coastguard Worker mt->opts = stpcpy(mt->device, me->mnt_fsname)+1;
160*cf5a6c84SAndroid Build Coastguard Worker strcpy(mt->opts, me->mnt_opts);
161*cf5a6c84SAndroid Build Coastguard Worker
162*cf5a6c84SAndroid Build Coastguard Worker octal_deslash(mt->dir);
163*cf5a6c84SAndroid Build Coastguard Worker octal_deslash(mt->device);
164*cf5a6c84SAndroid Build Coastguard Worker }
165*cf5a6c84SAndroid Build Coastguard Worker endmntent(fp);
166*cf5a6c84SAndroid Build Coastguard Worker
167*cf5a6c84SAndroid Build Coastguard Worker return mtlist;
168*cf5a6c84SAndroid Build Coastguard Worker }
169*cf5a6c84SAndroid Build Coastguard Worker
170*cf5a6c84SAndroid Build Coastguard Worker #endif
171*cf5a6c84SAndroid Build Coastguard Worker
172*cf5a6c84SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
173*cf5a6c84SAndroid Build Coastguard Worker
174*cf5a6c84SAndroid Build Coastguard Worker #include <sys/event.h>
175*cf5a6c84SAndroid Build Coastguard Worker
xnotify_init(int max)176*cf5a6c84SAndroid Build Coastguard Worker struct xnotify *xnotify_init(int max)
177*cf5a6c84SAndroid Build Coastguard Worker {
178*cf5a6c84SAndroid Build Coastguard Worker struct xnotify *not = xzalloc(sizeof(struct xnotify));
179*cf5a6c84SAndroid Build Coastguard Worker
180*cf5a6c84SAndroid Build Coastguard Worker not->max = max;
181*cf5a6c84SAndroid Build Coastguard Worker if ((not->kq = kqueue()) == -1) perror_exit("kqueue");
182*cf5a6c84SAndroid Build Coastguard Worker not->paths = xmalloc(max * sizeof(char *));
183*cf5a6c84SAndroid Build Coastguard Worker not->fds = xmalloc(max * sizeof(int));
184*cf5a6c84SAndroid Build Coastguard Worker
185*cf5a6c84SAndroid Build Coastguard Worker return not;
186*cf5a6c84SAndroid Build Coastguard Worker }
187*cf5a6c84SAndroid Build Coastguard Worker
xnotify_add(struct xnotify * not,int fd,char * path)188*cf5a6c84SAndroid Build Coastguard Worker int xnotify_add(struct xnotify *not, int fd, char *path)
189*cf5a6c84SAndroid Build Coastguard Worker {
190*cf5a6c84SAndroid Build Coastguard Worker struct kevent event;
191*cf5a6c84SAndroid Build Coastguard Worker
192*cf5a6c84SAndroid Build Coastguard Worker if (not->count == not->max) error_exit("xnotify_add overflow");
193*cf5a6c84SAndroid Build Coastguard Worker EV_SET(&event, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE, 0, NULL);
194*cf5a6c84SAndroid Build Coastguard Worker if (kevent(not->kq, &event, 1, NULL, 0, NULL) == -1 || event.flags & EV_ERROR)
195*cf5a6c84SAndroid Build Coastguard Worker error_exit("xnotify_add failed on %s", path);
196*cf5a6c84SAndroid Build Coastguard Worker not->paths[not->count] = path;
197*cf5a6c84SAndroid Build Coastguard Worker not->fds[not->count++] = fd;
198*cf5a6c84SAndroid Build Coastguard Worker
199*cf5a6c84SAndroid Build Coastguard Worker return 0;
200*cf5a6c84SAndroid Build Coastguard Worker }
201*cf5a6c84SAndroid Build Coastguard Worker
xnotify_wait(struct xnotify * not,char ** path)202*cf5a6c84SAndroid Build Coastguard Worker int xnotify_wait(struct xnotify *not, char **path)
203*cf5a6c84SAndroid Build Coastguard Worker {
204*cf5a6c84SAndroid Build Coastguard Worker struct kevent event;
205*cf5a6c84SAndroid Build Coastguard Worker int i;
206*cf5a6c84SAndroid Build Coastguard Worker
207*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
208*cf5a6c84SAndroid Build Coastguard Worker if (kevent(not->kq, NULL, 0, &event, 1, NULL) != -1) {
209*cf5a6c84SAndroid Build Coastguard Worker // We get the fd for free, but still have to search for the path.
210*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<not->count; i++) if (not->fds[i]==event.ident) {
211*cf5a6c84SAndroid Build Coastguard Worker *path = not->paths[i];
212*cf5a6c84SAndroid Build Coastguard Worker
213*cf5a6c84SAndroid Build Coastguard Worker return event.ident;
214*cf5a6c84SAndroid Build Coastguard Worker }
215*cf5a6c84SAndroid Build Coastguard Worker }
216*cf5a6c84SAndroid Build Coastguard Worker }
217*cf5a6c84SAndroid Build Coastguard Worker }
218*cf5a6c84SAndroid Build Coastguard Worker
219*cf5a6c84SAndroid Build Coastguard Worker #else
220*cf5a6c84SAndroid Build Coastguard Worker
221*cf5a6c84SAndroid Build Coastguard Worker #include <sys/inotify.h>
222*cf5a6c84SAndroid Build Coastguard Worker
xnotify_init(int max)223*cf5a6c84SAndroid Build Coastguard Worker struct xnotify *xnotify_init(int max)
224*cf5a6c84SAndroid Build Coastguard Worker {
225*cf5a6c84SAndroid Build Coastguard Worker struct xnotify *not = xzalloc(sizeof(struct xnotify));
226*cf5a6c84SAndroid Build Coastguard Worker
227*cf5a6c84SAndroid Build Coastguard Worker not->max = max;
228*cf5a6c84SAndroid Build Coastguard Worker if ((not->kq = inotify_init()) < 0) perror_exit("inotify_init");
229*cf5a6c84SAndroid Build Coastguard Worker not->paths = xmalloc(max * sizeof(char *));
230*cf5a6c84SAndroid Build Coastguard Worker not->fds = xmalloc(max * 2 * sizeof(int));
231*cf5a6c84SAndroid Build Coastguard Worker
232*cf5a6c84SAndroid Build Coastguard Worker return not;
233*cf5a6c84SAndroid Build Coastguard Worker }
234*cf5a6c84SAndroid Build Coastguard Worker
xnotify_add(struct xnotify * not,int fd,char * path)235*cf5a6c84SAndroid Build Coastguard Worker int xnotify_add(struct xnotify *not, int fd, char *path)
236*cf5a6c84SAndroid Build Coastguard Worker {
237*cf5a6c84SAndroid Build Coastguard Worker int i = 2*not->count;
238*cf5a6c84SAndroid Build Coastguard Worker
239*cf5a6c84SAndroid Build Coastguard Worker if (not->max == not->count) error_exit("xnotify_add overflow");
240*cf5a6c84SAndroid Build Coastguard Worker if ((not->fds[i] = inotify_add_watch(not->kq, path, IN_MODIFY))==-1)
241*cf5a6c84SAndroid Build Coastguard Worker perror_exit("xnotify_add failed on %s", path);
242*cf5a6c84SAndroid Build Coastguard Worker not->fds[i+1] = fd;
243*cf5a6c84SAndroid Build Coastguard Worker not->paths[not->count++] = path;
244*cf5a6c84SAndroid Build Coastguard Worker
245*cf5a6c84SAndroid Build Coastguard Worker return 0;
246*cf5a6c84SAndroid Build Coastguard Worker }
247*cf5a6c84SAndroid Build Coastguard Worker
xnotify_wait(struct xnotify * not,char ** path)248*cf5a6c84SAndroid Build Coastguard Worker int xnotify_wait(struct xnotify *not, char **path)
249*cf5a6c84SAndroid Build Coastguard Worker {
250*cf5a6c84SAndroid Build Coastguard Worker struct inotify_event ev;
251*cf5a6c84SAndroid Build Coastguard Worker int i;
252*cf5a6c84SAndroid Build Coastguard Worker
253*cf5a6c84SAndroid Build Coastguard Worker for (;;) {
254*cf5a6c84SAndroid Build Coastguard Worker if (sizeof(ev)!=read(not->kq, &ev, sizeof(ev))) perror_exit("inotify");
255*cf5a6c84SAndroid Build Coastguard Worker
256*cf5a6c84SAndroid Build Coastguard Worker for (i = 0; i<not->count; i++) if (ev.wd==not->fds[2*i]) {
257*cf5a6c84SAndroid Build Coastguard Worker *path = not->paths[i];
258*cf5a6c84SAndroid Build Coastguard Worker
259*cf5a6c84SAndroid Build Coastguard Worker return not->fds[2*i+1];
260*cf5a6c84SAndroid Build Coastguard Worker }
261*cf5a6c84SAndroid Build Coastguard Worker }
262*cf5a6c84SAndroid Build Coastguard Worker }
263*cf5a6c84SAndroid Build Coastguard Worker
264*cf5a6c84SAndroid Build Coastguard Worker #endif
265*cf5a6c84SAndroid Build Coastguard Worker
266*cf5a6c84SAndroid Build Coastguard Worker #ifdef __APPLE__
267*cf5a6c84SAndroid Build Coastguard Worker
xattr_get(const char * path,const char * name,void * value,size_t size)268*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_get(const char *path, const char *name, void *value, size_t size)
269*cf5a6c84SAndroid Build Coastguard Worker {
270*cf5a6c84SAndroid Build Coastguard Worker return getxattr(path, name, value, size, 0, 0);
271*cf5a6c84SAndroid Build Coastguard Worker }
272*cf5a6c84SAndroid Build Coastguard Worker
xattr_lget(const char * path,const char * name,void * value,size_t size)273*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_lget(const char *path, const char *name, void *value, size_t size)
274*cf5a6c84SAndroid Build Coastguard Worker {
275*cf5a6c84SAndroid Build Coastguard Worker return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
276*cf5a6c84SAndroid Build Coastguard Worker }
277*cf5a6c84SAndroid Build Coastguard Worker
xattr_fget(int fd,const char * name,void * value,size_t size)278*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_fget(int fd, const char *name, void *value, size_t size)
279*cf5a6c84SAndroid Build Coastguard Worker {
280*cf5a6c84SAndroid Build Coastguard Worker return fgetxattr(fd, name, value, size, 0, 0);
281*cf5a6c84SAndroid Build Coastguard Worker }
282*cf5a6c84SAndroid Build Coastguard Worker
xattr_list(const char * path,char * list,size_t size)283*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_list(const char *path, char *list, size_t size)
284*cf5a6c84SAndroid Build Coastguard Worker {
285*cf5a6c84SAndroid Build Coastguard Worker return listxattr(path, list, size, 0);
286*cf5a6c84SAndroid Build Coastguard Worker }
287*cf5a6c84SAndroid Build Coastguard Worker
xattr_llist(const char * path,char * list,size_t size)288*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_llist(const char *path, char *list, size_t size)
289*cf5a6c84SAndroid Build Coastguard Worker {
290*cf5a6c84SAndroid Build Coastguard Worker return listxattr(path, list, size, XATTR_NOFOLLOW);
291*cf5a6c84SAndroid Build Coastguard Worker }
292*cf5a6c84SAndroid Build Coastguard Worker
xattr_flist(int fd,char * list,size_t size)293*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_flist(int fd, char *list, size_t size)
294*cf5a6c84SAndroid Build Coastguard Worker {
295*cf5a6c84SAndroid Build Coastguard Worker return flistxattr(fd, list, size, 0);
296*cf5a6c84SAndroid Build Coastguard Worker }
297*cf5a6c84SAndroid Build Coastguard Worker
xattr_set(const char * path,const char * name,const void * value,size_t size,int flags)298*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_set(const char* path, const char* name,
299*cf5a6c84SAndroid Build Coastguard Worker const void* value, size_t size, int flags)
300*cf5a6c84SAndroid Build Coastguard Worker {
301*cf5a6c84SAndroid Build Coastguard Worker return setxattr(path, name, value, size, 0, flags);
302*cf5a6c84SAndroid Build Coastguard Worker }
303*cf5a6c84SAndroid Build Coastguard Worker
xattr_lset(const char * path,const char * name,const void * value,size_t size,int flags)304*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_lset(const char* path, const char* name,
305*cf5a6c84SAndroid Build Coastguard Worker const void* value, size_t size, int flags)
306*cf5a6c84SAndroid Build Coastguard Worker {
307*cf5a6c84SAndroid Build Coastguard Worker return setxattr(path, name, value, size, 0, flags | XATTR_NOFOLLOW);
308*cf5a6c84SAndroid Build Coastguard Worker }
309*cf5a6c84SAndroid Build Coastguard Worker
xattr_fset(int fd,const char * name,const void * value,size_t size,int flags)310*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_fset(int fd, const char* name,
311*cf5a6c84SAndroid Build Coastguard Worker const void* value, size_t size, int flags)
312*cf5a6c84SAndroid Build Coastguard Worker {
313*cf5a6c84SAndroid Build Coastguard Worker return fsetxattr(fd, name, value, size, 0, flags);
314*cf5a6c84SAndroid Build Coastguard Worker }
315*cf5a6c84SAndroid Build Coastguard Worker
316*cf5a6c84SAndroid Build Coastguard Worker #elif !defined(__FreeBSD__) && !defined(__OpenBSD__)
317*cf5a6c84SAndroid Build Coastguard Worker
xattr_get(const char * path,const char * name,void * value,size_t size)318*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_get(const char *path, const char *name, void *value, size_t size)
319*cf5a6c84SAndroid Build Coastguard Worker {
320*cf5a6c84SAndroid Build Coastguard Worker return getxattr(path, name, value, size);
321*cf5a6c84SAndroid Build Coastguard Worker }
322*cf5a6c84SAndroid Build Coastguard Worker
xattr_lget(const char * path,const char * name,void * value,size_t size)323*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_lget(const char *path, const char *name, void *value, size_t size)
324*cf5a6c84SAndroid Build Coastguard Worker {
325*cf5a6c84SAndroid Build Coastguard Worker return lgetxattr(path, name, value, size);
326*cf5a6c84SAndroid Build Coastguard Worker }
327*cf5a6c84SAndroid Build Coastguard Worker
xattr_fget(int fd,const char * name,void * value,size_t size)328*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_fget(int fd, const char *name, void *value, size_t size)
329*cf5a6c84SAndroid Build Coastguard Worker {
330*cf5a6c84SAndroid Build Coastguard Worker return fgetxattr(fd, name, value, size);
331*cf5a6c84SAndroid Build Coastguard Worker }
332*cf5a6c84SAndroid Build Coastguard Worker
xattr_list(const char * path,char * list,size_t size)333*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_list(const char *path, char *list, size_t size)
334*cf5a6c84SAndroid Build Coastguard Worker {
335*cf5a6c84SAndroid Build Coastguard Worker return listxattr(path, list, size);
336*cf5a6c84SAndroid Build Coastguard Worker }
337*cf5a6c84SAndroid Build Coastguard Worker
xattr_llist(const char * path,char * list,size_t size)338*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_llist(const char *path, char *list, size_t size)
339*cf5a6c84SAndroid Build Coastguard Worker {
340*cf5a6c84SAndroid Build Coastguard Worker return llistxattr(path, list, size);
341*cf5a6c84SAndroid Build Coastguard Worker }
342*cf5a6c84SAndroid Build Coastguard Worker
xattr_flist(int fd,char * list,size_t size)343*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_flist(int fd, char *list, size_t size)
344*cf5a6c84SAndroid Build Coastguard Worker {
345*cf5a6c84SAndroid Build Coastguard Worker return flistxattr(fd, list, size);
346*cf5a6c84SAndroid Build Coastguard Worker }
347*cf5a6c84SAndroid Build Coastguard Worker
xattr_set(const char * path,const char * name,const void * value,size_t size,int flags)348*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_set(const char* path, const char* name,
349*cf5a6c84SAndroid Build Coastguard Worker const void* value, size_t size, int flags)
350*cf5a6c84SAndroid Build Coastguard Worker {
351*cf5a6c84SAndroid Build Coastguard Worker return setxattr(path, name, value, size, flags);
352*cf5a6c84SAndroid Build Coastguard Worker }
353*cf5a6c84SAndroid Build Coastguard Worker
xattr_lset(const char * path,const char * name,const void * value,size_t size,int flags)354*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_lset(const char* path, const char* name,
355*cf5a6c84SAndroid Build Coastguard Worker const void* value, size_t size, int flags)
356*cf5a6c84SAndroid Build Coastguard Worker {
357*cf5a6c84SAndroid Build Coastguard Worker return lsetxattr(path, name, value, size, flags);
358*cf5a6c84SAndroid Build Coastguard Worker }
359*cf5a6c84SAndroid Build Coastguard Worker
xattr_fset(int fd,const char * name,const void * value,size_t size,int flags)360*cf5a6c84SAndroid Build Coastguard Worker ssize_t xattr_fset(int fd, const char* name,
361*cf5a6c84SAndroid Build Coastguard Worker const void* value, size_t size, int flags)
362*cf5a6c84SAndroid Build Coastguard Worker {
363*cf5a6c84SAndroid Build Coastguard Worker return fsetxattr(fd, name, value, size, flags);
364*cf5a6c84SAndroid Build Coastguard Worker }
365*cf5a6c84SAndroid Build Coastguard Worker
366*cf5a6c84SAndroid Build Coastguard Worker
367*cf5a6c84SAndroid Build Coastguard Worker #endif
368*cf5a6c84SAndroid Build Coastguard Worker
369*cf5a6c84SAndroid Build Coastguard Worker #ifdef __APPLE__
370*cf5a6c84SAndroid Build Coastguard Worker // In the absence of a mknodat system call, fchdir to dirfd and back
371*cf5a6c84SAndroid Build Coastguard Worker // around a regular mknod call...
mknodat(int dirfd,const char * path,mode_t mode,dev_t dev)372*cf5a6c84SAndroid Build Coastguard Worker int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev)
373*cf5a6c84SAndroid Build Coastguard Worker {
374*cf5a6c84SAndroid Build Coastguard Worker int old_dirfd = open(".", O_RDONLY), result;
375*cf5a6c84SAndroid Build Coastguard Worker
376*cf5a6c84SAndroid Build Coastguard Worker if (old_dirfd == -1 || fchdir(dirfd) == -1) return -1;
377*cf5a6c84SAndroid Build Coastguard Worker result = mknod(path, mode, dev);
378*cf5a6c84SAndroid Build Coastguard Worker if (fchdir(old_dirfd) == -1) perror_exit("mknodat couldn't return");
379*cf5a6c84SAndroid Build Coastguard Worker return result;
380*cf5a6c84SAndroid Build Coastguard Worker }
381*cf5a6c84SAndroid Build Coastguard Worker
382*cf5a6c84SAndroid Build Coastguard Worker // As of 10.15, macOS offers an fcntl F_PREALLOCATE rather than fallocate()
383*cf5a6c84SAndroid Build Coastguard Worker // or posix_fallocate() calls. The fcntl only (as the name implies)
384*cf5a6c84SAndroid Build Coastguard Worker // pre-allocates, so we also need to ftruncate() afterwards.
posix_fallocate(int fd,off_t offset,off_t length)385*cf5a6c84SAndroid Build Coastguard Worker int posix_fallocate(int fd, off_t offset, off_t length)
386*cf5a6c84SAndroid Build Coastguard Worker {
387*cf5a6c84SAndroid Build Coastguard Worker int e = errno, result = 0;
388*cf5a6c84SAndroid Build Coastguard Worker fstore_t f;
389*cf5a6c84SAndroid Build Coastguard Worker
390*cf5a6c84SAndroid Build Coastguard Worker f.fst_flags = F_ALLOCATEALL;
391*cf5a6c84SAndroid Build Coastguard Worker f.fst_posmode = F_PEOFPOSMODE;
392*cf5a6c84SAndroid Build Coastguard Worker f.fst_offset = 0;
393*cf5a6c84SAndroid Build Coastguard Worker f.fst_length = offset + length;
394*cf5a6c84SAndroid Build Coastguard Worker if (fcntl(fd, F_PREALLOCATE, &f) == -1) result = errno;
395*cf5a6c84SAndroid Build Coastguard Worker else if (ftruncate(fd, maxof(offset+length, fdlength(fd)))) result = errno;
396*cf5a6c84SAndroid Build Coastguard Worker errno = e;
397*cf5a6c84SAndroid Build Coastguard Worker return result;
398*cf5a6c84SAndroid Build Coastguard Worker }
399*cf5a6c84SAndroid Build Coastguard Worker #endif
400*cf5a6c84SAndroid Build Coastguard Worker
401*cf5a6c84SAndroid Build Coastguard Worker // Signals required by POSIX 2008:
402*cf5a6c84SAndroid Build Coastguard Worker // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
403*cf5a6c84SAndroid Build Coastguard Worker
404*cf5a6c84SAndroid Build Coastguard Worker #define SIGNIFY(x) {SIG##x, #x}
405*cf5a6c84SAndroid Build Coastguard Worker
406*cf5a6c84SAndroid Build Coastguard Worker static const struct signame signames[] = {
407*cf5a6c84SAndroid Build Coastguard Worker {0, "0"},
408*cf5a6c84SAndroid Build Coastguard Worker // POSIX
409*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(ABRT), SIGNIFY(ALRM), SIGNIFY(BUS),
410*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(FPE), SIGNIFY(HUP), SIGNIFY(ILL), SIGNIFY(INT), SIGNIFY(KILL),
411*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(PIPE), SIGNIFY(QUIT), SIGNIFY(SEGV), SIGNIFY(TERM),
412*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(USR1), SIGNIFY(USR2), SIGNIFY(SYS), SIGNIFY(TRAP),
413*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(VTALRM), SIGNIFY(XCPU), SIGNIFY(XFSZ),
414*cf5a6c84SAndroid Build Coastguard Worker // Non-POSIX signals that cause termination
415*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(PROF), SIGNIFY(IO),
416*cf5a6c84SAndroid Build Coastguard Worker // signals only present/absent on some targets (mips and macos)
417*cf5a6c84SAndroid Build Coastguard Worker #ifdef SIGEMT
418*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(EMT),
419*cf5a6c84SAndroid Build Coastguard Worker #endif
420*cf5a6c84SAndroid Build Coastguard Worker #ifdef SIGINFO
421*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(INFO),
422*cf5a6c84SAndroid Build Coastguard Worker #endif
423*cf5a6c84SAndroid Build Coastguard Worker #ifdef SIGPOLL
424*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(POLL),
425*cf5a6c84SAndroid Build Coastguard Worker #endif
426*cf5a6c84SAndroid Build Coastguard Worker #ifdef SIGPWR
427*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(PWR),
428*cf5a6c84SAndroid Build Coastguard Worker #endif
429*cf5a6c84SAndroid Build Coastguard Worker #ifdef SIGSTKFLT
430*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(STKFLT),
431*cf5a6c84SAndroid Build Coastguard Worker #endif
432*cf5a6c84SAndroid Build Coastguard Worker
433*cf5a6c84SAndroid Build Coastguard Worker // Note: sigatexit relies on all the signals with a default disposition that
434*cf5a6c84SAndroid Build Coastguard Worker // terminates the process coming *before* SIGCHLD.
435*cf5a6c84SAndroid Build Coastguard Worker
436*cf5a6c84SAndroid Build Coastguard Worker // POSIX signals that don't cause termination
437*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(CHLD), SIGNIFY(CONT), SIGNIFY(STOP), SIGNIFY(TSTP),
438*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(TTIN), SIGNIFY(TTOU), SIGNIFY(URG),
439*cf5a6c84SAndroid Build Coastguard Worker // Non-POSIX signals that don't cause termination
440*cf5a6c84SAndroid Build Coastguard Worker SIGNIFY(WINCH),
441*cf5a6c84SAndroid Build Coastguard Worker };
442*cf5a6c84SAndroid Build Coastguard Worker
443*cf5a6c84SAndroid Build Coastguard Worker #undef SIGNIFY
444*cf5a6c84SAndroid Build Coastguard Worker
xsignal_all_killers(void * handler)445*cf5a6c84SAndroid Build Coastguard Worker void xsignal_all_killers(void *handler)
446*cf5a6c84SAndroid Build Coastguard Worker {
447*cf5a6c84SAndroid Build Coastguard Worker int i;
448*cf5a6c84SAndroid Build Coastguard Worker
449*cf5a6c84SAndroid Build Coastguard Worker for (i = 1; signames[i].num != SIGCHLD; i++)
450*cf5a6c84SAndroid Build Coastguard Worker if (signames[i].num != SIGKILL) xsignal(signames[i].num, handler);
451*cf5a6c84SAndroid Build Coastguard Worker }
452*cf5a6c84SAndroid Build Coastguard Worker
453*cf5a6c84SAndroid Build Coastguard Worker // Convert a string like "9", "KILL", "SIGHUP", or "SIGRTMIN+2" to a number.
sig_to_num(char * sigstr)454*cf5a6c84SAndroid Build Coastguard Worker int sig_to_num(char *sigstr)
455*cf5a6c84SAndroid Build Coastguard Worker {
456*cf5a6c84SAndroid Build Coastguard Worker int i, offset;
457*cf5a6c84SAndroid Build Coastguard Worker char *s;
458*cf5a6c84SAndroid Build Coastguard Worker
459*cf5a6c84SAndroid Build Coastguard Worker // Numeric?
460*cf5a6c84SAndroid Build Coastguard Worker offset = estrtol(sigstr, &s, 10);
461*cf5a6c84SAndroid Build Coastguard Worker if (!errno && !*s) return offset;
462*cf5a6c84SAndroid Build Coastguard Worker
463*cf5a6c84SAndroid Build Coastguard Worker // Skip leading "SIG".
464*cf5a6c84SAndroid Build Coastguard Worker strcasestart(&sigstr, "sig");
465*cf5a6c84SAndroid Build Coastguard Worker
466*cf5a6c84SAndroid Build Coastguard Worker // Named signal?
467*cf5a6c84SAndroid Build Coastguard Worker for (i=0; i<ARRAY_LEN(signames); i++)
468*cf5a6c84SAndroid Build Coastguard Worker if (!strcasecmp(sigstr, signames[i].name)) return signames[i].num;
469*cf5a6c84SAndroid Build Coastguard Worker
470*cf5a6c84SAndroid Build Coastguard Worker // Real-time signal?
471*cf5a6c84SAndroid Build Coastguard Worker #ifdef SIGRTMIN
472*cf5a6c84SAndroid Build Coastguard Worker if (strcasestart(&sigstr, "rtmin")) i = SIGRTMIN;
473*cf5a6c84SAndroid Build Coastguard Worker else if (strcasestart(&sigstr, "rtmax")) i = SIGRTMAX;
474*cf5a6c84SAndroid Build Coastguard Worker else return -1;
475*cf5a6c84SAndroid Build Coastguard Worker
476*cf5a6c84SAndroid Build Coastguard Worker // No offset?
477*cf5a6c84SAndroid Build Coastguard Worker if (!*sigstr) return i;
478*cf5a6c84SAndroid Build Coastguard Worker
479*cf5a6c84SAndroid Build Coastguard Worker // We allow any offset that's still a real-time signal: SIGRTMIN+20 is fine.
480*cf5a6c84SAndroid Build Coastguard Worker // Others are more restrictive, only accepting what they show with -l.
481*cf5a6c84SAndroid Build Coastguard Worker offset = estrtol(sigstr, &s, 10);
482*cf5a6c84SAndroid Build Coastguard Worker if (errno || *s) return -1;
483*cf5a6c84SAndroid Build Coastguard Worker i += offset;
484*cf5a6c84SAndroid Build Coastguard Worker if (i >= SIGRTMIN && i <= SIGRTMAX) return i;
485*cf5a6c84SAndroid Build Coastguard Worker #endif
486*cf5a6c84SAndroid Build Coastguard Worker
487*cf5a6c84SAndroid Build Coastguard Worker return -1;
488*cf5a6c84SAndroid Build Coastguard Worker }
489*cf5a6c84SAndroid Build Coastguard Worker
num_to_sig(int sig)490*cf5a6c84SAndroid Build Coastguard Worker char *num_to_sig(int sig)
491*cf5a6c84SAndroid Build Coastguard Worker {
492*cf5a6c84SAndroid Build Coastguard Worker int i;
493*cf5a6c84SAndroid Build Coastguard Worker
494*cf5a6c84SAndroid Build Coastguard Worker // A named signal?
495*cf5a6c84SAndroid Build Coastguard Worker for (i=0; i<ARRAY_LEN(signames); i++)
496*cf5a6c84SAndroid Build Coastguard Worker if (signames[i].num == sig) return signames[i].name;
497*cf5a6c84SAndroid Build Coastguard Worker
498*cf5a6c84SAndroid Build Coastguard Worker // A real-time signal?
499*cf5a6c84SAndroid Build Coastguard Worker #ifdef SIGRTMIN
500*cf5a6c84SAndroid Build Coastguard Worker if (sig == SIGRTMIN) return "RTMIN";
501*cf5a6c84SAndroid Build Coastguard Worker if (sig == SIGRTMAX) return "RTMAX";
502*cf5a6c84SAndroid Build Coastguard Worker if (sig > SIGRTMIN && sig < SIGRTMAX) {
503*cf5a6c84SAndroid Build Coastguard Worker if (sig-SIGRTMIN <= SIGRTMAX-sig) sprintf(libbuf, "RTMIN+%d", sig-SIGRTMIN);
504*cf5a6c84SAndroid Build Coastguard Worker else sprintf(libbuf, "RTMAX-%d", SIGRTMAX-sig);
505*cf5a6c84SAndroid Build Coastguard Worker return libbuf;
506*cf5a6c84SAndroid Build Coastguard Worker }
507*cf5a6c84SAndroid Build Coastguard Worker #endif
508*cf5a6c84SAndroid Build Coastguard Worker
509*cf5a6c84SAndroid Build Coastguard Worker return NULL;
510*cf5a6c84SAndroid Build Coastguard Worker }
511*cf5a6c84SAndroid Build Coastguard Worker
dev_minor(int dev)512*cf5a6c84SAndroid Build Coastguard Worker int dev_minor(int dev)
513*cf5a6c84SAndroid Build Coastguard Worker {
514*cf5a6c84SAndroid Build Coastguard Worker #if defined(__linux__)
515*cf5a6c84SAndroid Build Coastguard Worker return ((dev&0xfff00000)>>12)|(dev&0xff);
516*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__APPLE__)
517*cf5a6c84SAndroid Build Coastguard Worker return dev&0xffffff;
518*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__FreeBSD__) || defined(__OpenBSD__)
519*cf5a6c84SAndroid Build Coastguard Worker return minor(dev);
520*cf5a6c84SAndroid Build Coastguard Worker #else
521*cf5a6c84SAndroid Build Coastguard Worker #error
522*cf5a6c84SAndroid Build Coastguard Worker #endif
523*cf5a6c84SAndroid Build Coastguard Worker }
524*cf5a6c84SAndroid Build Coastguard Worker
dev_major(int dev)525*cf5a6c84SAndroid Build Coastguard Worker int dev_major(int dev)
526*cf5a6c84SAndroid Build Coastguard Worker {
527*cf5a6c84SAndroid Build Coastguard Worker #if defined(__linux__)
528*cf5a6c84SAndroid Build Coastguard Worker return (dev&0xfff00)>>8;
529*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__APPLE__)
530*cf5a6c84SAndroid Build Coastguard Worker return (dev>>24)&0xff;
531*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__FreeBSD__) || defined(__OpenBSD__)
532*cf5a6c84SAndroid Build Coastguard Worker return major(dev);
533*cf5a6c84SAndroid Build Coastguard Worker #else
534*cf5a6c84SAndroid Build Coastguard Worker #error
535*cf5a6c84SAndroid Build Coastguard Worker #endif
536*cf5a6c84SAndroid Build Coastguard Worker }
537*cf5a6c84SAndroid Build Coastguard Worker
dev_makedev(int major,int minor)538*cf5a6c84SAndroid Build Coastguard Worker int dev_makedev(int major, int minor)
539*cf5a6c84SAndroid Build Coastguard Worker {
540*cf5a6c84SAndroid Build Coastguard Worker #if defined(__linux__)
541*cf5a6c84SAndroid Build Coastguard Worker return (minor&0xff)|((major&0xfff)<<8)|((minor&0xfff00)<<12);
542*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__APPLE__)
543*cf5a6c84SAndroid Build Coastguard Worker return (minor&0xffffff)|((major&0xff)<<24);
544*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__FreeBSD__) || defined(__OpenBSD__)
545*cf5a6c84SAndroid Build Coastguard Worker return makedev(major, minor);
546*cf5a6c84SAndroid Build Coastguard Worker #else
547*cf5a6c84SAndroid Build Coastguard Worker #error
548*cf5a6c84SAndroid Build Coastguard Worker #endif
549*cf5a6c84SAndroid Build Coastguard Worker }
550*cf5a6c84SAndroid Build Coastguard Worker
fs_type_name(struct statfs * statfs)551*cf5a6c84SAndroid Build Coastguard Worker char *fs_type_name(struct statfs *statfs)
552*cf5a6c84SAndroid Build Coastguard Worker {
553*cf5a6c84SAndroid Build Coastguard Worker #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
554*cf5a6c84SAndroid Build Coastguard Worker // macOS has an `f_type` field, but assigns values dynamically as filesystems
555*cf5a6c84SAndroid Build Coastguard Worker // are registered. They do give you the name directly though, so use that.
556*cf5a6c84SAndroid Build Coastguard Worker return statfs->f_fstypename;
557*cf5a6c84SAndroid Build Coastguard Worker #else
558*cf5a6c84SAndroid Build Coastguard Worker char *s = NULL;
559*cf5a6c84SAndroid Build Coastguard Worker struct {unsigned num; char *name;} nn[] = {
560*cf5a6c84SAndroid Build Coastguard Worker {0xADF5, "adfs"}, {0xADFF, "affs"}, {0x5346414F, "afs"}, {0x187, "autofs"},
561*cf5a6c84SAndroid Build Coastguard Worker {0x1BADFACE, "bfs"}, {0x6C6F6F70, "binder"}, {0x9123683E, "btrfs"},
562*cf5a6c84SAndroid Build Coastguard Worker {0xFF534D42, "cifs"}, {0x27E0EB, "cgroup"}, {0x63677270, "cgroup2"},
563*cf5a6c84SAndroid Build Coastguard Worker {0x73757245, "coda"}, {0x28cd3d45, "cramfs"}, {0x1CD1, "devpts"},
564*cf5a6c84SAndroid Build Coastguard Worker {0xF15F, "ecryptfs"}, {0x414A53, "efs"}, {0xE0F5E1E2, "erofs"},
565*cf5a6c84SAndroid Build Coastguard Worker {0x2011BAB0, "exfat"}, {0x137D, "ext"}, {0xEF51, "ext2"},
566*cf5a6c84SAndroid Build Coastguard Worker {0xEF53, "ext3/4"}, {0xF2F52010, "f2fs"}, {0xBAD1DEA, "futexfs"},
567*cf5a6c84SAndroid Build Coastguard Worker {0x00C0FFEE, "hostfs"}, {0xF995E849, "hpfs"},
568*cf5a6c84SAndroid Build Coastguard Worker {0x9660, "isofs"}, {0x72B6, "jffs2"}, {0x3153464a, "jfs"},
569*cf5a6c84SAndroid Build Coastguard Worker {0x137F, "minix"}, {0x2468, "minix2"}, {0x4D5A, "minix3"},
570*cf5a6c84SAndroid Build Coastguard Worker {0x4D44, "vfat"}, {0x6969, "nfs"}, {0x3434, "nilfs2"},
571*cf5a6c84SAndroid Build Coastguard Worker {0x5346544E, "ntfs"}, {0x7461636F, "ocfs2"}, {0x9FA1, "openpromfs"},
572*cf5a6c84SAndroid Build Coastguard Worker {0x794C7630, "overlay"}, {0x9FA0, "proc"}, {0x002f, "qnx4"},
573*cf5a6c84SAndroid Build Coastguard Worker {0x68191122, "qnx6"}, {0x7275, "romfs"}, {0x7655821, "resctrl"},
574*cf5a6c84SAndroid Build Coastguard Worker {0x534F434B, "sockfs"}, {0x62656572, "sysfs"}, {0x517B, "smb"},
575*cf5a6c84SAndroid Build Coastguard Worker {0x01021994, "tmpfs"}, {0x15013346, "udf"}, {0x43415d53, "smackfs"},
576*cf5a6c84SAndroid Build Coastguard Worker {0x73717368, "squashfs"}, {0xabba1974, "xenfs"}, {0x58465342, "xfs"}
577*cf5a6c84SAndroid Build Coastguard Worker };
578*cf5a6c84SAndroid Build Coastguard Worker int i;
579*cf5a6c84SAndroid Build Coastguard Worker
580*cf5a6c84SAndroid Build Coastguard Worker for (i=0; i<ARRAY_LEN(nn); i++)
581*cf5a6c84SAndroid Build Coastguard Worker if (nn[i].num == statfs->f_type) s = nn[i].name;
582*cf5a6c84SAndroid Build Coastguard Worker if (!s) sprintf(s = libbuf, "0x%x", (unsigned)statfs->f_type);
583*cf5a6c84SAndroid Build Coastguard Worker return s;
584*cf5a6c84SAndroid Build Coastguard Worker #endif
585*cf5a6c84SAndroid Build Coastguard Worker }
586*cf5a6c84SAndroid Build Coastguard Worker
587*cf5a6c84SAndroid Build Coastguard Worker #if defined(__APPLE__)
588*cf5a6c84SAndroid Build Coastguard Worker #include <sys/disk.h>
get_block_device_size(int fd,unsigned long long * size)589*cf5a6c84SAndroid Build Coastguard Worker int get_block_device_size(int fd, unsigned long long* size)
590*cf5a6c84SAndroid Build Coastguard Worker {
591*cf5a6c84SAndroid Build Coastguard Worker unsigned long block_size, block_count;
592*cf5a6c84SAndroid Build Coastguard Worker
593*cf5a6c84SAndroid Build Coastguard Worker if (!ioctl(fd, DKIOCGETBLOCKSIZE, &block_size) &&
594*cf5a6c84SAndroid Build Coastguard Worker !ioctl(fd, DKIOCGETBLOCKCOUNT, &block_count)) {
595*cf5a6c84SAndroid Build Coastguard Worker *size = block_count * block_size;
596*cf5a6c84SAndroid Build Coastguard Worker return 1;
597*cf5a6c84SAndroid Build Coastguard Worker }
598*cf5a6c84SAndroid Build Coastguard Worker return 0;
599*cf5a6c84SAndroid Build Coastguard Worker }
600*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__linux__)
get_block_device_size(int fd,unsigned long long * size)601*cf5a6c84SAndroid Build Coastguard Worker int get_block_device_size(int fd, unsigned long long* size)
602*cf5a6c84SAndroid Build Coastguard Worker {
603*cf5a6c84SAndroid Build Coastguard Worker return (ioctl(fd, BLKGETSIZE64, size) >= 0);
604*cf5a6c84SAndroid Build Coastguard Worker }
605*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__OpenBSD__)
606*cf5a6c84SAndroid Build Coastguard Worker #include <sys/dkio.h>
607*cf5a6c84SAndroid Build Coastguard Worker #include <sys/disklabel.h>
get_block_device_size(int fd,unsigned long long * size)608*cf5a6c84SAndroid Build Coastguard Worker int get_block_device_size(int fd, unsigned long long* size)
609*cf5a6c84SAndroid Build Coastguard Worker {
610*cf5a6c84SAndroid Build Coastguard Worker struct disklabel lab;
611*cf5a6c84SAndroid Build Coastguard Worker int status = (ioctl(fd, DIOCGDINFO, &lab) >= 0);
612*cf5a6c84SAndroid Build Coastguard Worker *size = lab.d_secsize * lab.d_nsectors;
613*cf5a6c84SAndroid Build Coastguard Worker return status;
614*cf5a6c84SAndroid Build Coastguard Worker }
615*cf5a6c84SAndroid Build Coastguard Worker #else
get_block_device_size(int fd,unsigned long long * size)616*cf5a6c84SAndroid Build Coastguard Worker int get_block_device_size(int fd, unsigned long long* size)
617*cf5a6c84SAndroid Build Coastguard Worker {
618*cf5a6c84SAndroid Build Coastguard Worker return 0;
619*cf5a6c84SAndroid Build Coastguard Worker }
620*cf5a6c84SAndroid Build Coastguard Worker #endif
621*cf5a6c84SAndroid Build Coastguard Worker
622*cf5a6c84SAndroid Build Coastguard Worker #if defined(__ANDROID__)
android_api_level(void)623*cf5a6c84SAndroid Build Coastguard Worker static int android_api_level(void)
624*cf5a6c84SAndroid Build Coastguard Worker {
625*cf5a6c84SAndroid Build Coastguard Worker // Cached so we don't do a system property lookup on every call.
626*cf5a6c84SAndroid Build Coastguard Worker static int api_level;
627*cf5a6c84SAndroid Build Coastguard Worker
628*cf5a6c84SAndroid Build Coastguard Worker if (!api_level) api_level = android_get_device_api_level();
629*cf5a6c84SAndroid Build Coastguard Worker return api_level;
630*cf5a6c84SAndroid Build Coastguard Worker }
631*cf5a6c84SAndroid Build Coastguard Worker #endif
632*cf5a6c84SAndroid Build Coastguard Worker
check_copy_file_range(void)633*cf5a6c84SAndroid Build Coastguard Worker static int check_copy_file_range(void)
634*cf5a6c84SAndroid Build Coastguard Worker {
635*cf5a6c84SAndroid Build Coastguard Worker #if defined(__ANDROID__)
636*cf5a6c84SAndroid Build Coastguard Worker // Android's had the constant for years, but seccomp means you'll get
637*cf5a6c84SAndroid Build Coastguard Worker // SIGSYS if you try the system call before 2023's Android U.
638*cf5a6c84SAndroid Build Coastguard Worker return (android_api_level() >= __ANDROID_API_U__) ? __NR_copy_file_range : 0;
639*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__NR_copy_file_range)
640*cf5a6c84SAndroid Build Coastguard Worker // glibc added this constant in git at the end of 2017, shipped 2018-02.
641*cf5a6c84SAndroid Build Coastguard Worker return __NR_copy_file_range;
642*cf5a6c84SAndroid Build Coastguard Worker #else
643*cf5a6c84SAndroid Build Coastguard Worker return 0;
644*cf5a6c84SAndroid Build Coastguard Worker #endif
645*cf5a6c84SAndroid Build Coastguard Worker }
646*cf5a6c84SAndroid Build Coastguard Worker
647*cf5a6c84SAndroid Build Coastguard Worker // Return bytes copied from in to out. If bytes <0 copy all of in to out.
648*cf5a6c84SAndroid Build Coastguard Worker // If consumed isn't null, amount read saved there (return is written or error)
sendfile_len(int in,int out,long long bytes,long long * consumed)649*cf5a6c84SAndroid Build Coastguard Worker long long sendfile_len(int in, int out, long long bytes, long long *consumed)
650*cf5a6c84SAndroid Build Coastguard Worker {
651*cf5a6c84SAndroid Build Coastguard Worker long long total = 0, len, ww;
652*cf5a6c84SAndroid Build Coastguard Worker int try_cfr = check_copy_file_range();
653*cf5a6c84SAndroid Build Coastguard Worker
654*cf5a6c84SAndroid Build Coastguard Worker if (consumed) *consumed = 0;
655*cf5a6c84SAndroid Build Coastguard Worker if (in>=0) while (bytes != total) {
656*cf5a6c84SAndroid Build Coastguard Worker ww = 0;
657*cf5a6c84SAndroid Build Coastguard Worker len = bytes-total;
658*cf5a6c84SAndroid Build Coastguard Worker
659*cf5a6c84SAndroid Build Coastguard Worker errno = 0;
660*cf5a6c84SAndroid Build Coastguard Worker if (try_cfr) {
661*cf5a6c84SAndroid Build Coastguard Worker if (bytes<0 || len>(1<<30)) len = (1<<30);
662*cf5a6c84SAndroid Build Coastguard Worker len = syscall(try_cfr, in, 0, out, 0, len, 0);
663*cf5a6c84SAndroid Build Coastguard Worker if (len < 0) {
664*cf5a6c84SAndroid Build Coastguard Worker try_cfr = 0;
665*cf5a6c84SAndroid Build Coastguard Worker
666*cf5a6c84SAndroid Build Coastguard Worker continue;
667*cf5a6c84SAndroid Build Coastguard Worker }
668*cf5a6c84SAndroid Build Coastguard Worker } else {
669*cf5a6c84SAndroid Build Coastguard Worker if (bytes<0 || len>sizeof(libbuf)) len = sizeof(libbuf);
670*cf5a6c84SAndroid Build Coastguard Worker ww = len = read(in, libbuf, len);
671*cf5a6c84SAndroid Build Coastguard Worker }
672*cf5a6c84SAndroid Build Coastguard Worker if (len<1 && errno==EAGAIN) continue;
673*cf5a6c84SAndroid Build Coastguard Worker if (len<1) break;
674*cf5a6c84SAndroid Build Coastguard Worker if (consumed) *consumed += len;
675*cf5a6c84SAndroid Build Coastguard Worker if (ww && writeall(out, libbuf, len) != len) return -1;
676*cf5a6c84SAndroid Build Coastguard Worker total += len;
677*cf5a6c84SAndroid Build Coastguard Worker }
678*cf5a6c84SAndroid Build Coastguard Worker
679*cf5a6c84SAndroid Build Coastguard Worker return total;
680*cf5a6c84SAndroid Build Coastguard Worker }
681*cf5a6c84SAndroid Build Coastguard Worker
682*cf5a6c84SAndroid Build Coastguard Worker #ifdef __APPLE__
683*cf5a6c84SAndroid Build Coastguard Worker // The absolute minimum POSIX timer implementation to build timeout(1).
684*cf5a6c84SAndroid Build Coastguard Worker // Note that although timeout(1) uses POSIX timers to get the monotonic clock,
685*cf5a6c84SAndroid Build Coastguard Worker // that doesn't seem to be an option on macOS (without using other libraries),
686*cf5a6c84SAndroid Build Coastguard Worker // so we just mangle that back into a regular setitimer(ITIMER_REAL) call.
timer_create(clock_t c,struct sigevent * se,timer_t * t)687*cf5a6c84SAndroid Build Coastguard Worker int timer_create(clock_t c, struct sigevent *se, timer_t *t)
688*cf5a6c84SAndroid Build Coastguard Worker {
689*cf5a6c84SAndroid Build Coastguard Worker if (se->sigev_notify != SIGEV_SIGNAL || se->sigev_signo != SIGALRM)
690*cf5a6c84SAndroid Build Coastguard Worker error_exit("unimplemented");
691*cf5a6c84SAndroid Build Coastguard Worker *t = 1;
692*cf5a6c84SAndroid Build Coastguard Worker return 0;
693*cf5a6c84SAndroid Build Coastguard Worker }
694*cf5a6c84SAndroid Build Coastguard Worker
timer_settime(timer_t t,int flags,struct itimerspec * new,void * old)695*cf5a6c84SAndroid Build Coastguard Worker int timer_settime(timer_t t, int flags, struct itimerspec *new, void *old)
696*cf5a6c84SAndroid Build Coastguard Worker {
697*cf5a6c84SAndroid Build Coastguard Worker struct itimerval mangled;
698*cf5a6c84SAndroid Build Coastguard Worker
699*cf5a6c84SAndroid Build Coastguard Worker if (flags != 0 || old != 0) error_exit("unimplemented");
700*cf5a6c84SAndroid Build Coastguard Worker memset(&mangled, 0, sizeof(mangled));
701*cf5a6c84SAndroid Build Coastguard Worker mangled.it_value.tv_sec = new->it_value.tv_sec;
702*cf5a6c84SAndroid Build Coastguard Worker mangled.it_value.tv_usec = new->it_value.tv_nsec / 1000;
703*cf5a6c84SAndroid Build Coastguard Worker return setitimer(ITIMER_REAL, &mangled, NULL);
704*cf5a6c84SAndroid Build Coastguard Worker }
705*cf5a6c84SAndroid Build Coastguard Worker // glibc requires -lrt for linux syscalls, which pulls in libgcc_eh.a for
706*cf5a6c84SAndroid Build Coastguard Worker // static linking, and gcc 9.3 leaks pthread calls from that breaking the build
707*cf5a6c84SAndroid Build Coastguard Worker // These are both just linux syscalls: wrap them ourselves
708*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__GLIBC__)
timer_create_wrap(clockid_t c,struct sigevent * se,timer_t * t)709*cf5a6c84SAndroid Build Coastguard Worker int timer_create_wrap(clockid_t c, struct sigevent *se, timer_t *t)
710*cf5a6c84SAndroid Build Coastguard Worker {
711*cf5a6c84SAndroid Build Coastguard Worker // convert overengineered structure to what kernel actually uses
712*cf5a6c84SAndroid Build Coastguard Worker struct ksigevent { void *sv; int signo, notify, tid; } kk = {
713*cf5a6c84SAndroid Build Coastguard Worker 0, se->sigev_signo, se->sigev_notify, 0
714*cf5a6c84SAndroid Build Coastguard Worker };
715*cf5a6c84SAndroid Build Coastguard Worker int timer;
716*cf5a6c84SAndroid Build Coastguard Worker
717*cf5a6c84SAndroid Build Coastguard Worker if (syscall(SYS_timer_create, c, &kk, &timer)<0) return -1;
718*cf5a6c84SAndroid Build Coastguard Worker *t = (timer_t)(long)timer;
719*cf5a6c84SAndroid Build Coastguard Worker
720*cf5a6c84SAndroid Build Coastguard Worker return 0;
721*cf5a6c84SAndroid Build Coastguard Worker }
722*cf5a6c84SAndroid Build Coastguard Worker
723*cf5a6c84SAndroid Build Coastguard Worker #if !defined(SYS_timer_settime) && defined(SYS_timer_settime64)
724*cf5a6c84SAndroid Build Coastguard Worker // glibc does not define defines SYS_timer_settime on 32-bit systems
725*cf5a6c84SAndroid Build Coastguard Worker // with 64-bit time_t defaults e.g. riscv32
726*cf5a6c84SAndroid Build Coastguard Worker #define SYS_timer_settime SYS_timer_settime64
727*cf5a6c84SAndroid Build Coastguard Worker #endif
728*cf5a6c84SAndroid Build Coastguard Worker
timer_settime_wrap(timer_t t,int flags,struct itimerspec * val,struct itimerspec * old)729*cf5a6c84SAndroid Build Coastguard Worker int timer_settime_wrap(timer_t t, int flags, struct itimerspec *val,
730*cf5a6c84SAndroid Build Coastguard Worker struct itimerspec *old)
731*cf5a6c84SAndroid Build Coastguard Worker {
732*cf5a6c84SAndroid Build Coastguard Worker return syscall(SYS_timer_settime, t, flags, val, old);
733*cf5a6c84SAndroid Build Coastguard Worker }
734*cf5a6c84SAndroid Build Coastguard Worker #endif
735*cf5a6c84SAndroid Build Coastguard Worker
736*cf5a6c84SAndroid Build Coastguard Worker // Atomically swap two files
rename_exchange(char * file1,char * file2)737*cf5a6c84SAndroid Build Coastguard Worker int rename_exchange(char *file1, char *file2)
738*cf5a6c84SAndroid Build Coastguard Worker {
739*cf5a6c84SAndroid Build Coastguard Worker #if defined(__linux__)
740*cf5a6c84SAndroid Build Coastguard Worker // 2 is RENAME_EXCHANGE
741*cf5a6c84SAndroid Build Coastguard Worker return syscall(SYS_renameat2, AT_FDCWD, file1, AT_FDCWD, file2, 2);
742*cf5a6c84SAndroid Build Coastguard Worker #else
743*cf5a6c84SAndroid Build Coastguard Worker return ENOSYS;
744*cf5a6c84SAndroid Build Coastguard Worker #endif
745*cf5a6c84SAndroid Build Coastguard Worker }
746