summaryrefslogtreecommitdiffhomepage
path: root/libbb/safe_strtol.c
blob: a7f012fbcad236ba93b3953ae8a0d852648f5400 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* vi: set sw=4 ts=4: */
/*
 * Utility routines.
 *
 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
 *
 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
 */

#include <assert.h>
#include "libbb.h"

int safe_strtod(const char *arg, double* value)
{
	char *endptr;
	int errno_save = errno;

	assert(arg!=NULL);
	errno = 0;
	*value = strtod(arg, &endptr);
	if (errno != 0 || *endptr != '\0' || endptr == arg) {
		return 1;
	}
	errno = errno_save;
	return 0;
}

int safe_strtoull(const char *arg, unsigned long long* value)
{
	char *endptr;
	int errno_save = errno;

	assert(arg!=NULL);
	if (!isdigit(arg[0])) /* strtouXX takes minus signs w/o error! :( */
		return 1;
	errno = 0;
	*value = strtoull(arg, &endptr, 0);
	if (errno != 0 || *endptr != '\0' || endptr == arg) {
		return 1;
	}
	errno = errno_save;
	return 0;
}

int safe_strtoll(const char *arg, long long* value)
{
	char *endptr;
	int errno_save = errno;

	assert(arg!=NULL);
	errno = 0;
	*value = strtoll(arg, &endptr, 0);
	if (errno != 0 || *endptr != '\0' || endptr == arg) {
		return 1;
	}
	errno = errno_save;
	return 0;
}

int safe_strtoul(const char *arg, unsigned long* value)
{
	char *endptr;
	int errno_save = errno;

	assert(arg!=NULL);
	if (!isdigit(arg[0])) /* strtouXX takes minus signs w/o error! :( */
		return 1;
	errno = 0;
	*value = strtoul(arg, &endptr, 0);
	if (errno != 0 || *endptr != '\0' || endptr == arg) {
		return 1;
	}
	errno = errno_save;
	return 0;
}

int safe_strtol(const char *arg, long* value)
{
	char *endptr;
	int errno_save = errno;

	assert(arg!=NULL);
	errno = 0;
	*value = strtol(arg, &endptr, 0);
	if (errno != 0 || *endptr != '\0' || endptr == arg) {
		return 1;
	}
	errno = errno_save;
	return 0;
}

/* TODO: This is what uclibc is doing. Try to do the same? */

#if 0
#if defined __HAVE_ELF__

# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
# define _strong_alias(name, aliasname) \
  extern __typeof (name) aliasname __attribute__ ((alias (#name)));

#else /* !defined __HAVE_ELF__ */

#  define strong_alias(name, aliasname) _strong_alias (name, aliasname)
#  define _strong_alias(name, aliasname) \
        __asm__(".global " __C_SYMBOL_PREFIX__ #aliasname "\n" \
                ".set " __C_SYMBOL_PREFIX__ #aliasname "," __C_SYMBOL_PREFIX__ #name);

#endif
#endif

int safe_strtoi(const char *arg, int* value)
{
	if (sizeof(long) == sizeof(int)) {
		return safe_strtol(arg, (long*)value);
	} else {
		int error;
		long lvalue = *value;
		error = safe_strtol(arg, &lvalue);
		if (lvalue < INT_MIN || lvalue > INT_MAX)
			return 1;
		*value = (int) lvalue;
		return error;
	}
}

int safe_strtou(const char *arg, unsigned* value)
{
	if (sizeof(unsigned long) == sizeof(unsigned)) {
		return safe_strtoul(arg, (unsigned long*)value);
	} else {
		int error;
		unsigned long lvalue = *value;
		error = safe_strtoul(arg, &lvalue);
		if (lvalue > UINT_MAX)
			return 1;
		*value = (unsigned) lvalue;
		return error;
	}
}

int BUG_safe_strtou32_unimplemented(void);
int safe_strtou32(const char *arg, uint32_t* value)
{
	if (sizeof(uint32_t) == sizeof(unsigned))
		return safe_strtou(arg, (unsigned*)value);
	if (sizeof(uint32_t) == sizeof(unsigned long))
		return safe_strtoul(arg, (unsigned long*)value);
	return BUG_safe_strtou32_unimplemented();
}