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 * $FreeBSD$
21 */
22
23/*
24 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#pragma ident	"@(#)mktree.c	1.3	07/05/25 SMI"
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <unistd.h>
33#include <string.h>
34#include <fcntl.h>
35#include <sys/stat.h>
36#include <sys/types.h>
37#include <sys/errno.h>
38#include <sys/param.h>
39
40#define	TYPE_D 'D'
41#define	TYPE_F 'F'
42
43extern int errno;
44
45static char fdname[MAXPATHLEN] = {0};
46static char *pbasedir = NULL;
47static int nlevel = 2;
48static int ndir = 2;
49static int nfile = 2;
50
51static void  usage(char *this);
52static void  crtfile(char *pname);
53static char *getfdname(char *pdir, char type, int level, int dir, int file);
54static int   mktree(char *pbasedir, int level);
55
56int
57main(int argc, char *argv[])
58{
59	int c, ret;
60
61	while ((c = getopt(argc, argv, "b:l:d:f:")) != -1) {
62		switch (c) {
63		case 'b':
64			pbasedir = optarg;
65			break;
66		case 'l':
67			nlevel = atoi(optarg);
68			break;
69		case 'd':
70			ndir = atoi(optarg);
71			break;
72		case 'f':
73			nfile = atoi(optarg);
74			break;
75		case '?':
76			usage(argv[0]);
77		}
78	}
79	if (nlevel < 0 || ndir < 0 || nfile < 0 || pbasedir == NULL) {
80		usage(argv[0]);
81	}
82
83	ret = mktree(pbasedir, 1);
84
85	return (ret);
86}
87
88static void
89usage(char *this)
90{
91	(void) fprintf(stderr,
92	    "\tUsage: %s -b <base_dir> -l [nlevel] -d [ndir] -f [nfile]\n",
93	    this);
94	exit(1);
95}
96
97static int
98mktree(char *pdir, int level)
99{
100	int d, f;
101	char dname[MAXPATHLEN] = {0};
102	char fname[MAXPATHLEN] = {0};
103
104	if (level > nlevel) {
105		return (1);
106	}
107
108	for (d = 0; d < ndir; d++) {
109		(void) memset(dname, '\0', sizeof (dname));
110		(void) strcpy(dname, getfdname(pdir, TYPE_D, level, d, 0));
111
112		if (mkdir(dname, 0777) != 0) {
113			(void) fprintf(stderr, "mkdir(%s) failed."
114			    "\n[%d]: %s.\n",
115			    dname, errno, strerror(errno));
116			exit(errno);
117		}
118
119		/*
120		 * No sub-directory need be created, only create files in it.
121		 */
122		if (mktree(dname, level+1) != 0) {
123			for (f = 0; f < nfile; f++) {
124				(void) memset(fname, '\0', sizeof (fname));
125				(void) strcpy(fname,
126				    getfdname(dname, TYPE_F, level+1, d, f));
127				crtfile(fname);
128			}
129		}
130	}
131
132	for (f = 0; f < nfile; f++) {
133		(void) memset(fname, '\0', sizeof (fname));
134		(void) strcpy(fname, getfdname(pdir, TYPE_F, level, d, f));
135		crtfile(fname);
136	}
137
138	return (0);
139}
140
141static char *
142getfdname(char *pdir, char type, int level, int dir, int file)
143{
144	(void) snprintf(fdname, sizeof (fdname),
145	    "%s/%c-l%dd%df%d", pdir, type, level, dir, file);
146	return (fdname);
147}
148
149static void
150crtfile(char *pname)
151{
152	int fd = -1;
153	int afd = -1;
154	int i, size;
155	char *context = "0123456789ABCDF";
156	char *pbuf;
157
158	if (pname == NULL) {
159		exit(1);
160	}
161
162	size = sizeof (char) * 1024;
163	pbuf = (char *)valloc(size);
164	for (i = 0; i < size / strlen(context); i++) {
165		int offset = i * strlen(context);
166		(void) snprintf(pbuf+offset, size-offset, "%s", context);
167	}
168
169	if ((fd = open(pname, O_CREAT|O_RDWR, 0777)) < 0) {
170		(void) fprintf(stderr, "open(%s, O_CREAT|O_RDWR, 0777) failed."
171		    "\n[%d]: %s.\n", pname, errno, strerror(errno));
172		exit(errno);
173	}
174	if (write(fd, pbuf, 1024) < 1024) {
175		(void) fprintf(stderr, "write(fd, pbuf, 1024) failed."
176		    "\n[%d]: %s.\n", errno, strerror(errno));
177		exit(errno);
178	}
179
180#if UNSUPPORTED
181	if ((afd = openat(fd, "xattr", O_CREAT | O_RDWR | O_XATTR, 0777)) < 0) {
182		(void) fprintf(stderr, "openat failed.\n[%d]: %s.\n",
183		    errno, strerror(errno));
184		exit(errno);
185	}
186	if (write(afd, pbuf, 1024) < 1024) {
187		(void) fprintf(stderr, "write(afd, pbuf, 1024) failed."
188		    "\n[%d]: %s.\n", errno, strerror(errno));
189		exit(errno);
190	}
191
192	(void) close(afd);
193#endif
194	(void) close(fd);
195	free(pbuf);
196}
197