t_msgget.c revision 285830
190075Sobrien/* $NetBSD: t_msgget.c,v 1.2 2014/02/27 00:59:50 joerg Exp $ */ 250397Sobrien 3169689Skan/*- 450397Sobrien * Copyright (c) 2011 The NetBSD Foundation, Inc. 590075Sobrien * All rights reserved. 650397Sobrien * 790075Sobrien * This code is derived from software contributed to The NetBSD Foundation 890075Sobrien * by Jukka Ruohonen. 990075Sobrien * 1090075Sobrien * Redistribution and use in source and binary forms, with or without 1150397Sobrien * modification, are permitted provided that the following conditions 1290075Sobrien * are met: 1390075Sobrien * 1. Redistributions of source code must retain the above copyright 1490075Sobrien * notice, this list of conditions and the following disclaimer. 1590075Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1650397Sobrien * notice, this list of conditions and the following disclaimer in the 1750397Sobrien * documentation and/or other materials provided with the distribution. 1890075Sobrien * 19169689Skan * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20169689Skan * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2150397Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2250397Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2350397Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2450397Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2550397Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2650397Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2750397Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2850397Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2990075Sobrien * POSSIBILITY OF SUCH DAMAGE. 3090075Sobrien */ 3150397Sobrien#include <sys/cdefs.h> 3290075Sobrien__RCSID("$NetBSD: t_msgget.c,v 1.2 2014/02/27 00:59:50 joerg Exp $"); 3350397Sobrien 3450397Sobrien#include <sys/msg.h> 35169689Skan#include <sys/stat.h> 3650397Sobrien#include <sys/sysctl.h> 3750397Sobrien#include <sys/wait.h> 3850397Sobrien 3990075Sobrien#include <atf-c.h> 4090075Sobrien#include <errno.h> 4190075Sobrien#include <pwd.h> 4290075Sobrien#include <stdio.h> 4390075Sobrien#include <stdlib.h> 4490075Sobrien#include <string.h> 4590075Sobrien#include <sysexits.h> 4690075Sobrien#include <time.h> 4790075Sobrien#include <unistd.h> 4890075Sobrien 4990075Sobrien#define MSG_KEY 12345689 5090075Sobrien 5190075Sobrienstatic void clean(void); 5290075Sobrien 5350397Sobrienstatic void 54117395Skanclean(void) 5550397Sobrien{ 5690075Sobrien int id; 5790075Sobrien 5890075Sobrien if ((id = msgget(MSG_KEY, 0)) != -1) 5990075Sobrien (void)msgctl(id, IPC_RMID, 0); 6090075Sobrien} 6190075Sobrien 62117395SkanATF_TC_WITH_CLEANUP(msgget_excl); 6390075SobrienATF_TC_HEAD(msgget_excl, tc) 6490075Sobrien{ 6590075Sobrien atf_tc_set_md_var(tc, "descr", "Test msgget(2) with IPC_EXCL"); 6690075Sobrien} 6790075Sobrien 6890075SobrienATF_TC_BODY(msgget_excl, tc) 6990075Sobrien{ 7090075Sobrien int id; 7190075Sobrien 72117395Skan /* 7390075Sobrien * Create a message queue and re-open it with 7490075Sobrien * O_CREAT and IPC_EXCL set. This should fail. 7590075Sobrien */ 7690075Sobrien id = msgget(MSG_KEY, IPC_CREAT | 0600); 7790075Sobrien 7890075Sobrien if (id < 0) 7990075Sobrien atf_tc_fail("failed to create message queue"); 80117395Skan 8190075Sobrien errno = 0; 8290075Sobrien 8390075Sobrien if (msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | 0600) != -1) 8490075Sobrien atf_tc_fail("msgget(2) failed for IPC_EXCL"); 8590075Sobrien 8690075Sobrien ATF_REQUIRE(errno == EEXIST); 8790075Sobrien 88117395Skan /* 8990075Sobrien * However, the same call should succeed 9090075Sobrien * when IPC_EXCL is not set in the flags. 9190075Sobrien */ 9290075Sobrien id = msgget(MSG_KEY, IPC_CREAT | 0600); 9390075Sobrien 9490075Sobrien if (id < 0) 95117395Skan atf_tc_fail("msgget(2) failed to re-open"); 9690075Sobrien 9790075Sobrien ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0); 9890075Sobrien} 9990075Sobrien 10090075SobrienATF_TC_CLEANUP(msgget_excl, tc) 10190075Sobrien{ 102117395Skan clean(); 10390075Sobrien} 10490075Sobrien 10590075SobrienATF_TC_WITH_CLEANUP(msgget_exit); 106117395SkanATF_TC_HEAD(msgget_exit, tc) 10790075Sobrien{ 10890075Sobrien atf_tc_set_md_var(tc, "descr", 10990075Sobrien "Test that XSI message queues are " 11090075Sobrien "not removed when the process exits"); 11190075Sobrien} 112117395Skan 11390075SobrienATF_TC_BODY(msgget_exit, tc) 11490075Sobrien{ 115117395Skan int id, sta; 11690075Sobrien pid_t pid; 11790075Sobrien 11890075Sobrien pid = fork(); 11990075Sobrien ATF_REQUIRE(pid >= 0); 120117395Skan 12190075Sobrien if (pid == 0) { 12290075Sobrien 12350397Sobrien if (msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | 0600) == -1) 12450397Sobrien _exit(EXIT_FAILURE); 12550397Sobrien 12690075Sobrien _exit(EXIT_SUCCESS); 12790075Sobrien } 128117395Skan 12990075Sobrien (void)wait(&sta); 13090075Sobrien 13190075Sobrien if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) 13290075Sobrien atf_tc_fail("failed to create message queue"); 13390075Sobrien 13490075Sobrien id = msgget(MSG_KEY, 0); 13590075Sobrien 13650397Sobrien if (id == -1) 137117395Skan atf_tc_fail("message queue was removed on process exit"); 13850397Sobrien 13950397Sobrien ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0); 14050397Sobrien} 14150397Sobrien 14290075SobrienATF_TC_CLEANUP(msgget_exit, tc) 14350397Sobrien{ 144117395Skan clean(); 14550397Sobrien} 14650397Sobrien 14750397SobrienATF_TC_WITH_CLEANUP(msgget_init); 14850397SobrienATF_TC_HEAD(msgget_init, tc) 14990075Sobrien{ 15050397Sobrien atf_tc_set_md_var(tc, "descr", 151117395Skan "Test that msgget(2) initializes data structures properly"); 15250397Sobrien} 15390075Sobrien 15450397SobrienATF_TC_BODY(msgget_init, tc) 15550397Sobrien{ 15650397Sobrien const uid_t uid = geteuid(); 15790075Sobrien const gid_t gid = getegid(); 15890075Sobrien struct msqid_ds msgds; 159117395Skan time_t t; 16090075Sobrien int id; 16190075Sobrien 16290075Sobrien (void)memset(&msgds, 0x9, sizeof(struct msqid_ds)); 16390075Sobrien 16490075Sobrien t = time(NULL); 16590075Sobrien id = msgget(MSG_KEY, IPC_CREAT | 0600); 16690075Sobrien 167117395Skan ATF_REQUIRE(id !=-1); 16890075Sobrien ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0); 16990075Sobrien 17090075Sobrien ATF_CHECK(msgds.msg_qnum == 0); 17190075Sobrien ATF_CHECK(msgds.msg_lspid == 0); 17290075Sobrien ATF_CHECK(msgds.msg_lrpid == 0); 17390075Sobrien ATF_CHECK(msgds.msg_rtime == 0); 17490075Sobrien ATF_CHECK(msgds.msg_stime == 0); 17590075Sobrien ATF_CHECK(msgds.msg_perm.uid == uid); 176117395Skan ATF_CHECK(msgds.msg_perm.gid == gid); 17790075Sobrien ATF_CHECK(msgds.msg_perm.cuid == uid); 17890075Sobrien ATF_CHECK(msgds.msg_perm.cgid == gid); 17990075Sobrien ATF_CHECK(msgds.msg_perm.mode == 0600); 18090075Sobrien 18190075Sobrien if (llabs(t - msgds.msg_ctime) > 5) 18290075Sobrien atf_tc_fail("msgget(2) initialized current time incorrectly"); 183117395Skan 18490075Sobrien ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0); 18590075Sobrien} 18690075Sobrien 18790075SobrienATF_TC_CLEANUP(msgget_init, tc) 18890075Sobrien{ 18990075Sobrien clean(); 190117395Skan} 191117395Skan 19290075SobrienATF_TC(msgget_limit); 19390075SobrienATF_TC_HEAD(msgget_limit, tc) 19490075Sobrien{ 19590075Sobrien atf_tc_set_md_var(tc, "descr", "Test msgget(2) against system limits"); 19690075Sobrien} 19790075Sobrien 198117395SkanATF_TC_BODY(msgget_limit, tc) 19990075Sobrien{ 20090075Sobrien size_t len = sizeof(int); 20190075Sobrien bool fail = false; 20290075Sobrien int i, lim = 0; 20390075Sobrien int *buf; 20490075Sobrien 205117395Skan if (sysctlbyname("kern.ipc.msgmni", &lim, &len, NULL, 0) != 0) 20690075Sobrien atf_tc_skip("failed to read kern.ipc.msgmni sysctl"); 20790075Sobrien 20890075Sobrien buf = calloc(lim + 1, sizeof(*buf)); 20990075Sobrien ATF_REQUIRE(buf != NULL); 21090075Sobrien 21190075Sobrien for (i = 0; i < lim; i++) { 21290075Sobrien 21390075Sobrien buf[i] = msgget(MSG_KEY + i, IPC_CREAT | IPC_EXCL | 0600); 21490075Sobrien 21590075Sobrien (void)fprintf(stderr, "key[%d] = %d\n", i, buf[i]); 21690075Sobrien 21790075Sobrien /* 21890075Sobrien * This test only works when there are zero existing 21990075Sobrien * message queues. Thus, bypass the unit test when 22090075Sobrien * this precondition is not met, for reason or another. 22190075Sobrien */ 22290075Sobrien if (buf[i] == -1) 22390075Sobrien goto out; 22490075Sobrien } 22590075Sobrien 22690075Sobrien i++; 22790075Sobrien errno = 0; 22890075Sobrien 22990075Sobrien buf[i] = msgget(MSG_KEY + i, IPC_CREAT | IPC_EXCL | 0600); 23090075Sobrien 23190075Sobrien if (buf[i] != -1 || errno != ENOSPC) 23290075Sobrien fail = true; 23390075Sobrien 23490075Sobrienout: /* Remember to clean-up. */ 23590075Sobrien for (i = 0; i < lim; i++) 236169689Skan (void)msgctl(buf[i], IPC_RMID, 0); 237169689Skan 238169689Skan free(buf); 239169689Skan 240169689Skan if (fail != false) 241169689Skan atf_tc_fail("msgget(2) opened more than %d queues", lim); 242169689Skan} 243169689Skan 244169689SkanATF_TC_WITH_CLEANUP(msgget_mode); 245169689SkanATF_TC_HEAD(msgget_mode, tc) 246169689Skan{ 247169689Skan atf_tc_set_md_var(tc, "descr", "Test different modes with msgget(2)"); 248169689Skan atf_tc_set_md_var(tc, "require.user", "root"); 249169689Skan} 250169689Skan 251169689SkanATF_TC_BODY(msgget_mode, tc) 252169689Skan{ 253169689Skan static const mode_t mode[] = { 25490075Sobrien S_IRWXU, S_IRUSR, S_IWUSR, S_IXUSR, S_IRWXG, S_IRGRP, 25590075Sobrien S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH 25690075Sobrien }; 25790075Sobrien 25890075Sobrien struct msqid_ds msgds; 259 size_t i; 260 int id; 261 262 for (i = 0; i < __arraycount(mode); i++) { 263 264 (void)fprintf(stderr, "testing mode %d\n", mode[i]); 265 (void)memset(&msgds, 0, sizeof(struct msqid_ds)); 266 267 id = msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | (int)mode[i]); 268 269 ATF_REQUIRE(id != -1); 270 ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0); 271 ATF_REQUIRE(msgds.msg_perm.mode == mode[i]); 272 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0); 273 } 274} 275 276ATF_TC_CLEANUP(msgget_mode, tc) 277{ 278 clean(); 279} 280 281 282ATF_TP_ADD_TCS(tp) 283{ 284 285 ATF_TP_ADD_TC(tp, msgget_excl); 286 ATF_TP_ADD_TC(tp, msgget_exit); 287 ATF_TP_ADD_TC(tp, msgget_init); 288 ATF_TP_ADD_TC(tp, msgget_limit); 289 ATF_TP_ADD_TC(tp, msgget_mode); 290 291 return atf_no_error(); 292} 293