Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/tests/zfs-tests/cmd/mkbusy.c
48529 views
1
// SPDX-License-Identifier: CDDL-1.0
2
/*
3
* This file and its contents are supplied under the terms of the
4
* Common Development and Distribution License ("CDDL"), version 1.0.
5
* You may only use this file in accordance with the terms of version
6
* 1.0 of the CDDL.
7
*
8
* A full copy of the text of the CDDL should have accompanied this
9
* source. A copy of the CDDL is also available via the Internet at
10
* http://www.illumos.org/license/CDDL.
11
*/
12
13
/*
14
* Copyright (c) 2012 by Delphix. All rights reserved.
15
*/
16
17
/*
18
* Make a directory busy. If the argument is an existing file or directory,
19
* simply open it directly and pause. If not, verify that the parent directory
20
* exists, and create a new file in that directory.
21
*/
22
23
#include <stdio.h>
24
#include <sys/types.h>
25
#include <sys/stat.h>
26
#include <fcntl.h>
27
#include <dirent.h>
28
#include <string.h>
29
#include <stdlib.h>
30
#include <unistd.h>
31
#include <errno.h>
32
#include <string.h>
33
34
35
static __attribute__((noreturn)) void
36
usage(const char *progname)
37
{
38
(void) fprintf(stderr, "Usage: %s <dirname|filename>\n", progname);
39
exit(1);
40
}
41
42
static __attribute__((noreturn)) void
43
fail(const char *err)
44
{
45
perror(err);
46
exit(1);
47
}
48
49
static void
50
daemonize(void)
51
{
52
pid_t pid;
53
54
if ((pid = fork()) < 0) {
55
fail("fork");
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
68
static const char *
69
get_basename(const char *path)
70
{
71
const char *bn = strrchr(path, '/');
72
return (bn ? bn + 1 : path);
73
}
74
75
static ssize_t
76
get_dirnamelen(const char *path)
77
{
78
const char *end = strrchr(path, '/');
79
return (end ? end - path : -1);
80
}
81
82
int
83
main(int argc, char *argv[])
84
{
85
int c;
86
boolean_t isdir = B_FALSE;
87
struct stat sbuf;
88
char *fpath = NULL;
89
char *prog = argv[0];
90
91
while ((c = getopt(argc, argv, "")) != -1) {
92
switch (c) {
93
default:
94
usage(prog);
95
}
96
}
97
98
argc -= optind;
99
argv += optind;
100
101
if (argc != 1)
102
usage(prog);
103
104
if (stat(argv[0], &sbuf) != 0) {
105
char *arg;
106
const char *dname, *fname;
107
size_t arglen;
108
ssize_t dnamelen;
109
110
/*
111
* The argument supplied doesn't exist. Copy the path, and
112
* remove the trailing slash if present.
113
*/
114
if ((arg = strdup(argv[0])) == NULL)
115
fail("strdup");
116
arglen = strlen(arg);
117
if (arg[arglen - 1] == '/')
118
arg[arglen - 1] = '\0';
119
120
/* Get the directory and file names. */
121
fname = get_basename(arg);
122
dname = arg;
123
if ((dnamelen = get_dirnamelen(arg)) != -1)
124
arg[dnamelen] = '\0';
125
else
126
dname = ".";
127
128
/* The directory portion of the path must exist */
129
if (stat(dname, &sbuf) != 0 || !(sbuf.st_mode & S_IFDIR))
130
usage(prog);
131
132
if (asprintf(&fpath, "%s/%s", dname, fname) == -1)
133
fail("asprintf");
134
135
free(arg);
136
} else
137
switch (sbuf.st_mode & S_IFMT) {
138
case S_IFDIR:
139
isdir = B_TRUE;
140
zfs_fallthrough;
141
case S_IFLNK:
142
case S_IFCHR:
143
case S_IFBLK:
144
if ((fpath = strdup(argv[0])) == NULL)
145
fail("strdup");
146
break;
147
default:
148
usage(prog);
149
}
150
151
if (!isdir) {
152
if (open(fpath, O_CREAT | O_RDWR, 0600) < 0)
153
fail("open");
154
} else {
155
if (opendir(fpath) == NULL)
156
fail("opendir");
157
}
158
free(fpath);
159
160
daemonize();
161
(void) pause();
162
163
return (0);
164
}
165
166