(root)/
glibc-2.38/
io/
tst-fcntl-lock.c
       1  /* Test for advisory record locking.
       2     Copyright (C) 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 <fcntl.h>
      19  #include <errno.h>
      20  #include <unistd.h>
      21  
      22  /* This is essentially the POSIX lockf.  */
      23  
      24  static int
      25  fcntl_lockf (int fd, int cmd, off_t len)
      26  {
      27    struct flock fl = {
      28      .l_type = F_WRLCK,
      29      .l_whence = SEEK_CUR,
      30      .l_len = len
      31    };
      32  
      33    switch (cmd)
      34      {
      35      case F_TEST:
      36        fl.l_type = F_RDLCK;
      37        if (fcntl (fd, F_GETLK, &fl) < 0)
      38  	return -1;
      39        if (fl.l_type == F_UNLCK || fl.l_pid == getpid ())
      40  	return 0;
      41        errno = EACCES;
      42        return -1;
      43  
      44      case F_ULOCK:
      45        fl.l_type = F_UNLCK;
      46        return fcntl (fd, F_SETLK, &fl);
      47  
      48      case F_LOCK:
      49        return fcntl (fd, F_SETLKW, &fl);
      50  
      51      case F_TLOCK:
      52        return fcntl (fd, F_SETLK, &fl);
      53      }
      54  
      55    errno = EINVAL;
      56    return -1;
      57  }
      58  
      59  static int
      60  fcntl64_lockf (int fd, int cmd, off64_t len64)
      61    {
      62    struct flock64 fl64 = {
      63      .l_type = F_WRLCK,
      64      .l_whence = SEEK_CUR,
      65      .l_len = len64
      66    };
      67  
      68    switch (cmd)
      69      {
      70      case F_TEST:
      71        fl64.l_type = F_RDLCK;
      72        if (fcntl64 (fd, F_GETLK64, &fl64) < 0)
      73  	return -1;
      74        if (fl64.l_type == F_UNLCK || fl64.l_pid == getpid ())
      75  	return 0;
      76        errno = EACCES;
      77        return -1;
      78  
      79      case F_ULOCK:
      80        fl64.l_type = F_UNLCK;
      81        return fcntl64 (fd, F_SETLK64, &fl64);
      82  
      83      case F_LOCK:
      84        return fcntl64 (fd, F_SETLKW64, &fl64);
      85  
      86      case F_TLOCK:
      87        return fcntl64 (fd, F_SETLK64, &fl64);
      88      }
      89  
      90    errno = EINVAL;
      91    return -1;
      92  }
      93  
      94  #define TST_LOCKFD  "tst-fcntl-lock."
      95  #define LOCKF       fcntl_lockf
      96  #define LOCKF64     fcntl64_lockf
      97  #include "tst-lockf.c"