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 fstat(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) and verify .st_mode value. 46 */ 47 48 static void 49 test_stat_mode(mode_t mask) 50 { 51 struct stat 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, "fstat(%s)", penv[0]); 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 /* Verify fstat(2) result at old path */ 82 mode = fst.st_mode & 0777; 83 if (mode != masked) 84 errx(5, "fstat(2) %o != %o\n", mode, masked); 85 86 fd = open(dpath, O_RDWR); 87 if (fd == -1) 88 err(6, "open(%s)", dpath); 89 90 if (fstat(fd, &fst) == -1) 91 err(7, "fstat(%s)", dpath); 92 93 /* Verify fstat(2) result at new path */ 94 mode = fst.st_mode & 0777; 95 if (mode != masked) 96 errx(8, "fstat(2) %o != %o\n", mode, masked); 97 close(fd); 98 } 99 100 int 101 main(void) 102 { 103 fprintf(stdout, "Verify stat(2) for O_TMPFILE file considers umask.\n"); 104 105 test_stat_mode(0022); 106 test_stat_mode(0077); 107 108 return (0); 109 } 110