"Fossies" - the Fresh Open Source Software Archive

Member "gnuastro-0.8/bootstrapped/tests/test-fcntl.c" (28 Dec 2018, 10024 Bytes) of package /linux/privat/gnuastro-0.8.tar.lz:


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. See also the last Fossies "Diffs" side-by-side code changes report for "test-fcntl.c": 0.5_vs_0.6.

    1 /* Test of fcntl(2).
    2    Copyright (C) 2009-2018 Free Software Foundation, Inc.
    3 
    4    This program is free software: you can redistribute it and/or modify
    5    it under the terms of the GNU General Public License as published by
    6    the Free Software Foundation; either version 3 of the License, or
    7    (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, see <https://www.gnu.org/licenses/>.  */
   16 
   17 /* Written by Eric Blake <ebb9@byu.net>, 2009.  */
   18 
   19 #include <config.h>
   20 
   21 /* Specification.  */
   22 #include <fcntl.h>
   23 
   24 #include "signature.h"
   25 SIGNATURE_CHECK (fcntl, int, (int, int, ...));
   26 
   27 /* Helpers.  */
   28 #include <errno.h>
   29 #include <stdarg.h>
   30 #include <stdbool.h>
   31 #include <unistd.h>
   32 
   33 #if defined _WIN32 && ! defined __CYGWIN__
   34 /* Get declarations of the native Windows API functions.  */
   35 # define WIN32_LEAN_AND_MEAN
   36 # include <windows.h>
   37 /* Get _get_osfhandle.  */
   38 # if GNULIB_MSVC_NOTHROW
   39 #  include "msvc-nothrow.h"
   40 # else
   41 #  include <io.h>
   42 # endif
   43 #endif
   44 
   45 #include "binary-io.h"
   46 #include "macros.h"
   47 
   48 #if !O_BINARY
   49 # define setmode(f,m) zero ()
   50 static int zero (void) { return 0; }
   51 #endif
   52 
   53 /* Return true if FD is open.  */
   54 static bool
   55 is_open (int fd)
   56 {
   57 #if defined _WIN32 && ! defined __CYGWIN__
   58   /* On native Windows, the initial state of unassigned standard file
   59      descriptors is that they are open but point to an
   60      INVALID_HANDLE_VALUE, and there is no fcntl.  */
   61   return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
   62 #else
   63 # ifndef F_GETFL
   64 #  error Please port fcntl to your platform
   65 # endif
   66   return 0 <= fcntl (fd, F_GETFL);
   67 #endif
   68 }
   69 
   70 /* Return true if FD is open and inheritable across exec/spawn.  */
   71 static bool
   72 is_inheritable (int fd)
   73 {
   74 #if defined _WIN32 && ! defined __CYGWIN__
   75   /* On native Windows, the initial state of unassigned standard file
   76      descriptors is that they are open but point to an
   77      INVALID_HANDLE_VALUE, and there is no fcntl.  */
   78   HANDLE h = (HANDLE) _get_osfhandle (fd);
   79   DWORD flags;
   80   if (h == INVALID_HANDLE_VALUE || GetHandleInformation (h, &flags) == 0)
   81     return false;
   82   return (flags & HANDLE_FLAG_INHERIT) != 0;
   83 #else
   84 # ifndef F_GETFD
   85 #  error Please port fcntl to your platform
   86 # endif
   87   int i = fcntl (fd, F_GETFD);
   88   return 0 <= i && (i & FD_CLOEXEC) == 0;
   89 #endif
   90 }
   91 
   92 /* Return non-zero if FD is open in the given MODE, which is either
   93    O_TEXT or O_BINARY.  */
   94 static bool
   95 is_mode (int fd, int mode)
   96 {
   97   int value = setmode (fd, O_BINARY);
   98   setmode (fd, value);
   99   return mode == value;
  100 }
  101 
  102 /* Since native fcntl can have more supported operations than our
  103    replacement is aware of, and since various operations assign
  104    different types to the vararg argument, a wrapper around fcntl must
  105    be able to pass a vararg of unknown type on through to the original
  106    fcntl.  Make sure that this works properly: func1 behaves like the
  107    original fcntl interpreting the vararg as an int or a pointer to a
  108    struct, and func2 behaves like rpl_fcntl that doesn't know what
  109    type to forward.  */
  110 struct dummy_struct
  111 {
  112   long filler;
  113   int value;
  114 };
  115 static int
  116 func1 (int a, ...)
  117 {
  118   va_list arg;
  119   int i;
  120   va_start (arg, a);
  121   if (a < 4)
  122     i = va_arg (arg, int);
  123   else
  124     {
  125       struct dummy_struct *s = va_arg (arg, struct dummy_struct *);
  126       i = s->value;
  127     }
  128   va_end (arg);
  129   return i;
  130 }
  131 static int
  132 func2 (int a, ...)
  133 {
  134   va_list arg;
  135   void *p;
  136   va_start (arg, a);
  137   p = va_arg (arg, void *);
  138   va_end (arg);
  139   return func1 (a, p);
  140 }
  141 
  142 /* Ensure that all supported fcntl actions are distinct, and
  143    usable in preprocessor expressions.  */
  144 static void
  145 check_flags (void)
  146 {
  147   switch (0)
  148     {
  149     case F_DUPFD:
  150 #if F_DUPFD
  151 #endif
  152 
  153     case F_DUPFD_CLOEXEC:
  154 #if F_DUPFD_CLOEXEC
  155 #endif
  156 
  157     case F_GETFD:
  158 #if F_GETFD
  159 #endif
  160 
  161 #ifdef F_SETFD
  162     case F_SETFD:
  163 # if F_SETFD
  164 # endif
  165 #endif
  166 
  167 #ifdef F_GETFL
  168     case F_GETFL:
  169 # if F_GETFL
  170 # endif
  171 #endif
  172 
  173 #ifdef F_SETFL
  174     case F_SETFL:
  175 # if F_SETFL
  176 # endif
  177 #endif
  178 
  179 #ifdef F_GETOWN
  180     case F_GETOWN:
  181 # if F_GETOWN
  182 # endif
  183 #endif
  184 
  185 #ifdef F_SETOWN
  186     case F_SETOWN:
  187 # if F_SETOWN
  188 # endif
  189 #endif
  190 
  191 #ifdef F_GETLK
  192     case F_GETLK:
  193 # if F_GETLK
  194 # endif
  195 #endif
  196 
  197 #ifdef F_SETLK
  198     case F_SETLK:
  199 # if F_SETLK
  200 # endif
  201 #endif
  202 
  203 #ifdef F_SETLKW
  204     case F_SETLKW:
  205 # if F_SETLKW
  206 # endif
  207 #endif
  208 
  209       ;
  210     }
  211 }
  212 
  213 int
  214 main (void)
  215 {
  216   const char *file = "test-fcntl.tmp";
  217   int fd;
  218   int bad_fd = getdtablesize ();
  219 
  220   /* Sanity check that rpl_fcntl is likely to work.  */
  221   ASSERT (func2 (1, 2) == 2);
  222   ASSERT (func2 (2, -2) == -2);
  223   ASSERT (func2 (3, 0x80000000) == 0x80000000);
  224   {
  225     struct dummy_struct s = { 0L, 4 };
  226     ASSERT (func2 (4, &s) == 4);
  227   }
  228   check_flags ();
  229 
  230   /* Assume std descriptors were provided by invoker, and ignore fds
  231      that might have been inherited.  */
  232   fd = creat (file, 0600);
  233   ASSERT (STDERR_FILENO < fd);
  234   close (fd + 1);
  235   close (fd + 2);
  236 
  237   /* For F_DUPFD*, the source must be valid.  */
  238   errno = 0;
  239   ASSERT (fcntl (-1, F_DUPFD, 0) == -1);
  240   ASSERT (errno == EBADF);
  241   errno = 0;
  242   ASSERT (fcntl (fd + 1, F_DUPFD, 0) == -1);
  243   ASSERT (errno == EBADF);
  244   errno = 0;
  245   ASSERT (fcntl (bad_fd, F_DUPFD, 0) == -1);
  246   ASSERT (errno == EBADF);
  247   errno = 0;
  248   ASSERT (fcntl (-1, F_DUPFD_CLOEXEC, 0) == -1);
  249   ASSERT (errno == EBADF);
  250   errno = 0;
  251   ASSERT (fcntl (fd + 1, F_DUPFD_CLOEXEC, 0) == -1);
  252   ASSERT (errno == EBADF);
  253   errno = 0;
  254   ASSERT (fcntl (bad_fd, F_DUPFD_CLOEXEC, 0) == -1);
  255   ASSERT (errno == EBADF);
  256 
  257   /* For F_DUPFD*, the destination must be valid.  */
  258   errno = 0;
  259   ASSERT (fcntl (fd, F_DUPFD, -1) == -1);
  260   ASSERT (errno == EINVAL);
  261   errno = 0;
  262   ASSERT (fcntl (fd, F_DUPFD, bad_fd) == -1);
  263   ASSERT (errno == EINVAL);
  264   errno = 0;
  265   ASSERT (fcntl (fd, F_DUPFD_CLOEXEC, -1) == -1);
  266   ASSERT (errno == EINVAL);
  267   errno = 0;
  268   ASSERT (fcntl (fd, F_DUPFD_CLOEXEC, bad_fd) == -1);
  269   ASSERT (errno == EINVAL
  270           || errno == EMFILE /* WSL */);
  271 
  272   /* For F_DUPFD*, check for correct inheritance, as well as
  273      preservation of text vs. binary.  */
  274   setmode (fd, O_BINARY);
  275   ASSERT (is_open (fd));
  276   ASSERT (!is_open (fd + 1));
  277   ASSERT (!is_open (fd + 2));
  278   ASSERT (is_inheritable (fd));
  279   ASSERT (is_mode (fd, O_BINARY));
  280 
  281   ASSERT (fcntl (fd, F_DUPFD, fd) == fd + 1);
  282   ASSERT (is_open (fd));
  283   ASSERT (is_open (fd + 1));
  284   ASSERT (!is_open (fd + 2));
  285   ASSERT (is_inheritable (fd + 1));
  286   ASSERT (is_mode (fd, O_BINARY));
  287   ASSERT (is_mode (fd + 1, O_BINARY));
  288   ASSERT (close (fd + 1) == 0);
  289 
  290   ASSERT (fcntl (fd, F_DUPFD_CLOEXEC, fd + 2) == fd + 2);
  291   ASSERT (is_open (fd));
  292   ASSERT (!is_open (fd + 1));
  293   ASSERT (is_open (fd + 2));
  294   ASSERT (is_inheritable (fd));
  295   ASSERT (!is_inheritable (fd + 2));
  296   ASSERT (is_mode (fd, O_BINARY));
  297   ASSERT (is_mode (fd + 2, O_BINARY));
  298   ASSERT (close (fd) == 0);
  299 
  300   setmode (fd + 2, O_TEXT);
  301   ASSERT (fcntl (fd + 2, F_DUPFD, fd + 1) == fd + 1);
  302   ASSERT (!is_open (fd));
  303   ASSERT (is_open (fd + 1));
  304   ASSERT (is_open (fd + 2));
  305   ASSERT (is_inheritable (fd + 1));
  306   ASSERT (!is_inheritable (fd + 2));
  307   ASSERT (is_mode (fd + 1, O_TEXT));
  308   ASSERT (is_mode (fd + 2, O_TEXT));
  309   ASSERT (close (fd + 1) == 0);
  310 
  311   ASSERT (fcntl (fd + 2, F_DUPFD_CLOEXEC, 0) == fd);
  312   ASSERT (is_open (fd));
  313   ASSERT (!is_open (fd + 1));
  314   ASSERT (is_open (fd + 2));
  315   ASSERT (!is_inheritable (fd));
  316   ASSERT (!is_inheritable (fd + 2));
  317   ASSERT (is_mode (fd, O_TEXT));
  318   ASSERT (is_mode (fd + 2, O_TEXT));
  319   ASSERT (close (fd + 2) == 0);
  320 
  321   /* Test F_GETFD on invalid file descriptors.  */
  322   errno = 0;
  323   ASSERT (fcntl (-1, F_GETFD) == -1);
  324   ASSERT (errno == EBADF);
  325   errno = 0;
  326   ASSERT (fcntl (fd + 1, F_GETFD) == -1);
  327   ASSERT (errno == EBADF);
  328   errno = 0;
  329   ASSERT (fcntl (bad_fd, F_GETFD) == -1);
  330   ASSERT (errno == EBADF);
  331 
  332   /* Test F_GETFD, the FD_CLOEXEC bit.  */
  333   {
  334     int result = fcntl (fd, F_GETFD);
  335     ASSERT (0 <= result);
  336     ASSERT ((result & FD_CLOEXEC) == FD_CLOEXEC);
  337     ASSERT (dup (fd) == fd + 1);
  338     result = fcntl (fd + 1, F_GETFD);
  339     ASSERT (0 <= result);
  340     ASSERT ((result & FD_CLOEXEC) == 0);
  341     ASSERT (close (fd + 1) == 0);
  342   }
  343 
  344 #ifdef F_SETFD
  345   /* Test F_SETFD on invalid file descriptors.  */
  346   errno = 0;
  347   ASSERT (fcntl (-1, F_SETFD, 0) == -1);
  348   ASSERT (errno == EBADF);
  349   errno = 0;
  350   ASSERT (fcntl (fd + 1, F_SETFD, 0) == -1);
  351   ASSERT (errno == EBADF);
  352   errno = 0;
  353   ASSERT (fcntl (bad_fd, F_SETFD, 0) == -1);
  354   ASSERT (errno == EBADF);
  355 #endif
  356 
  357 #ifdef F_GETFL
  358   /* Test F_GETFL on invalid file descriptors.  */
  359   errno = 0;
  360   ASSERT (fcntl (-1, F_GETFL) == -1);
  361   ASSERT (errno == EBADF);
  362   errno = 0;
  363   ASSERT (fcntl (fd + 1, F_GETFL) == -1);
  364   ASSERT (errno == EBADF);
  365   errno = 0;
  366   ASSERT (fcntl (bad_fd, F_GETFL) == -1);
  367   ASSERT (errno == EBADF);
  368 #endif
  369 
  370 #ifdef F_SETFL
  371   /* Test F_SETFL on invalid file descriptors.  */
  372   errno = 0;
  373   ASSERT (fcntl (-1, F_SETFL, 0) == -1);
  374   ASSERT (errno == EBADF);
  375   errno = 0;
  376   ASSERT (fcntl (fd + 1, F_SETFL, 0) == -1);
  377   ASSERT (errno == EBADF);
  378   errno = 0;
  379   ASSERT (fcntl (bad_fd, F_SETFL, 0) == -1);
  380   ASSERT (errno == EBADF);
  381 #endif
  382 
  383 #ifdef F_GETOWN
  384   /* Test F_GETOWN on invalid file descriptors.  */
  385   errno = 0;
  386   ASSERT (fcntl (-1, F_GETOWN) == -1);
  387   ASSERT (errno == EBADF);
  388   errno = 0;
  389   ASSERT (fcntl (fd + 1, F_GETOWN) == -1);
  390   ASSERT (errno == EBADF);
  391   errno = 0;
  392   ASSERT (fcntl (bad_fd, F_GETOWN) == -1);
  393   ASSERT (errno == EBADF);
  394 #endif
  395 
  396 #ifdef F_SETOWN
  397   /* Test F_SETFL on invalid file descriptors.  */
  398   errno = 0;
  399   ASSERT (fcntl (-1, F_SETOWN, 0) == -1);
  400   ASSERT (errno == EBADF);
  401   errno = 0;
  402   ASSERT (fcntl (fd + 1, F_SETOWN, 0) == -1);
  403   ASSERT (errno == EBADF);
  404   errno = 0;
  405   ASSERT (fcntl (bad_fd, F_SETOWN, 0) == -1);
  406   ASSERT (errno == EBADF);
  407 #endif
  408 
  409   /* Cleanup.  */
  410   ASSERT (close (fd) == 0);
  411   ASSERT (unlink (file) == 0);
  412 
  413   return 0;
  414 }