fifo_create.c revision 149959
16448Sache/*- 26448Sache * Copyright (c) 2005 Robert N. M. Watson 36448Sache * All rights reserved. 46448Sache * 58857Srgrimes * Redistribution and use in source and binary forms, with or without 66448Sache * modification, are permitted provided that the following conditions 76448Sache * are met: 86448Sache * 1. Redistributions of source code must retain the above copyright 96448Sache * notice, this list of conditions and the following disclaimer. 1029612Sjmg * 2. Redistributions in binary form must reproduce the above copyright 1129612Sjmg * notice, this list of conditions and the following disclaimer in the 126448Sache * documentation and/or other materials provided with the distribution. 136448Sache * 14114601Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15114601Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1629963Scharnier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1729963Scharnier * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1829963Scharnier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 196448Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 206448Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2129612Sjmg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2229612Sjmg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 236448Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 246448Sache * SUCH DAMAGE. 2578778Sdd * 266448Sache * $FreeBSD: head/tools/regression/fifo/fifo_create/fifo_create.c 149959 2005-09-10 21:09:26Z rwatson $ 2729612Sjmg */ 2829612Sjmg 2929612Sjmg#include <sys/stat.h> 306448Sache 3129612Sjmg#include <err.h> 3229612Sjmg#include <errno.h> 336448Sache#include <limits.h> 3429612Sjmg#include <stdio.h> 356448Sache#include <stdlib.h> 36113299Smdodd#include <string.h> 37113299Smdodd#include <unistd.h> 38113299Smdodd 3929753Sache/* 4029612Sjmg * Simple regression test for the creation and destruction of POSIX fifos in 416448Sache * the file system name space. Using a specially created directory, create 426448Sache * a fifo in it and check that the following properties are present, as 4329612Sjmg * specified in IEEE Std 1003.1, 2004 Edition: 4469258Skris * 456448Sache * - When mkfifo() is called, on success, a fifo is created. 468857Srgrimes * 4729753Sache * - On an error, no fifo is created. (XXX: Not tested) 4829612Sjmg * 4929612Sjmg * - The mode bits on the fifo are a product of combining the umask and 5029612Sjmg * requested mode. 5129612Sjmg * 5269258Skris * - The fifo's owner will be the processes effective user ID. (XXX: Not 5329612Sjmg * tested) 5429612Sjmg * 5529612Sjmg * - The fifo's group will be the parent directory's group or the effective 566448Sache * group ID of the process. For historical reasons, BSD prefers the group 576448Sache * ID of the process, so we will generate an error if it's not that. (XXX: 586448Sache * Not tested) 5929612Sjmg * 6029612Sjmg * - The st_atime, st_ctime, st_mtime of the fifo will be set appropriately, 616448Sache * and st_ctime and st_mtime on the directory will be updated. (XXX: We 6229612Sjmg * test they are updated, not correct) 6329612Sjmg * 6429612Sjmg * - EEXIST is returned if the named file already exists. 6529612Sjmg * 6629612Sjmg * In addition, we check that we can unlink the fifo, and that if we do, it 6729612Sjmg * disappears. 6829612Sjmg * 6929612Sjmg * This test must run as root in order to usefully frob the process 7029612Sjmg * credential to test permission parts. 7129612Sjmg */ 7229612Sjmg 7329612Sjmg/* 746448Sache * All activity occurs within a temporary directory created early in the 756448Sache * test. 766448Sache */ 776448Sachechar temp_dir[PATH_MAX]; 786448Sache 796448Sachestatic void __unused 806448Sacheatexit_temp_dir(void) 8169258Skris{ 826448Sache 836448Sache rmdir(temp_dir); 846448Sache} 856448Sache 866448Sache/* 878857Srgrimes * Basic creation tests: verify that mkfifo() creates a fifo, that the time 886448Sache * stamps on the directory are updated, that if we try twice we get EEXIST, 896448Sache * and that we can unlink it. 906448Sache */ 9129612Sjmgstatic void 9260741Sjkhfifo_create_test(void) 9375334Sgreid{ 94113299Smdodd struct stat old_dirsb, dirsb, fifosb; 95113299Smdodd char path[PATH_MAX]; 9664657Ssobomax int error; 976448Sache 9829612Sjmg /* 996448Sache * Sleep to make sure that the time stamp on the directory will be 10029612Sjmg * updated. 10129612Sjmg */ 1026448Sache sleep(2); 10329612Sjmg 10429612Sjmg if (stat(temp_dir, &old_dirsb) < 0) 10529612Sjmg err(-1, "basic_create_test: stat: %s", temp_dir); 1066448Sache 10764657Ssobomax snprintf(path, PATH_MAX, "%s/testfifo", temp_dir); 10864657Ssobomax 10964657Ssobomax if (mkfifo(path, 0600) < 0) 11064657Ssobomax err(-1, "basic_create_test: mkfifo: %s", path); 11164657Ssobomax 11264657Ssobomax if (stat(path, &fifosb) < 0) { 11364657Ssobomax error = errno; 11464657Ssobomax (void)unlink(path); 11564657Ssobomax errno = error; 11664657Ssobomax err(-1, "basic_create_test: stat: %s", path); 11764657Ssobomax } 11864657Ssobomax 11964657Ssobomax if (!(S_ISFIFO(fifosb.st_mode))) { 12029612Sjmg (void)unlink(path); 12129963Scharnier errx(-1, "basic_create_test: mkfifo produced non-fifo"); 12229963Scharnier } 12329612Sjmg 12429963Scharnier if (mkfifo(path, 0600) == 0) 12530028Scharnier errx(-1, "basic_create_test: dup mkfifo succeeded"); 12629963Scharnier 12730028Scharnier if (errno != EEXIST) 12829963Scharnier err(-1, "basic_create_test: dup mkfifo unexpected error"); 12930028Scharnier 13029612Sjmg if (stat(temp_dir, &dirsb) < 0) { 1316448Sache error = errno; 13264657Ssobomax (void)unlink(path); 13313803Smpp errno = error; 13413803Smpp err(-1, "basic_create_test: stat: %s", temp_dir); 13513803Smpp } 13613803Smpp 13729963Scharnier if (old_dirsb.st_ctime == dirsb.st_ctime) { 13813803Smpp (void)unlink(path); 13913803Smpp errx(-1, "basic_create_test: old_dirsb.st_ctime == " 14060741Sjkh "dirsb.st_ctime"); 14160741Sjkh } 14260741Sjkh 14360741Sjkh if (old_dirsb.st_mtime == dirsb.st_mtime) { 14413803Smpp (void)unlink(path); 14513803Smpp errx(-1, "basic_create_test: old_dirsb.st_mtime == " 14613803Smpp "dirsb.st_mtime"); 14713803Smpp } 14829612Sjmg 1496448Sache if (unlink(path) < 0) 15075334Sgreid err(-1, "basic_create_test: unlink: %s", path); 15129612Sjmg 15229612Sjmg if (stat(path, &fifosb) == 0) 15329612Sjmg errx(-1, "basic_create_test: unlink failed to unlink"); 15429612Sjmg if (errno != ENOENT) 15529612Sjmg err(-1, "basic_create_test: unlink unexpected error"); 15629612Sjmg} 15729612Sjmg 15864657Ssobomax/* 15929612Sjmg * Having determined that basic create/remove/etc functionality is present 16064657Ssobomax * for fifos, now make sure that the umask, requested permissions, and 16113435Smpp * resulting mode are handled properly. 16229612Sjmg */ 16364657Ssobomaxstatic const struct permission_test { 16429612Sjmg mode_t pt_umask; 16564657Ssobomax mode_t pt_reqmode; 1666448Sache mode_t pt_mode; 16729612Sjmg} permission_test[] = { 16829612Sjmg {0000, 0, S_IFIFO}, 1696448Sache {0000, S_IRWXU, S_IFIFO | S_IRWXU}, 17029612Sjmg {0000, S_IRWXU | S_IRWXG | S_IRWXO, S_IFIFO | S_IRWXU | S_IRWXG | 17129612Sjmg S_IRWXO }, 1726448Sache {0077, S_IRWXU, S_IFIFO | S_IRWXU}, 17329612Sjmg {0077, S_IRWXU | S_IRWXG | S_IRWXO, S_IFIFO | S_IRWXU}, 17429612Sjmg}; 17529612Sjmgstatic const int permission_test_count = sizeof(permission_test) / 17629612Sjmg sizeof(struct permission_test); 17729612Sjmg 17829612Sjmgstatic void 17929612Sjmgfifo_permission_test(void) 18029612Sjmg{ 18129612Sjmg const struct permission_test *ptp; 18229612Sjmg mode_t __unused old_umask; 18329612Sjmg char path[PATH_MAX]; 18429612Sjmg struct stat sb; 1856448Sache int error, i; 18675334Sgreid 18775334Sgreid snprintf(path, PATH_MAX, "%s/testfifo", temp_dir); 18875334Sgreid old_umask = umask(0022); 18975334Sgreid for (i = 0; i < permission_test_count; i++) { 19064657Ssobomax ptp = &permission_test[i]; 19129612Sjmg 19264657Ssobomax umask(ptp->pt_umask); 19329612Sjmg if (mkfifo(path, ptp->pt_reqmode) < 0) 19429612Sjmg err(-1, "fifo_permission_test: %08o %08o %08o\n", 195113299Smdodd ptp->pt_umask, ptp->pt_reqmode, ptp->pt_mode); 196113299Smdodd 197113299Smdodd if (stat(path, &sb) < 0) { 198113299Smdodd error = errno; 199113299Smdodd (void)unlink(path); 200113299Smdodd errno = error; 201113299Smdodd err(-1, "fifo_permission_test: %s", path); 202113299Smdodd } 203113299Smdodd 204113299Smdodd if (sb.st_mode != ptp->pt_mode) { 205113299Smdodd (void)unlink(path); 206113299Smdodd errx(-1, "fifo_permission_test: %08o %08o %08o " 207113299Smdodd "got %08o", ptp->pt_umask, ptp->pt_reqmode, 208113299Smdodd ptp->pt_mode, sb.st_mode); 209113299Smdodd } 210113299Smdodd 211113299Smdodd if (unlink(path) < 0) 212113299Smdodd err(-1, "fifo_permission_test: unlink: %s", path); 21329612Sjmg } 21429612Sjmg umask(old_umask); 21529963Scharnier} 21629612Sjmg 21729612Sjmgint 2186448Sachemain(int argc, char *argv[]) 21960741Sjkh{ 22060741Sjkh 22160741Sjkh if (geteuid() != 0) 22260741Sjkh errx(-1, "must be run as root"); 22360741Sjkh 2246448Sache strcpy(temp_dir, "/tmp/fifo_create.XXXXXXXXXXX"); 22529612Sjmg if (mkdtemp(temp_dir) == NULL) 22629612Sjmg err(-1, "mkdtemp"); 22729612Sjmg atexit(atexit_temp_dir); 22829612Sjmg 22929612Sjmg if (chdir(temp_dir) < 0) 230113299Smdodd err(-1, "chdir"); 231113299Smdodd 232113299Smdodd fifo_create_test(); 233113299Smdodd 234113299Smdodd fifo_permission_test(); 235113299Smdodd 236113299Smdodd return (0); 237113299Smdodd} 238113299Smdodd