Commit | Line | Data |
---|---|---|
805e021f CE |
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 <roken.h> | |
14 | ||
15 | #include "afsutil.h" | |
16 | ||
17 | /* maximum number of partitions - must match vol/voldefs.h */ | |
18 | #define VOLMAXPARTS 255 | |
19 | ||
20 | /** | |
21 | * map a partition id from any partition-style name. | |
22 | * | |
23 | * @param[in] aname partition name string | |
24 | * | |
25 | * @return partition index number | |
26 | * @retval -1 invalid partition name | |
27 | * | |
28 | * @see volutil_PartitionName2_r | |
29 | * @see volutil_PartitionName_r | |
30 | * @see volutil_PartitionName | |
31 | */ | |
32 | afs_int32 | |
33 | volutil_GetPartitionID(char *aname) | |
34 | { | |
35 | char tc; | |
36 | afs_int32 temp; | |
37 | char ascii[3]; | |
38 | ||
39 | tc = *aname; | |
40 | if (tc == 0) | |
41 | return -1; /* unknown */ | |
42 | /* numbers go straight through */ | |
43 | if (tc >= '0' && tc <= '9') { | |
44 | temp = atoi(aname); | |
45 | /* this next check is to make the syntax less ambiguous when discriminating | |
46 | * between volume numbers and partition IDs. This lets things like | |
47 | * bos salvage do some reasonability checks on its input w/o checking | |
48 | * to see if the partition is really on the server. | |
49 | */ | |
50 | if (temp < 0 || temp >= VOLMAXPARTS) | |
51 | return -1; | |
52 | else | |
53 | return temp; | |
54 | } | |
55 | /* otherwise check for vicepa or /vicepa, or just plain "a" */ | |
56 | ascii[2] = 0; | |
57 | if (strlen(aname) <= 2) { | |
58 | strcpy(ascii, aname); | |
59 | } else if (!strncmp(aname, "/vicep", 6)) { | |
60 | if(strlcpy(ascii, aname + 6, sizeof(ascii)) >= sizeof(ascii)) | |
61 | return -1; /* bad partition name: trailing characters */ | |
62 | } else if (!strncmp(aname, "vicep", 5)) { | |
63 | if(strlcpy(ascii, aname + 5, sizeof(ascii)) >= sizeof(ascii)) | |
64 | return -1; /* bad partition name: trailing characters */ | |
65 | } else | |
66 | return -1; /* bad partition name */ | |
67 | /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz, | |
68 | * and are numbered from 0. Do the appropriate conversion */ | |
69 | if (ascii[1] == 0) { | |
70 | /* one char name, 0..25 */ | |
71 | if (ascii[0] < 'a' || ascii[0] > 'z') | |
72 | return -1; /* wrongo */ | |
73 | return ascii[0] - 'a'; | |
74 | } else { | |
75 | /* two char name, 26 .. <whatever> */ | |
76 | if (ascii[0] < 'a' || ascii[0] > 'z') | |
77 | return -1; /* wrongo */ | |
78 | if (ascii[1] < 'a' || ascii[1] > 'z') | |
79 | return -1; /* just as bad */ | |
80 | temp = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26; | |
81 | return (temp >= VOLMAXPARTS ? -1 : temp); | |
82 | } | |
83 | } | |
84 | ||
85 | /** | |
86 | * convert a partition index number into a partition name string (/vicepXX). | |
87 | * | |
88 | * @param[in] part partition index number | |
89 | * @param[out] tbuffer buffer in which to store name | |
90 | * @param[in] buflen length of tbuffer | |
91 | * | |
92 | * @return operation status | |
93 | * @retval 0 success | |
94 | * @retval -1 buffer too short | |
95 | * @retval -2 invalid partition id | |
96 | * | |
97 | * @see volutil_PartitionName_r | |
98 | * @see volutil_PartitionName | |
99 | * @see volutil_GetPartitionID | |
100 | */ | |
101 | afs_int32 | |
102 | volutil_PartitionName2_r(afs_int32 part, char *tbuffer, size_t buflen) | |
103 | { | |
104 | char tempString[3]; | |
105 | int i; | |
106 | ||
107 | if (part < 0 || part >= VOLMAXPARTS) { | |
108 | return -2; | |
109 | } | |
110 | ||
111 | tempString[1] = tempString[2] = 0; | |
112 | strncpy(tbuffer, "/vicep", buflen); | |
113 | if (part <= 25) { | |
114 | tempString[0] = 'a' + part; | |
115 | } else { | |
116 | part -= 26; | |
117 | i = (part / 26); | |
118 | tempString[0] = i + 'a'; | |
119 | tempString[1] = (part % 26) + 'a'; | |
120 | } | |
121 | if (strlcat(tbuffer, tempString, buflen) >= buflen) { | |
122 | return -1; | |
123 | } | |
124 | return 0; | |
125 | } | |
126 | ||
127 | #define BAD_VID "BAD VOLUME ID" | |
128 | #define BAD_VID_LEN (sizeof(BAD_VID)) | |
129 | /** | |
130 | * convert a partition index number into a partition name string (/vicepXX). | |
131 | * | |
132 | * @param[in] part partition index number | |
133 | * @param[out] tbuffer buffer in which to store name | |
134 | * @param[in] buflen length of tbuffer | |
135 | * | |
136 | * @return partition name string | |
137 | * @retval "" buffer too short | |
138 | * @retval "SPC" buffer too short | |
139 | * @retval "BAD VOLUME ID" avalue contains an invalid partition index | |
140 | * | |
141 | * @note you may wish to consider using volutil_PartitionName2_r, as its | |
142 | * error handling is more standard | |
143 | * | |
144 | * @see volutil_PartitionName2_r | |
145 | * @see volutil_PartitionName | |
146 | * @see volutil_GetPartitionID | |
147 | */ | |
148 | char * | |
149 | volutil_PartitionName_r(int part, char *tbuffer, int buflen) | |
150 | { | |
151 | afs_int32 code; | |
152 | ||
153 | if (buflen < BAD_VID_LEN) { | |
154 | strlcpy(tbuffer, "SPC", buflen); | |
155 | return tbuffer; | |
156 | } | |
157 | ||
158 | code = volutil_PartitionName2_r(part, tbuffer, buflen); | |
159 | ||
160 | if (code == -2) { | |
161 | strlcpy(tbuffer, BAD_VID, buflen); | |
162 | } | |
163 | ||
164 | return tbuffer; | |
165 | } | |
166 | ||
167 | /** | |
168 | * convert a partition index number into a partition name string (/vicepXX). | |
169 | * | |
170 | * @param[in] avalue partition index number | |
171 | * | |
172 | * @return partition name string | |
173 | * @retval "BAD VOLUME ID" avalue contains an invalid partition index | |
174 | * | |
175 | * @warning this interface is not re-entrant | |
176 | * | |
177 | * @see volutil_PartitionName2_r | |
178 | * @see volutil_PartitionName_r | |
179 | * @see volutil_GetPartitionID | |
180 | */ | |
181 | char * | |
182 | volutil_PartitionName(int avalue) | |
183 | { | |
184 | #define VPN_TBUFLEN 64 | |
185 | static char tbuffer[VPN_TBUFLEN]; | |
186 | return volutil_PartitionName_r(avalue, tbuffer, VPN_TBUFLEN - 1); | |
187 | } | |
188 | ||
189 | /* is this a digit or a digit-like thing? */ | |
190 | static int | |
191 | ismeta(int ac, int abase) | |
192 | { | |
193 | /* if (ac == '-' || ac == 'x' || ac == 'X') return 1; */ | |
194 | if (ac >= '0' && ac <= '7') | |
195 | return 1; | |
196 | if (abase <= 8) | |
197 | return 0; | |
198 | if (ac >= '8' && ac <= '9') | |
199 | return 1; | |
200 | if (abase <= 10) | |
201 | return 0; | |
202 | if (ac >= 'a' && ac <= 'f') | |
203 | return 1; | |
204 | if (ac >= 'A' && ac <= 'F') | |
205 | return 1; | |
206 | return 0; | |
207 | } | |
208 | ||
209 | /* given that this is a digit or a digit-like thing, compute its value */ | |
210 | static int | |
211 | getmeta(int ac) | |
212 | { | |
213 | if (ac >= '0' && ac <= '9') | |
214 | return ac - '0'; | |
215 | if (ac >= 'a' && ac <= 'f') | |
216 | return ac - 'a' + 10; | |
217 | if (ac >= 'A' && ac <= 'F') | |
218 | return ac - 'A' + 10; | |
219 | return 0; | |
220 | } | |
221 | ||
222 | afs_int32 | |
223 | util_GetInt32(char *as, afs_int32 * aval) | |
224 | { | |
225 | afs_int32 total; | |
226 | int tc; | |
227 | int base; | |
228 | int negative; | |
229 | ||
230 | total = 0; /* initialize things */ | |
231 | negative = 0; | |
232 | ||
233 | /* skip over leading spaces */ | |
234 | for (tc = *as; tc !='\0'; as++, tc = *as) { | |
235 | if (tc != ' ' && tc != '\t') | |
236 | break; | |
237 | } | |
238 | ||
239 | /* compute sign */ | |
240 | if (*as == '-') { | |
241 | negative = 1; | |
242 | as++; /* skip over character */ | |
243 | } | |
244 | ||
245 | /* compute the base */ | |
246 | if (*as == '0') { | |
247 | as++; | |
248 | if (*as == 'x' || *as == 'X') { | |
249 | base = 16; | |
250 | as++; | |
251 | } else | |
252 | base = 8; | |
253 | } else | |
254 | base = 10; | |
255 | ||
256 | /* compute the # itself */ | |
257 | for (tc = *as; tc !='\0'; as++, tc = *as) { | |
258 | if (!ismeta(tc, base)) | |
259 | return -1; | |
260 | total *= base; | |
261 | total += getmeta(tc); | |
262 | } | |
263 | ||
264 | if (negative) | |
265 | *aval = -total; | |
266 | else | |
267 | *aval = total; | |
268 | return 0; | |
269 | } | |
270 | ||
271 | afs_uint32 | |
272 | util_GetUInt32(char *as, afs_uint32 * aval) | |
273 | { | |
274 | afs_uint32 total; | |
275 | int tc; | |
276 | int base; | |
277 | ||
278 | total = 0; /* initialize things */ | |
279 | ||
280 | /* skip over leading spaces */ | |
281 | for (tc = *as; tc !='\0'; as++, tc = *as) { | |
282 | if (tc != ' ' && tc != '\t') | |
283 | break; | |
284 | } | |
285 | ||
286 | /* compute the base */ | |
287 | if (*as == '0') { | |
288 | as++; | |
289 | if (*as == 'x' || *as == 'X') { | |
290 | base = 16; | |
291 | as++; | |
292 | } else | |
293 | base = 8; | |
294 | } else | |
295 | base = 10; | |
296 | ||
297 | /* compute the # itself */ | |
298 | for (tc = *as; tc !='\0'; as++, tc = *as) { | |
299 | if (!ismeta(tc, base)) | |
300 | return -1; | |
301 | total *= base; | |
302 | total += getmeta(tc); | |
303 | } | |
304 | ||
305 | *aval = total; | |
306 | return 0; | |
307 | } | |
308 | ||
309 | static const char power_letter[] = { | |
310 | 'K', /* kibi */ | |
311 | 'M', /* mebi */ | |
312 | 'G', /* gibi */ | |
313 | 'T', /* tebi */ | |
314 | }; | |
315 | ||
316 | afs_int32 | |
317 | util_GetHumanInt32(char *as, afs_int32 * aval) | |
318 | { | |
319 | long value; | |
320 | char * unit; | |
321 | long mult = 1; | |
322 | int exponent = 0; | |
323 | ||
324 | errno = 0; | |
325 | value = strtol(as, &unit, 0); | |
326 | if (errno) | |
327 | return -1; | |
328 | if (unit[0] != 0) { | |
329 | for (exponent = 0; exponent < sizeof(power_letter) && power_letter[exponent] != unit[0]; exponent++) { | |
330 | mult *= 1024; | |
331 | } | |
332 | if (exponent == sizeof(power_letter)) | |
333 | return -1; | |
334 | } | |
335 | if (value > MAX_AFS_INT32 / mult || value < MIN_AFS_INT32 / mult) | |
336 | return -1; | |
337 | ||
338 | *aval = value * mult; | |
339 | ||
340 | return 0; | |
341 | } | |
342 | ||
343 | afs_int32 | |
344 | util_GetInt64(char *as, afs_int64 * aval) | |
345 | { | |
346 | afs_int64 total; | |
347 | int tc; | |
348 | int base; | |
349 | int negative; | |
350 | ||
351 | total = 0; /* initialize things */ | |
352 | negative = 0; | |
353 | ||
354 | /* skip over leading spaces */ | |
355 | while ((tc = *as)) { | |
356 | if (tc != ' ' && tc != '\t') | |
357 | break; | |
358 | } | |
359 | ||
360 | /* compute sign */ | |
361 | if (*as == '-') { | |
362 | negative = 1; | |
363 | as++; /* skip over character */ | |
364 | } | |
365 | ||
366 | /* compute the base */ | |
367 | if (*as == '0') { | |
368 | as++; | |
369 | if (*as == 'x' || *as == 'X') { | |
370 | base = 16; | |
371 | as++; | |
372 | } else | |
373 | base = 8; | |
374 | } else | |
375 | base = 10; | |
376 | ||
377 | /* compute the # itself */ | |
378 | while ((tc = *as)) { | |
379 | if (!ismeta(tc, base)) | |
380 | return -1; | |
381 | total *= base; | |
382 | total += getmeta(tc); | |
383 | as++; | |
384 | } | |
385 | ||
386 | if (negative) | |
387 | *aval = -total; | |
388 | else | |
389 | *aval = total; | |
390 | return 0; | |
391 | } | |
392 | ||
393 | afs_uint32 | |
394 | util_GetUInt64(char *as, afs_uint64 * aval) | |
395 | { | |
396 | afs_uint64 total; | |
397 | int tc; | |
398 | int base; | |
399 | ||
400 | total = 0; /* initialize things */ | |
401 | ||
402 | /* skip over leading spaces */ | |
403 | while ((tc = *as)) { | |
404 | if (tc != ' ' && tc != '\t') | |
405 | break; | |
406 | } | |
407 | ||
408 | /* compute the base */ | |
409 | if (*as == '0') { | |
410 | as++; | |
411 | if (*as == 'x' || *as == 'X') { | |
412 | base = 16; | |
413 | as++; | |
414 | } else | |
415 | base = 8; | |
416 | } else | |
417 | base = 10; | |
418 | ||
419 | /* compute the # itself */ | |
420 | while ((tc = *as)) { | |
421 | if (!ismeta(tc, base)) | |
422 | return -1; | |
423 | total *= base; | |
424 | total += getmeta(tc); | |
425 | as++; | |
426 | } | |
427 | ||
428 | *aval = total; | |
429 | return 0; | |
430 | } |