2.9
[glibc/nacl-glibc.git] / sysdeps / unix / sysv / linux / i386 / lockf64.c
blob8b568ff4a3707d8257ca1f165e6f485234b5f8da
1 /* Copyright (C) 1994,1996,1997,1998,1999,2000,2003,2006
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <sysdep.h>
27 #include <kernel-features.h>
29 /* lockf is a simplified interface to fcntl's locking facilities. */
31 #ifdef __NR_fcntl64
32 # if __ASSUME_FCNTL64 == 0
33 /* This variable is shared with all files that check for fcntl64. The
34 declaration is in fcntl.c. */
35 extern int __have_no_fcntl64;
36 # endif
37 #endif
39 int
40 lockf64 (int fd, int cmd, off64_t len64)
42 #if __ASSUME_FCNTL64 == 0
43 struct flock fl;
44 off_t len = (off_t) len64;
45 #endif
46 #ifdef __NR_fcntl64
47 struct flock64 fl64;
48 int cmd64;
49 #endif
51 #if __ASSUME_FCNTL64 == 0
52 memset ((char *) &fl, '\0', sizeof (fl));
54 /* lockf is always relative to the current file position. */
55 fl.l_whence = SEEK_CUR;
56 fl.l_start = 0;
57 fl.l_len = len;
58 #endif
59 #ifdef __NR_fcntl64
60 # if __ASSUME_FCNTL64 == 0
61 if (!__have_no_fcntl64)
63 # endif
64 memset ((char *) &fl64, '\0', sizeof (fl64));
65 fl64.l_whence = SEEK_CUR;
66 fl64.l_start = 0;
67 fl64.l_len = len64;
68 # if __ASSUME_FCNTL64 == 0
70 # endif
71 #endif
73 #if __ASSUME_FCNTL64 == 0 && !defined __NR_fcntl64
74 if (len64 != (off64_t) len)
76 /* We can't represent the length. */
77 __set_errno (EOVERFLOW);
78 return -1;
80 #endif
81 switch (cmd)
83 case F_TEST:
84 /* Test the lock: return 0 if FD is unlocked or locked by this process;
85 return -1, set errno to EACCES, if another process holds the lock. */
86 #if __ASSUME_FCNTL64 > 0
87 fl64.l_type = F_RDLCK;
88 if (INLINE_SYSCALL (fcntl64, 3, fd, F_GETLK64, &fl64) < 0)
89 return -1;
90 if (fl64.l_type == F_UNLCK || fl64.l_pid == __getpid ())
91 return 0;
92 __set_errno (EACCES);
93 return -1;
94 #else
95 # ifdef __NR_fcntl64
96 if (!__have_no_fcntl64)
98 int res;
100 fl64.l_type = F_RDLCK;
101 res = INLINE_SYSCALL (fcntl64, 3, fd, F_GETLK64, &fl64);
102 /* If errno == ENOSYS try the 32bit interface if len64 can
103 be represented with 32 bits. */
105 if (res == 0)
107 if (fl64.l_type == F_UNLCK || fl64.l_pid == __getpid ())
108 return 0;
109 __set_errno (EACCES);
110 return -1;
112 else if (errno == ENOSYS)
113 __have_no_fcntl64 = 1;
114 else
115 /* res < 0 && errno != ENOSYS. */
116 return -1;
117 if (len64 != (off64_t) len)
119 /* We can't represent the length. */
120 __set_errno (EOVERFLOW);
121 return -1;
124 # endif
125 fl.l_type = F_RDLCK;
126 if (__fcntl (fd, F_GETLK, &fl) < 0)
127 return -1;
128 if (fl.l_type == F_UNLCK || fl.l_pid == __getpid ())
129 return 0;
130 __set_errno (EACCES);
131 return -1;
132 #endif
133 case F_ULOCK:
134 #if __ASSUME_FCNTL64 == 0
135 fl.l_type = F_UNLCK;
136 cmd = F_SETLK;
137 #endif
138 #ifdef __NR_fcntl64
139 fl64.l_type = F_UNLCK;
140 cmd64 = F_SETLK64;
141 #endif
142 break;
143 case F_LOCK:
144 #if __ASSUME_FCNTL64 == 0
145 fl.l_type = F_WRLCK;
146 cmd = F_SETLKW;
147 #endif
148 #ifdef __NR_fcntl64
149 fl64.l_type = F_WRLCK;
150 cmd64 = F_SETLKW64;
151 #endif
152 break;
153 case F_TLOCK:
154 #if __ASSUME_FCNTL64 == 0
155 fl.l_type = F_WRLCK;
156 cmd = F_SETLK;
157 #endif
158 #ifdef __NR_fcntl64
159 fl64.l_type = F_WRLCK;
160 cmd64 = F_SETLK64;
161 #endif
162 break;
164 default:
165 __set_errno (EINVAL);
166 return -1;
168 #if __ASSUME_FCNTL64 > 0
169 return INLINE_SYSCALL (fcntl64, 3, fd, cmd64, &fl64);
170 #else
171 # ifdef __NR_fcntl64
173 if (!__have_no_fcntl64)
175 int res = INLINE_SYSCALL (fcntl64, 3, fd, cmd64, &fl64);
177 /* If errno == ENOSYS try the 32bit interface if len64 can
178 be represented with 32 bits. */
179 if (res == 0 || errno != ENOSYS)
180 return res;
182 __have_no_fcntl64 = 1;
184 if (len64 != (off64_t) len)
186 /* We can't represent the length. */
187 __set_errno (EOVERFLOW);
188 return -1;
191 # endif
192 return __fcntl (fd, cmd, &fl);
193 #endif