xref: /illumos-gate/usr/src/test/zfs-tests/cmd/mktree/mktree.c (revision dd72704bd9e794056c558153663c739e2012d721)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright 2022 MNX Cloud, Inc.
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <fcntl.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <sys/errno.h>
39 #include <sys/param.h>
40 
41 #define	TYPE_D 'D'
42 #define	TYPE_F 'F'
43 
44 extern int errno;
45 
46 static char fdname[MAXPATHLEN] = {0};
47 static char *pbasedir = NULL;
48 static int nlevel = 2;
49 static int ndir = 2;
50 static int nfile = 2;
51 
52 static void  usage(char *this);
53 static void  crtfile(char *pname);
54 static char *getfdname(char *pdir, char type, int level, int dir, int file);
55 static int   mktree(char *pbasedir, int level);
56 
57 int
58 main(int argc, char *argv[])
59 {
60 	int c, ret;
61 
62 	while ((c = getopt(argc, argv, "b:l:d:f:")) != -1) {
63 		switch (c) {
64 		case 'b':
65 			pbasedir = optarg;
66 			break;
67 		case 'l':
68 			nlevel = atoi(optarg);
69 			break;
70 		case 'd':
71 			ndir = atoi(optarg);
72 			break;
73 		case 'f':
74 			nfile = atoi(optarg);
75 			break;
76 		case '?':
77 			usage(argv[0]);
78 		}
79 	}
80 	if (nlevel < 0 || ndir < 0 || nfile < 0 || pbasedir == NULL) {
81 		usage(argv[0]);
82 	}
83 
84 	ret = mktree(pbasedir, 1);
85 
86 	return (ret);
87 }
88 
89 static void
90 usage(char *this)
91 {
92 	(void) fprintf(stderr,
93 	    "\tUsage: %s -b <base_dir> -l [nlevel] -d [ndir] -f [nfile]\n",
94 	    this);
95 	exit(1);
96 }
97 
98 static int
99 mktree(char *pdir, int level)
100 {
101 	int d, f;
102 	char dname[MAXPATHLEN] = {0};
103 	char fname[MAXPATHLEN] = {0};
104 
105 	if (level > nlevel) {
106 		return (1);
107 	}
108 
109 	for (d = 0; d < ndir; d++) {
110 		(void) memset(dname, '\0', sizeof (dname));
111 		(void) strcpy(dname, getfdname(pdir, TYPE_D, level, d, 0));
112 
113 		if (mkdir(dname, 0777) != 0) {
114 			int exitcode = errno;
115 			(void) fprintf(stderr, "mkdir(%s) failed."
116 			    "\n[%d]: %s.\n",
117 			    dname, errno, strerror(errno));
118 			exit(exitcode);
119 		}
120 
121 		/*
122 		 * No sub-directory need be created, only create files in it.
123 		 */
124 		if (mktree(dname, level+1) != 0) {
125 			for (f = 0; f < nfile; f++) {
126 				(void) memset(fname, '\0', sizeof (fname));
127 				(void) strcpy(fname,
128 				    getfdname(dname, TYPE_F, level+1, d, f));
129 				crtfile(fname);
130 			}
131 		}
132 	}
133 
134 	for (f = 0; f < nfile; f++) {
135 		(void) memset(fname, '\0', sizeof (fname));
136 		(void) strcpy(fname, getfdname(pdir, TYPE_F, level, d, f));
137 		crtfile(fname);
138 	}
139 
140 	return (0);
141 }
142 
143 static char *
144 getfdname(char *pdir, char type, int level, int dir, int file)
145 {
146 	(void) snprintf(fdname, sizeof (fdname),
147 	    "%s/%c-l%dd%df%d", pdir, type, level, dir, file);
148 	return (fdname);
149 }
150 
151 static void
152 crtfile(char *pname)
153 {
154 	int fd = -1;
155 	int afd = -1;
156 	int i, size;
157 	int exitcode;
158 	char *context = "0123456789ABCDF";
159 	char *pbuf;
160 
161 	if (pname == NULL) {
162 		exit(1);
163 	}
164 
165 	size = sizeof (char) * 1024;
166 	pbuf = (char *)valloc(size);
167 	for (i = 0; i < size / strlen(context); i++) {
168 		int offset = i * strlen(context);
169 		(void) snprintf(pbuf+offset, size-offset, "%s", context);
170 	}
171 
172 	if ((fd = open(pname, O_CREAT|O_RDWR, 0777)) < 0) {
173 		exitcode = errno;
174 		(void) fprintf(stderr, "open(%s, O_CREAT|O_RDWR, 0777) failed."
175 		    "\n[%d]: %s.\n", pname, errno, strerror(errno));
176 		exit(exitcode);
177 	}
178 	if (write(fd, pbuf, 1024) < 1024) {
179 		exitcode = errno;
180 		(void) fprintf(stderr, "write(fd, pbuf, 1024) failed."
181 		    "\n[%d]: %s.\n", errno, strerror(errno));
182 		exit(exitcode);
183 	}
184 
185 	if ((afd = openat(fd, "xattr", O_CREAT | O_RDWR | O_XATTR, 0777)) < 0) {
186 		exitcode = errno;
187 		(void) fprintf(stderr, "openat failed.\n[%d]: %s.\n",
188 		    errno, strerror(errno));
189 		exit(exitcode);
190 	}
191 	if (write(afd, pbuf, 1024) < 1024) {
192 		exitcode = errno;
193 		(void) fprintf(stderr, "write(afd, pbuf, 1024) failed."
194 		    "\n[%d]: %s.\n", errno, strerror(errno));
195 		exit(exitcode);
196 	}
197 
198 	(void) close(afd);
199 	(void) close(fd);
200 	free(pbuf);
201 }
202