1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or https://opensource.org/licenses/CDDL-1.0. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2019 by Tomohiro Kusumi. All rights reserved. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <unistd.h> 30 #include <fcntl.h> 31 #include <err.h> 32 33 /* backward compat in case it's not defined */ 34 #ifndef O_TMPFILE 35 #define O_TMPFILE (020000000|O_DIRECTORY) 36 #endif 37 38 /* 39 * DESCRIPTION: 40 * Verify stat(2) for O_TMPFILE file considers umask. 41 * 42 * STRATEGY: 43 * 1. open(2) with O_TMPFILE. 44 * 2. linkat(2). 45 * 3. fstat(2)/stat(2) and verify .st_mode value. 46 */ 47 48 static void 49 test_stat_mode(mode_t mask) 50 { 51 struct stat st, fst; 52 int i, fd; 53 char spath[1024], dpath[1024]; 54 const char *penv[] = {"TESTDIR", "TESTFILE0"}; 55 mode_t masked = 0777 & ~mask; 56 mode_t mode; 57 58 /* 59 * Get the environment variable values. 60 */ 61 for (i = 0; i < ARRAY_SIZE(penv); i++) 62 if ((penv[i] = getenv(penv[i])) == NULL) 63 errx(1, "getenv(penv[%d])", i); 64 65 umask(mask); 66 fd = open(penv[0], O_RDWR|O_TMPFILE, 0777); 67 if (fd == -1) 68 err(2, "open(%s)", penv[0]); 69 70 if (fstat(fd, &fst) == -1) 71 err(3, "open"); 72 73 snprintf(spath, sizeof (spath), "/proc/self/fd/%d", fd); 74 snprintf(dpath, sizeof (dpath), "%s/%s", penv[0], penv[1]); 75 76 unlink(dpath); 77 if (linkat(AT_FDCWD, spath, AT_FDCWD, dpath, AT_SYMLINK_FOLLOW) == -1) 78 err(4, "linkat"); 79 close(fd); 80 81 if (stat(dpath, &st) == -1) 82 err(5, "stat"); 83 unlink(dpath); 84 85 /* Verify fstat(2) result */ 86 mode = fst.st_mode & 0777; 87 if (mode != masked) 88 errx(6, "fstat(2) %o != %o\n", mode, masked); 89 90 /* Verify stat(2) result */ 91 mode = st.st_mode & 0777; 92 if (mode != masked) 93 errx(7, "stat(2) %o != %o\n", mode, masked); 94 } 95 96 int 97 main(void) 98 { 99 fprintf(stdout, "Verify stat(2) for O_TMPFILE file considers umask.\n"); 100 101 test_stat_mode(0022); 102 test_stat_mode(0077); 103 104 return (0); 105 } 106