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 14static const char path[] = "."; 15static 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 27static 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 86static 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 107int 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