• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _XOPEN_SOURCE
2 #define _XOPEN_SOURCE 700
3 #endif
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <time.h>
8 #include <sys/types.h>
9 #include <sys/sem.h>
10 #include <sys/wait.h>
11 #include <unistd.h>
12 #include "test.h"
13 
14 static const char path[] = ".";
15 static const int id = 's';
16 
17 #define T(f) do{ \
18 	if ((f)+1 == 0) \
19 		t_error("%s failed: %s\n", #f, strerror(errno)); \
20 }while(0)
21 
22 #define EQ(a,b,fmt) do{ \
23 	if ((a) != (b)) \
24 		t_error("%s == %s failed: " fmt "\n", #a, #b, a, b); \
25 }while(0)
26 
inc()27 static void inc()
28 {
29 	time_t t;
30 	key_t k;
31 	int semid, semval, sempid, semncnt, semzcnt;
32 	struct semid_ds semid_ds;
33 	union semun {
34 		int val;
35 		struct semid_ds *buf;
36 		unsigned short *array;
37 	} arg;
38 	struct sembuf sops;
39 
40 	T(t = time(0));
41 	T(k = ftok(path, id));
42 
43 	/* make sure we get a clean semaphore id */
44 	T(semid = semget(k, 1, IPC_CREAT|0666));
45 	T(semctl(semid, 0, IPC_RMID));
46 	T(semid = semget(k, 1, IPC_CREAT|IPC_EXCL|0666));
47 
48 	if (t_status)
49 		exit(t_status);
50 
51 	/* check IPC_EXCL */
52 	errno = 0;
53 	if (semget(k, 1, IPC_CREAT|IPC_EXCL|0666) != -1 || errno != EEXIST)
54 		t_error("semget(IPC_CREAT|IPC_EXCL) should have failed with EEXIST, got %s\n", strerror(errno));
55 
56 	/* check if msgget initilaized the msqid_ds structure correctly */
57 	arg.buf = &semid_ds;
58 	T(semctl(semid, 0, IPC_STAT, arg));
59 	EQ(semid_ds.sem_perm.cuid, geteuid(), "got %d, want %d");
60 	EQ(semid_ds.sem_perm.uid, geteuid(), "got %d, want %d");
61 	EQ(semid_ds.sem_perm.cgid, getegid(), "got %d, want %d");
62 	EQ(semid_ds.sem_perm.gid, getegid(), "got %d, want %d");
63 	EQ(semid_ds.sem_perm.mode & 0x1ff, 0666, "got %o, want %o");
64 	EQ(semid_ds.sem_nsems, 1, "got %d, want %d");
65 	EQ((long long)semid_ds.sem_otime, 0, "got %lld, want %d");
66 	if (semid_ds.sem_ctime < t)
67 		t_error("semid_ds.sem_ctime >= t failed: got %lld, want >= %lld\n", (long long)semid_ds.sem_ctime, (long long)t);
68 	if (semid_ds.sem_ctime > t+5)
69 		t_error("semid_ds.sem_ctime <= t+5 failed: got %lld, want <= %lld\n", (long long)semid_ds.sem_ctime, (long long)t+5);
70 
71 	/* test sem_op > 0 */
72 	sops.sem_num = 0;
73 	sops.sem_op = 1;
74 	sops.sem_flg = 0;
75 	T(semop(semid, &sops, 1));
76 	T(semval = semctl(semid, 0, GETVAL));
77 	EQ(semval, 1, "got %d, want %d");
78 	T(sempid = semctl(semid, 0, GETPID));
79 	EQ(sempid, getpid(), "got %d, want %d");
80 	T(semncnt = semctl(semid, 0, GETNCNT));
81 	EQ(semncnt, 0, "got %d, want %d");
82 	T(semzcnt = semctl(semid, 0, GETZCNT));
83 	EQ(semzcnt, 0, "got %d, want %d");
84 }
85 
dec()86 static void dec()
87 {
88 	key_t k;
89 	int semid, semval;
90 	struct sembuf sops;
91 
92 	T(k = ftok(path, id));
93 	T(semid = semget(k, 0, 0));
94 
95 	/* test sem_op < 0 */
96 	sops.sem_num = 0;
97 	sops.sem_op = -1;
98 	sops.sem_flg = 0;
99 	T(semop(semid, &sops, 1));
100 	T(semval = semctl(semid, 0, GETVAL));
101 	EQ(semval, 0, "got %d, want %d");
102 
103 	/* cleanup */
104 	T(semctl(semid, 0, IPC_RMID));
105 }
106 
main(void)107 int main(void)
108 {
109 	int p;
110 	int status;
111 
112 	inc();
113 	p = fork();
114 	if (p == -1)
115 		t_error("fork failed: %s\n", strerror(errno));
116 	else if (p == 0)
117 		dec();
118 	else {
119 		T(waitpid(p, &status, 0));
120 		if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
121 			t_error("child exit status: %d\n", status);
122 	}
123 	return t_status;
124 }
125 
126