portability.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. /* portability.c - code to workaround the deficiencies of various platforms.
  2. *
  3. * Copyright 2012 Rob Landley <rob@landley.net>
  4. * Copyright 2012 Georgi Chorbadzhiyski <gf@unixsol.org>
  5. */
  6. #include "toys.h"
  7. // We can't fork() on nommu systems, and vfork() requires an exec() or exit()
  8. // before resuming the parent (because they share a heap until then). And no,
  9. // we can't implement our own clone() call that does the equivalent of fork()
  10. // because nommu heaps use physical addresses so if we copy the heap all our
  11. // pointers are wrong. (You need an mmu in order to map two heaps to the same
  12. // address range without interfering with each other.) In the absence of
  13. // a portable way to tell malloc() to start a new heap without freeing the old
  14. // one, you pretty much need the exec().)
  15. // So we exec ourselves (via /proc/self/exe, if anybody knows a way to
  16. // re-exec self without depending on the filesystem, I'm all ears),
  17. // and use the arguments to signal reentry.
  18. #if CFG_TOYBOX_FORK
  19. pid_t xfork(void)
  20. {
  21. pid_t pid = fork();
  22. if (pid < 0) perror_exit("fork");
  23. return pid;
  24. }
  25. #endif
  26. int xgetrandom(void *buf, unsigned buflen, unsigned flags)
  27. {
  28. int fd;
  29. #if CFG_TOYBOX_GETRANDOM
  30. if (buflen == getrandom(buf, buflen, flags&~WARN_ONLY)) return 1;
  31. if (errno!=ENOSYS && !(flags&WARN_ONLY)) perror_exit("getrandom");
  32. #endif
  33. fd = xopen(flags ? "/dev/random" : "/dev/urandom",O_RDONLY|(flags&WARN_ONLY));
  34. if (fd == -1) return 0;
  35. xreadall(fd, buf, buflen);
  36. close(fd);
  37. return 1;
  38. }
  39. // Get list of mounted filesystems, including stat and statvfs info.
  40. // Returns a reversed list, which is good for finding overmounts and such.
  41. #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
  42. #include <sys/mount.h>
  43. struct mtab_list *xgetmountlist(char *path)
  44. {
  45. struct mtab_list *mtlist = 0, *mt;
  46. struct statfs *entries;
  47. int i, count;
  48. if (path) error_exit("xgetmountlist");
  49. if ((count = getmntinfo(&entries, 0)) == 0) perror_exit("getmntinfo");
  50. // The "test" part of the loop is done before the first time through and
  51. // again after each "increment", so putting the actual load there avoids
  52. // duplicating it. If the load was NULL, the loop stops.
  53. for (i = 0; i < count; ++i) {
  54. struct statfs *me = &entries[i];
  55. mt = xzalloc(sizeof(struct mtab_list) + strlen(me->f_fstypename) +
  56. strlen(me->f_mntonname) + strlen(me->f_mntfromname) + strlen("") + 4);
  57. dlist_add_nomalloc((void *)&mtlist, (void *)mt);
  58. // Collect details about mounted filesystem.
  59. // Don't report errors, just leave data zeroed.
  60. stat(me->f_mntonname, &(mt->stat));
  61. statvfs(me->f_mntonname, &(mt->statvfs));
  62. // Remember information from struct statfs.
  63. mt->dir = stpcpy(mt->type, me->f_fstypename)+1;
  64. mt->device = stpcpy(mt->dir, me->f_mntonname)+1;
  65. mt->opts = stpcpy(mt->device, me->f_mntfromname)+1;
  66. strcpy(mt->opts, ""); /* TODO: reverse from f_flags? */
  67. }
  68. return mtlist;
  69. }
  70. #else
  71. #include <mntent.h>
  72. static void octal_deslash(char *s)
  73. {
  74. char *o = s;
  75. while (*s) {
  76. if (*s == '\\') {
  77. int i, oct = 0;
  78. for (i = 1; i < 4; i++) {
  79. if (!isdigit(s[i])) break;
  80. oct = (oct<<3)+s[i]-'0';
  81. }
  82. if (i == 4) {
  83. *o++ = oct;
  84. s += i;
  85. continue;
  86. }
  87. }
  88. *o++ = *s++;
  89. }
  90. *o = 0;
  91. }
  92. // Check if this type matches list.
  93. // Odd syntax: typelist all yes = if any, typelist all no = if none.
  94. int mountlist_istype(struct mtab_list *ml, char *typelist)
  95. {
  96. int len, skip;
  97. char *t;
  98. if (!typelist) return 1;
  99. // leading "no" indicates whether entire list is inverted
  100. skip = strncmp(typelist, "no", 2);
  101. for (;;) {
  102. if (!(t = comma_iterate(&typelist, &len))) break;
  103. if (!skip) {
  104. // later "no" after first are ignored
  105. strstart(&t, "no");
  106. if (!strncmp(t, ml->type, len-2)) {
  107. skip = 1;
  108. break;
  109. }
  110. } else if (!strncmp(t, ml->type, len) && !ml->type[len]) {
  111. skip = 0;
  112. break;
  113. }
  114. }
  115. return !skip;
  116. }
  117. struct mtab_list *xgetmountlist(char *path)
  118. {
  119. struct mtab_list *mtlist = 0, *mt;
  120. struct mntent *me;
  121. FILE *fp;
  122. char *p = path ? path : "/proc/mounts";
  123. if (!(fp = setmntent(p, "r"))) perror_exit("bad %s", p);
  124. // The "test" part of the loop is done before the first time through and
  125. // again after each "increment", so putting the actual load there avoids
  126. // duplicating it. If the load was NULL, the loop stops.
  127. while ((me = getmntent(fp))) {
  128. mt = xzalloc(sizeof(struct mtab_list) + strlen(me->mnt_fsname) +
  129. strlen(me->mnt_dir) + strlen(me->mnt_type) + strlen(me->mnt_opts) + 4);
  130. dlist_add_nomalloc((void *)&mtlist, (void *)mt);
  131. // Collect details about mounted filesystem
  132. // Don't report errors, just leave data zeroed
  133. if (!path) {
  134. stat(me->mnt_dir, &(mt->stat));
  135. statvfs(me->mnt_dir, &(mt->statvfs));
  136. }
  137. // Remember information from /proc/mounts
  138. mt->dir = stpcpy(mt->type, me->mnt_type)+1;
  139. mt->device = stpcpy(mt->dir, me->mnt_dir)+1;
  140. mt->opts = stpcpy(mt->device, me->mnt_fsname)+1;
  141. strcpy(mt->opts, me->mnt_opts);
  142. octal_deslash(mt->dir);
  143. octal_deslash(mt->device);
  144. }
  145. endmntent(fp);
  146. return mtlist;
  147. }
  148. #endif
  149. #if defined(__APPLE__) || defined(__OpenBSD__)
  150. #include <sys/event.h>
  151. struct xnotify *xnotify_init(int max)
  152. {
  153. struct xnotify *not = xzalloc(sizeof(struct xnotify));
  154. not->max = max;
  155. if ((not->kq = kqueue()) == -1) perror_exit("kqueue");
  156. not->paths = xmalloc(max * sizeof(char *));
  157. not->fds = xmalloc(max * sizeof(int));
  158. return not;
  159. }
  160. int xnotify_add(struct xnotify *not, int fd, char *path)
  161. {
  162. struct kevent event;
  163. if (not->count == not->max) error_exit("xnotify_add overflow");
  164. EV_SET(&event, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE, 0, NULL);
  165. if (kevent(not->kq, &event, 1, NULL, 0, NULL) == -1 || event.flags & EV_ERROR)
  166. error_exit("xnotify_add failed on %s", path);
  167. not->paths[not->count] = path;
  168. not->fds[not->count++] = fd;
  169. return 0;
  170. }
  171. int xnotify_wait(struct xnotify *not, char **path)
  172. {
  173. struct kevent event;
  174. int i;
  175. for (;;) {
  176. if (kevent(not->kq, NULL, 0, &event, 1, NULL) != -1) {
  177. // We get the fd for free, but still have to search for the path.
  178. for (i = 0; i<not->count; i++) if (not->fds[i]==event.ident) {
  179. *path = not->paths[i];
  180. return event.ident;
  181. }
  182. }
  183. }
  184. }
  185. #else
  186. #include <sys/inotify.h>
  187. struct xnotify *xnotify_init(int max)
  188. {
  189. struct xnotify *not = xzalloc(sizeof(struct xnotify));
  190. not->max = max;
  191. if ((not->kq = inotify_init()) < 0) perror_exit("inotify_init");
  192. not->paths = xmalloc(max * sizeof(char *));
  193. not->fds = xmalloc(max * 2 * sizeof(int));
  194. return not;
  195. }
  196. int xnotify_add(struct xnotify *not, int fd, char *path)
  197. {
  198. int i = 2*not->count;
  199. if (not->max == not->count) error_exit("xnotify_add overflow");
  200. if ((not->fds[i] = inotify_add_watch(not->kq, path, IN_MODIFY))==-1)
  201. perror_exit("xnotify_add failed on %s", path);
  202. not->fds[i+1] = fd;
  203. not->paths[not->count++] = path;
  204. return 0;
  205. }
  206. int xnotify_wait(struct xnotify *not, char **path)
  207. {
  208. struct inotify_event ev;
  209. int i;
  210. for (;;) {
  211. if (sizeof(ev)!=read(not->kq, &ev, sizeof(ev))) perror_exit("inotify");
  212. for (i = 0; i<not->count; i++) if (ev.wd==not->fds[2*i]) {
  213. *path = not->paths[i];
  214. return not->fds[2*i+1];
  215. }
  216. }
  217. }
  218. #endif
  219. #ifdef __APPLE__
  220. ssize_t xattr_get(const char *path, const char *name, void *value, size_t size)
  221. {
  222. return getxattr(path, name, value, size, 0, 0);
  223. }
  224. ssize_t xattr_lget(const char *path, const char *name, void *value, size_t size)
  225. {
  226. return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
  227. }
  228. ssize_t xattr_fget(int fd, const char *name, void *value, size_t size)
  229. {
  230. return fgetxattr(fd, name, value, size, 0, 0);
  231. }
  232. ssize_t xattr_list(const char *path, char *list, size_t size)
  233. {
  234. return listxattr(path, list, size, 0);
  235. }
  236. ssize_t xattr_llist(const char *path, char *list, size_t size)
  237. {
  238. return listxattr(path, list, size, XATTR_NOFOLLOW);
  239. }
  240. ssize_t xattr_flist(int fd, char *list, size_t size)
  241. {
  242. return flistxattr(fd, list, size, 0);
  243. }
  244. ssize_t xattr_set(const char* path, const char* name,
  245. const void* value, size_t size, int flags)
  246. {
  247. return setxattr(path, name, value, size, 0, flags);
  248. }
  249. ssize_t xattr_lset(const char* path, const char* name,
  250. const void* value, size_t size, int flags)
  251. {
  252. return setxattr(path, name, value, size, 0, flags | XATTR_NOFOLLOW);
  253. }
  254. ssize_t xattr_fset(int fd, const char* name,
  255. const void* value, size_t size, int flags)
  256. {
  257. return fsetxattr(fd, name, value, size, 0, flags);
  258. }
  259. #elif !defined(__OpenBSD__)
  260. ssize_t xattr_get(const char *path, const char *name, void *value, size_t size)
  261. {
  262. return getxattr(path, name, value, size);
  263. }
  264. ssize_t xattr_lget(const char *path, const char *name, void *value, size_t size)
  265. {
  266. return lgetxattr(path, name, value, size);
  267. }
  268. ssize_t xattr_fget(int fd, const char *name, void *value, size_t size)
  269. {
  270. return fgetxattr(fd, name, value, size);
  271. }
  272. ssize_t xattr_list(const char *path, char *list, size_t size)
  273. {
  274. return listxattr(path, list, size);
  275. }
  276. ssize_t xattr_llist(const char *path, char *list, size_t size)
  277. {
  278. return llistxattr(path, list, size);
  279. }
  280. ssize_t xattr_flist(int fd, char *list, size_t size)
  281. {
  282. return flistxattr(fd, list, size);
  283. }
  284. ssize_t xattr_set(const char* path, const char* name,
  285. const void* value, size_t size, int flags)
  286. {
  287. return setxattr(path, name, value, size, flags);
  288. }
  289. ssize_t xattr_lset(const char* path, const char* name,
  290. const void* value, size_t size, int flags)
  291. {
  292. return lsetxattr(path, name, value, size, flags);
  293. }
  294. ssize_t xattr_fset(int fd, const char* name,
  295. const void* value, size_t size, int flags)
  296. {
  297. return fsetxattr(fd, name, value, size, flags);
  298. }
  299. #endif
  300. #ifdef __APPLE__
  301. // In the absence of a mknodat system call, fchdir to dirfd and back
  302. // around a regular mknod call...
  303. int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev)
  304. {
  305. int old_dirfd = open(".", O_RDONLY), result;
  306. if (old_dirfd == -1 || fchdir(dirfd) == -1) return -1;
  307. result = mknod(path, mode, dev);
  308. if (fchdir(old_dirfd) == -1) perror_exit("mknodat couldn't return");
  309. return result;
  310. }
  311. // As of 10.15, macOS offers an fcntl F_PREALLOCATE rather than fallocate()
  312. // or posix_fallocate() calls.
  313. int posix_fallocate(int fd, off_t offset, off_t length)
  314. {
  315. int e = errno, result;
  316. fstore_t f;
  317. f.fst_flags = F_ALLOCATEALL;
  318. f.fst_posmode = F_PEOFPOSMODE;
  319. f.fst_offset = offset;
  320. f.fst_length = length;
  321. if (fcntl(fd, F_PREALLOCATE, &f) == -1) result = errno;
  322. else result = ftruncate(fd, length);
  323. errno = e;
  324. return result;
  325. }
  326. #endif
  327. // Signals required by POSIX 2008:
  328. // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
  329. #define SIGNIFY(x) {SIG##x, #x}
  330. static const struct signame signames[] = {
  331. {0, "0"},
  332. // POSIX
  333. SIGNIFY(ABRT), SIGNIFY(ALRM), SIGNIFY(BUS),
  334. SIGNIFY(FPE), SIGNIFY(HUP), SIGNIFY(ILL), SIGNIFY(INT), SIGNIFY(KILL),
  335. SIGNIFY(PIPE), SIGNIFY(QUIT), SIGNIFY(SEGV), SIGNIFY(TERM),
  336. SIGNIFY(USR1), SIGNIFY(USR2), SIGNIFY(SYS), SIGNIFY(TRAP),
  337. SIGNIFY(VTALRM), SIGNIFY(XCPU), SIGNIFY(XFSZ),
  338. // Non-POSIX signals that cause termination
  339. SIGNIFY(PROF), SIGNIFY(IO),
  340. // signals only present/absent on some targets (mips and macos)
  341. #ifdef SIGEMT
  342. SIGNIFY(EMT),
  343. #endif
  344. #ifdef SIGINFO
  345. SIGNIFY(INFO),
  346. #endif
  347. #ifdef SIGPOLL
  348. SIGNIFY(POLL),
  349. #endif
  350. #ifdef SIGPWR
  351. SIGNIFY(PWR),
  352. #endif
  353. #ifdef SIGSTKFLT
  354. SIGNIFY(STKFLT),
  355. #endif
  356. // Note: sigatexit relies on all the signals with a default disposition that
  357. // terminates the process coming *before* SIGCHLD.
  358. // POSIX signals that don't cause termination
  359. SIGNIFY(CHLD), SIGNIFY(CONT), SIGNIFY(STOP), SIGNIFY(TSTP),
  360. SIGNIFY(TTIN), SIGNIFY(TTOU), SIGNIFY(URG),
  361. // Non-POSIX signals that don't cause termination
  362. SIGNIFY(WINCH),
  363. };
  364. #undef SIGNIFY
  365. void xsignal_all_killers(void *handler)
  366. {
  367. int i;
  368. for (i = 1; signames[i].num != SIGCHLD; i++)
  369. if (signames[i].num != SIGKILL) xsignal(signames[i].num, handler);
  370. }
  371. // Convert a string like "9", "KILL", "SIGHUP", or "SIGRTMIN+2" to a number.
  372. int sig_to_num(char *sigstr)
  373. {
  374. int i, offset;
  375. char *s;
  376. // Numeric?
  377. offset = estrtol(sigstr, &s, 10);
  378. if (!errno && !*s) return offset;
  379. // Skip leading "SIG".
  380. strcasestart(&sigstr, "sig");
  381. // Named signal?
  382. for (i=0; i<ARRAY_LEN(signames); i++)
  383. if (!strcasecmp(sigstr, signames[i].name)) return signames[i].num;
  384. // Real-time signal?
  385. #ifdef SIGRTMIN
  386. if (strcasestart(&sigstr, "rtmin")) i = SIGRTMIN;
  387. else if (strcasestart(&sigstr, "rtmax")) i = SIGRTMAX;
  388. else return -1;
  389. // No offset?
  390. if (!*sigstr) return i;
  391. // We allow any offset that's still a real-time signal: SIGRTMIN+20 is fine.
  392. // Others are more restrictive, only accepting what they show with -l.
  393. offset = estrtol(sigstr, &s, 10);
  394. if (errno || *s) return -1;
  395. i += offset;
  396. if (i >= SIGRTMIN && i <= SIGRTMAX) return i;
  397. #endif
  398. return -1;
  399. }
  400. char *num_to_sig(int sig)
  401. {
  402. int i;
  403. // A named signal?
  404. for (i=0; i<ARRAY_LEN(signames); i++)
  405. if (signames[i].num == sig) return signames[i].name;
  406. // A real-time signal?
  407. #ifdef SIGRTMIN
  408. if (sig == SIGRTMIN) return "RTMIN";
  409. if (sig == SIGRTMAX) return "RTMAX";
  410. if (sig > SIGRTMIN && sig < SIGRTMAX) {
  411. if (sig-SIGRTMIN <= SIGRTMAX-sig) sprintf(libbuf, "RTMIN+%d", sig-SIGRTMIN);
  412. else sprintf(libbuf, "RTMAX-%d", SIGRTMAX-sig);
  413. return libbuf;
  414. }
  415. #endif
  416. return NULL;
  417. }
  418. int dev_minor(int dev)
  419. {
  420. #if defined(__linux__)
  421. return ((dev&0xfff00000)>>12)|(dev&0xff);
  422. #elif defined(__APPLE__)
  423. return dev&0xffffff;
  424. #elif defined(__OpenBSD__)
  425. return minor(dev);
  426. #else
  427. #error
  428. #endif
  429. }
  430. int dev_major(int dev)
  431. {
  432. #if defined(__linux__)
  433. return (dev&0xfff00)>>8;
  434. #elif defined(__APPLE__)
  435. return (dev>>24)&0xff;
  436. #elif defined(__OpenBSD__)
  437. return major(dev);
  438. #else
  439. #error
  440. #endif
  441. }
  442. int dev_makedev(int major, int minor)
  443. {
  444. #if defined(__linux__)
  445. return (minor&0xff)|((major&0xfff)<<8)|((minor&0xfff00)<<12);
  446. #elif defined(__APPLE__)
  447. return (minor&0xffffff)|((major&0xff)<<24);
  448. #elif defined(__OpenBSD__)
  449. return makedev(major, minor);
  450. #else
  451. #error
  452. #endif
  453. }
  454. char *fs_type_name(struct statfs *statfs)
  455. {
  456. #if defined(__APPLE__) || defined(__OpenBSD__)
  457. // macOS has an `f_type` field, but assigns values dynamically as filesystems
  458. // are registered. They do give you the name directly though, so use that.
  459. return statfs->f_fstypename;
  460. #else
  461. char *s = NULL;
  462. struct {unsigned num; char *name;} nn[] = {
  463. {0xADFF, "affs"}, {0x5346544e, "ntfs"}, {0x1Cd1, "devpts"},
  464. {0x137D, "ext"}, {0xEF51, "ext2"}, {0xEF53, "ext3"},
  465. {0x1BADFACE, "bfs"}, {0x9123683E, "btrfs"}, {0x28cd3d45, "cramfs"},
  466. {0x3153464a, "jfs"}, {0x7275, "romfs"}, {0x01021994, "tmpfs"},
  467. {0x3434, "nilfs"}, {0x6969, "nfs"}, {0x9fa0, "proc"},
  468. {0x534F434B, "sockfs"}, {0x62656572, "sysfs"}, {0x517B, "smb"},
  469. {0x4d44, "msdos"}, {0x4006, "fat"}, {0x43415d53, "smackfs"},
  470. {0x73717368, "squashfs"}
  471. };
  472. int i;
  473. for (i=0; i<ARRAY_LEN(nn); i++)
  474. if (nn[i].num == statfs->f_type) s = nn[i].name;
  475. if (!s) sprintf(s = libbuf, "0x%x", (unsigned)statfs->f_type);
  476. return s;
  477. #endif
  478. }
  479. #if defined(__APPLE__)
  480. #include <sys/disk.h>
  481. int get_block_device_size(int fd, unsigned long long* size)
  482. {
  483. unsigned long block_size, block_count;
  484. if (!ioctl(fd, DKIOCGETBLOCKSIZE, &block_size) &&
  485. !ioctl(fd, DKIOCGETBLOCKCOUNT, &block_count)) {
  486. *size = block_count * block_size;
  487. return 1;
  488. }
  489. return 0;
  490. }
  491. #elif defined(__linux__)
  492. int get_block_device_size(int fd, unsigned long long* size)
  493. {
  494. return (ioctl(fd, BLKGETSIZE64, size) >= 0);
  495. }
  496. #elif defined(__OpenBSD__)
  497. #include <sys/dkio.h>
  498. #include <sys/disklabel.h>
  499. int get_block_device_size(int fd, unsigned long long* size)
  500. {
  501. struct disklabel lab;
  502. int status = (ioctl(fd, DIOCGDINFO, &lab) >= 0);
  503. *size = lab.d_secsize * lab.d_nsectors;
  504. return status;
  505. }
  506. #endif
  507. ssize_t copy_file_range_wrap(int infd, off_t *inoff, int outfd,
  508. off_t *outoff, size_t len, unsigned flags)
  509. {
  510. #if defined(__linux__)
  511. return syscall(__NR_copy_file_range, infd, inoff, outfd, outoff, len, flags);
  512. #else
  513. errno = EINVAL;
  514. return -1;
  515. #endif
  516. }
  517. // Return bytes copied from in to out. If bytes <0 copy all of in to out.
  518. // If consumed isn't null, amount read saved there (return is written or error)
  519. long long sendfile_len(int in, int out, long long bytes, long long *consumed)
  520. {
  521. long long total = 0, len, ww;
  522. int copy_file_range = CFG_TOYBOX_COPYFILERANGE;
  523. if (consumed) *consumed = 0;
  524. if (in<0) return 0;
  525. while (bytes != total) {
  526. ww = 0;
  527. len = bytes-total;
  528. errno = 0;
  529. if (copy_file_range) {
  530. if (bytes<0 || bytes>(1<<30)) len = (1<<30);
  531. len = copy_file_range_wrap(in, 0, out, 0, len, 0);
  532. if (len < 0 && errno == EINVAL) {
  533. copy_file_range = 0;
  534. continue;
  535. }
  536. }
  537. if (!copy_file_range) {
  538. if (bytes<0 || len>sizeof(libbuf)) len = sizeof(libbuf);
  539. ww = len = read(in, libbuf, len);
  540. }
  541. if (len<1 && errno==EAGAIN) continue;
  542. if (len<1) break;
  543. if (consumed) *consumed += len;
  544. if (ww && writeall(out, libbuf, len) != len) return -1;
  545. total += len;
  546. }
  547. return total;
  548. }
  549. #ifdef __APPLE__
  550. // The absolute minimum POSIX timer implementation to build timeout(1).
  551. // Note that although timeout(1) uses POSIX timers to get the monotonic clock,
  552. // that doesn't seem to be an option on macOS (without using other libraries),
  553. // so we just mangle that back into a regular setitimer(ITIMER_REAL) call.
  554. int timer_create(clock_t c, struct sigevent *se, timer_t *t)
  555. {
  556. if (se->sigev_notify != SIGEV_SIGNAL || se->sigev_signo != SIGALRM)
  557. error_exit("unimplemented");
  558. *t = 1;
  559. return 0;
  560. }
  561. int timer_settime(timer_t t, int flags, struct itimerspec *new, void *old)
  562. {
  563. struct itimerval mangled;
  564. if (flags != 0 || old != 0) error_exit("unimplemented");
  565. memset(&mangled, 0, sizeof(mangled));
  566. mangled.it_value.tv_sec = new->it_value.tv_sec;
  567. mangled.it_value.tv_usec = new->it_value.tv_nsec / 1000;
  568. return setitimer(ITIMER_REAL, &mangled, NULL);
  569. }
  570. // glibc requires -lrt for linux syscalls, which pulls in libgcc_eh.a for
  571. // static linking, and gcc 9.3 leaks pthread calls from that breaking the build
  572. // These are both just linux syscalls: wrap them ourselves
  573. #elif !CFG_TOYBOX_HASTIMERS
  574. int timer_create_wrap(clockid_t c, struct sigevent *se, timer_t *t)
  575. {
  576. // convert overengineered structure to what kernel actually uses
  577. struct ksigevent { void *sv; int signo, notify, tid; } kk = {
  578. 0, se->sigev_signo, se->sigev_notify, 0
  579. };
  580. int timer;
  581. if (syscall(SYS_timer_create, c, &kk, &timer)<0) return -1;
  582. *t = (timer_t)(long)timer;
  583. return 0;
  584. }
  585. int timer_settime_wrap(timer_t t, int flags, struct itimerspec *val,
  586. struct itimerspec *old)
  587. {
  588. return syscall(SYS_timer_settime, t, flags, val, old);
  589. }
  590. #endif