strcmp() needs string.h
[dragonfly.git] / sbin / vinum / vinumutil.c
1 /*-
2  * Copyright (c) 1997, 1998, 1999
3  *      Nan Yang Computer Services Limited.  All rights reserved.
4  *
5  *  Written by Greg Lehey
6  *
7  *  This software is distributed under the so-called ``Berkeley
8  *  License'':
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by Nan Yang Computer
21  *      Services Limited.
22  * 4. Neither the name of the Company nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * This software is provided ``as is'', and any express or implied
27  * warranties, including, but not limited to, the implied warranties of
28  * merchantability and fitness for a particular purpose are disclaimed.
29  * In no event shall the company or contributors be liable for any
30  * direct, indirect, incidental, special, exemplary, or consequential
31  * damages (including, but not limited to, procurement of substitute
32  * goods or services; loss of use, data, or profits; or business
33  * interruption) however caused and on any theory of liability, whether
34  * in contract, strict liability, or tort (including negligence or
35  * otherwise) arising in any way out of the use of this software, even if
36  * advised of the possibility of such damage.
37  *
38  * $Id: vinumutil.c,v 1.14 1999/12/30 07:04:02 grog Exp grog $
39  * $FreeBSD: src/sys/dev/vinum/vinumutil.c,v 1.15 2000/02/29 06:16:44 grog Exp $
40  * $DragonFly: src/sbin/vinum/vinumutil.c,v 1.6 2005/02/03 22:05:27 joerg Exp $
41  */
42
43 /* This file contains utility routines used both in kernel and user context */
44
45 #include <dev/raid/vinum/vinumhdr.h>
46 #include <dev/raid/vinum/statetexts.h>
47 #include <stdio.h>
48 #include <string.h>
49 extern jmp_buf command_fail;                                /* return on a failed command */
50
51 static char numeric_state[32];                              /* temporary buffer for ASCII conversions */
52 #define STATECOUNT(x) (sizeof (x##statetext) / sizeof (char *))
53 /* Return drive state as a string */
54 char *
55 drive_state(enum drivestate state)
56 {
57     if (((unsigned) state) >= STATECOUNT(drive)) {
58         sprintf(numeric_state, "Invalid state %d", (int) state);
59         return numeric_state;
60     } else
61         return drivestatetext[state];
62 }
63
64 /* Return volume state as a string */
65 char *
66 volume_state(enum volumestate state)
67 {
68     if (((unsigned) state) >= STATECOUNT(vol)) {
69         sprintf(numeric_state, "Invalid state %d", (int) state);
70         return numeric_state;
71     } else
72         return volstatetext[state];
73 }
74
75 /* Return plex state as a string */
76 char *
77 plex_state(enum plexstate state)
78 {
79     if (((unsigned) state) >= STATECOUNT(plex)) {
80         sprintf(numeric_state, "Invalid state %d", (int) state);
81         return numeric_state;
82     } else
83         return plexstatetext[state];
84 }
85
86 /* Return plex organization as a string */
87 char *
88 plex_org(enum plexorg org)
89 {
90     switch (org) {
91     case plex_disorg:                                       /* disorganized */
92         return "disorg";
93         break;
94
95     case plex_concat:                                       /* concatenated plex */
96         return "concat";
97         break;
98
99     case plex_striped:                                      /* striped plex */
100         return "striped";
101         break;
102
103     case plex_raid4:                                        /* RAID-4 plex */
104         return "raid4";
105
106     case plex_raid5:                                        /* RAID-5 plex */
107         return "raid5";
108         break;
109
110     default:
111         sprintf(numeric_state, "Invalid org %d", (int) org);
112         return numeric_state;
113     }
114 }
115
116 /* Return sd state as a string */
117 char *
118 sd_state(enum sdstate state)
119 {
120     if (((unsigned) state) >= STATECOUNT(sd)) {
121         sprintf(numeric_state, "Invalid state %d", (int) state);
122         return numeric_state;
123     } else
124         return sdstatetext[state];
125 }
126
127 /* Now convert in the other direction */
128 /*
129  * These are currently used only internally,
130  * so we don't do too much error checking
131  */
132 enum drivestate
133 DriveState(char *text)
134 {
135     int i;
136     for (i = 0; i < STATECOUNT(drive); i++)
137         if (strcmp(text, drivestatetext[i]) == 0)           /* found it */
138             return (enum drivestate) i;
139     return -1;
140 }
141
142 enum sdstate
143 SdState(char *text)
144 {
145     int i;
146     for (i = 0; i < STATECOUNT(sd); i++)
147         if (strcmp(text, sdstatetext[i]) == 0)              /* found it */
148             return (enum sdstate) i;
149     return -1;
150 }
151
152 enum plexstate
153 PlexState(char *text)
154 {
155     int i;
156     for (i = 0; i < STATECOUNT(plex); i++)
157         if (strcmp(text, plexstatetext[i]) == 0)            /* found it */
158             return (enum plexstate) i;
159     return -1;
160 }
161
162 enum volumestate
163 VolState(char *text)
164 {
165     int i;
166     for (i = 0; i < STATECOUNT(vol); i++)
167         if (strcmp(text, volstatetext[i]) == 0)             /* found it */
168             return (enum volumestate) i;
169     return -1;
170 }
171
172 /*
173  * Take a number with an optional scale factor and convert
174  * it to a number of bytes.
175  *
176  * The scale factors are:
177  *
178  * s    sectors (of 512 bytes)
179  * b    blocks (of 512 bytes).  This unit is deprecated,
180  *      because it's confusing, but maintained to avoid
181  *      confusing Veritas users.
182  * k    kilobytes (1024 bytes)
183  * m    megabytes (of 1024 * 1024 bytes)
184  * g    gigabytes (of 1024 * 1024 * 1024 bytes)
185  */
186 u_int64_t
187 sizespec(char *spec)
188 {
189     u_int64_t size;
190     char *s;
191     int sign = 1;                                           /* -1 if negative */
192
193     size = 0;
194     if (spec != NULL) {                                     /* we have a parameter */
195         s = spec;
196         if (*s == '-') {                                    /* negative, */
197             sign = -1;
198             s++;                                            /* skip */
199         }
200         if ((*s >= '0') && (*s <= '9')) {                   /* it's numeric */
201             while ((*s >= '0') && (*s <= '9'))              /* it's numeric */
202                 size = size * 10 + *s++ - '0';              /* convert it */
203             switch (*s) {
204             case '\0':
205                 return size * sign;
206
207             case 'B':
208             case 'b':
209             case 'S':
210             case 's':
211                 return size * sign * 512;
212
213             case 'K':
214             case 'k':
215                 return size * sign * 1024;
216
217             case 'M':
218             case 'm':
219                 return size * sign * 1024 * 1024;
220
221             case 'G':
222             case 'g':
223                 return size * sign * 1024 * 1024 * 1024;
224             }
225         }
226         fprintf(stderr, "Invalid length specification: %s", spec);
227         longjmp(command_fail, -1);
228     }
229     fprintf(stderr, "Missing length specification");
230     longjmp(command_fail, -1);
231 }
232
233 /*
234  * Extract the volume number from a device number.
235  * Perform no checking.
236  */
237 int
238 Volno(dev_t dev)
239 {
240     return (minor(dev) & MASK(VINUM_VOL_WIDTH)) >> VINUM_VOL_SHIFT;
241 }
242
243 /*
244  * Extract a plex number from a device number.
245  * Don't check the major number, but check the
246  * type.  Return -1 for invalid types.
247  */
248 int
249 Plexno(dev_t dev)
250 {
251     switch (DEVTYPE(dev)) {
252     case VINUM_VOLUME_TYPE:
253     case VINUM_DRIVE_TYPE:
254     case VINUM_SUPERDEV_TYPE:                               /* ordinary super device */
255     case VINUM_RAWSD_TYPE:
256         return -1;
257
258     case VINUM_PLEX_TYPE:
259     case VINUM_SD_TYPE:
260         return VOL[Volno(dev)].plex[(minor(dev) >> VINUM_PLEX_SHIFT) & (MASK(VINUM_PLEX_WIDTH))];
261
262     case VINUM_RAWPLEX_TYPE:
263         return ((minor(dev) & MASK(VINUM_VOL_WIDTH)) >> VINUM_VOL_SHIFT) /* low order 8 bits */
264         |((minor(dev) >> VINUM_RAWPLEX_SHIFT)
265             & (MASK(VINUM_RAWPLEX_WIDTH)
266                 << (VINUM_VOL_SHIFT + VINUM_VOL_WIDTH)));   /* upper 12 bits */
267     }
268     return 0;                                               /* compiler paranoia */
269 }
270
271 /*
272  * Extract a subdisk number from a device number.
273  * Don't check the major number, but check the
274  * type.  Return -1 for invalid types.
275  */
276 int
277 Sdno(dev_t dev)
278 {
279     switch (DEVTYPE(dev)) {
280     case VINUM_VOLUME_TYPE:
281     case VINUM_DRIVE_TYPE:
282     case VINUM_SUPERDEV_TYPE:                               /* ordinary super device */
283     case VINUM_PLEX_TYPE:
284     case VINUM_RAWPLEX_TYPE:
285         return -1;
286
287     case VINUM_SD_TYPE:
288         return PLEX[Plexno(dev)].sdnos[(minor(dev) >> VINUM_SD_SHIFT) & (MASK(VINUM_SD_WIDTH))];
289
290     case VINUM_RAWSD_TYPE:
291         return ((minor(dev) & MASK(VINUM_VOL_WIDTH)) >> VINUM_VOL_SHIFT) /* low order 8 bits */
292         |((minor(dev) >> VINUM_RAWPLEX_SHIFT) & (MASK(VINUM_RAWPLEX_WIDTH)
293                 << (VINUM_VOL_SHIFT + VINUM_VOL_WIDTH)));   /* upper 12 bits */
294     }
295     return -1;                                              /* compiler paranoia */
296 }