(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
tst-o_path-locks.c
       1  /* Test that closing O_PATH descriptors does not release POSIX advisory locks.
       2     Copyright (C) 2020-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <fcntl.h>
      21  #include <stdbool.h>
      22  #include <stdlib.h>
      23  #include <support/check.h>
      24  #include <support/namespace.h>
      25  #include <support/support.h>
      26  #include <support/temp_file.h>
      27  #include <support/xunistd.h>
      28  
      29  /* The subprocess writes the errno value of the lock operation
      30     here.  */
      31  static int *shared_errno;
      32  
      33  /* The path of the temporary file which is locked.  */
      34  static char *path;
      35  
      36  /* Try to obtain an exclusive lock on the file at path.  */
      37  static void
      38  subprocess (void *closure)
      39  {
      40    int fd = xopen (path, O_RDWR, 0);
      41    struct flock64 lock = { .l_type = F_WRLCK, };
      42    int ret = fcntl64 (fd, F_SETLK, &lock);
      43    if (ret == 0)
      44      *shared_errno = 0;
      45    else
      46      *shared_errno = errno;
      47    xclose (fd);
      48  }
      49  
      50  /* Return true if the file at path is currently locked, false if
      51     not.  */
      52  static bool
      53  probe_lock (void)
      54  {
      55    *shared_errno = -1;
      56    support_isolate_in_subprocess (subprocess, NULL);
      57    if (*shared_errno == 0)
      58      /* Lock was acquired by the subprocess, so this process has not
      59         locked it.  */
      60      return false;
      61    else
      62      {
      63        /* POSIX allows both EACCES and EAGAIN.  Linux use EACCES.  */
      64        TEST_COMPARE (*shared_errno, EAGAIN);
      65        return true;
      66      }
      67  }
      68  
      69  static int
      70  do_test (void)
      71  {
      72    shared_errno = support_shared_allocate (sizeof (*shared_errno));
      73    int fd = create_temp_file ("tst-o_path-locks-", &path);
      74  
      75    /* The file is not locked initially.  */
      76    TEST_VERIFY (!probe_lock ());
      77  
      78    struct flock64 lock = { .l_type = F_WRLCK, };
      79    TEST_COMPARE (fcntl64 (fd, F_SETLK, &lock), 0);
      80  
      81    /* The lock has been acquired.  */
      82    TEST_VERIFY (probe_lock ());
      83  
      84    /* Closing the same file via a different descriptor releases the
      85       lock.  */
      86    xclose (xopen (path, O_RDONLY, 0));
      87    TEST_VERIFY (!probe_lock ());
      88  
      89    /* But not if it is an O_PATH descriptor.  */
      90    TEST_COMPARE (fcntl64 (fd, F_SETLK, &lock), 0);
      91    xclose (xopen (path, O_PATH, 0));
      92    TEST_VERIFY (probe_lock ());
      93  
      94    xclose (fd);
      95    free (path);
      96    support_shared_free (shared_errno);
      97    return 0;
      98  }
      99  
     100  #include <support/test-driver.c>