replace: use a wrapper around strtoll if it didn't behave as expected
authorMatthieu Patou <mat@matws.net>
Wed, 20 Oct 2010 20:13:54 +0000 (00:13 +0400)
committerMatthieu Patou <mat@matws.net>
Thu, 21 Oct 2010 21:00:53 +0000 (01:00 +0400)
lib/replace/replace.c
lib/replace/replace.h
lib/replace/wscript

index a00f7053e2d064219539deaf21132f860a9faa8b..5ecda9226f01711e7269c7baba52ddf94491be03 100644 (file)
@@ -3,6 +3,7 @@
    replacement routines for broken systems
    Copyright (C) Andrew Tridgell 1992-1998
    Copyright (C) Jelmer Vernooij 2005-2008
+   Copyright (C) Matthieu Patou  2010
 
      ** NOTE! The following LGPL license applies to the replace
      ** library. This does NOT imply that all of Samba is released
@@ -502,6 +503,7 @@ char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
 }
 #endif
 
+
 #ifndef HAVE_STRTOLL
 long long int rep_strtoll(const char *str, char **endptr, int base)
 {
@@ -515,7 +517,29 @@ long long int rep_strtoll(const char *str, char **endptr, int base)
 # error "You need a strtoll function"
 #endif
 }
-#endif
+#else
+#ifdef HAVE_BSD_STRTOLL
+#ifdef HAVE_STRTOQ
+long long int rep_strtoll(const char *str, char **endptr, int base)
+{
+       long long int nb = strtoq(str, endptr, base);
+       /* In linux EINVAL is only returned if base is not ok */
+       if (errno == EINVAL) {
+               if (base == 0 || (base >1 && base <37)) {
+                       /* Base was ok so it's because we were not
+                        * able to make the convertion.
+                        * Let's reset errno.
+                        */
+                       errno = 0;
+               }
+       }
+       return nb;
+}
+#else
+#error "You need the strtoq function"
+#endif /* HAVE_STRTOQ */
+#endif /* HAVE_BSD_STRTOLL */
+#endif /* HAVE_STRTOLL */
 
 
 #ifndef HAVE_STRTOULL
@@ -531,7 +555,29 @@ unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
 # error "You need a strtoull function"
 #endif
 }
-#endif
+#else
+#ifdef HAVE_BSD_STRTOLL
+#ifdef HAVE_STRTOUQ
+long long int rep_strtoull(const char *str, char **endptr, int base)
+{
+       unsigned long long int nb = strtouq(str, endptr, base);
+       /* In linux EINVAL is only returned if base is not ok */
+       if (errno == EINVAL) {
+               if (base == 0 || (base >1 && base <37)) {
+                       /* Base was ok so it's because we were not
+                        * able to make the convertion.
+                        * Let's reset errno.
+                        */
+                       errno = 0;
+               }
+       }
+       return nb;
+}
+#else
+#error "You need the strtouq function"
+#endif /* HAVE_STRTOUQ */
+#endif /* HAVE_BSD_STRTOLL */
+#endif /* HAVE_STRTOULL */
 
 #ifndef HAVE_SETENV
 int rep_setenv(const char *name, const char *value, int overwrite) 
index 10c7ee701c5f3f5476a512ebd094b914c4c80fca..8f820a949cad431236e1176924507d3fd857cb5c 100644 (file)
@@ -283,14 +283,26 @@ char *rep_strcasestr(const char *haystack, const char *needle);
 char *rep_strtok_r(char *s, const char *delim, char **save_ptr);
 #endif
 
+
+
 #ifndef HAVE_STRTOLL
+long long int rep_strtoll(const char *str, char **endptr, int base);
 #define strtoll rep_strtoll
+#else
+#ifdef HAVE_BSD_STRTOLL
 long long int rep_strtoll(const char *str, char **endptr, int base);
+#define strtoll rep_strtoll
+#endif
 #endif
 
 #ifndef HAVE_STRTOULL
 #define strtoull rep_strtoull
 unsigned long long int rep_strtoull(const char *str, char **endptr, int base);
+#else
+#ifdef HAVE_BSD_STRTOLL
+long long int rep_strtoull(const char *str, char **endptr, int base);
+#define strtoull rep_strtoull
+#endif
 #endif
 
 #ifndef HAVE_FTRUNCATE
index 48871d644290264feb5b27f62ac818fbbf2573e0..1778ea71b075c3b76d1ab2478e86814657ed451b 100644 (file)
@@ -160,6 +160,23 @@ def configure(conf):
     conf.CHECK_FUNCS('link readlink symlink realpath snprintf vsnprintf')
     conf.CHECK_FUNCS('asprintf vasprintf setenv unsetenv strnlen strtoull __strtoull')
     conf.CHECK_FUNCS('strtouq strtoll __strtoll strtoq')
+    #Some OS (ie. freebsd) return EINVAL if the convertion could not be done, it's not what we expect
+    #Let's detect those cases
+    if conf.CONFIG_SET('HAVE_STRTOLL'):
+        conf.CHECK_CODE('''
+                        long long nb = strtoll("Text", NULL, 0);
+                        if (errno == EINVAL) {
+                            return 0;
+                        } else {
+                            return 1;
+                        }
+                        ''',
+                        msg="Checking correct behavior of strtoll",
+                        headers = 'errno.h',
+                        execute = True,
+                        define_ret = True,
+                        define = 'HAVE_BSD_STRTOLL',
+                        )
     conf.CHECK_FUNCS('if_nametoindex strerror_r')
     conf.CHECK_FUNCS('getdirentries getdents syslog')
     conf.CHECK_FUNCS('gai_strerror get_current_dir_name')