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 http://www.opensolaris.org/os/licensing. 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 32 /* backward compat in case it's not defined */ 33 #ifndef O_TMPFILE 34 #define O_TMPFILE (020000000|O_DIRECTORY) 35 #endif 36 37 /* 38 * DESCRIPTION: 39 * Verify stat(2) for O_TMPFILE file considers umask. 40 * 41 * STRATEGY: 42 * 1. open(2) with O_TMPFILE. 43 * 2. linkat(2). 44 * 3. fstat(2)/stat(2) and verify .st_mode value. 45 */ 46 47 static void 48 test_stat_mode(mode_t mask) 49 { 50 struct stat st, fst; 51 int i, fd; 52 char spath[1024], dpath[1024]; 53 char *penv[] = {"TESTDIR", "TESTFILE0"}; 54 mode_t masked = 0777 & ~mask; 55 mode_t mode; 56 57 /* 58 * Get the environment variable values. 59 */ 60 for (i = 0; i < sizeof (penv) / sizeof (char *); i++) { 61 if ((penv[i] = getenv(penv[i])) == NULL) { 62 fprintf(stderr, "getenv(penv[%d])\n", i); 63 exit(1); 64 } 65 } 66 67 umask(mask); 68 fd = open(penv[0], O_RDWR|O_TMPFILE, 0777); 69 if (fd == -1) { 70 perror("open"); 71 exit(2); 72 } 73 74 if (fstat(fd, &fst) == -1) { 75 perror("fstat"); 76 close(fd); 77 exit(3); 78 } 79 80 snprintf(spath, sizeof (spath), "/proc/self/fd/%d", fd); 81 snprintf(dpath, sizeof (dpath), "%s/%s", penv[0], penv[1]); 82 83 unlink(dpath); 84 if (linkat(AT_FDCWD, spath, AT_FDCWD, dpath, AT_SYMLINK_FOLLOW) == -1) { 85 perror("linkat"); 86 close(fd); 87 exit(4); 88 } 89 close(fd); 90 91 if (stat(dpath, &st) == -1) { 92 perror("stat"); 93 exit(5); 94 } 95 unlink(dpath); 96 97 /* Verify fstat(2) result */ 98 mode = fst.st_mode & 0777; 99 if (mode != masked) { 100 fprintf(stderr, "fstat(2) %o != %o\n", mode, masked); 101 exit(6); 102 } 103 104 /* Verify stat(2) result */ 105 mode = st.st_mode & 0777; 106 if (mode != masked) { 107 fprintf(stderr, "stat(2) %o != %o\n", mode, masked); 108 exit(7); 109 } 110 } 111 112 int 113 main(int argc, char *argv[]) 114 { 115 fprintf(stdout, "Verify stat(2) for O_TMPFILE file considers umask.\n"); 116 117 test_stat_mode(0022); 118 test_stat_mode(0077); 119 120 return (0); 121 } 122