Home | History | Annotate | Line # | Download | only in sys
      1 /* $NetBSD: t_umask.c,v 1.2 2017/01/13 19:34:19 christos Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jukka Ruohonen.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: t_umask.c,v 1.2 2017/01/13 19:34:19 christos Exp $");
     33 
     34 #include <sys/stat.h>
     35 #include <sys/wait.h>
     36 
     37 #include <atf-c.h>
     38 #include <fcntl.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <unistd.h>
     42 
     43 static const char path[] = "umask";
     44 static const mode_t mask[] = {
     45 	S_IRWXU,
     46 	S_IRUSR,
     47 	S_IWUSR,
     48 	S_IXUSR,
     49 	S_IRWXG,
     50 	S_IRGRP,
     51 	S_IWGRP,
     52 	S_IXGRP,
     53 	S_IRWXO,
     54 	S_IROTH,
     55 	S_IWOTH,
     56 	S_IXOTH
     57 };
     58 
     59 ATF_TC_WITH_CLEANUP(umask_fork);
     60 ATF_TC_HEAD(umask_fork, tc)
     61 {
     62 	atf_tc_set_md_var(tc, "descr", "Check that umask(2) is inherited");
     63 }
     64 
     65 ATF_TC_BODY(umask_fork, tc)
     66 {
     67 	mode_t mode;
     68 	pid_t pid;
     69 	size_t i;
     70 	int sta;
     71 
     72 	for (i = 0; i < __arraycount(mask) - 1; i++) {
     73 
     74 		(void)umask(mask[i] | mask[i + 1]);
     75 
     76 		pid = fork();
     77 
     78 		if (pid < 0)
     79 			continue;
     80 
     81 		if (pid == 0) {
     82 
     83 			mode = umask(mask[i]);
     84 
     85 			if (mode != (mask[i] | mask[i + 1]))
     86 				_exit(EXIT_FAILURE);
     87 
     88 			_exit(EXIT_SUCCESS);
     89 		}
     90 
     91 		(void)wait(&sta);
     92 
     93 		if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
     94 			goto fail;
     95 	}
     96 
     97 	return;
     98 
     99 fail:
    100 	(void)umask(S_IWGRP | S_IWOTH);
    101 
    102 	atf_tc_fail("umask(2) was not inherited");
    103 }
    104 
    105 ATF_TC_CLEANUP(umask_fork, tc)
    106 {
    107 	(void)umask(S_IWGRP | S_IWOTH);
    108 }
    109 
    110 ATF_TC_WITH_CLEANUP(umask_open);
    111 ATF_TC_HEAD(umask_open, tc)
    112 {
    113 	atf_tc_set_md_var(tc, "descr", "A basic test of open(2) and umask(2)");
    114 }
    115 
    116 ATF_TC_BODY(umask_open, tc)
    117 {
    118 	const char *str = NULL;
    119 	struct stat st;
    120 	size_t i;
    121 	int fd;
    122 
    123 	for (i = 0; i < __arraycount(mask); i++) {
    124 
    125 		(void)umask(mask[i]);
    126 
    127 		fd = open(path, O_RDWR | O_CREAT, 0777);
    128 
    129 		if (fd < 0)
    130 			continue;
    131 
    132 		(void)close(fd);
    133 		(void)memset(&st, 0, sizeof(struct stat));
    134 
    135 		if (stat(path, &st) != 0) {
    136 			str = "failed to stat(2)";
    137 			goto out;
    138 		}
    139 
    140 		if ((st.st_mode & mask[i]) != 0) {
    141 			str = "invalid umask(2)";
    142 			goto out;
    143 		}
    144 
    145 		if (unlink(path) != 0) {
    146 			str = "failed to unlink(2)";
    147 			goto out;
    148 		}
    149 
    150 	}
    151 
    152 out:
    153 	(void)umask(S_IWGRP | S_IWOTH);
    154 
    155 	if (str != NULL)
    156 		atf_tc_fail("%s", str);
    157 }
    158 
    159 ATF_TC_CLEANUP(umask_open, tc)
    160 {
    161 	(void)umask(S_IWGRP | S_IWOTH);
    162 	(void)unlink(path);
    163 }
    164 
    165 ATF_TC_WITH_CLEANUP(umask_previous);
    166 ATF_TC_HEAD(umask_previous, tc)
    167 {
    168 	atf_tc_set_md_var(tc, "descr", "Test the return value from umask(2)");
    169 }
    170 
    171 ATF_TC_BODY(umask_previous, tc)
    172 {
    173 	mode_t mode;
    174 	size_t i;
    175 
    176 	for (i = 0; i < __arraycount(mask); i++) {
    177 
    178 		mode = umask(mask[i]);
    179 		mode = umask(mask[i]);
    180 
    181 		if (mode != mask[i])
    182 			goto fail;
    183 	}
    184 
    185 	return;
    186 
    187 fail:
    188 	(void)umask(S_IWGRP | S_IWOTH);
    189 
    190 	atf_tc_fail("umask(2) did not return the previous mask");
    191 }
    192 
    193 ATF_TC_CLEANUP(umask_previous, tc)
    194 {
    195 	(void)umask(S_IWGRP | S_IWOTH);
    196 }
    197 
    198 ATF_TP_ADD_TCS(tp)
    199 {
    200 
    201 	ATF_TP_ADD_TC(tp, umask_fork);
    202 	ATF_TP_ADD_TC(tp, umask_open);
    203 	ATF_TP_ADD_TC(tp, umask_previous);
    204 
    205 	return atf_no_error();
    206 }
    207