maint: update copyright
[gnulib.git] / tests / test-flock.c
1 /* Test of flock() function.
2    Copyright (C) 2008-2014 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (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 <http://www.gnu.org/licenses/>.  */
16
17 #include <config.h>
18
19 #include <sys/file.h>
20
21 #include "signature.h"
22 SIGNATURE_CHECK (flock, int, (int, int));
23
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <errno.h>
27
28 #include "macros.h"
29
30 static void
31 test_shared (const char *file, int fd)
32 {
33   /* Should be able to acquire several shared locks on a file, through
34    * different file table entries.
35    */
36   int fd2, r;
37
38   ASSERT (flock (fd, LOCK_SH) == 0);
39
40   fd2 = open (file, O_RDWR, 0644);
41   ASSERT (fd2 >= 0);
42
43   r = flock (fd2, LOCK_SH | LOCK_NB);
44   ASSERT (r == 0);              /* Was able to acquire a second shared lock. */
45
46   ASSERT (flock (fd, LOCK_UN) == 0);
47   ASSERT (close (fd2) == 0);
48 }
49
50 static void
51 test_exclusive (const char *file, int fd)
52 {
53   /* Should not be able to acquire more than one exclusive lock on a file. */
54   int fd2, r;
55
56   ASSERT (flock (fd, LOCK_EX) == 0);
57
58   fd2 = open (file, O_RDWR, 0644);
59   ASSERT (fd2 >= 0);
60
61   r = flock (fd2, LOCK_EX | LOCK_NB);
62   ASSERT (r == -1);             /* Was unable to acquire a second exclusive lock. */
63
64 #if 0
65   /* The Linux manual page of flock(2) says:
66        "A process may only hold one type of lock (shared or exclusive) on a
67        file. Subsequent flock() calls on an already locked file will convert
68        an existing lock to the new lock mode."
69      So, the call below should convert the exclusive lock for fd to a shared
70      and thus succeeds.  The fact that it doesn't but instead fails is
71      apparently a bug.  */
72   /* The Solaris manual page of flock(2) says:
73        "More than one process may hold a shared lock for a file at any given
74         time, but multiple exclusive, or both shared and exclusive, locks may
75         not exist simultaneously on a file. ...
76         Requesting a lock on an object that is already locked normally causes
77         the caller to block until the lock may be acquired. If LOCK_NB is
78         included in operation, then this will not happen; instead, the call
79         will fail and the error EWOULDBLOCK will be returned."
80      So, the call below should fail and set errno to EWOULDBLOCK.  The fact
81      that it succeeds is apparently a bug.  */
82   r = flock (fd2, LOCK_SH | LOCK_NB);
83   ASSERT (r == -1);
84 #endif
85
86   ASSERT (flock (fd, LOCK_UN) == 0);
87   ASSERT (close (fd2) == 0);
88 }
89
90 int
91 main (int argc, char *argv[])
92 {
93   int fd;
94   const char *file = "test-flock.txt";
95
96   /* Open a non-empty file for testing. */
97   fd = open (file, O_RDWR | O_CREAT | O_TRUNC, 0644);
98   ASSERT (fd >= 0);
99   ASSERT (write (fd, "hello", 5) == 5);
100
101 #if defined __linux__
102   /* Invalid operation codes are rejected by the Linux implementation and by
103      the gnulib replacement,  but not by the Mac OS X implementation.  */
104   ASSERT (flock (fd, LOCK_SH | LOCK_EX) == -1);
105   ASSERT (errno == EINVAL);
106   ASSERT (flock (fd, LOCK_SH | LOCK_UN) == -1);
107   ASSERT (errno == EINVAL);
108   ASSERT (flock (fd, LOCK_EX | LOCK_UN) == -1);
109   ASSERT (errno == EINVAL);
110   ASSERT (flock (fd, 0) == -1);
111   ASSERT (errno == EINVAL);
112 #endif
113
114   test_shared (file, fd);
115   test_exclusive (file, fd);
116
117   /* Close and remove the test file. */
118   ASSERT (close (fd) == 0);
119   ASSERT (unlink (file) == 0);
120
121   return 0;
122 }