mirror of https://github.com/apache/cloudstack.git
219 lines
5.0 KiB
C
219 lines
5.0 KiB
C
/*
|
|
* Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifdef __KERNEL__
|
|
# include <linux/config.h>
|
|
# include <linux/module.h>
|
|
# include <linux/kernel.h>
|
|
# include <linux/errno.h>
|
|
#else
|
|
# include <errno.h>
|
|
#endif
|
|
|
|
#include "allocate.h"
|
|
#include "sys_string.h"
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#define deferr(_err) case _err: return #_err
|
|
|
|
extern char *strerror(int err)
|
|
{
|
|
switch(err){
|
|
deferr(EPERM);
|
|
deferr(ENOENT);
|
|
deferr(ESRCH);
|
|
deferr(EINTR);
|
|
deferr(EIO);
|
|
deferr(EINVAL);
|
|
deferr(ENOMEM);
|
|
deferr(EACCES);
|
|
deferr(EFAULT);
|
|
deferr(EBUSY);
|
|
|
|
default:
|
|
return "ERROR";
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/** Set the base to use for converting a string to a number. Base is
|
|
* hex if starts with 0x, otherwise decimal.
|
|
*
|
|
* @param s input string
|
|
* @param base where to put the base
|
|
* @return rest of s to parse as a number
|
|
*/
|
|
inline static const char * convert_set_base(const char *s, int *base){
|
|
*base = 10;
|
|
if(s){
|
|
if(*s=='0'){
|
|
s++;
|
|
if(*s=='x' || *s=='X'){
|
|
*base = 16;
|
|
s++;
|
|
}
|
|
}
|
|
}
|
|
return s;
|
|
}
|
|
|
|
/** Set the sign to use for converting a string to a number.
|
|
* Value is 1 for positive, -1 for negative.
|
|
*
|
|
* @param s input string
|
|
* @param sign where to put the sign
|
|
* @return rest of s to parse as a number
|
|
*/
|
|
inline static const char * convert_set_sign(const char *s, int *sign){
|
|
*sign = 1;
|
|
if(s){
|
|
if(*s == '+'){
|
|
*sign = 1;
|
|
s++;
|
|
} else if (*s == '-'){
|
|
*sign = -1;
|
|
s++;
|
|
}
|
|
}
|
|
return s;
|
|
}
|
|
|
|
/** Get the numerical value of a digit in the given base.
|
|
*
|
|
* @param c digit character
|
|
* @param base to use
|
|
* @return numerical value of digit in range 0..base-1 or
|
|
* -1 if not in range for the base
|
|
*/
|
|
inline static int convert_get_digit(char c, int base){
|
|
int d;
|
|
|
|
if('0'<=c && c<='9'){
|
|
d = c - '0';
|
|
} else if('a'<=c && c<='f'){
|
|
d = c - 'a' + 10;
|
|
} else if('A'<=c && c<='F'){
|
|
d = c - 'A' + 10;
|
|
} else {
|
|
d = -1;
|
|
}
|
|
return (d < base ? d : -1);
|
|
}
|
|
|
|
/** Convert a string to an unsigned long by parsing it as a number.
|
|
* Will accept hex or decimal in usual C syntax.
|
|
*
|
|
* @param str input string
|
|
* @param val where to put the result
|
|
* @return 0 if converted OK, negative otherwise
|
|
*/
|
|
int convert_atoul(const char *str, unsigned long *val){
|
|
int err = 0;
|
|
unsigned long v = 0;
|
|
int base;
|
|
const char *s = str;
|
|
|
|
if(!s) {
|
|
err = -EINVAL;
|
|
goto exit;
|
|
}
|
|
s = convert_set_base(s, &base);
|
|
for( ; !err && *s; s++){
|
|
int digit = convert_get_digit(*s, base);
|
|
if(digit<0){
|
|
err = -EINVAL;
|
|
goto exit;
|
|
}
|
|
v *= base;
|
|
v += digit;
|
|
}
|
|
exit:
|
|
*val = (err ? 0 : v);
|
|
return err;
|
|
}
|
|
|
|
/** Convert a string to a long by parsing it as a number.
|
|
* Will accept hex or decimal in usual C syntax.
|
|
*
|
|
* @param str input string
|
|
* @param val where to put the result
|
|
* @return 0 if converted OK, negative otherwise
|
|
*/
|
|
int convert_atol(const char *str, long *val){
|
|
int err = 0;
|
|
unsigned long v = 0;
|
|
int base, sign = 1;
|
|
const char *s = str;
|
|
|
|
if(!s) {
|
|
err = -EINVAL;
|
|
goto exit;
|
|
}
|
|
s = convert_set_sign(s, &sign);
|
|
s = convert_set_base(s, &base);
|
|
for( ; !err && *s; s++){
|
|
int digit = convert_get_digit(*s, base);
|
|
if(digit<0){
|
|
err = -EINVAL;
|
|
goto exit;
|
|
}
|
|
v *= base;
|
|
v += digit;
|
|
}
|
|
if(sign < 0) v = -v;
|
|
exit:
|
|
*val = (err ? 0 : v);
|
|
return err;
|
|
}
|
|
|
|
/** Combine a directory path with a relative path to produce
|
|
* a new path.
|
|
*
|
|
* @param s directory path
|
|
* @param t relative path
|
|
* @return new combined path s/t
|
|
*/
|
|
int path_concat(char *s, char *t, char **val){
|
|
int err = 0;
|
|
int sn, tn, vn;
|
|
char *v;
|
|
sn = strlen(s);
|
|
if(sn > 0 && s[sn-1] == '/'){
|
|
sn--;
|
|
}
|
|
tn = strlen(t);
|
|
if(tn > 0 && t[0] == '/'){
|
|
tn--;
|
|
}
|
|
vn = sn+tn+1;
|
|
v = (char*)allocate(vn+1);
|
|
if(!v){
|
|
err = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
strncpy(v, s, sn);
|
|
v[sn] = '/';
|
|
strncpy(v+sn+1, t, tn);
|
|
v[vn] = '\0';
|
|
exit:
|
|
*val = (err ? NULL : v);
|
|
return err;
|
|
}
|