Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/mkbusy.c
48529 views
// SPDX-License-Identifier: CDDL-1.01/*2* This file and its contents are supplied under the terms of the3* Common Development and Distribution License ("CDDL"), version 1.0.4* You may only use this file in accordance with the terms of version5* 1.0 of the CDDL.6*7* A full copy of the text of the CDDL should have accompanied this8* source. A copy of the CDDL is also available via the Internet at9* http://www.illumos.org/license/CDDL.10*/1112/*13* Copyright (c) 2012 by Delphix. All rights reserved.14*/1516/*17* Make a directory busy. If the argument is an existing file or directory,18* simply open it directly and pause. If not, verify that the parent directory19* exists, and create a new file in that directory.20*/2122#include <stdio.h>23#include <sys/types.h>24#include <sys/stat.h>25#include <fcntl.h>26#include <dirent.h>27#include <string.h>28#include <stdlib.h>29#include <unistd.h>30#include <errno.h>31#include <string.h>323334static __attribute__((noreturn)) void35usage(const char *progname)36{37(void) fprintf(stderr, "Usage: %s <dirname|filename>\n", progname);38exit(1);39}4041static __attribute__((noreturn)) void42fail(const char *err)43{44perror(err);45exit(1);46}4748static void49daemonize(void)50{51pid_t pid;5253if ((pid = fork()) < 0) {54fail("fork");55} else if (pid != 0) {56(void) fprintf(stdout, "%ld\n", (long)pid);57exit(0);58}5960(void) setsid();61(void) close(0);62(void) close(1);63(void) close(2);64}656667static const char *68get_basename(const char *path)69{70const char *bn = strrchr(path, '/');71return (bn ? bn + 1 : path);72}7374static ssize_t75get_dirnamelen(const char *path)76{77const char *end = strrchr(path, '/');78return (end ? end - path : -1);79}8081int82main(int argc, char *argv[])83{84int c;85boolean_t isdir = B_FALSE;86struct stat sbuf;87char *fpath = NULL;88char *prog = argv[0];8990while ((c = getopt(argc, argv, "")) != -1) {91switch (c) {92default:93usage(prog);94}95}9697argc -= optind;98argv += optind;99100if (argc != 1)101usage(prog);102103if (stat(argv[0], &sbuf) != 0) {104char *arg;105const char *dname, *fname;106size_t arglen;107ssize_t dnamelen;108109/*110* The argument supplied doesn't exist. Copy the path, and111* remove the trailing slash if present.112*/113if ((arg = strdup(argv[0])) == NULL)114fail("strdup");115arglen = strlen(arg);116if (arg[arglen - 1] == '/')117arg[arglen - 1] = '\0';118119/* Get the directory and file names. */120fname = get_basename(arg);121dname = arg;122if ((dnamelen = get_dirnamelen(arg)) != -1)123arg[dnamelen] = '\0';124else125dname = ".";126127/* The directory portion of the path must exist */128if (stat(dname, &sbuf) != 0 || !(sbuf.st_mode & S_IFDIR))129usage(prog);130131if (asprintf(&fpath, "%s/%s", dname, fname) == -1)132fail("asprintf");133134free(arg);135} else136switch (sbuf.st_mode & S_IFMT) {137case S_IFDIR:138isdir = B_TRUE;139zfs_fallthrough;140case S_IFLNK:141case S_IFCHR:142case S_IFBLK:143if ((fpath = strdup(argv[0])) == NULL)144fail("strdup");145break;146default:147usage(prog);148}149150if (!isdir) {151if (open(fpath, O_CREAT | O_RDWR, 0600) < 0)152fail("open");153} else {154if (opendir(fpath) == NULL)155fail("opendir");156}157free(fpath);158159daemonize();160(void) pause();161162return (0);163}164165166