"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/core-shim.c" (15 Mar 2019, 24854 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "core-shim.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.51_vs_0.09.52.

    1 /*
    2  * Copyright (C) 2014-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 /*
   28  *  Various shim abstraction wrappers around systems calls and
   29  *  GCC helper functions that may not be supported by some
   30  *  kernels or versions of different C libraries.
   31  */
   32 
   33 /*
   34  *  shim_sched_yield()
   35  *      wrapper for sched_yield(2) - yield the processor
   36  */
   37 int shim_sched_yield(void)
   38 {
   39 #if defined(HAVE_SCHED_YIELD)
   40     return sched_yield();
   41 #else
   42     return sleep(0);
   43 #endif
   44 }
   45 
   46 /*
   47  *  shim_cacheflush()
   48  *  wrapper for cacheflush(2), flush contents of
   49  *  instruction and/or data cache
   50  */
   51 int shim_cacheflush(char *addr, int nbytes, int cache)
   52 {
   53 #if defined(__NR_cacheflush)
   54     return (int)syscall(__NR_cacheflush, addr, nbytes, cache);
   55 #else
   56     (void)addr;
   57     (void)nbytes;
   58     (void)cache;
   59 
   60     errno = -ENOSYS;
   61     return -1;
   62 #endif
   63 }
   64 
   65 /*
   66  * shim_copy_file_range()
   67  *  wrapper for copy_file_range(2), copy range of data
   68  *  from one file to another
   69  */
   70 ssize_t shim_copy_file_range(
   71     int fd_in,
   72     shim_loff_t *off_in,
   73     int fd_out,
   74     shim_loff_t *off_out,
   75     size_t len,
   76     unsigned int flags)
   77 {
   78 #if defined(HAVE_COPY_FILE_RANGE)
   79     return copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
   80 #elif defined(__NR_copy_file_range)
   81     return syscall(__NR_copy_file_range,
   82         fd_in, off_in, fd_out, off_out, len, flags);
   83 #else
   84     (void)fd_in;
   85     (void)off_in;
   86     (void)fd_out;
   87     (void)off_out;
   88     (void)len;
   89     (void)flags;
   90 
   91     errno = -ENOSYS;
   92     return -1;
   93 #endif
   94 }
   95 
   96 /*
   97  * shim_emulate_fallocate()
   98  *  emulate fallocate (very slow!)
   99  */
  100 static int shim_emulate_fallocate(int fd, off_t offset, off_t len)
  101 {
  102     const off_t buf_sz = 65536;
  103     char buffer[buf_sz];
  104     off_t n;
  105 
  106     n = lseek(fd, offset, SEEK_SET);
  107     if (n == (off_t)-1)
  108         return -1;
  109 
  110     (void)memset(buffer, 0, buf_sz);
  111     n = len;
  112 
  113     while (g_keep_stressing_flag && (n > 0)) {
  114         ssize_t ret;
  115         size_t count = (size_t)STRESS_MINIMUM(n, buf_sz);
  116 
  117         ret = write(fd, buffer, count);
  118         if (ret >= 0) {
  119             n -= ret;
  120         } else {
  121             return -1;
  122         }
  123     }
  124     return 0;
  125 }
  126 
  127 /*
  128  * shim_fallocate()
  129  *  shim wrapper for fallocate system call
  130  *  - falls back to posix_fallocate w/o mode
  131  *  - falls back to direct writes
  132  */
  133 int shim_fallocate(int fd, int mode, off_t offset, off_t len)
  134 {
  135 #if defined(HAVE_FALLOCATE)
  136     int ret;
  137 
  138     ret = fallocate(fd, mode, offset, len);
  139     /* mode not supported? try with zero mode (dirty hack) */
  140     if ((ret < 0) && (errno == EOPNOTSUPP)) {
  141         ret = syscall(__NR_fallocate, fd, 0, offset, len);
  142         /* fallocate failed, try emulation mode */
  143         if ((ret < 0) && (errno == EOPNOTSUPP)) {
  144             ret = shim_emulate_fallocate(fd, offset, len);
  145         }
  146     }
  147     return ret;
  148 #elif defined(__NR_fallocate)
  149     int ret;
  150 
  151     ret = syscall(__NR_fallocate, fd, mode, offset, len);
  152     /* mode not supported? try with zero mode (dirty hack) */
  153     if ((ret < 0) && (errno == EOPNOTSUPP)) {
  154         ret = syscall(__NR_fallocate, fd, 0, offset, len);
  155         /* fallocate failed, try emulation mode */
  156         if ((ret < 0) && (errno == EOPNOTSUPP)) {
  157             ret = shim_emulate_fallocate(fd, offset, len);
  158         }
  159     }
  160     return ret;
  161 #elif defined(HAVE_POSIX_FALLOCATE) && !defined(__FreeBSD_kernel__)
  162     /*
  163      *  Even though FreeBSD kernels support this, large
  164      *  allocations take forever to be interrupted and so
  165      *  we don't use this for FreeBSD for now.
  166      */
  167     int ret;
  168 
  169     (void)mode;
  170 
  171     /*
  172      *  posix_fallocate returns 0 for success, > 0 as errno
  173      */
  174     ret = posix_fallocate(fd, offset, len);
  175     errno = 0;
  176     if (ret != 0) {
  177         /* failed, so retry with slower emulated fallocate */
  178         ret = shim_emulate_fallocate(fd, offset, len);
  179     }
  180     return ret;
  181 #else
  182     (void)mode;
  183 
  184     return shim_emulate_fallocate(fd, offset, len);
  185 #endif
  186 }
  187 
  188 /*
  189  *  shim_gettid()
  190  *  wrapper for gettid(2), get thread identification
  191  */
  192 int shim_gettid(void)
  193 {
  194 #if defined(__NR_gettid)
  195     return syscall(__NR_gettid);
  196 #else
  197     errno = -ENOSYS;
  198     return -1;
  199 #endif
  200 }
  201 
  202 /*
  203  *  shim_getcpu()
  204  *  wrapper for getcpu(2) - get CPU and NUMA node of
  205  *  calling thread
  206  */
  207 long shim_getcpu(
  208     unsigned *cpu,
  209     unsigned *node,
  210     void *tcache)
  211 {
  212 #if defined(__NR_getcpu)
  213     return syscall(__NR_getcpu, cpu, node, tcache);
  214 #else
  215     (void)cpu;
  216     (void)node;
  217     (void)tcache;
  218 
  219     errno = -ENOSYS;
  220     return -1;
  221 #endif
  222 }
  223 
  224 /*
  225  *  shim_getdents()
  226  *  wrapper for getdents(2) - get directory entries
  227  */
  228 int shim_getdents(
  229     unsigned int fd,
  230     struct shim_linux_dirent *dirp,
  231     unsigned int count)
  232 {
  233 #if defined(__NR_getdents)
  234     return syscall(__NR_getdents, fd, dirp, count);
  235 #else
  236     (void)fd;
  237     (void)dirp;
  238     (void)count;
  239 
  240     errno = ENOSYS;
  241     return -1;
  242 #endif
  243 }
  244 
  245 /*
  246  *  shim_getdent64()
  247  *  wrapper for getdents64(2) - get directory entries
  248  */
  249 int shim_getdents64(
  250     unsigned int fd,
  251     struct shim_linux_dirent64 *dirp,
  252     unsigned int count)
  253 {
  254 #if defined(__NR_getdents64)
  255     return syscall(__NR_getdents64, fd, dirp, count);
  256 #else
  257     (void)fd;
  258     (void)dirp;
  259     (void)count;
  260 
  261     errno = ENOSYS;
  262     return -1;
  263 #endif
  264 }
  265 
  266 /*
  267  *  shim_getrandom()
  268  *  wrapper for Linux getrandom(2) and BSD getentropy(2)
  269  */
  270 int shim_getrandom(void *buff, size_t buflen, unsigned int flags)
  271 {
  272 #if defined(__NR_getrandom)
  273     return syscall(__NR_getrandom, buff, buflen, flags);
  274 #elif defined(__OpenBSD__) || defined(__APPLE__)
  275     (void)flags;
  276 
  277     return getentropy(buff, buflen);
  278 #else
  279     (void)buff;
  280     (void)buflen;
  281     (void)flags;
  282 
  283     errno = ENOSYS;
  284     return -1;
  285 #endif
  286 }
  287 
  288 /*
  289  *  shim_clear_cache()
  290  *  wrapper for ARM GNUC clear cache intrinsic
  291  */
  292 void shim_clear_cache(char* begin, char *end)
  293 {
  294 #if defined(__GNUC__) && defined(STRESS_ARM)
  295     __clear_cache(begin, end);
  296 #else
  297     (void)begin;
  298     (void)end;
  299 #endif
  300 }
  301 
  302 /*
  303  *  shim_kcmp()
  304  *  wrapper for Linux kcmp(2) - compre two processes to
  305  *  see if they share a kernel resource.
  306  */
  307 long shim_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2)
  308 {
  309 #if defined(__NR_kcmp)
  310     errno = 0;
  311     return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
  312 #else
  313     (void)pid1;
  314     (void)pid2;
  315     (void)type;
  316     (void)idx1;
  317     (void)idx2;
  318 
  319     errno = ENOSYS;
  320     return -1;
  321 #endif
  322 }
  323 
  324 /*
  325  *  shim_syslog()
  326  *  wrapper for syslog(2) (NOT syslog(3))
  327  */
  328 int shim_syslog(int type, char *bufp, int len)
  329 {
  330 #if defined(__NR_syslog)
  331     return syscall(__NR_syslog, type, bufp, len);
  332 #else
  333     (void)type;
  334     (void)bufp;
  335     (void)len;
  336 
  337     errno = ENOSYS;
  338     return -1;
  339 #endif
  340 }
  341 
  342 /*
  343  *  shim_membarrier()
  344  *  wrapper for membarrier(2) - issue memory barriers
  345  */
  346 int shim_membarrier(int cmd, int flags)
  347 {
  348 #if defined(__NR_membarrier)
  349     return syscall(__NR_membarrier, cmd, flags);
  350 #else
  351     (void)cmd;
  352     (void)flags;
  353 
  354     errno = ENOSYS;
  355     return -1;
  356 #endif
  357 }
  358 
  359 /*
  360  *  shim_memfd_create()
  361  *  wrapper for memfd_create(2)
  362  */
  363 int shim_memfd_create(const char *name, unsigned int flags)
  364 {
  365 #if defined(__NR_memfd_create)
  366     return syscall(__NR_memfd_create, name, flags);
  367 #else
  368     (void)name;
  369     (void)flags;
  370 
  371     errno = ENOSYS;
  372     return -1;
  373 #endif
  374 }
  375 
  376 /*
  377  *  shim_get_mempolicy()
  378  *  wrapper for get_mempolicy(2) - get NUMA memory policy
  379  */
  380 int shim_get_mempolicy(
  381     int *mode,
  382     unsigned long *nodemask,
  383     unsigned long maxnode,
  384     unsigned long addr,
  385     unsigned long flags)
  386 {
  387 #if defined(__NR_get_mempolicy)
  388     return syscall(__NR_get_mempolicy,
  389         mode, nodemask, maxnode, addr, flags);
  390 #else
  391     (void)mode;
  392     (void)nodemask;
  393     (void)maxnode;
  394     (void)addr;
  395     (void)flags;
  396 
  397     errno = ENOSYS;
  398     return -1;
  399 #endif
  400 }
  401 
  402 /*
  403  *  shim_set_mempolicy()
  404  *  wrapper for set_mempolicy(2) - set NUMA memory policy
  405  */
  406 int shim_set_mempolicy(
  407     int mode,
  408     unsigned long *nodemask,
  409     unsigned long maxnode)
  410 {
  411 #if defined(__NR_set_mempolicy)
  412     return syscall(__NR_set_mempolicy,
  413         mode, nodemask, maxnode);
  414 #else
  415     (void)mode;
  416     (void)nodemask;
  417     (void)maxnode;
  418 
  419     errno = ENOSYS;
  420     return -1;
  421 #endif
  422 }
  423 
  424 /*
  425  *  shim_mbind()
  426  *  wrapper for mbind(2) - set memory policy for a memory range
  427  */
  428 long shim_mbind(
  429     void *addr,
  430     unsigned long len,
  431     int mode,
  432     const unsigned long *nodemask,
  433     unsigned long maxnode,
  434     unsigned flags)
  435 {
  436 #if defined(__NR_mbind)
  437     return syscall(__NR_mbind,
  438         addr, len, mode, nodemask, maxnode, flags);
  439 #else
  440     (void)addr;
  441     (void)len;
  442     (void)mode;
  443     (void)nodemask;
  444     (void)maxnode;
  445     (void)flags;
  446 
  447     errno = ENOSYS;
  448     return -1;
  449 #endif
  450 }
  451 
  452 /*
  453  *  shim_migrate_pages()
  454  *  wrapper for migrate_pages(2) - move all pages in a process to other nodes
  455  */
  456 long shim_migrate_pages(
  457     int pid,
  458     unsigned long maxnode,
  459     const unsigned long *old_nodes,
  460     const unsigned long *new_nodes)
  461 {
  462 #if defined(__NR_migrate_pages)
  463     return syscall(__NR_migrate_pages,
  464         pid, maxnode, old_nodes, new_nodes);
  465 #else
  466     (void)pid;
  467     (void)maxnode;
  468     (void)old_nodes;
  469     (void)new_nodes;
  470 
  471     errno = ENOSYS;
  472     return -1;
  473 #endif
  474 }
  475 
  476 /*
  477  *  shim_move_pages()
  478  *  wrapper for move_pages(2) - move pages in a process to other nodes
  479  */
  480 long shim_move_pages(
  481     int pid,
  482     unsigned long count,
  483     void **pages,
  484     const int *nodes,
  485     int *status,
  486     int flags)
  487 {
  488 #if defined(__NR_move_pages)
  489     return syscall(__NR_move_pages,
  490         pid, count, pages, nodes,
  491         status, flags);
  492 #else
  493     (void)pid;
  494     (void)count;
  495     (void)pages;
  496     (void)nodes;
  497     (void)status;
  498     (void)flags;
  499 
  500     errno = ENOSYS;
  501     return -1;
  502 #endif
  503 }
  504 
  505 /*
  506  *  shim_userfaultfd()
  507  *  wrapper for userfaultfd(2)
  508  */
  509 int shim_userfaultfd(int flags)
  510 {
  511 #if defined(__NR_userfaultfd)
  512     return syscall(__NR_userfaultfd, flags);
  513 #else
  514     (void)flags;
  515 
  516     errno = ENOSYS;
  517     return -1;
  518 #endif
  519 }
  520 
  521 /*
  522  *  shim_seccomp()
  523  *  wrapper for seccomp(2) - operate on Secure Computing state of process
  524  */
  525 int shim_seccomp(unsigned int operation, unsigned int flags, void *args)
  526 {
  527 #if defined(__NR_seccomp)
  528     return (int)syscall(__NR_seccomp, operation, flags, args);
  529 #else
  530     (void)operation;
  531     (void)flags;
  532     (void)args;
  533 
  534     errno = ENOSYS;
  535     return -1;
  536 #endif
  537 }
  538 
  539 /*
  540  *  shim_unshare()
  541  *  wrapper for unshare(2)
  542  */
  543 int shim_unshare(int flags)
  544 {
  545 #if defined(__NR_unshare)
  546 #if NEED_GLIBC(2,14,0)
  547     return unshare(flags);
  548 #else
  549     return syscall(__NR_unshare, flags);
  550 #endif
  551 #else
  552     (void)flags;
  553 
  554     errno = ENOSYS;
  555     return -1;
  556 #endif
  557 }
  558 
  559 /*
  560  *  shim_shed_getattr()
  561  *  wrapper for shed_getattr(2)
  562  */
  563 int shim_sched_getattr(
  564     pid_t pid,
  565     struct shim_sched_attr *attr,
  566     unsigned int size,
  567     unsigned int flags)
  568 {
  569 #if defined(__NR_sched_getattr)
  570     return syscall(__NR_sched_getattr, pid, attr, size, flags);
  571 #else
  572     (void)pid;
  573     (void)attr;
  574     (void)size;
  575     (void)flags;
  576 
  577     errno = ENOSYS;
  578     return -1;
  579 #endif
  580 }
  581 
  582 /*
  583  *  shim_shed_setattr()
  584  *  wrapper for shed_setattr(2)
  585  */
  586 int shim_sched_setattr(
  587     pid_t pid,
  588     struct shim_sched_attr *attr,
  589     unsigned int flags)
  590 {
  591 #if defined(__NR_sched_setattr)
  592     return syscall(__NR_sched_setattr, pid, attr, flags);
  593 #else
  594     (void)pid;
  595     (void)attr;
  596     (void)flags;
  597 
  598     errno = ENOSYS;
  599     return -1;
  600 #endif
  601 }
  602 
  603 /*
  604  *  shim_mlock()
  605  *  wrapper for mlock(2) - lock memory
  606  */
  607 int shim_mlock(const void *addr, size_t len)
  608 {
  609 #if defined(HAVE_MLOCK)
  610 #if defined(__sun__)
  611     return mlock((caddr_t)addr, len);
  612 #else
  613     return mlock(addr, len);
  614 #endif
  615 #else
  616     (void)addr;
  617     (void)len;
  618 
  619     errno = ENOSYS;
  620     return -1;
  621 #endif
  622 }
  623 
  624 /*
  625  *  shim_munlock()
  626  *  wrapper for munlock(2) - unlock memory
  627  */
  628 int shim_munlock(const void *addr, size_t len)
  629 {
  630 #if defined(HAVE_MUNLOCK)
  631 #if defined(__sun__)
  632     return munlock((caddr_t)addr, len);
  633 #else
  634     return munlock(addr, len);
  635 #endif
  636 #else
  637     (void)addr;
  638     (void)len;
  639 
  640     errno = ENOSYS;
  641     return -1;
  642 #endif
  643 }
  644 
  645 /*
  646  *  shim_mlock2()
  647  *  wrapper for mlock2(2) - lock memory
  648  */
  649 int shim_mlock2(const void *addr, size_t len, int flags)
  650 {
  651 #if defined(__NR_mlock2)
  652     return (int)syscall(__NR_mlock2, addr, len, flags);
  653 #else
  654     (void)addr;
  655     (void)len;
  656     (void)flags;
  657 
  658     errno = ENOSYS;
  659     return -1;
  660 #endif
  661 }
  662 
  663 /*
  664  *  shim_mlockall()
  665  *  wrapper for mlockall() - lock all memmory
  666  */
  667 int shim_mlockall(int flags)
  668 {
  669 #if defined(HAVE_MLOCKALL)
  670     return mlockall(flags);
  671 #else
  672     (void)flags;
  673 
  674     errno = ENOSYS;
  675     return -1;
  676 #endif
  677 }
  678 
  679 /*
  680  *  shim_munlockall()
  681  *  wrapper for munlockall() - unlock all memmory
  682  */
  683 int shim_munlockall(void)
  684 {
  685 /* if HAVE_MLOCKALL defined we also have munlockall */
  686 #if defined(HAVE_MLOCKALL)
  687     return munlockall();
  688 #else
  689     errno = ENOSYS;
  690     return -1;
  691 #endif
  692 }
  693 
  694 /*
  695  *  shim_nanosleep_uint64()
  696  *  nanosecond sleep that handles being interrupted but will
  697  *  be preempted if an ALARM signal has triggered a termination
  698  */
  699 int shim_nanosleep_uint64(uint64_t nsec)
  700 {
  701 #if defined(HAVE_NANOSLEEP)
  702     struct timespec t, trem;
  703 
  704     t.tv_sec = nsec / 1000000000;
  705     t.tv_nsec = nsec % 1000000000;
  706 
  707     for (;;) {
  708         errno = 0;
  709         if (nanosleep(&t, &trem) < 0) {
  710             if (errno == EINTR) {
  711                 t = trem;
  712                 if (g_keep_stressing_flag)
  713                     continue;
  714             } else {
  715                 return -1;
  716             }
  717         }
  718         break;
  719     }
  720 #else
  721     useconds_t usec = nsec / 1000;
  722     const double t_end = time_now() + ((double)usec) / 1000000.0;
  723 
  724     for (;;) {
  725         errno = 0;
  726         if (usleep(usec) < 0) {
  727             if (errno == EINTR) {
  728                 double t_left = t_end - time_now();
  729 
  730                 if (t_left < 0.0)
  731                     return 0;
  732                 usec = (useconds_t)(t_left * 1000000.0);
  733                 if (usec == 0)
  734                     return 0;
  735                 if (g_keep_stressing_flag)
  736                     continue;
  737             } else {
  738                 return -1;
  739             }
  740         }
  741         break;
  742     }
  743 #endif
  744     return 0;
  745 }
  746 
  747 /*
  748  *  shim_usleep()
  749  *  usleep is now deprecated, so
  750  *  emulate it with nanosleep
  751  */
  752 int shim_usleep(uint64_t usec)
  753 {
  754     return shim_nanosleep_uint64(usec * 1000);
  755 }
  756 
  757 /*
  758  *  shim_usleep_interruptible()
  759  *  interruptible usleep
  760  */
  761 int shim_usleep_interruptible(uint64_t usec)
  762 {
  763 #if defined(HAVE_NANOSLEEP)
  764     struct timespec t, trem;
  765 
  766     t.tv_sec = usec / 1000000;
  767     t.tv_nsec = (usec - (t.tv_sec * 1000000)) * 1000;
  768 
  769     errno = 0;
  770     return nanosleep(&t, &trem);
  771 #else
  772     return usleep((useconds_t)usec);
  773 #endif
  774 }
  775 
  776 
  777 /*
  778  *  shim_getlogin
  779  *  a more secure abstracted version of getlogin
  780  *
  781  * According to flawfinder:
  782  * "It's often easy to fool getlogin. Sometimes it does not work at all,
  783  * because some program messed up the utmp file. Often, it gives only the
  784  * first 8 characters of the login name. The user currently logged in on the
  785  * controlling tty of our program need not be the user who started it. Avoid
  786  * getlogin() for security-related purposes (CWE-807). Use getpwuid(geteuid())
  787  * and extract the desired information instead."
  788  */
  789 char *shim_getlogin(void)
  790 {
  791 #if defined(BUILD_STATIC)
  792     /*
  793      *  static builds can't use getpwuid because of
  794      *  dynamic linking issues. Ugh.
  795      */
  796     return NULL;
  797 #else
  798     static char pw_name[256];
  799     struct passwd *pw;
  800 
  801     pw = getpwuid(geteuid());
  802     if (!pw)
  803         return NULL;
  804 
  805     (void)shim_strlcpy(pw_name, pw->pw_name, sizeof(pw_name));
  806     pw_name[sizeof(pw_name) - 1 ] = '\0';
  807 
  808     return pw_name;
  809 #endif
  810 }
  811 
  812 /*
  813  *  shim_msync()
  814  *  wrapper for msync(2) - synchronize a file with a memory map
  815  */
  816 int shim_msync(void *addr, size_t length, int flags)
  817 {
  818 #if defined(HAVE_MSYNC)
  819     return msync(addr, length, flags);
  820 #else
  821     (void)addr;
  822     (void)length;
  823     (void)flags;
  824 
  825     return 0;
  826 #endif
  827 }
  828 
  829 /*
  830  *  shim_sysfs()
  831  *  wrapper for sysfs(2) - get filesystem type information
  832  */
  833 int shim_sysfs(int option, ...)
  834 {
  835 #if defined(__NR_sysfs)
  836     int ret;
  837     va_list ap;
  838     char *fsname;
  839     unsigned int fs_index;
  840     char *buf;
  841 
  842     va_start(ap, option);
  843 
  844     switch (option) {
  845     case 1:
  846         fsname = va_arg(ap, char *);
  847         ret = syscall(__NR_sysfs, option, fsname);
  848         break;
  849     case 2:
  850         fs_index = va_arg(ap, unsigned int);
  851         buf = va_arg(ap, char *);
  852         ret = syscall(__NR_sysfs, option, fs_index, buf);
  853         break;
  854     case 3:
  855         ret = syscall(__NR_sysfs, option);
  856         break;
  857     default:
  858         ret = -1;
  859         errno = EINVAL;
  860     }
  861 
  862     va_end(ap);
  863 
  864     return ret;
  865 #else
  866     (void)option;
  867 
  868     errno = ENOSYS;
  869     return -1;
  870 #endif
  871 }
  872 
  873 /*
  874  *  shim_madvise()
  875  *  wrapper for madvise(2) - get filesystem type information
  876  */
  877 int shim_madvise(void *addr, size_t length, int advice)
  878 {
  879 #if defined(HAVE_MADVISE)
  880     return madvise(addr, length, advice);
  881 #elif defined(HAVE_POSIX_MADVISE)
  882     int posix_advice;
  883 
  884     switch (advice) {
  885 #if defined(POSIX_MADV_NORMAL) && defined(MADV_NORMAL)
  886     case MADV_NORMAL:
  887         posix_advice = POSIX_MADV_NORMAL;
  888         break;
  889 #endif
  890 #if defined(POSIX_MADV_SEQUENTIAL) && defined(MADV_SEQUENTIAL)
  891     case MADV_SEQUENTIAL:
  892         posix_advice = POSIX_MADV_SEQUENTIAL;
  893         break;
  894 #endif
  895 #if defined(POSIX_MADV_RANDOM) && defined(MADV_RANDOM)
  896     case MADV_RANDOM:
  897         posix_advice = POSIX_MADV_RANDOM;
  898         break;
  899 #endif
  900 #if defined(POSIX_MADV_WILLNEED) && defined(MADV_WILLNEED)
  901     case MADV_WILLNEED:
  902         posix_advice = POSIX_MADV_WILLNEED;
  903         break;
  904 #endif
  905 #if defined(POSIX_MADV_DONTNEED) && defined(MADV_DONTNEED)
  906     case MADV_DONTNEED:
  907         posix_advice = POSIX_MADV_DONTNEED;
  908         break;
  909 #endif
  910     default:
  911         posix_advice = POSIX_MADV_NORMAL;
  912         break;
  913     }
  914     return posix_madvise(addr, length, posix_advice);
  915 #else
  916     (void)addr;
  917     (void)length;
  918     (void)advice;
  919 
  920     errno = ENOSYS;
  921     return -1;
  922 #endif
  923 }
  924 
  925 /*
  926  *  shim_mincore()
  927  *  wrapper for mincore(2) -  determine whether pages are resident in memory
  928  */
  929 int shim_mincore(void *addr, size_t length, unsigned char *vec)
  930 {
  931 #if defined(HAVE_MINCORE) && NEED_GLIBC(2,2,0)
  932 #if defined(__FreeBSD__) || defined(__OpenBSD__) || \
  933     defined(__NetBSD__) || defined(__sun__)
  934     return mincore(addr, length, (char *)vec);
  935 #else
  936     return mincore(addr, length, vec);
  937 #endif
  938 #else
  939     (void)addr;
  940     (void)length;
  941     (void)vec;
  942 
  943     errno = ENOSYS;
  944     return -1;
  945 #endif
  946 }
  947 
  948 ssize_t shim_statx(
  949     int dfd,
  950     const char *filename,
  951     unsigned int flags,
  952     unsigned int mask,
  953     struct shim_statx *buffer)
  954 {
  955 #if defined(__NR_statx)
  956     return syscall(__NR_statx, dfd, filename, flags, mask, buffer);
  957 #else
  958     (void)dfd;
  959     (void)filename;
  960     (void)flags;
  961     (void)mask;
  962     (void)buffer;
  963 
  964     errno = ENOSYS;
  965     return -1;
  966 #endif
  967 }
  968 
  969 /*
  970  *  futex wake()
  971  *  wake n waiters on futex
  972  */
  973 #if defined(__NR_futex)
  974 int shim_futex_wake(const void *futex, const int n)
  975 {
  976     return syscall(__NR_futex, futex, FUTEX_WAKE, n, NULL, NULL, 0);
  977 }
  978 #else
  979 int shim_futex_wake(const void *futex, const int n)
  980 {
  981     (void)futex;
  982     (void)n;
  983 
  984     errno = -ENOSYS;
  985     return -1;
  986 }
  987 #endif
  988 
  989 /*
  990  *  futex_wait()
  991  *  wait on futex with a timeout
  992  */
  993 #if defined(__NR_futex)
  994 int shim_futex_wait(
  995     const void *futex,
  996     const int val,
  997     const struct timespec *timeout)
  998 {
  999     return syscall(__NR_futex, futex, FUTEX_WAIT, val, timeout, NULL, 0);
 1000 }
 1001 #else
 1002 int shim_futex_wait(
 1003     const void *futex,
 1004     const int val,
 1005     const struct timespec *timeout)
 1006 {
 1007     (void)futex;
 1008     (void)val;
 1009     (void)timeout;
 1010 
 1011     errno = -ENOSYS;
 1012     return -1;
 1013 }
 1014 #endif
 1015 
 1016 /*
 1017  *  dup3()
 1018  *  linux special dup
 1019  */
 1020 #if defined(HAVE_DUP3)
 1021 int shim_dup3(int oldfd, int newfd, int flags)
 1022 {
 1023     return dup3(oldfd, newfd, flags);
 1024 }
 1025 #else
 1026 int shim_dup3(int oldfd, int newfd, int flags)
 1027 {
 1028     (void)oldfd;
 1029     (void)newfd;
 1030     (void)flags;
 1031 
 1032     errno = -ENOSYS;
 1033     return -1;
 1034 }
 1035 #endif
 1036 
 1037 
 1038 int shim_sync_file_range(
 1039     int fd,
 1040     shim_off64_t offset,
 1041     shim_off64_t nbytes,
 1042     unsigned int flags)
 1043 {
 1044 #if defined(HAVE_SYNC_FILE_RANGE)
 1045     return sync_file_range(fd, offset, nbytes, flags);
 1046 #elif defined(__NR_sync_file_range)
 1047     return syscall(__NR_sync_file_range, fd, offset, nbytes, flags);
 1048 #elif defined(__NR_sync_file_range2)
 1049     /*
 1050      * from sync_file_range(2):
 1051      * "Some architectures (e.g., PowerPC, ARM) need  64-bit  arguments
 1052      * to be aligned in a suitable pair of registers.  On such
 1053      * architectures, the call signature of sync_file_range() shown in
 1054      * the SYNOPSIS would force a register to be wasted as padding
 1055      * between the fd and offset arguments.  (See syscall(2) for details.)
 1056      * Therefore, these architectures define a different system call that
 1057      * orders the arguments suitably"
 1058      */
 1059     return syscall(__NR_sync_file_range2, fd, flags, offset, nbytes);
 1060 #else
 1061     (void)fd;
 1062     (void)offset;
 1063     (void)nbytes;
 1064     (void)flags;
 1065 
 1066     errno = -ENOSYS;
 1067     return -1;
 1068 #endif
 1069 }
 1070 
 1071 /*
 1072  *  shim_ioprio_set()
 1073  *  ioprio_set system call
 1074  */
 1075 int shim_ioprio_set(int which, int who, int ioprio)
 1076 {
 1077 #if defined(__NR_ioprio_set)
 1078     return syscall(__NR_ioprio_set, which, who, ioprio);
 1079 #else
 1080     (void)which;
 1081     (void)who;
 1082     (void)ioprio;
 1083 
 1084     errno = ENOSYS;
 1085     return -1;
 1086 #endif
 1087 }
 1088 
 1089 /*
 1090  *  shim_ioprio_get()
 1091  *  ioprio_get system call
 1092  */
 1093 int shim_ioprio_get(int which, int who)
 1094 {
 1095 #if defined(__NR_ioprio_get)
 1096     return syscall(__NR_ioprio_get, which, who);
 1097 #else
 1098     (void)which;
 1099     (void)who;
 1100 
 1101     errno = ENOSYS;
 1102     return -1;
 1103 #endif
 1104 }
 1105 
 1106 /*
 1107  *   shim_brk()
 1108  *  brk system call shim
 1109  */
 1110 #if defined(__APPLE__)
 1111 PRAGMA_PUSH
 1112 PRAGMA_WARN_OFF
 1113 #endif
 1114 int shim_brk(void *addr)
 1115 {
 1116 #if defined(__APPLE__)
 1117     return (int)brk(addr);
 1118 #else
 1119     return brk(addr);
 1120 #endif
 1121 }
 1122 #if defined(__APPLE__)
 1123 PRAGMA_POP
 1124 #endif
 1125 
 1126 /*
 1127  *   shim_sbrk()
 1128  *  sbrk system call shim
 1129  */
 1130 #if defined(__APPLE__)
 1131 PRAGMA_PUSH
 1132 PRAGMA_WARN_OFF
 1133 #endif
 1134 void *shim_sbrk(intptr_t increment)
 1135 {
 1136     return sbrk(increment);
 1137 }
 1138 #if defined(__APPLE__)
 1139 PRAGMA_POP
 1140 #endif
 1141 
 1142 /*
 1143  *   shim_strlcpy()
 1144  *  wrapper / implementation of BSD strlcpy
 1145  */
 1146 size_t shim_strlcpy(char *dst, const char *src, size_t len)
 1147 {
 1148 #if defined(HAVE_STRLCPY)
 1149     return strlcpy(dst, src, len);
 1150 #else
 1151     register char *d = dst;
 1152     register const char *s = src;
 1153     register size_t n = len;
 1154 
 1155     if (n) {
 1156         while (--n) {
 1157             register char c = *s++;
 1158 
 1159             *d++ = c;
 1160             if (c == '\0')
 1161                 break;
 1162         }
 1163     }
 1164 
 1165     if (!n) {
 1166         if (len)
 1167             *d = '\0';
 1168         while (*s)
 1169             s++;
 1170     }
 1171 
 1172     return (s - src - 1);
 1173 #endif
 1174 }
 1175 
 1176 /*
 1177  *   shim_strlcat()
 1178  *  wrapper / implementation of BSD strlcat
 1179  */
 1180 size_t shim_strlcat(char *dst, const char *src, size_t len)
 1181 {
 1182 #if defined(HAVE_STRLCAT)
 1183     return strlcat(dst, src, len);
 1184 #else
 1185     register char *d = dst;
 1186     register const char *s = src;
 1187     register size_t n = len, tmplen;
 1188 
 1189     while (n-- && *d != '\0') {
 1190         d++;
 1191     }
 1192 
 1193     tmplen = d - dst;
 1194     n = len - tmplen;
 1195 
 1196     if (!n) {
 1197         return strlen(s) + tmplen;
 1198     }
 1199 
 1200     while (*s != '\0') {
 1201         if (n != 1) {
 1202             *d = *s;
 1203             d++;
 1204             n--;
 1205         }
 1206         s++;
 1207     }
 1208     *d = '\0';
 1209 
 1210     return (s - src) + tmplen;
 1211 #endif
 1212 }
 1213 
 1214 /*
 1215  *  shim_fsync
 1216  *  wrapper for fsync
 1217  */
 1218 int shim_fsync(int fd)
 1219 {
 1220 #if defined(__APPLE__) && defined(F_FULLFSYNC)
 1221     int ret;
 1222 
 1223     /*
 1224      *  For APPLE Mac OS X try to use the full fsync fcntl
 1225      *  first and then fall back to a potential no-op'd fsync
 1226      *  implementation.
 1227      */
 1228     ret = fcntl(fd, F_FULLFSYNC, NULL);
 1229     if (ret == 0)
 1230         return 0;
 1231 #endif
 1232     return fsync(fd);
 1233 }
 1234 
 1235 /*
 1236  *  shim_fdatasync
 1237  *  wrapper for fdatasync
 1238  */
 1239 int shim_fdatasync(int fd)
 1240 {
 1241 #if defined(HAVE_FDATASYNC)
 1242     /*
 1243      *  For some reason, fdatasync prototype may be missing
 1244      *  in some __APPLE__ systems.
 1245      */
 1246 #if defined(__APPLE__)
 1247     extern int fdatasync(int fd);
 1248 #endif
 1249     return fdatasync(fd);
 1250 #else
 1251     (void)fd;
 1252     errno = -ENOSYS;
 1253     return -1;
 1254 #endif
 1255 }
 1256 
 1257 /*
 1258  *   shim_pkey_alloc()
 1259  *  wrapper for pkey_alloc()
 1260  */
 1261 int shim_pkey_alloc(unsigned long flags, unsigned long access_rights)
 1262 {
 1263 #if defined(__NR_pkey_alloc)
 1264     return syscall(__NR_pkey_alloc, flags, access_rights);
 1265 #else
 1266     (void)flags;
 1267     (void)access_rights;
 1268 
 1269     errno = -ENOSYS;
 1270     return -1;
 1271 #endif
 1272 }
 1273 
 1274 /*
 1275  *   shim_pkey_free()
 1276  *  wrapper for pkey_free()
 1277  */
 1278 int shim_pkey_free(int pkey)
 1279 {
 1280 #if defined(__NR_pkey_free)
 1281     return syscall(__NR_pkey_free, pkey);
 1282 #else
 1283     (void)pkey;
 1284 
 1285     errno = -ENOSYS;
 1286     return -1;
 1287 #endif
 1288 }
 1289 
 1290 /*
 1291  *   shim_pkey_mprotect()
 1292  *  wrapper for pkey_mprotect()
 1293  */
 1294 int shim_pkey_mprotect(void *addr, size_t len, int prot, int pkey)
 1295 {
 1296 #if defined(__NR_pkey_mprotect)
 1297     return syscall(__NR_pkey_mprotect, addr, len, prot, pkey);
 1298 #else
 1299     (void)addr;
 1300     (void)len;
 1301     (void)prot;
 1302     (void)pkey;
 1303 
 1304     errno = -ENOSYS;
 1305     return -1;
 1306 #endif
 1307 }
 1308 
 1309 /*
 1310  *   shim_pkey_get()
 1311  *  wrapper for pkey_get()
 1312  */
 1313 int shim_pkey_get(int pkey)
 1314 {
 1315 #if defined(__NR_pkey_get)
 1316     return syscall(__NR_pkey_get, pkey);
 1317 #else
 1318     (void)pkey;
 1319 
 1320     errno = -ENOSYS;
 1321     return -1;
 1322 #endif
 1323 }
 1324 
 1325 /*
 1326  *   shim_pkey_set()
 1327  *  wrapper for pkey_set()
 1328  */
 1329 int shim_pkey_set(int pkey, unsigned int rights)
 1330 {
 1331 #if defined(__NR_pkey_set)
 1332     return syscall(__NR_pkey_set, pkey, rights);
 1333 #else
 1334     (void)pkey;
 1335     (void)rights;
 1336 
 1337     errno = -ENOSYS;
 1338     return -1;
 1339 #endif
 1340 }
 1341 
 1342 /*
 1343  *   shim_execveat()
 1344  *  wrapper for execveat()
 1345  */
 1346 int shim_execveat(
 1347         int dirfd,
 1348         const char *pathname,
 1349         char *const argv[],
 1350         char *const envp[],
 1351         int flags)
 1352 {
 1353 #if defined(__NR_execveat)
 1354         return syscall(__NR_execveat, dirfd, pathname, argv, envp, flags);
 1355 #else
 1356     (void)dirfd;
 1357     (void)pathname;
 1358     (void)argv;
 1359     (void)envp;
 1360     (void)flags;
 1361 
 1362     errno = -ENOSYS;
 1363     return -1;
 1364 #endif
 1365 }
 1366 
 1367 /*
 1368  *   shim_getxattr
 1369  *  wrapper for getxattr
 1370  */
 1371 ssize_t shim_getxattr(
 1372     const char *path,
 1373     const char *name,
 1374     void *value,
 1375     size_t size)
 1376 {
 1377 #if defined(HAVE_GETXATTR)
 1378 #if defined(__APPLE__)
 1379     return getxattr(path, name, value, size, 0, 0);
 1380 #else
 1381     return getxattr(path, name, value, size);
 1382 #endif
 1383 #else
 1384     (void)path;
 1385     (void)name;
 1386     (void)value;
 1387     (void)size;
 1388 
 1389     errno = -ENOSYS;
 1390     return -1;
 1391 #endif
 1392 }
 1393