Back to index

glibc  2.9
lockf64.c
Go to the documentation of this file.
00001 /* Copyright (C) 1994,1996,1997,1998,1999,2000,2003,2006
00002        Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <sys/types.h>
00021 #include <unistd.h>
00022 #include <fcntl.h>
00023 #include <errno.h>
00024 #include <string.h>
00025 #include <sysdep.h>
00026 
00027 #include <kernel-features.h>
00028 
00029 /* lockf is a simplified interface to fcntl's locking facilities.  */
00030 
00031 #ifdef __NR_fcntl64
00032 # if __ASSUME_FCNTL64 == 0
00033 /* This variable is shared with all files that check for fcntl64. The
00034    declaration is in fcntl.c.  */
00035 extern int __have_no_fcntl64;
00036 # endif
00037 #endif
00038 
00039 int
00040 lockf64 (int fd, int cmd, off64_t len64)
00041 {
00042 #if __ASSUME_FCNTL64 == 0
00043   struct flock fl;
00044   off_t len = (off_t) len64;
00045 #endif
00046 #ifdef __NR_fcntl64
00047   struct flock64 fl64;
00048   int cmd64;
00049 #endif
00050 
00051 #if __ASSUME_FCNTL64 == 0
00052   memset ((char *) &fl, '\0', sizeof (fl));
00053 
00054   /* lockf is always relative to the current file position.  */
00055   fl.l_whence = SEEK_CUR;
00056   fl.l_start = 0;
00057   fl.l_len = len;
00058 #endif
00059 #ifdef __NR_fcntl64
00060 # if __ASSUME_FCNTL64 == 0
00061   if (!__have_no_fcntl64)
00062     {
00063 # endif
00064       memset ((char *) &fl64, '\0', sizeof (fl64));
00065       fl64.l_whence = SEEK_CUR;
00066       fl64.l_start = 0;
00067       fl64.l_len = len64;
00068 # if __ASSUME_FCNTL64 == 0
00069     }
00070 # endif
00071 #endif
00072 
00073 #if __ASSUME_FCNTL64 == 0 && !defined __NR_fcntl64
00074   if (len64 != (off64_t) len)
00075     {
00076       /* We can't represent the length.  */
00077       __set_errno (EOVERFLOW);
00078       return -1;
00079     }
00080 #endif
00081   switch (cmd)
00082     {
00083     case F_TEST:
00084       /* Test the lock: return 0 if FD is unlocked or locked by this process;
00085         return -1, set errno to EACCES, if another process holds the lock.  */
00086 #if __ASSUME_FCNTL64 > 0
00087       fl64.l_type = F_RDLCK;
00088       if (INLINE_SYSCALL (fcntl64, 3, fd, F_GETLK64, &fl64) < 0)
00089         return -1;
00090       if (fl64.l_type == F_UNLCK || fl64.l_pid == __getpid ())
00091         return 0;
00092       __set_errno (EACCES);
00093       return -1;
00094 #else
00095 # ifdef __NR_fcntl64
00096       if (!__have_no_fcntl64)
00097        {
00098          int res;
00099 
00100          fl64.l_type = F_RDLCK;
00101          res = INLINE_SYSCALL (fcntl64, 3, fd, F_GETLK64, &fl64);
00102          /* If errno == ENOSYS try the 32bit interface if len64 can
00103              be represented with 32 bits.  */
00104 
00105          if (res == 0)
00106            {
00107              if (fl64.l_type == F_UNLCK || fl64.l_pid == __getpid ())
00108               return 0;
00109              __set_errno (EACCES);
00110              return -1;
00111            }
00112          else if (errno == ENOSYS)
00113            __have_no_fcntl64 = 1;
00114          else
00115            /* res < 0 && errno != ENOSYS.  */
00116            return -1;
00117          if (len64 != (off64_t) len)
00118            {
00119              /* We can't represent the length.  */
00120              __set_errno (EOVERFLOW);
00121              return -1;
00122            }
00123        }
00124 # endif
00125       fl.l_type = F_RDLCK;
00126       if (__fcntl (fd, F_GETLK, &fl) < 0)
00127        return -1;
00128       if (fl.l_type == F_UNLCK || fl.l_pid == __getpid ())
00129        return 0;
00130       __set_errno (EACCES);
00131       return -1;
00132 #endif
00133     case F_ULOCK:
00134 #if __ASSUME_FCNTL64 == 0
00135       fl.l_type = F_UNLCK;
00136       cmd = F_SETLK;
00137 #endif
00138 #ifdef __NR_fcntl64
00139       fl64.l_type = F_UNLCK;
00140       cmd64 = F_SETLK64;
00141 #endif
00142       break;
00143     case F_LOCK:
00144 #if __ASSUME_FCNTL64 == 0
00145       fl.l_type = F_WRLCK;
00146       cmd = F_SETLKW;
00147 #endif
00148 #ifdef __NR_fcntl64
00149       fl64.l_type = F_WRLCK;
00150       cmd64 = F_SETLKW64;
00151 #endif
00152       break;
00153     case F_TLOCK:
00154 #if __ASSUME_FCNTL64 == 0
00155       fl.l_type = F_WRLCK;
00156       cmd = F_SETLK;
00157 #endif
00158 #ifdef __NR_fcntl64
00159       fl64.l_type = F_WRLCK;
00160       cmd64 = F_SETLK64;
00161 #endif
00162       break;
00163 
00164     default:
00165       __set_errno (EINVAL);
00166       return -1;
00167     }
00168 #if __ASSUME_FCNTL64 > 0
00169   return INLINE_SYSCALL (fcntl64, 3, fd, cmd64, &fl64);
00170 #else
00171 # ifdef __NR_fcntl64
00172 
00173   if (!__have_no_fcntl64)
00174     {
00175       int res = INLINE_SYSCALL (fcntl64, 3, fd, cmd64, &fl64);
00176 
00177       /* If errno == ENOSYS try the 32bit interface if len64 can
00178         be represented with 32 bits.  */
00179       if (res == 0 || errno != ENOSYS)
00180        return res;
00181 
00182       __have_no_fcntl64 = 1;
00183 
00184       if (len64 != (off64_t) len)
00185        {
00186          /* We can't represent the length.  */
00187          __set_errno (EOVERFLOW);
00188          return -1;
00189        }
00190     }
00191 # endif
00192   return __fcntl (fd, cmd, &fl);
00193 #endif
00194 }