xref: /illumos-gate/usr/src/cmd/devmgmt/cmds/devfree.c (revision 367731f049bfcb9d9d460279bdeece464fbd5ef9)
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 /*    Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /*	All Rights Reserved */
29 
30 /*
31  *	devfree key [device [...]]
32  */
33 
34 #include	<sys/types.h>
35 #include	<sys/param.h>
36 #include	<stdio.h>
37 #include	<errno.h>
38 #include	<stdlib.h>
39 #include	<string.h>
40 #include	<fmtmsg.h>
41 #include	<devmgmt.h>
42 #include	<values.h>
43 #include	<devtab.h>
44 
45 /*
46  *  Local definitions
47  *	TRUE		Boolean TRUE value
48  *	FALSE		Boolean FALSE value
49  */
50 #ifndef		TRUE
51 #define		TRUE		('t')
52 #endif
53 
54 #ifndef		FALSE
55 #define		FALSE		0
56 #endif
57 
58 
59 /*
60  *  Exit codes:
61  *	EX_OK		Exit code for all went well
62  *	EX_ERROR	Exit code for something failed
63  *	EX_TBLERR	Exit code for errors relating to device or lock tables
64  *	EX_NOFREE	Exit code for free failed
65  */
66 
67 #define		EX_OK		0
68 #define		EX_ERROR	1
69 #define		EX_TBLERR	2
70 #define		EX_NOFREE	3
71 
72 
73 /*
74  * Messages
75  *	M_USAGE		Usage error
76  *	M_INVKEY	Invalid key specified
77  *	M_NOTRSVD	Attempting to free something not alloc'd
78  *	M_NOTONKEY	Attempting to free with wrong key
79  *	M_DEVTAB	Error opening the device table
80  *	M_RSVTAB	Error opening the device-reservation table
81  *	M_ERROR		Some internal error
82  */
83 
84 #define		M_USAGE		"usage: devfree key [device [...]]"
85 #define		M_INVKEY	"Invalid key: %s"
86 #define		M_NOTRSVD	"Device not reserved: %s"
87 #define		M_NOTONKEY	"Cannot unreserve device: %s"
88 #define		M_DEVTAB	"Cannot open the device table: %s"
89 #define		M_RSVTAB	"Cannot open the device-reservation table: %s"
90 #define		M_ERROR		"Internal error, errno=%d"
91 
92 
93 /*
94  *  Local functions and static data
95  *	stdmsg(r,l,s,m)		Macro for standard message generation
96  *				r	MM_NRECOV or MM_RECOV (recoverability)
97  *				l	Label
98  *				s	Severity
99  *				m	Message
100  *	lbl			Buffer for the label-component of a message.
101  *	msg			Buffer for the text-component of a message.
102  */
103 
104 #define	stdmsg(r, l, s, m)	\
105 	(void) fmtmsg(MM_PRINT | MM_UTIL | r, l, s, m, MM_NULLACT, MM_NULLTAG)
106 
107 static	char	lbl[MM_MXLABELLN+1];
108 static	char	msg[MM_MXTXTLN+1];
109 
110 /*
111  *  devfree key [device [device [...]]]
112  *
113  *	This command frees devices that have been reserved using
114  *	the devreserv command (or the devreserv() function).
115  *
116  *  Options:  None
117  *
118  *  Arguments:
119  *	key		The key on which the device to free was allocated on.
120  *			If omitted, all keys are assumed.
121  *	device		The device to free.  If omitted, all devices allocated
122  *			using the key are freed.
123  *
124  *  Command Values:
125  *	EX_OK		0	Device(s) successfully freed
126  *	EX_ERROR	1	A syntax error or other error occurred
127  *	EX_TBLERR	2	A problem with device management tables
128  *	EX_NOFREE	3	A requested device couldn't be freed
129  */
130 
131 int
main(int argc,char * argv[])132 main(int argc, char *argv[])
133 {
134 	/* Automatics */
135 	char			**argp;		/* Ptr to current argument */
136 	struct reservdev	**rsvd;		/* Ptr to list of locks */
137 	struct reservdev	**plk;		/* Running ptr to locks */
138 	char			*devtab;	/* Ptr to device table name */
139 	char			*rsvtab;	/* Ptr to dev-rsv-tbl name */
140 	char			*p;		/* Temp char pointer */
141 	int			argcount;	/* Number of args on cmd */
142 	long			lkey;		/* Key for locking (long) */
143 	int			key;		/* Key for locking */
144 	int			halt;		/* TRUE if we need to stop */
145 	int			sev;		/* Message severity */
146 	int			exitcode;	/* Value of command */
147 	int			syntaxerr;	/* Flag, TRUE if syntax error */
148 	int			exitcd;		/* Value for exit() */
149 	int			c;		/* Option character */
150 	const char		*errstr;
151 
152 
153 	/*
154 	 * Initializations
155 	 */
156 
157 	/* Build a message label */
158 	if (p = strrchr(argv[0], '/'))
159 		p++;
160 	else
161 		p = argv[0];
162 	(void) strlcat(strcpy(lbl, "UX:"), p, sizeof (lbl));
163 
164 	/*
165 	 * Make only the text component of messages appear
166 	 * (remove this in SVR4.1)
167 	 */
168 	(void) putenv("MSGVERB=text");
169 
170 
171 	/*
172 	 * Parse the options from the command line
173 	 */
174 
175 	opterr = 0;
176 	syntaxerr = FALSE;
177 	while ((c = getopt(argc, argv, "")) != EOF) {
178 		switch (c) {
179 		default:
180 			syntaxerr = FALSE;
181 			break;
182 		}
183 	}
184 
185 
186 	/* Argument initializations */
187 	argp = &argv[optind];
188 	if ((argcount = argc-optind) < 1)
189 		syntaxerr = TRUE;
190 
191 
192 	/* If there's (an obvious) syntax error, write a message and quit */
193 	if (syntaxerr) {
194 		stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE);
195 		exit(EX_ERROR);
196 	}
197 
198 
199 	/*
200 	 *  devfree key
201 	 *
202 	 *	Free all devices that have been reserved using the key "key".
203 	 */
204 
205 	if (argcount == 1) {
206 
207 		/* Extract the key from the command */
208 		lkey = strtonum(*argp, 1, MAXINT, &errstr);
209 		if (errstr != NULL) {
210 			(void) snprintf(msg, sizeof (msg), M_INVKEY, *argp);
211 			stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
212 			exit(EX_ERROR);
213 		}
214 		key = (int)lkey;
215 
216 		/* Get the list of devices currently reserved */
217 		if (rsvd = reservdev()) {
218 			exitcd = EX_OK;
219 			for (plk = rsvd; *plk; plk++) {
220 				if ((*plk)->key == key)
221 					if (devfree(key, (*plk)->devname) != 0)
222 						exitcd = EX_NOFREE;
223 			}
224 		} else {
225 			if (((errno == ENOENT) || (errno == EACCES)) &&
226 			    (rsvtab = _rsvtabpath())) {
227 				(void) snprintf(msg, sizeof (msg), M_RSVTAB,
228 				    rsvtab);
229 				exitcd = EX_TBLERR;
230 				sev = MM_ERROR;
231 			} else {
232 				(void) snprintf(msg, sizeof (msg), M_ERROR,
233 				    errno);
234 				exitcd = EX_ERROR;
235 				sev = MM_HALT;
236 			}
237 			stdmsg(MM_NRECOV, lbl, sev, msg);
238 		}
239 
240 		/* Done */
241 		exit(exitcd);
242 	}
243 
244 
245 	/*
246 	 *  devfree key device [...]
247 	 *
248 	 *	Free specific devices
249 	 */
250 
251 	/* Open the device file (if there's one to be opened) */
252 	if (!_opendevtab("r")) {
253 		if (devtab = _devtabpath()) {
254 			(void) snprintf(msg, sizeof (msg), M_DEVTAB, devtab);
255 			exitcd = EX_TBLERR;
256 			sev = MM_ERROR;
257 		} else {
258 			(void) snprintf(msg, sizeof (msg), M_ERROR, errno);
259 			exitcd = EX_ERROR;
260 			sev = MM_HALT;
261 		}
262 		stdmsg(MM_NRECOV, lbl, sev, msg);
263 		exit(exitcd);
264 	}
265 
266 	/* Extract the key from the command */
267 	lkey = strtonum(*argp, 1, MAXINT, &errstr);
268 	if (errstr != NULL) {
269 		(void) snprintf(msg, sizeof (msg), M_INVKEY, *argp);
270 		stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
271 		exit(EX_ERROR);
272 	}
273 	key = (int)lkey;
274 	argp++;
275 
276 	/* Loop through the list of devices to free */
277 	exitcode = EX_OK;
278 	halt = FALSE;
279 	while (!halt && *argp) {
280 
281 		/* Try to free the device */
282 		if (devfree(key, *argp) != 0) {
283 			if ((errno == EACCES) || (errno == ENOENT)) {
284 
285 				/* Can't get at reservation file */
286 				if (rsvtab = _rsvtabpath()) {
287 					exitcode = EX_TBLERR;
288 					(void) snprintf(msg, sizeof (msg),
289 					    M_RSVTAB, rsvtab);
290 					sev = MM_ERROR;
291 				} else {
292 					exitcode = EX_ERROR;
293 					(void) snprintf(msg, sizeof (msg),
294 					    M_ERROR, errno);
295 					sev = MM_HALT;
296 				}
297 				stdmsg(MM_NRECOV, lbl, sev, msg);
298 				halt = TRUE;
299 			} else if (errno == EPERM) {
300 
301 				/* Wrong key */
302 				(void) snprintf(msg, sizeof (msg), M_NOTONKEY,
303 				    *argp);
304 				stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
305 				exitcode = EX_NOFREE;
306 			} else if (errno == EINVAL) {
307 
308 				/* Device not reserved */
309 				(void) snprintf(msg, sizeof (msg), M_NOTRSVD,
310 				    *argp);
311 				stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
312 				exitcode = EX_NOFREE;
313 			} else {
314 
315 				/* Some other strange error occurred */
316 				(void) snprintf(msg, sizeof (msg), M_ERROR,
317 				    errno);
318 				stdmsg(MM_NRECOV, lbl, MM_HALT, msg);
319 				exitcode = EX_ERROR;
320 				halt = TRUE;
321 			}
322 		}
323 		argp++;
324 	}
325 
326 	/* Exit with the appropriate code */
327 	return (exitcode);
328 }
329