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