xref: /illumos-gate/usr/src/cmd/emul64ioctl/emul64ioctl.c (revision 3d393ee6c37fa10ac512ed6d36109ad616dc7c1a)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * This program provides a command line interface to the
31  * three new ioctls for the emul64 driver - EMUL64_WRITE_OFF,
32  * EMUL64_WRITE_ON and EMUL64_ZERO_RANGE. All three of these
33  * ioctls require the range of blocks to be specified. The
34  * range is specified by starting block number and block count
35  * both of which are 64 bit.
36  *
37  * Returns 0 on success, >0 on failure.
38  *
39  */
40 #include <stdio.h>
41 #include <fcntl.h>
42 #include <unistd.h>
43 #include <stropts.h>
44 #include <string.h>
45 #include <stdlib.h>
46 #include <errno.h>
47 #include <sys/types.h>
48 #include <sys/emul64.h>
49 
50 #define	DEBUG	1
51 #define	ADMIN_DIR	"/dev/cfg/"
52 
53 char *Pname;
54 
55 static int	get_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin);
56 
57 static void
58 usage(void)
59 {
60 	(void) fprintf(stderr, "Usage: emul64ioctl -s start_block "
61 	    "-b block_count -c write_off | write_on | zero emul64_dev\n");
62 	exit(1);
63 }
64 
65 int
66 main(int argc, char **argv)
67 {
68 	extern char	*optarg;
69 	extern int	optind;
70 	char		*admin;
71 	int		count_seen = 0;
72 	int 		fd, retval;
73 	int		cmd = -1;
74 	int		do_usage = 0;
75 	char		*slice;
76 	int		sb_seen = 0;
77 	emul64_tgt_range_t tr;
78 
79 	Pname = strrchr(argv[0], '/');
80 	if (Pname == NULL)
81 		Pname = argv[0];
82 	else
83 		Pname++;
84 
85 	while ((retval = getopt(argc, argv, "s:b:c:")) != -1) {
86 		switch (retval) {
87 		case 's':
88 			sb_seen = 1;
89 			tr.emul64_blkrange.emul64_sb = atoll(optarg);
90 			break;
91 		case 'b':
92 			count_seen = 1;
93 			tr.emul64_blkrange.emul64_blkcnt = atoll(optarg);
94 			break;
95 		case 'c':
96 			if (strncmp(optarg, "write_off",
97 			    strlen("write_off")) == 0) {
98 				cmd = EMUL64_WRITE_OFF;
99 			} else if (strncmp(optarg, "write_on",
100 			    strlen("write_on")) == 0) {
101 				cmd = EMUL64_WRITE_ON;
102 			} else if (strncmp(optarg, "zero",
103 			    strlen("zero")) == 0) {
104 				cmd = EMUL64_ZERO_RANGE;
105 			} else {
106 			    do_usage = 1;
107 			}
108 			break;
109 		    default:
110 			break;
111 		}
112 	}
113 
114 	if (do_usage || (optind != argc - 1)) {
115 		usage();
116 	}
117 	if ((sb_seen == 0) || (count_seen == 0) || (cmd == -1))
118 		usage();
119 
120 	slice = argv[optind];
121 
122 	/*
123 	 * Get admin device, target and lun
124 	 */
125 	if (get_disk_addr(slice, &tr, &admin) != 0)
126 		exit(1);
127 
128 	/*
129 	 * open the specified emul64_dev.
130 	 */
131 	if ((fd = open(admin, O_RDONLY, 0444)) != -1)	{
132 
133 		retval = ioctl(fd, cmd, &tr);
134 		(void) close(fd);
135 
136 		if (retval != -1) {
137 			free(admin);
138 			return (0);
139 		}
140 		(void) printf("emul64ioctl: %s: ioctl %s\n",
141 		    admin, strerror(errno));
142 	} else {
143 		(void) printf("emul64ioctl: %s: open %s\n",
144 		    admin, strerror(errno));
145 	}
146 	free(admin);
147 	return (1);
148 }
149 
150 #define	TOK_CHECK(s)	if (token == NULL) {\
151 						bogus = (s);\
152 						goto err_out;\
153 			}
154 
155 static int
156 get_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin)
157 {
158 	size_t		admin_size;
159 	int		ctlr_num;
160 	int		conversions;
161 	char		*ctds;
162 
163 	*admin = NULL;
164 	ctds = strrchr(path, '/');
165 	if (ctds == NULL)
166 		ctds = path;
167 	else
168 		ctds++;
169 	conversions = sscanf(ctds, "c%dt%hud%hu", &ctlr_num,
170 				&tr->emul64_target, &tr->emul64_lun);
171 	if (conversions != 3) {
172 		(void) fprintf(stderr, "%s: \"%s\" is invalid disk name.  "
173 			"%d conversions\n", Pname, ctds, conversions);
174 		return (-1);
175 	}
176 
177 	/* Build controller name */
178 	admin_size = strlen(ADMIN_DIR) +
179 		10 +		/* enough digits for an int */
180 		1 +		/* c */
181 		1;		/* Null terminator */
182 	*admin = malloc(admin_size);
183 	if (*admin == NULL) {
184 		(void) fprintf(stderr, "%s: out of memory\n", Pname);
185 		return (-1);
186 	}
187 	(void) snprintf(*admin, admin_size, "%sc%d", ADMIN_DIR, ctlr_num);
188 	return (0);
189 }
190