Postfix3.3.1
off_cvt.c
[詳解]
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 /* Wietse Venema
43 /* Google, Inc.
44 /* 111 8th Avenue
45 /* New York, NY 10011, USA
46 /*--*/
47 
48 /* System library. */
49 
50 #include <sys_defs.h>
51 #include <sys/types.h>
52 #include <ctype.h>
53 
54 /* Utility library. */
55 
56 #include <msg.h>
57 #include <vstring.h>
58 
59 /* Global library. */
60 
61 #include "off_cvt.h"
62 
63 /* Application-specific. */
64 
65 #define STR vstring_str
66 #define END vstring_end
67 #define SWAP(type, a, b) { type temp; temp = a; a = b; b = temp; }
68 
69 /* off_cvt_string - string to number */
70 
71 off_t off_cvt_string(const char *str)
72 {
73  int ch;
74  off_t result;
75  off_t digit_value;
76 
77  /*
78  * Detect overflow before it happens. Code that attempts to detect
79  * overflow after-the-fact makes assumptions about undefined behavior.
80  * Compilers may invalidate such assumptions.
81  */
82  for (result = 0; (ch = *(unsigned char *) str) != 0; str++) {
83  if (!ISDIGIT(ch))
84  return (-1);
85  digit_value = ch - '0';
86  if (result > OFF_T_MAX / 10
87  || (result *= 10) > OFF_T_MAX - digit_value)
88  return (-1);
89  result += digit_value;
90  }
91  return (result);
92 }
93 
94 /* off_cvt_number - number to string */
95 
96 VSTRING *off_cvt_number(VSTRING *buf, off_t offset)
97 {
98  static char digs[] = "0123456789";
99  char *start;
100  char *last;
101  int i;
102 
103  /*
104  * Sanity checks
105  */
106  if (offset < 0)
107  msg_panic("off_cvt_number: negative offset -%s",
108  STR(off_cvt_number(buf, -offset)));
109 
110  /*
111  * First accumulate the result, backwards.
112  */
113  VSTRING_RESET(buf);
114  while (offset != 0) {
115  VSTRING_ADDCH(buf, digs[offset % 10]);
116  offset /= 10;
117  }
118  VSTRING_TERMINATE(buf);
119 
120  /*
121  * Then, reverse the result.
122  */
123  start = STR(buf);
124  last = END(buf) - 1;
125  for (i = 0; i < VSTRING_LEN(buf) / 2; i++)
126  SWAP(int, start[i], last[-i]);
127  return (buf);
128 }
129 
130 #ifdef TEST
131 
132  /*
133  * Proof-of-concept test program. Read a number from stdin, convert to
134  * off_t, back to string, and print the result.
135  */
136 #include <vstream.h>
137 #include <vstring_vstream.h>
138 
139 int main(int unused_argc, char **unused_argv)
140 {
141  VSTRING *buf = vstring_alloc(100);
142  off_t offset;
143 
144  while (vstring_fgets_nonl(buf, VSTREAM_IN)) {
145  if (STR(buf)[0] == '#' || STR(buf)[0] == 0)
146  continue;
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  }
153  }
154  vstring_free(buf);
155  return (0);
156 }
157 
158 #endif
#define vstring_fgets_nonl(s, p)
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define VSTREAM_OUT
Definition: vstream.h:67
int main(int argc, char **argv)
Definition: anvil.c:1010
off_t off_cvt_string(const char *str)
Definition: off_cvt.c:71
#define VSTREAM_IN
Definition: vstream.h:66
#define VSTRING_LEN(vp)
Definition: vstring.h:72
#define SWAP(type, a, b)
Definition: off_cvt.c:67
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define END
Definition: off_cvt.c:66
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
#define ISDIGIT(c)
Definition: sys_defs.h:1748
#define OFF_T_MAX
Definition: sys_defs.h:1683
VSTREAM * vstream_printf(const char *fmt,...)
Definition: vstream.c:1335
#define VSTRING_RESET(vp)
Definition: vstring.h:77
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define STR
Definition: off_cvt.c:65
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
VSTRING * off_cvt_number(VSTRING *buf, off_t offset)
Definition: off_cvt.c:96