Imported Upstream version 4.5.14
[platform/upstream/findutils.git] / locate / word_io.c
1 /* word_io.c -- word oriented I/O
2    Copyright (C) 2007, 2010, 2011 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /* config.h must be included first. */
19 #include <config.h>
20
21 /* system headers. */
22 #include <assert.h>
23 #include <errno.h>
24 #include <stdbool.h>            /* for bool */
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 /* gnulib headers. */
30 #include "byteswap.h"
31 #include "error.h"
32 #include "gettext.h"
33 #include "quotearg.h"
34
35 /* find headers. */
36 #include "locatedb.h"
37
38 #if ENABLE_NLS
39 # include <libintl.h>
40 # define _(Text) gettext (Text)
41 #else
42 # define _(Text) Text
43 #define textdomain(Domain)
44 #define bindtextdomain(Package, Directory)
45 #endif
46 #ifdef gettext_noop
47 # define N_(String) gettext_noop (String)
48 #else
49 /* We used to use (String) instead of just String, but apparently ISO C
50  * doesn't allow this (at least, that's what HP said when someone reported
51  * this as a compiler bug).  This is HP case number 1205608192.  See
52  * also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11250 (which references
53  * ANSI 3.5.7p14-15).  The Intel icc compiler also rejects constructs
54  * like: static const char buf[] = ("string");
55  */
56 # define N_(String) String
57 #endif
58
59
60 enum { WORDBYTES=4 };
61
62 static int
63 decode_value (const unsigned char data[],
64               int limit,
65               GetwordEndianState *endian_state_flag,
66               const char *filename)
67 {
68   int swapped;
69   union
70   {
71     int ival;                   /* native representation */
72     unsigned char data[WORDBYTES];
73   } u;
74   u.ival = 0;
75   memcpy (&u.data, data, WORDBYTES);
76   swapped = bswap_32(u.ival);   /* byteswapped */
77
78   if (*endian_state_flag == GetwordEndianStateInitial)
79     {
80       if (u.ival <= limit)
81         {
82           if (swapped > limit)
83             {
84               /* the native value is inside the limit and the
85                * swapped value is not.  We take this as proof
86                * that we should be using the ative byte order.
87                */
88               *endian_state_flag = GetwordEndianStateNative;
89             }
90           return u.ival;
91         }
92       else
93         {
94           if (swapped <= limit)
95             {
96               /* Aha, now we know we have to byte-swap. */
97               error (0, 0,
98                      _("WARNING: locate database %s was "
99                        "built with a different byte order"),
100                      quotearg_n_style (0, locale_quoting_style, filename));
101               *endian_state_flag = GetwordEndianStateSwab;
102               return swapped;
103             }
104           else
105             {
106               /* u.ival > limit and swapped > limit.  For the moment, assume
107                * native ordering.
108                */
109               return u.ival;
110             }
111         }
112     }
113   else
114     {
115       /* We already know the byte order. */
116       if (*endian_state_flag == GetwordEndianStateSwab)
117         return swapped;
118       else
119         return u.ival;
120     }
121 }
122
123
124
125 int
126 getword (FILE *fp,
127          const char *filename,
128          size_t minvalue,
129          size_t maxvalue,
130          GetwordEndianState *endian_state_flag)
131 {
132   unsigned char data[4];
133   size_t bytes_read;
134
135   clearerr (fp);
136   bytes_read = fread (data, WORDBYTES, 1, fp);
137   if (bytes_read != 1)
138     {
139       const char * quoted_name = quotearg_n_style (0, locale_quoting_style,
140                                                    filename);
141       /* Distinguish between a truncated database and an I/O error.
142        * Either condition is fatal.
143        */
144       if (feof (fp))
145         error (EXIT_FAILURE, 0, _("unexpected EOF in %s"), quoted_name);
146       else
147         error (EXIT_FAILURE, errno,
148                _("error reading a word from %s"), quoted_name);
149       abort ();
150     }
151   else
152     {
153       return decode_value (data, maxvalue, endian_state_flag, filename);
154     }
155 }
156
157
158 bool
159 putword (FILE *fp, int word,
160          GetwordEndianState endian_state_flag)
161 {
162   size_t items_written;
163
164   /* You must decide before calling this function which
165    * endianness you want to use.
166    */
167   assert (endian_state_flag != GetwordEndianStateInitial);
168   if (GetwordEndianStateSwab == endian_state_flag)
169     {
170       word = bswap_32(word);
171     }
172
173   items_written = fwrite (&word, sizeof (word), 1, fp);
174   if (1 == items_written)
175     return true;
176   else
177     return false;
178 }