72bee5ee45f7af51e5434c8a3d48f8cb3ec32c1e
[openafs.git] / src / util / volparse.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <string.h>
14 #ifdef HAVE_STDLIB_H
15 #include <stdlib.h>
16 #endif
17
18 #include "afsutil.h"
19
20 /* maximum number of partitions - must match vol/voldefs.h */
21 #define VOLMAXPARTS 255
22
23 /**
24  * map a partition id from any partition-style name.
25  *
26  * @param[in] aname  partition name string
27  *
28  * @return partition index number
29  *   @retval -1  invalid partition name
30  *
31  * @see volutil_PartitionName2_r
32  * @see volutil_PartitionName_r
33  * @see volutil_PartitionName
34  */
35 afs_int32
36 volutil_GetPartitionID(char *aname)
37 {
38     register char tc;
39     afs_int32 temp;
40     char ascii[3];
41
42     tc = *aname;
43     if (tc == 0)
44         return -1;              /* unknown */
45     /* numbers go straight through */
46     if (tc >= '0' && tc <= '9') {
47         temp = atoi(aname);
48         /* this next check is to make the syntax less ambiguous when discriminating
49          * between volume numbers and partition IDs.  This lets things like
50          * bos salvage do some reasonability checks on its input w/o checking
51          * to see if the partition is really on the server.
52          */
53         if (temp < 0 || temp >= VOLMAXPARTS)
54             return -1;
55         else
56             return temp;
57     }
58     /* otherwise check for vicepa or /vicepa, or just plain "a" */
59     ascii[2] = 0;
60     if (strlen(aname) <= 2) {
61         strcpy(ascii, aname);
62     } else if (!strncmp(aname, "/vicep", 6)) {
63         strncpy(ascii, aname + 6, 2);
64     } else if (!strncmp(aname, "vicep", 5)) {
65         strncpy(ascii, aname + 5, 2);
66     } else
67         return -1;              /* bad partition name */
68     /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz,
69      * and are numbered from 0.  Do the appropriate conversion */
70     if (ascii[1] == 0) {
71         /* one char name, 0..25 */
72         if (ascii[0] < 'a' || ascii[0] > 'z')
73             return -1;          /* wrongo */
74         return ascii[0] - 'a';
75     } else {
76         /* two char name, 26 .. <whatever> */
77         if (ascii[0] < 'a' || ascii[0] > 'z')
78             return -1;          /* wrongo */
79         if (ascii[1] < 'a' || ascii[1] > 'z')
80             return -1;          /* just as bad */
81         temp = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
82         return (temp >= VOLMAXPARTS ? -1 : temp);
83     }
84 }
85
86 /**
87  * convert a partition index number into a partition name string (/vicepXX).
88  *
89  * @param[in]  part     partition index number
90  * @param[out] tbuffer  buffer in which to store name
91  * @param[in]  buflen   length of tbuffer
92  *
93  * @return operation status
94  *   @retval 0   success
95  *   @retval -1  buffer too short
96  *   @retval -2  invalid partition id
97  *
98  * @see volutil_PartitionName_r
99  * @see volutil_PartitionName
100  * @see volutil_GetPartitionID
101  */
102 afs_int32
103 volutil_PartitionName2_r(afs_int32 part, char *tbuffer, size_t buflen)
104 {
105     char tempString[3];
106     register int i;
107
108     if (part < 0 || part >= VOLMAXPARTS) {
109         return -2;
110     }
111
112     tempString[1] = tempString[2] = 0;
113     strncpy(tbuffer, "/vicep", buflen);
114     if (part <= 25) {
115         tempString[0] = 'a' + part;
116     } else {
117         part -= 26;
118         i = (part / 26);
119         tempString[0] = i + 'a';
120         tempString[1] = (part % 26) + 'a';
121     }
122     if (strlcat(tbuffer, tempString, buflen) >= buflen) {
123         return -1;
124     }
125     return 0;
126 }
127
128 #define BAD_VID "BAD VOLUME ID"
129 #define BAD_VID_LEN (sizeof(BAD_VID))
130 /**
131  * convert a partition index number into a partition name string (/vicepXX).
132  *
133  * @param[in]  part     partition index number
134  * @param[out] tbuffer  buffer in which to store name
135  * @param[in]  buflen   length of tbuffer
136  *
137  * @return partition name string
138  *   @retval ""               buffer too short
139  *   @retval "SPC"            buffer too short
140  *   @retval "BAD VOLUME ID"  avalue contains an invalid partition index
141  *
142  * @note you may wish to consider using volutil_PartitionName2_r, as its
143  *       error handling is more standard
144  *
145  * @see volutil_PartitionName2_r
146  * @see volutil_PartitionName
147  * @see volutil_GetPartitionID
148  */
149 char *
150 volutil_PartitionName_r(int part, char *tbuffer, int buflen)
151 {
152     afs_int32 code;
153
154     if (buflen < BAD_VID_LEN) {
155         strlcpy(tbuffer, "SPC", buflen);
156         return tbuffer;
157     }
158
159     code = volutil_PartitionName2_r(part, tbuffer, buflen);
160
161     if (code == -2) {
162         strlcpy(tbuffer, BAD_VID, buflen);
163     }
164
165     return tbuffer;
166 }
167
168 /**
169  * convert a partition index number into a partition name string (/vicepXX).
170  *
171  * @param[in] avalue  partition index number
172  *
173  * @return partition name string
174  *   @retval "BAD VOLUME ID"  avalue contains an invalid partition index
175  *
176  * @warning this interface is not re-entrant
177  *
178  * @see volutil_PartitionName2_r
179  * @see volutil_PartitionName_r
180  * @see volutil_GetPartitionID
181  */
182 char *
183 volutil_PartitionName(int avalue)
184 {
185 #define VPN_TBUFLEN 64
186     static char tbuffer[VPN_TBUFLEN];
187     return volutil_PartitionName_r(avalue, tbuffer, VPN_TBUFLEN - 1);
188 }
189
190 /* is this a digit or a digit-like thing? */
191 static int
192 ismeta(register int ac, register int abase)
193 {
194 /*    if (ac == '-' || ac == 'x' || ac == 'X') return 1; */
195     if (ac >= '0' && ac <= '7')
196         return 1;
197     if (abase <= 8)
198         return 0;
199     if (ac >= '8' && ac <= '9')
200         return 1;
201     if (abase <= 10)
202         return 0;
203     if (ac >= 'a' && ac <= 'f')
204         return 1;
205     if (ac >= 'A' && ac <= 'F')
206         return 1;
207     return 0;
208 }
209
210 /* given that this is a digit or a digit-like thing, compute its value */
211 static int
212 getmeta(register int ac)
213 {
214     if (ac >= '0' && ac <= '9')
215         return ac - '0';
216     if (ac >= 'a' && ac <= 'f')
217         return ac - 'a' + 10;
218     if (ac >= 'A' && ac <= 'F')
219         return ac - 'A' + 10;
220     return 0;
221 }
222
223 afs_int32
224 util_GetInt32(register char *as, afs_int32 * aval)
225 {
226     register afs_int32 total;
227     register int tc;
228     int base;
229     int negative;
230
231     total = 0;                  /* initialize things */
232     negative = 0;
233
234     /* skip over leading spaces */
235     for (tc = *as; tc !='\0'; as++, tc = *as) {
236         if (tc != ' ' && tc != '\t')
237             break;
238     }
239
240     /* compute sign */
241     if (*as == '-') {
242         negative = 1;
243         as++;                   /* skip over character */
244     }
245
246     /* compute the base */
247     if (*as == '0') {
248         as++;
249         if (*as == 'x' || *as == 'X') {
250             base = 16;
251             as++;
252         } else
253             base = 8;
254     } else
255         base = 10;
256
257     /* compute the # itself */
258     for (tc = *as; tc !='\0'; as++, tc = *as) {
259         if (!ismeta(tc, base))
260             return -1;
261         total *= base;
262         total += getmeta(tc);
263     }
264
265     if (negative)
266         *aval = -total;
267     else
268         *aval = total;
269     return 0;
270 }
271
272 afs_uint32
273 util_GetUInt32(register char *as, afs_uint32 * aval)
274 {
275     register afs_uint32 total;
276     register int tc;
277     int base;
278
279     total = 0;                  /* initialize things */
280
281     /* skip over leading spaces */
282     for (tc = *as; tc !='\0'; as++, tc = *as) {
283         if (tc != ' ' && tc != '\t')
284             break;
285     }
286
287     /* compute the base */
288     if (*as == '0') {
289         as++;
290         if (*as == 'x' || *as == 'X') {
291             base = 16;
292             as++;
293         } else
294             base = 8;
295     } else
296         base = 10;
297
298     /* compute the # itself */
299     for (tc = *as; tc !='\0'; as++, tc = *as) {
300         if (!ismeta(tc, base))
301             return -1;
302         total *= base;
303         total += getmeta(tc);
304     }
305
306     *aval = total;
307     return 0;
308 }