]> git.proxmox.com Git - mirror_zfs-debian.git/blob - tests/zfs-tests/cmd/mkbusy/mkbusy.c
1e4567488d98be997bbb343b710b3531c3252abe
[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, dlen, flen;
102 char *slash;
103
104 /*
105 * The argument supplied doesn't exist. Copy the path, and
106 * remove the trailing slash if presnt.
107 */
108 if ((arg = strdup(argv[0])) == NULL)
109 fail("strdup", 1);
110 arglen = strlen(arg);
111 if (arg[arglen - 1] == '/')
112 arg[arglen - 1] = '\0';
113
114 /*
115 * Get the directory and file names, using the current directory
116 * if the provided path doesn't specify a directory at all.
117 */
118 if ((slash = strrchr(arg, '/')) == NULL) {
119 dname = strdup(".");
120 fname = strdup(arg);
121 } else {
122 *slash = '\0';
123 dname = strdup(arg);
124 fname = strdup(slash + 1);
125 }
126 free(arg);
127 if (dname == NULL || fname == NULL)
128 fail("strdup", 1);
129 dlen = strlen(dname);
130 flen = strlen(fname);
131
132 /* The directory portion of the path must exist */
133 if ((ret = stat(dname, &sbuf)) != 0 || !(sbuf.st_mode &
134 S_IFDIR))
135 usage(prog);
136
137 if ((fpath = (char *)malloc(dlen + 1 + flen + 1)) == NULL)
138 fail("malloc", 1);
139 (void) memset(fpath, '\0', dlen + 1 + flen + 1);
140
141 (void) strncpy(fpath, dname, dlen);
142 fpath[dlen] = '/';
143 (void) strncat(fpath, fname, flen);
144 free(dname);
145 free(fname);
146 } else if ((sbuf.st_mode & S_IFMT) == S_IFREG ||
147 (sbuf.st_mode & S_IFMT) == S_IFLNK ||
148 (sbuf.st_mode & S_IFMT) == S_IFCHR ||
149 (sbuf.st_mode & S_IFMT) == S_IFBLK) {
150 fpath = strdup(argv[0]);
151 } else if ((sbuf.st_mode & S_IFMT) == S_IFDIR) {
152 fpath = strdup(argv[0]);
153 isdir = B_TRUE;
154 } else {
155 usage(prog);
156 }
157
158 if (fpath == NULL)
159 fail("strdup", 1);
160
161 if (isdir == B_FALSE) {
162 int fd, flags;
163 mode_t mode = S_IRUSR | S_IWUSR;
164
165 flags = rflag == B_FALSE ? O_CREAT | O_RDWR : O_RDONLY;
166
167 if ((fd = open(fpath, flags, mode)) < 0)
168 fail("open", 1);
169 } else {
170 DIR *dp;
171
172 if ((dp = opendir(fpath)) == NULL)
173 fail("opendir", 1);
174 }
175 free(fpath);
176
177 if (fflag == B_FALSE)
178 daemonize();
179 (void) pause();
180
181 /* NOTREACHED */
182 return (0);
183 }