1 /* Copyright (C) 2002-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library 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 GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <semaphore.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 
25 
26 static void
remove_sem(int status,void * arg)27 remove_sem (int status, void *arg)
28 {
29   sem_unlink (arg);
30 }
31 
32 
33 int
do_test(void)34 do_test (void)
35 {
36   sem_t *s;
37   sem_t *s2;
38   pid_t pid;
39   int val;
40 
41   /* Start with a clean slate and register a clean-up action.  No need to
42      act if sem_unlink fails because we will catch the same problem during the
43      sem_open below.  */
44   sem_unlink ("/glibc-tst-sem4");
45   on_exit (remove_sem, (void *) "/glibc-tst-sem4");
46 
47   s = sem_open ("/glibc-tst-sem4", O_CREAT, 0600, 1);
48   if (s == SEM_FAILED)
49     {
50       if (errno == ENOSYS)
51 	{
52 	  puts ("sem_open not supported.  Oh well.");
53 	  return 0;
54 	}
55 
56       /* Maybe the shm filesystem has strict permissions.  */
57       if (errno == EACCES)
58 	{
59 	  puts ("sem_open not allowed.  Oh well.");
60 	  return 0;
61 	}
62 
63       printf ("sem_open: %m\n");
64       return 1;
65     }
66 
67   /* We have the semaphore object.  Now try again with O_EXCL, this
68      should fail.  */
69   s2 = sem_open ("/glibc-tst-sem4", O_CREAT | O_EXCL, 0600, 1);
70   if (s2 != SEM_FAILED)
71     {
72       puts ("2nd sem_open didn't fail");
73       return 1;
74     }
75   if (errno != EEXIST)
76     {
77       puts ("2nd sem_open returned wrong error");
78       return 1;
79     }
80 
81   /* Check the value.  */
82   if (sem_getvalue (s, &val) == -1)
83     {
84       puts ("getvalue failed");
85       return 1;
86     }
87   if (val != 1)
88     {
89       printf ("initial value wrong: got %d, expected 1\n", val);
90       return 1;
91     }
92 
93   if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
94     {
95       puts ("1st sem_wait failed");
96       return 1;
97     }
98 
99   pid = fork ();
100   if (pid == -1)
101     {
102       printf ("fork failed: %m\n");
103       return 1;
104     }
105 
106   if (pid == 0)
107     {
108       /* Child.  */
109 
110       /* Check the value.  */
111       if (sem_getvalue (s, &val) == -1)
112 	{
113 	  puts ("child: getvalue failed");
114 	  return 1;
115 	}
116       if (val != 0)
117 	{
118 	  printf ("child: value wrong: got %d, expect 0\n", val);
119 	  return 1;
120 	}
121 
122       if (sem_post (s) == -1)
123 	{
124 	  puts ("child: post failed");
125 	  return 1;
126 	}
127     }
128   else
129     {
130       if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
131 	{
132 	  puts ("2nd sem_wait failed");
133 	  return 1;
134 	}
135 
136       if (sem_getvalue (s, &val) == -1)
137 	{
138 	  puts ("parent: 2nd getvalue failed");
139 	  return 1;
140 	}
141       if (val != 0)
142 	{
143 	  printf ("parent: value wrong: got %d, expected 0\n", val);
144 	  return 1;
145 	}
146     }
147 
148   return 0;
149 }
150 
151 #define TEST_FUNCTION do_test ()
152 #include "../test-skeleton.c"
153