1*d583b39bSJohn Wren Kennedy /* 2*d583b39bSJohn Wren Kennedy * This file and its contents are supplied under the terms of the 3*d583b39bSJohn Wren Kennedy * Common Development and Distribution License ("CDDL"), version 1.0. 4*d583b39bSJohn Wren Kennedy * You may only use this file in accordance with the terms of version 5*d583b39bSJohn Wren Kennedy * 1.0 of the CDDL. 6*d583b39bSJohn Wren Kennedy * 7*d583b39bSJohn Wren Kennedy * A full copy of the text of the CDDL should have accompanied this 8*d583b39bSJohn Wren Kennedy * source. A copy of the CDDL is also available via the Internet at 9*d583b39bSJohn Wren Kennedy * http://www.illumos.org/license/CDDL. 10*d583b39bSJohn Wren Kennedy */ 11*d583b39bSJohn Wren Kennedy 12*d583b39bSJohn Wren Kennedy /* 13*d583b39bSJohn Wren Kennedy * Copyright (c) 2012 by Delphix. All rights reserved. 14*d583b39bSJohn Wren Kennedy */ 15*d583b39bSJohn Wren Kennedy 16*d583b39bSJohn Wren Kennedy /* 17*d583b39bSJohn Wren Kennedy * Make a directory busy. If the argument is an existing file or directory, 18*d583b39bSJohn Wren Kennedy * simply open it directly and pause. If not, verify that the parent directory 19*d583b39bSJohn Wren Kennedy * exists, and create a new file in that directory. 20*d583b39bSJohn Wren Kennedy */ 21*d583b39bSJohn Wren Kennedy 22*d583b39bSJohn Wren Kennedy #include <stdio.h> 23*d583b39bSJohn Wren Kennedy #include <sys/types.h> 24*d583b39bSJohn Wren Kennedy #include <sys/stat.h> 25*d583b39bSJohn Wren Kennedy #include <fcntl.h> 26*d583b39bSJohn Wren Kennedy #include <dirent.h> 27*d583b39bSJohn Wren Kennedy #include <strings.h> 28*d583b39bSJohn Wren Kennedy #include <stdlib.h> 29*d583b39bSJohn Wren Kennedy #include <unistd.h> 30*d583b39bSJohn Wren Kennedy #include <errno.h> 31*d583b39bSJohn Wren Kennedy 32*d583b39bSJohn Wren Kennedy static void 33*d583b39bSJohn Wren Kennedy usage(char *progname) 34*d583b39bSJohn Wren Kennedy { 35*d583b39bSJohn Wren Kennedy (void) fprintf(stderr, "Usage: %s <dirname|filename>\n", progname); 36*d583b39bSJohn Wren Kennedy exit(1); 37*d583b39bSJohn Wren Kennedy } 38*d583b39bSJohn Wren Kennedy 39*d583b39bSJohn Wren Kennedy static void 40*d583b39bSJohn Wren Kennedy fail(char *err, int rval) 41*d583b39bSJohn Wren Kennedy { 42*d583b39bSJohn Wren Kennedy perror(err); 43*d583b39bSJohn Wren Kennedy exit(rval); 44*d583b39bSJohn Wren Kennedy } 45*d583b39bSJohn Wren Kennedy 46*d583b39bSJohn Wren Kennedy static void 47*d583b39bSJohn Wren Kennedy daemonize(void) 48*d583b39bSJohn Wren Kennedy { 49*d583b39bSJohn Wren Kennedy pid_t pid; 50*d583b39bSJohn Wren Kennedy 51*d583b39bSJohn Wren Kennedy if ((pid = fork()) < 0) { 52*d583b39bSJohn Wren Kennedy fail("fork", 1); 53*d583b39bSJohn Wren Kennedy } else if (pid != 0) { 54*d583b39bSJohn Wren Kennedy (void) fprintf(stdout, "%ld\n", pid); 55*d583b39bSJohn Wren Kennedy exit(0); 56*d583b39bSJohn Wren Kennedy } 57*d583b39bSJohn Wren Kennedy 58*d583b39bSJohn Wren Kennedy (void) setsid(); 59*d583b39bSJohn Wren Kennedy (void) close(0); 60*d583b39bSJohn Wren Kennedy (void) close(1); 61*d583b39bSJohn Wren Kennedy (void) close(2); 62*d583b39bSJohn Wren Kennedy } 63*d583b39bSJohn Wren Kennedy 64*d583b39bSJohn Wren Kennedy int 65*d583b39bSJohn Wren Kennedy main(int argc, char *argv[]) 66*d583b39bSJohn Wren Kennedy { 67*d583b39bSJohn Wren Kennedy int ret, c; 68*d583b39bSJohn Wren Kennedy boolean_t isdir = B_FALSE; 69*d583b39bSJohn Wren Kennedy boolean_t fflag = B_FALSE; 70*d583b39bSJohn Wren Kennedy boolean_t rflag = B_FALSE; 71*d583b39bSJohn Wren Kennedy struct stat sbuf; 72*d583b39bSJohn Wren Kennedy char *fpath = NULL; 73*d583b39bSJohn Wren Kennedy char *prog = argv[0]; 74*d583b39bSJohn Wren Kennedy 75*d583b39bSJohn Wren Kennedy while ((c = getopt(argc, argv, "fr")) != -1) { 76*d583b39bSJohn Wren Kennedy switch (c) { 77*d583b39bSJohn Wren Kennedy /* Open the file or directory read only */ 78*d583b39bSJohn Wren Kennedy case 'r': 79*d583b39bSJohn Wren Kennedy rflag = B_TRUE; 80*d583b39bSJohn Wren Kennedy break; 81*d583b39bSJohn Wren Kennedy /* Run in the foreground */ 82*d583b39bSJohn Wren Kennedy case 'f': 83*d583b39bSJohn Wren Kennedy fflag = B_TRUE; 84*d583b39bSJohn Wren Kennedy break; 85*d583b39bSJohn Wren Kennedy default: 86*d583b39bSJohn Wren Kennedy usage(prog); 87*d583b39bSJohn Wren Kennedy } 88*d583b39bSJohn Wren Kennedy } 89*d583b39bSJohn Wren Kennedy 90*d583b39bSJohn Wren Kennedy argc -= optind; 91*d583b39bSJohn Wren Kennedy argv += optind; 92*d583b39bSJohn Wren Kennedy 93*d583b39bSJohn Wren Kennedy if (argc != 1) 94*d583b39bSJohn Wren Kennedy usage(prog); 95*d583b39bSJohn Wren Kennedy 96*d583b39bSJohn Wren Kennedy if ((ret = stat(argv[0], &sbuf)) != 0) { 97*d583b39bSJohn Wren Kennedy char *arg, *dname, *fname; 98*d583b39bSJohn Wren Kennedy int arglen, dlen, flen; 99*d583b39bSJohn Wren Kennedy char *slash; 100*d583b39bSJohn Wren Kennedy 101*d583b39bSJohn Wren Kennedy /* 102*d583b39bSJohn Wren Kennedy * The argument supplied doesn't exist. Copy the path, and 103*d583b39bSJohn Wren Kennedy * remove the trailing slash if presnt. 104*d583b39bSJohn Wren Kennedy */ 105*d583b39bSJohn Wren Kennedy if ((arg = strdup(argv[0])) == NULL) 106*d583b39bSJohn Wren Kennedy fail("strdup", 1); 107*d583b39bSJohn Wren Kennedy arglen = strlen(arg); 108*d583b39bSJohn Wren Kennedy if (arg[arglen - 1] == '/') 109*d583b39bSJohn Wren Kennedy arg[arglen - 1] = '\0'; 110*d583b39bSJohn Wren Kennedy 111*d583b39bSJohn Wren Kennedy /* 112*d583b39bSJohn Wren Kennedy * Get the directory and file names, using the current directory 113*d583b39bSJohn Wren Kennedy * if the provided path doesn't specify a directory at all. 114*d583b39bSJohn Wren Kennedy */ 115*d583b39bSJohn Wren Kennedy if ((slash = strrchr(arg, '/')) == NULL) { 116*d583b39bSJohn Wren Kennedy dname = strdup("."); 117*d583b39bSJohn Wren Kennedy fname = strdup(arg); 118*d583b39bSJohn Wren Kennedy } else { 119*d583b39bSJohn Wren Kennedy *slash = '\0'; 120*d583b39bSJohn Wren Kennedy dname = strdup(arg); 121*d583b39bSJohn Wren Kennedy fname = strdup(slash + 1); 122*d583b39bSJohn Wren Kennedy } 123*d583b39bSJohn Wren Kennedy free(arg); 124*d583b39bSJohn Wren Kennedy if (dname == NULL || fname == NULL) 125*d583b39bSJohn Wren Kennedy fail("strdup", 1); 126*d583b39bSJohn Wren Kennedy dlen = strlen(dname); 127*d583b39bSJohn Wren Kennedy flen = strlen(fname); 128*d583b39bSJohn Wren Kennedy 129*d583b39bSJohn Wren Kennedy /* The directory portion of the path must exist */ 130*d583b39bSJohn Wren Kennedy if ((ret = stat(dname, &sbuf)) != 0 || !(sbuf.st_mode & 131*d583b39bSJohn Wren Kennedy S_IFDIR)) 132*d583b39bSJohn Wren Kennedy usage(prog); 133*d583b39bSJohn Wren Kennedy 134*d583b39bSJohn Wren Kennedy if ((fpath = (char *)malloc(dlen + 1 + flen + 1)) == NULL) 135*d583b39bSJohn Wren Kennedy fail("malloc", 1); 136*d583b39bSJohn Wren Kennedy (void) memset(fpath, '\0', dlen + 1 + flen + 1); 137*d583b39bSJohn Wren Kennedy 138*d583b39bSJohn Wren Kennedy (void) strncpy(fpath, dname, dlen); 139*d583b39bSJohn Wren Kennedy fpath[dlen] = '/'; 140*d583b39bSJohn Wren Kennedy (void) strncat(fpath, fname, flen); 141*d583b39bSJohn Wren Kennedy free(dname); 142*d583b39bSJohn Wren Kennedy free(fname); 143*d583b39bSJohn Wren Kennedy } else if ((sbuf.st_mode & S_IFMT) == S_IFREG || 144*d583b39bSJohn Wren Kennedy (sbuf.st_mode & S_IFMT) == S_IFLNK || 145*d583b39bSJohn Wren Kennedy (sbuf.st_mode & S_IFMT) == S_IFCHR || 146*d583b39bSJohn Wren Kennedy (sbuf.st_mode & S_IFMT) == S_IFBLK) { 147*d583b39bSJohn Wren Kennedy fpath = strdup(argv[0]); 148*d583b39bSJohn Wren Kennedy } else if ((sbuf.st_mode & S_IFMT) == S_IFDIR) { 149*d583b39bSJohn Wren Kennedy fpath = strdup(argv[0]); 150*d583b39bSJohn Wren Kennedy isdir = B_TRUE; 151*d583b39bSJohn Wren Kennedy } else { 152*d583b39bSJohn Wren Kennedy usage(prog); 153*d583b39bSJohn Wren Kennedy } 154*d583b39bSJohn Wren Kennedy 155*d583b39bSJohn Wren Kennedy if (fpath == NULL) 156*d583b39bSJohn Wren Kennedy fail("strdup", 1); 157*d583b39bSJohn Wren Kennedy 158*d583b39bSJohn Wren Kennedy if (isdir == B_FALSE) { 159*d583b39bSJohn Wren Kennedy int fd, flags; 160*d583b39bSJohn Wren Kennedy mode_t mode = S_IRUSR | S_IWUSR; 161*d583b39bSJohn Wren Kennedy 162*d583b39bSJohn Wren Kennedy flags = rflag == B_FALSE ? O_CREAT | O_RDWR : O_RDONLY; 163*d583b39bSJohn Wren Kennedy 164*d583b39bSJohn Wren Kennedy if ((fd = open(fpath, flags, mode)) < 0) 165*d583b39bSJohn Wren Kennedy fail("open", 1); 166*d583b39bSJohn Wren Kennedy } else { 167*d583b39bSJohn Wren Kennedy DIR *dp; 168*d583b39bSJohn Wren Kennedy 169*d583b39bSJohn Wren Kennedy if ((dp = opendir(fpath)) == NULL) 170*d583b39bSJohn Wren Kennedy fail("opendir", 1); 171*d583b39bSJohn Wren Kennedy } 172*d583b39bSJohn Wren Kennedy free(fpath); 173*d583b39bSJohn Wren Kennedy 174*d583b39bSJohn Wren Kennedy if (fflag == B_FALSE) 175*d583b39bSJohn Wren Kennedy daemonize(); 176*d583b39bSJohn Wren Kennedy (void) pause(); 177*d583b39bSJohn Wren Kennedy 178*d583b39bSJohn Wren Kennedy /* NOTREACHED */ 179*d583b39bSJohn Wren Kennedy return (0); 180*d583b39bSJohn Wren Kennedy } 181