(root)/
findutils-4.9.0/
locate/
word_io.c
       1  /* word_io.c -- word oriented I/O
       2     Copyright (C) 2007-2022 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 <https://www.gnu.org/licenses/>.
      16  */
      17  
      18  /* config.h must be included first. */
      19  #include <config.h>
      20  
      21  /* system headers. */
      22  #include <errno.h>
      23  #include <stdbool.h>		/* for bool */
      24  #include <stdio.h>
      25  #include <stdlib.h>
      26  #include <string.h>
      27  
      28  /* gnulib headers. */
      29  #include "byteswap.h"
      30  #include "error.h"
      31  #include "quotearg.h"
      32  
      33  /* find headers. */
      34  #include "system.h"
      35  #include "die.h"
      36  #include "locatedb.h"
      37  
      38  
      39  enum { WORDBYTES=4 };
      40  
      41  static int
      42  decode_value (const unsigned char data[],
      43  	      int limit,
      44  	      GetwordEndianState *endian_state_flag,
      45  	      const char *filename)
      46  {
      47    int swapped;
      48    union
      49    {
      50      int ival;			/* native representation */
      51      unsigned char data[WORDBYTES];
      52    } u;
      53    u.ival = 0;
      54    memcpy (&u.data, data, WORDBYTES);
      55    swapped = bswap_32(u.ival);	/* byteswapped */
      56  
      57    if (*endian_state_flag == GetwordEndianStateInitial)
      58      {
      59        if (u.ival <= limit)
      60  	{
      61  	  if (swapped > limit)
      62  	    {
      63  	      /* the native value is inside the limit and the
      64  	       * swapped value is not.  We take this as proof
      65  	       * that we should be using the native byte order.
      66  	       */
      67  	      *endian_state_flag = GetwordEndianStateNative;
      68  	    }
      69  	  return u.ival;
      70  	}
      71        else
      72  	{
      73  	  if (swapped <= limit)
      74  	    {
      75  	      /* Aha, now we know we have to byte-swap. */
      76  	      error (0, 0,
      77  		     _("WARNING: locate database %s was "
      78  		       "built with a different byte order"),
      79  		     quotearg_n_style (0, locale_quoting_style, filename));
      80  	      *endian_state_flag = GetwordEndianStateSwab;
      81  	      return swapped;
      82  	    }
      83  	  else
      84  	    {
      85  	      /* u.ival > limit and swapped > limit.  For the moment, assume
      86  	       * native ordering.
      87  	       */
      88  	      return u.ival;
      89  	    }
      90  	}
      91      }
      92    else
      93      {
      94        /* We already know the byte order. */
      95        if (*endian_state_flag == GetwordEndianStateSwab)
      96  	return swapped;
      97        else
      98  	return u.ival;
      99      }
     100  }
     101  
     102  
     103  
     104  int
     105  getword (FILE *fp,
     106  	 const char *filename,
     107  	 size_t maxvalue,
     108  	 GetwordEndianState *endian_state_flag)
     109  {
     110    unsigned char data[4];
     111    size_t bytes_read;
     112  
     113    clearerr (fp);
     114    bytes_read = fread (data, WORDBYTES, 1, fp);
     115    if (bytes_read != 1)
     116      {
     117        const char * quoted_name = quotearg_n_style (0, locale_quoting_style,
     118  						   filename);
     119        /* Distinguish between a truncated database and an I/O error.
     120         * Either condition is fatal.
     121         */
     122        if (feof (fp))
     123  	die (EXIT_FAILURE, 0, _("unexpected EOF in %s"), quoted_name);
     124        else
     125  	die (EXIT_FAILURE, errno,
     126  	     _("error reading a word from %s"), quoted_name);
     127        abort ();
     128      }
     129    else
     130      {
     131        return decode_value (data, maxvalue, endian_state_flag, filename);
     132      }
     133  }