1  /* Check non representable OFD locks regions in non-LFS mode (BZ #20251)
       2     Copyright (C) 2018-2023 Free Software Foundation, Inc.
       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, see <https://www.gnu.org/licenses/>.
      16  */
      17  
      18  #include <unistd.h>
      19  #include <fcntl.h>
      20  #include <stdint.h>
      21  #include <errno.h>
      22  
      23  #include <support/temp_file.h>
      24  #include <support/check.h>
      25  
      26  static char *temp_filename;
      27  static int temp_fd;
      28  
      29  static void
      30  do_prepare (int argc, char **argv)
      31  {
      32    temp_fd = create_temp_file ("tst-ofdlocks.", &temp_filename);
      33    TEST_VERIFY_EXIT (temp_fd != -1);
      34  }
      35  
      36  #define PREPARE do_prepare
      37  
      38  static int
      39  do_test (void)
      40  {
      41    /* It first allocates a open file description lock range which can not
      42       be represented in a 32 bit struct flock.   */
      43    struct flock64 lck64 = {
      44      .l_type   = F_WRLCK,
      45      .l_whence = SEEK_SET,
      46      .l_start  = (off64_t)INT32_MAX + 1024,
      47      .l_len    = 1024,
      48    };
      49    int ret = fcntl64 (temp_fd, F_OFD_SETLKW, &lck64);
      50    if (ret == -1 && errno == EINVAL)
      51      /* OFD locks are only available on Linux 3.15.  */
      52      FAIL_UNSUPPORTED ("fcntl (F_OFD_SETLKW) not supported");
      53  
      54    TEST_VERIFY_EXIT (ret == 0);
      55  
      56    /* Open file description locks placed through the same open file description
      57       (either by same file descriptor or a duplicated one created by fork,
      58       dup, fcntl F_DUPFD, etc.) overwrites then old lock.  To force a
      59       conflicting lock combination, it creates a new file descriptor.  */
      60    int fd = open64 (temp_filename, O_RDWR, 0666);
      61    TEST_VERIFY_EXIT (fd != -1);
      62  
      63    /* It tries then to allocate another open file descriptor with a valid
      64       non-LFS bits struct flock but which will result in a conflicted region
      65       which can not be represented in a non-LFS struct flock.  */
      66    struct flock lck = {
      67      .l_type   = F_WRLCK,
      68      .l_whence = SEEK_SET,
      69      .l_start  = INT32_MAX - 1024,
      70      .l_len    = 4 * 1024,
      71    };
      72    int r = fcntl (fd, F_OFD_GETLK, &lck);
      73    if (sizeof (off_t) != sizeof (off64_t))
      74      TEST_VERIFY (r == -1 && errno == EOVERFLOW);
      75    else
      76      TEST_VERIFY (r == 0);
      77  
      78    return 0;
      79  }
      80  
      81  #include <support/test-driver.c>