d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * This file and its contents are supplied under the terms of the
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Common Development and Distribution License ("CDDL"), version 1.0.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * You may only use this file in accordance with the terms of version
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * 1.0 of the CDDL.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * A full copy of the text of the CDDL should have accompanied this
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * source. A copy of the CDDL is also available via the Internet at
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * http://www.illumos.org/license/CDDL.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Copyright (c) 2012 by Delphix. All rights reserved.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy/*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Make a directory busy. If the argument is an existing file or directory,
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * simply open it directly and pause. If not, verify that the parent directory
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * exists, and create a new file in that directory.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <stdio.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/types.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <sys/stat.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <fcntl.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <dirent.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <strings.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <stdlib.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <unistd.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy#include <errno.h>
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyusage(char *progname)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) fprintf(stderr, "Usage: %s <dirname|filename>\n", progname);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy exit(1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyfail(char *err, int rval)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy perror(err);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy exit(rval);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedystatic void
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedydaemonize(void)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy pid_t pid;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((pid = fork()) < 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fail("fork", 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if (pid != 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) fprintf(stdout, "%ld\n", pid);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy exit(0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) setsid();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) close(0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) close(1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) close(2);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedyint
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedymain(int argc, char *argv[])
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy{
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int ret, c;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy boolean_t isdir = B_FALSE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy boolean_t fflag = B_FALSE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy boolean_t rflag = B_FALSE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy struct stat sbuf;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char *fpath = NULL;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char *prog = argv[0];
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy while ((c = getopt(argc, argv, "fr")) != -1) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy switch (c) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Open the file or directory read only */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case 'r':
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy rflag = B_TRUE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* Run in the foreground */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy case 'f':
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fflag = B_TRUE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy break;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy default:
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy usage(prog);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy argc -= optind;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy argv += optind;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (argc != 1)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy usage(prog);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((ret = stat(argv[0], &sbuf)) != 0) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char *arg, *dname, *fname;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int arglen, dlen, flen;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy char *slash;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * The argument supplied doesn't exist. Copy the path, and
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * remove the trailing slash if presnt.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((arg = strdup(argv[0])) == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fail("strdup", 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy arglen = strlen(arg);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (arg[arglen - 1] == '/')
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy arg[arglen - 1] = '\0';
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /*
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * Get the directory and file names, using the current directory
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy * if the provided path doesn't specify a directory at all.
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((slash = strrchr(arg, '/')) == NULL) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy dname = strdup(".");
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fname = strdup(arg);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy *slash = '\0';
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy dname = strdup(arg);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fname = strdup(slash + 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy free(arg);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (dname == NULL || fname == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fail("strdup", 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy dlen = strlen(dname);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flen = strlen(fname);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* The directory portion of the path must exist */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((ret = stat(dname, &sbuf)) != 0 || !(sbuf.st_mode &
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy S_IFDIR))
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy usage(prog);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((fpath = (char *)malloc(dlen + 1 + flen + 1)) == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fail("malloc", 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) memset(fpath, '\0', dlen + 1 + flen + 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) strncpy(fpath, dname, dlen);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fpath[dlen] = '/';
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) strncat(fpath, fname, flen);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy free(dname);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy free(fname);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if ((sbuf.st_mode & S_IFMT) == S_IFREG ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (sbuf.st_mode & S_IFMT) == S_IFLNK ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (sbuf.st_mode & S_IFMT) == S_IFCHR ||
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (sbuf.st_mode & S_IFMT) == S_IFBLK) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fpath = strdup(argv[0]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else if ((sbuf.st_mode & S_IFMT) == S_IFDIR) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fpath = strdup(argv[0]);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy isdir = B_TRUE;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy usage(prog);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (fpath == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fail("strdup", 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (isdir == B_FALSE) {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy int fd, flags;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy mode_t mode = S_IRUSR | S_IWUSR;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy flags = rflag == B_FALSE ? O_CREAT | O_RDWR : O_RDONLY;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((fd = open(fpath, flags, mode)) < 0)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fail("open", 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy } else {
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy DIR *dp;
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if ((dp = opendir(fpath)) == NULL)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy fail("opendir", 1);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy }
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy free(fpath);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy if (fflag == B_FALSE)
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy daemonize();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy (void) pause();
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy /* NOTREACHED */
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy return (0);
d583b39bfb4e2571d3e41097c5c357ffe353ad45John Wren Kennedy}