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 /*
28  * This program provides a command line interface to the
29  * three new ioctls for the emul64 driver - EMUL64_WRITE_OFF,
30  * EMUL64_WRITE_ON and EMUL64_ZERO_RANGE. All three of these
31  * ioctls require the range of blocks to be specified. The
32  * range is specified by starting block number and block count
33  * both of which are 64 bit.
34  *
35  * Returns 0 on success, >0 on failure.
36  *
37  */
38 #include <stdio.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <stropts.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <errno.h>
45 #include <sys/types.h>
46 #include <sys/emul64.h>
47 
48 #define	DEBUG	1
49 #define	ADMIN_DIR	"/dev/cfg/"
50 
51 char *Pname;
52 
53 static int	get_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin);
54 
55 static void
usage(void)56 usage(void)
57 {
58 	(void) fprintf(stderr, "Usage: emul64ioctl -s start_block "
59 	    "-b block_count -c write_off | write_on | zero emul64_dev\n");
60 	exit(1);
61 }
62 
63 int
main(int argc,char ** argv)64 main(int argc, char **argv)
65 {
66 	extern char	*optarg;
67 	extern int	optind;
68 	char		*admin;
69 	int		count_seen = 0;
70 	int 		fd, retval;
71 	int		cmd = -1;
72 	int		do_usage = 0;
73 	char		*slice;
74 	int		sb_seen = 0;
75 	emul64_tgt_range_t tr;
76 
77 	Pname = strrchr(argv[0], '/');
78 	if (Pname == NULL)
79 		Pname = argv[0];
80 	else
81 		Pname++;
82 
83 	while ((retval = getopt(argc, argv, "s:b:c:")) != -1) {
84 		switch (retval) {
85 		case 's':
86 			sb_seen = 1;
87 			tr.emul64_blkrange.emul64_sb = atoll(optarg);
88 			break;
89 		case 'b':
90 			count_seen = 1;
91 			tr.emul64_blkrange.emul64_blkcnt = atoll(optarg);
92 			break;
93 		case 'c':
94 			if (strncmp(optarg, "write_off",
95 			    strlen("write_off")) == 0) {
96 				cmd = EMUL64_WRITE_OFF;
97 			} else if (strncmp(optarg, "write_on",
98 			    strlen("write_on")) == 0) {
99 				cmd = EMUL64_WRITE_ON;
100 			} else if (strncmp(optarg, "zero",
101 			    strlen("zero")) == 0) {
102 				cmd = EMUL64_ZERO_RANGE;
103 			} else {
104 			    do_usage = 1;
105 			}
106 			break;
107 		    default:
108 			break;
109 		}
110 	}
111 
112 	if (do_usage || (optind != argc - 1)) {
113 		usage();
114 	}
115 	if ((sb_seen == 0) || (count_seen == 0) || (cmd == -1))
116 		usage();
117 
118 	slice = argv[optind];
119 
120 	/*
121 	 * Get admin device, target and lun
122 	 */
123 	if (get_disk_addr(slice, &tr, &admin) != 0)
124 		exit(1);
125 
126 	/*
127 	 * open the specified emul64_dev.
128 	 */
129 	if ((fd = open(admin, O_RDONLY, 0444)) != -1)	{
130 
131 		retval = ioctl(fd, cmd, &tr);
132 		(void) close(fd);
133 
134 		if (retval != -1) {
135 			free(admin);
136 			return (0);
137 		}
138 		(void) printf("emul64ioctl: %s: ioctl %s\n",
139 		    admin, strerror(errno));
140 	} else {
141 		(void) printf("emul64ioctl: %s: open %s\n",
142 		    admin, strerror(errno));
143 	}
144 	free(admin);
145 	return (1);
146 }
147 
148 #define	TOK_CHECK(s)	if (token == NULL) {\
149 						bogus = (s);\
150 						goto err_out;\
151 			}
152 
153 static int
get_disk_addr(char * path,emul64_tgt_range_t * tr,char ** admin)154 get_disk_addr(char *path, emul64_tgt_range_t *tr, char **admin)
155 {
156 	size_t		admin_size;
157 	int		ctlr_num;
158 	int		conversions;
159 	char		*ctds;
160 
161 	*admin = NULL;
162 	ctds = strrchr(path, '/');
163 	if (ctds == NULL)
164 		ctds = path;
165 	else
166 		ctds++;
167 	conversions = sscanf(ctds, "c%dt%hud%hu", &ctlr_num,
168 				&tr->emul64_target, &tr->emul64_lun);
169 	if (conversions != 3) {
170 		(void) fprintf(stderr, "%s: \"%s\" is invalid disk name.  "
171 			"%d conversions\n", Pname, ctds, conversions);
172 		return (-1);
173 	}
174 
175 	/* Build controller name */
176 	admin_size = strlen(ADMIN_DIR) +
177 		10 +		/* enough digits for an int */
178 		1 +		/* c */
179 		1;		/* Null terminator */
180 	*admin = malloc(admin_size);
181 	if (*admin == NULL) {
182 		(void) fprintf(stderr, "%s: out of memory\n", Pname);
183 		return (-1);
184 	}
185 	(void) snprintf(*admin, admin_size, "%sc%d", ADMIN_DIR, ctlr_num);
186 	return (0);
187 }
188