1 /* $NetBSD: off_cvt.c,v 1.1.1.1 2009/06/23 10:08:47 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* off_cvt 3 6 /* SUMMARY 7 /* off_t conversions 8 /* SYNOPSIS 9 /* #include <off_cvt.h> 10 /* 11 /* off_t off_cvt_string(string) 12 /* const char *string; 13 /* 14 /* VSTRING *off_cvt_number(result, offset) 15 /* VSTRING *result; 16 /* off_t offset; 17 /* DESCRIPTION 18 /* This module provides conversions between \fIoff_t\fR and string. 19 /* 20 /* off_cvt_string() converts a string, containing a non-negative 21 /* offset, to numerical form. The result is -1 in case of problems. 22 /* 23 /* off_cvt_number() converts a non-negative offset to string form. 24 /* 25 /* Arguments: 26 /* .IP string 27 /* String with non-negative number to be converted to off_t. 28 /* .IP result 29 /* Buffer for storage of the result of conversion to string. 30 /* .IP offset 31 /* Non-negative off_t value to be converted to string. 32 /* DIAGNOSTICS 33 /* Panic: negative offset 34 /* LICENSE 35 /* .ad 36 /* .fi 37 /* The Secure Mailer license must be distributed with this software. 38 /* AUTHOR(S) 39 /* Wietse Venema 40 /* IBM T.J. Watson Research 41 /* P.O. Box 704 42 /* Yorktown Heights, NY 10598, USA 43 /*--*/ 44 45 /* System library. */ 46 47 #include <sys_defs.h> 48 #include <ctype.h> 49 50 /* Utility library. */ 51 52 #include <msg.h> 53 #include <vstring.h> 54 55 /* Global library. */ 56 57 #include "off_cvt.h" 58 59 /* Application-specific. */ 60 61 #define STR vstring_str 62 #define END vstring_end 63 #define SWAP(type, a, b) { type temp; temp = a; a = b; b = temp; } 64 65 /* off_cvt_string - string to number */ 66 67 off_t off_cvt_string(const char *str) 68 { 69 int ch; 70 off_t result; 71 off_t res2; 72 off_t res4; 73 off_t res8; 74 off_t res10; 75 76 /* 77 * Multiplication by numbers > 2 can overflow without producing a smaller 78 * result mod 2^N (where N is the number of bits in the result type). 79 * (Victor Duchovni, Morgan Stanley). 80 */ 81 for (result = 0; (ch = *(unsigned char *) str) != 0; str++) { 82 if (!ISDIGIT(ch)) 83 return (-1); 84 if ((res2 = result + result) < result) 85 return (-1); 86 if ((res4 = res2 + res2) < res2) 87 return (-1); 88 if ((res8 = res4 + res4) < res4) 89 return (-1); 90 if ((res10 = res8 + res2) < res8) 91 return (-1); 92 if ((result = res10 + ch - '0') < res10) 93 return (-1); 94 } 95 return (result); 96 } 97 98 /* off_cvt_number - number to string */ 99 100 VSTRING *off_cvt_number(VSTRING *buf, off_t offset) 101 { 102 static char digs[] = "0123456789"; 103 char *start; 104 char *last; 105 int i; 106 107 /* 108 * Sanity checks 109 */ 110 if (offset < 0) 111 msg_panic("off_cvt_number: negative offset -%s", 112 STR(off_cvt_number(buf, -offset))); 113 114 /* 115 * First accumulate the result, backwards. 116 */ 117 VSTRING_RESET(buf); 118 while (offset != 0) { 119 VSTRING_ADDCH(buf, digs[offset % 10]); 120 offset /= 10; 121 } 122 VSTRING_TERMINATE(buf); 123 124 /* 125 * Then, reverse the result. 126 */ 127 start = STR(buf); 128 last = END(buf) - 1; 129 for (i = 0; i < VSTRING_LEN(buf) / 2; i++) 130 SWAP(int, start[i], last[-i]); 131 return (buf); 132 } 133 134 #ifdef TEST 135 136 /* 137 * Proof-of-concept test program. Read a number from stdin, convert to 138 * off_t, back to string, and print the result. 139 */ 140 #include <vstream.h> 141 #include <vstring_vstream.h> 142 143 int main(int unused_argc, char **unused_argv) 144 { 145 VSTRING *buf = vstring_alloc(100); 146 off_t offset; 147 148 while (vstring_fgets_nonl(buf, VSTREAM_IN)) { 149 if ((offset = off_cvt_string(STR(buf))) < 0) { 150 msg_warn("bad input %s", STR(buf)); 151 } else { 152 vstream_printf("%s\n", STR(off_cvt_number(buf, offset))); 153 } 154 vstream_fflush(VSTREAM_OUT); 155 } 156 vstring_free(buf); 157 return (0); 158 } 159 160 #endif 161