about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-08-01 11:34:00 -0700
committerEric Wong <normalperson@yhbt.net>2009-08-01 11:45:30 -0700
commit1ca0715f4bf2bb98cda7b8c5b80a2ce51e9f1473 (patch)
treebdd5e163db7cc937de301b6cf9e93a40c0bd85a3
parenta74ab1a5bd29d8d5980c8ad9913c89af63919eee (diff)
downloadpcu-1ca0715f4bf2bb98cda7b8c5b80a2ce51e9f1473.tar.gz
More accurate string => off_t conversion
off_t can either be 32-bits or 64-bits wide on popular
architectures in 2009, so we need to pick between strtol and
strtoll.  This allows us to (hopefully) deal with files larger
than 2G on 32-bit machines
-rw-r--r--compat-util.h18
-rw-r--r--fadvise.c4
-rw-r--r--mincore.c4
3 files changed, 22 insertions, 4 deletions
diff --git a/compat-util.h b/compat-util.h
index 60c4081..8b70b52 100644
--- a/compat-util.h
+++ b/compat-util.h
@@ -15,6 +15,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <assert.h>
+#include <stdint.h>
 
 #ifndef O_NOATIME
 #  define O_NOATIME 0
@@ -37,4 +38,21 @@ static inline size_t page_size(void)
 
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
 
+/*
+ * converts a C string to a non-negative off_t value, taking base into
+ * account.  On error, it'll return a negative value and set errno
+ * to EINVAL
+ */
+static off_t cstr_to_off_t(const char *nptr, char **endptr, int base)
+{
+        if (sizeof(long) == 8 || (sizeof(long) == 4 && sizeof(off_t) == 4))
+                return (off_t)strtol(nptr, endptr, base);
+        else if (sizeof(off_t) == 8 && sizeof(long) == 4)
+                return (off_t)strtoll(nptr, endptr, base);
+
+        fprintf(stderr, "unrecognized sizes:\n\toff_t: %u\n\tlong: %u\n",
+                        sizeof(off_t), sizeof(long));
+        exit(1);
+}
+
 #endif /* OS_COMPAT_H */
diff --git a/fadvise.c b/fadvise.c
index ddc07fb..12c9b1b 100644
--- a/fadvise.c
+++ b/fadvise.c
@@ -75,14 +75,14 @@ int main(int argc, char * const argv[])
                 argi += 2;
                 switch(opt) {
                 case 'o':
-                        offset = strtol(optarg, &err, 10);
+                        offset = cstr_to_off_t(optarg, &err, 10);
                         if (*err || offset < 0) {
                                 fprintf(stderr, "offset must be >= 0\n");
                                 return 1;
                         }
                         break;
                 case 'l':
-                        len = strtol(optarg, &err, 10);
+                        len = cstr_to_off_t(optarg, &err, 10);
                         if (*err || len < 0) {
                                 fprintf(stderr, "length must be >= 0\n");
                                 return 1;
diff --git a/mincore.c b/mincore.c
index 2e26582..c3aa618 100644
--- a/mincore.c
+++ b/mincore.c
@@ -82,14 +82,14 @@ int main(int argc, char * const argv[])
                 argi += 2;
                 switch(opt) {
                 case 'o':
-                        offset = strtol(optarg, &err, 10);
+                        offset = cstr_to_off_t(optarg, &err, 10);
                         if (*err || offset < 0) {
                                 fprintf(stderr, "offset must be >= 0\n");
                                 return 1;
                         }
                         break;
                 case 'l':
-                        len = strtol(optarg, &err, 10);
+                        len = cstr_to_off_t(optarg, &err, 10);
                         if (*err || len < 0) {
                                 fprintf(stderr, "length must be >= 0\n");
                                 return 1;