(root)/
glibc-2.38/
stdio-common/
tst-fmemopen2.c
       1  /* fmemopen tests.
       2     Copyright (C) 2015-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  
      20  #include <assert.h>
      21  #include <stdio.h>
      22  #include <string.h>
      23  #include <sys/types.h>
      24  #include <stdint.h>
      25  #include <errno.h>
      26  
      27  /* Check fmemopen with user provided buffer open for write.  */
      28  static int
      29  do_test_with_buffer (void)
      30  {
      31    int result = 0;
      32    char buf[100];
      33    const size_t nbuf = sizeof (buf);
      34  
      35    FILE *fp = fmemopen (buf, nbuf, "w");
      36    if (fp == NULL)
      37      {
      38        printf ("FAIL: fmemopen failed (%s)\n", __FUNCTION__);
      39        return 1;
      40      }
      41  
      42    /* Default write operation, check if file position is correct after it.  */
      43    static const char str[] = "hello world";
      44    const size_t nstr = sizeof (str) - 1;
      45    fputs (str, fp);
      46    off_t o = ftello (fp);
      47    if (o != nstr)
      48      {
      49        printf ("FAIL: first ftello returned %jd, expected %zu\n",
      50  	      (intmax_t)o, nstr);
      51        result = 1;
      52      }
      53  
      54    /* Rewind stream and seek tests, the position size should be equal to
      55       buffer size provided in open function.  */
      56    rewind (fp);
      57    o = ftello (fp);
      58    if (o != 0)
      59      {
      60        printf ("FAIL: second ftello returned %jd, expected 0\n",
      61  	      (intmax_t)o);
      62        result = 1;
      63      }
      64    if (fseeko (fp, 0, SEEK_END) != 0)
      65      {
      66        printf ("FAIL: fseeko failed\n");
      67        result = 1;
      68      }
      69    o = ftello (fp);
      70    if (o != nstr)
      71      {
      72        printf ("FAIL: third ftello returned %jd, expected %zu\n",
      73  	      (intmax_t)o, nstr);
      74        result = 1;
      75      }
      76  
      77    /* Rewind the stream and recheck by using a shorter string.  */
      78    rewind (fp);
      79    static const char str2[] = "just hello";
      80    const size_t nstr2 = sizeof (str2) - 1;
      81    assert (nstr2 < nstr);
      82    fputs (str2, fp);
      83    o = ftello (fp);
      84    if (o != nstr2)
      85      {
      86        printf ("FAIL: fourth ftello returned %jd, expected %zu\n",
      87  	      (intmax_t)o, nstr2);
      88        result = 1;
      89      }
      90    fclose (fp);
      91  
      92    /* Again, but now with a larger string.  */
      93    static const char str3[] = "just hellod";
      94    if (strcmp (buf, str3) != 0)
      95      {
      96        printf ("FAIL: final string is \"%s\", expected \"%s\"\n",
      97                buf, str3);
      98        result = 1;
      99      }
     100    return result;
     101  }
     102  
     103  /* Check fmemopen without user provided buffer open for write.  */
     104  static int
     105  do_test_without_buffer (void)
     106  {
     107    int result = 0;
     108    const size_t nbuf = 100;
     109  
     110    FILE *fp = fmemopen (NULL, nbuf, "w");
     111    if (fp == NULL)
     112      {
     113        printf ("FAIL: fmemopen failed (%s)\n", __FUNCTION__);
     114        return 1;
     115      }
     116  
     117    static const char str[] = "hello world";
     118    const size_t nstr = sizeof (str) - 1;
     119  
     120    /* Default write operation, check if file position is correct after it.  */
     121    fputs (str, fp);
     122    off_t o = ftello (fp);
     123    if (o != nstr)
     124      {
     125        printf ("FAIL: first ftello returned %jd, expected %zu\n",
     126  	      (intmax_t) o, nstr);
     127        result = 1;
     128      }
     129    if (fseeko (fp, 0, SEEK_END) != 0)
     130      {
     131        printf ("FAIL: fseeko failed\n");
     132        result = 1;
     133      }
     134    o = ftello (fp);
     135    if (o != nstr)
     136      {
     137        printf ("FAIL: second ftello returned %jd, expected %zu\n",
     138  	      (intmax_t) o, nbuf);
     139        result = 1;
     140      }
     141  
     142    /* Rewind the stream and recheck by using a shorter string.  */
     143    rewind (fp);
     144    static const char str2[] = "just hello";
     145    const size_t nstr2 = sizeof (str2) - 1;
     146    assert (nstr2 < nstr);
     147    fputs (str2, fp);
     148    o = ftello (fp);
     149    if (o != nstr2)
     150      {
     151        printf ("FAIL: third ftello returned %jd, expected %zu\n",
     152  	      (intmax_t) o, nstr2);
     153        result = 1;
     154      }
     155    fclose (fp);
     156  
     157    return result;
     158  }
     159  
     160  /* Check fmemopen with a buffer length of zero.  */
     161  static int
     162  do_test_length_zero (void)
     163  {
     164    int result = 0;
     165    FILE *fp;
     166  #define BUFCONTENTS "testing buffer"
     167    char buf[100] = BUFCONTENTS;
     168    const size_t nbuf = 0;
     169    int r;
     170  
     171    fp = fmemopen (buf, nbuf, "r");
     172    if (fp == NULL)
     173      {
     174        printf ("FAIL: fmemopen failed (%s)\n", __FUNCTION__);
     175        return 1;
     176      }
     177  
     178    /* Reading any data on a zero-length buffer should return EOF.  */
     179    if ((r = fgetc (fp)) != EOF)
     180      {
     181        printf ("FAIL: fgetc on a zero-length returned: %d\n", r);
     182        result = 1;
     183      }
     184    off_t o = ftello (fp);
     185    if (o != 0)
     186      {
     187        printf ("FAIL: first ftello returned %jd, expected 0\n",
     188  	      (intmax_t) o);
     189        result = 1;
     190      }
     191    fclose (fp);
     192  
     193    /* Writing any data shall start at current position and shall not pass
     194       current buffer size beyond the size in fmemopen call.  */
     195    fp = fmemopen (buf, nbuf, "w");
     196    if (fp == NULL)
     197      {
     198        printf ("FAIL: second fmemopen failed (%s)\n", __FUNCTION__);
     199        return 1;
     200      }
     201  
     202    static const char str[] = "hello world";
     203    /* Because of buffering, the fputs call itself will not fail. However the
     204       final buffer should be not changed because length 0 was passed to the
     205       fmemopen call.  */
     206    fputs (str, fp);
     207    r = 0;
     208    errno = 0;
     209    if (fflush (fp) != EOF)
     210      {
     211        printf ("FAIL: fflush did not return EOF\n");
     212        fclose (fp);
     213        return 1;
     214      }
     215    if (errno != ENOSPC)
     216      {
     217        printf ("FAIL: errno is %i (expected ENOSPC)\n", errno);
     218        fclose (fp);
     219        return 1;
     220      }
     221  
     222    fclose (fp);
     223  
     224    if (strcmp (buf, BUFCONTENTS) != 0)
     225      {
     226        printf ("FAIL: strcmp (%s, %s) failed\n", buf, BUFCONTENTS);
     227        return 1;
     228      }
     229  
     230    /* Different than 'w' mode, 'w+' truncates the buffer.  */
     231    fp = fmemopen (buf, nbuf, "w+");
     232    if (fp == NULL)
     233      {
     234        printf ("FAIL: third fmemopen failed (%s)\n", __FUNCTION__);
     235        return 1;
     236      }
     237  
     238    fclose (fp);
     239  
     240    if (strcmp (buf, "") != 0)
     241      {
     242        printf ("FAIL: strcmp (%s, \"\") failed\n", buf);
     243        return 1;
     244      }
     245  
     246    return result;
     247  }
     248  
     249  static int
     250  do_test (void)
     251  {
     252    int ret = 0;
     253  
     254    ret += do_test_with_buffer ();
     255    ret += do_test_without_buffer ();
     256    ret += do_test_length_zero ();
     257  
     258    return ret;
     259  }
     260  
     261  #define TEST_FUNCTION do_test ()
     262  #include "../test-skeleton.c"