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