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