(root)/
glibc-2.38/
libio/
tst-ftell-append.c
       1  /* Verify that ftell returns the correct value after a read and a write on a
       2     file opened in a+ mode.
       3     Copyright (C) 2014-2023 Free Software Foundation, Inc.
       4     This file is part of the GNU C Library.
       5  
       6     The GNU C Library is free software; you can redistribute it and/or
       7     modify it under the terms of the GNU Lesser General Public
       8     License as published by the Free Software Foundation; either
       9     version 2.1 of the License, or (at your option) any later version.
      10  
      11     The GNU C Library is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14     Lesser General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public
      17     License along with the GNU C Library; if not, see
      18     <https://www.gnu.org/licenses/>.  */
      19  
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <string.h>
      23  #include <errno.h>
      24  #include <unistd.h>
      25  #include <locale.h>
      26  #include <wchar.h>
      27  
      28  /* data points to either char_data or wide_data, depending on whether we're
      29     testing regular file mode or wide mode respectively.  Similarly,
      30     fputs_func points to either fputs or fputws.  data_len keeps track of the
      31     length of the current data and file_len maintains the current file
      32     length.  */
      33  #define BUF_LEN 4
      34  static void *buf;
      35  static char char_buf[BUF_LEN];
      36  static wchar_t wide_buf[BUF_LEN];
      37  static const void *data;
      38  static const char *char_data = "abcdefghijklmnopqrstuvwxyz";
      39  static const wchar_t *wide_data = L"abcdefghijklmnopqrstuvwxyz";
      40  static size_t data_len;
      41  static size_t file_len;
      42  
      43  typedef int (*fputs_func_t) (const void *data, FILE *fp);
      44  fputs_func_t fputs_func;
      45  
      46  typedef void *(*fgets_func_t) (void *s, int size, FILE *stream);
      47  fgets_func_t fgets_func;
      48  
      49  static int do_test (void);
      50  
      51  #define TEST_FUNCTION do_test ()
      52  #include "../test-skeleton.c"
      53  
      54  static FILE *
      55  init_file (const char *filename)
      56  {
      57    FILE *fp = fopen (filename, "w");
      58    if (fp == NULL)
      59      {
      60        printf ("fopen: %m\n");
      61        return NULL;
      62      }
      63  
      64    int written = fputs_func (data, fp);
      65  
      66    if (written == EOF)
      67      {
      68        printf ("fputs failed to write data\n");
      69        fclose (fp);
      70        return NULL;
      71      }
      72  
      73    file_len = data_len;
      74  
      75    fclose (fp);
      76  
      77    fp = fopen (filename, "a+");
      78    if (fp == NULL)
      79      {
      80        printf ("fopen(a+): %m\n");
      81        return NULL;
      82      }
      83  
      84    return fp;
      85  }
      86  
      87  static int
      88  do_one_test (const char *filename)
      89  {
      90    FILE *fp = init_file (filename);
      91  
      92    if (fp == NULL)
      93      return 1;
      94  
      95    void *ret = fgets_func (buf, BUF_LEN, fp);
      96  
      97    if (ret == NULL)
      98      {
      99        printf ("read failed: %m\n");
     100        fclose (fp);
     101        return 1;
     102      }
     103  
     104    int written = fputs_func (data, fp);
     105  
     106    if (written == EOF)
     107      {
     108        printf ("fputs failed to write data\n");
     109        fclose (fp);
     110        return 1;
     111      }
     112  
     113    file_len += data_len;
     114  
     115    long off = ftell (fp);
     116  
     117    if (off != file_len)
     118      {
     119        printf ("Incorrect offset %ld, expected %zu\n", off, file_len);
     120        fclose (fp);
     121        return 1;
     122      }
     123    else
     124      printf ("Correct offset %ld after write.\n", off);
     125  
     126    return 0;
     127  }
     128  
     129  /* Run the tests for regular files and wide mode files.  */
     130  static int
     131  do_test (void)
     132  {
     133    int ret = 0;
     134    char *filename;
     135    int fd = create_temp_file ("tst-ftell-append-tmp.", &filename);
     136  
     137    if (fd == -1)
     138      {
     139        printf ("create_temp_file: %m\n");
     140        return 1;
     141      }
     142  
     143    close (fd);
     144  
     145    /* Tests for regular files.  */
     146    puts ("Regular mode:");
     147    fputs_func = (fputs_func_t) fputs;
     148    fgets_func = (fgets_func_t) fgets;
     149    data = char_data;
     150    buf = char_buf;
     151    data_len = strlen (char_data);
     152    ret |= do_one_test (filename);
     153  
     154    /* Tests for wide files.  */
     155    puts ("Wide mode:");
     156    if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
     157      {
     158        printf ("Cannot set en_US.UTF-8 locale.\n");
     159        return 1;
     160      }
     161    fputs_func = (fputs_func_t) fputws;
     162    fgets_func = (fgets_func_t) fgetws;
     163    data = wide_data;
     164    buf = wide_buf;
     165    data_len = wcslen (wide_data);
     166    ret |= do_one_test (filename);
     167  
     168    return ret;
     169  }