LCOV - differential code coverage report
Current view: top level - src/common - pg_get_line.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 74.3 % 35 26 9 26
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 3 3 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 74.3 % 35 26 9 26
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 100.0 % 3 3 3

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * pg_get_line.c
                                  4                 :  *    fgets() with an expansible result buffer
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :  *
                                  9                 :  *
                                 10                 :  * IDENTIFICATION
                                 11                 :  *    src/common/pg_get_line.c
                                 12                 :  *
                                 13                 :  *-------------------------------------------------------------------------
                                 14                 :  */
                                 15                 : #ifndef FRONTEND
                                 16                 : #include "postgres.h"
                                 17                 : #else
                                 18                 : #include "postgres_fe.h"
                                 19                 : #endif
                                 20                 : 
                                 21                 : #include <setjmp.h>
                                 22                 : 
                                 23                 : #include "common/string.h"
                                 24                 : #include "lib/stringinfo.h"
                                 25                 : 
                                 26                 : 
                                 27                 : /*
                                 28                 :  * pg_get_line()
                                 29                 :  *
                                 30                 :  * This is meant to be equivalent to fgets(), except that instead of
                                 31                 :  * reading into a caller-supplied, fixed-size buffer, it reads into
                                 32                 :  * a palloc'd (in frontend, really malloc'd) string, which is resized
                                 33                 :  * as needed to handle indefinitely long input lines.  The caller is
                                 34                 :  * responsible for pfree'ing the result string when appropriate.
                                 35                 :  *
                                 36                 :  * As with fgets(), returns NULL if there is a read error or if no
                                 37                 :  * characters are available before EOF.  The caller can distinguish
                                 38                 :  * these cases by checking ferror(stream).
                                 39                 :  *
                                 40                 :  * Since this is meant to be equivalent to fgets(), the trailing newline
                                 41                 :  * (if any) is not stripped.  Callers may wish to apply pg_strip_crlf().
                                 42                 :  *
                                 43                 :  * Note that while I/O errors are reflected back to the caller to be
                                 44                 :  * dealt with, an OOM condition for the palloc'd buffer will not be;
                                 45                 :  * there'll be an ereport(ERROR) or exit(1) inside stringinfo.c.
                                 46                 :  *
                                 47                 :  * Also note that the palloc'd buffer is usually a lot longer than
                                 48                 :  * strictly necessary, so it may be inadvisable to use this function
                                 49                 :  * to collect lots of long-lived data.  A less memory-hungry option
                                 50                 :  * is to use pg_get_line_buf() or pg_get_line_append() in a loop,
                                 51                 :  * then pstrdup() each line.
                                 52                 :  *
                                 53                 :  * prompt_ctx can optionally be provided to allow this function to be
                                 54                 :  * canceled via an existing SIGINT signal handler that will longjmp to the
                                 55                 :  * specified place only when *(prompt_ctx->enabled) is true.  If canceled,
                                 56                 :  * this function returns NULL, and prompt_ctx->canceled is set to true.
                                 57                 :  */
                                 58                 : char *
  508 tgl                        59 CBC           2 : pg_get_line(FILE *stream, PromptInterruptContext *prompt_ctx)
                                 60                 : {
                                 61                 :     StringInfoData buf;
                                 62                 : 
  948                            63               2 :     initStringInfo(&buf);
                                 64                 : 
  508                            65               2 :     if (!pg_get_line_append(stream, &buf, prompt_ctx))
                                 66                 :     {
                                 67                 :         /* ensure that free() doesn't mess up errno */
  948 tgl                        68 UBC           0 :         int         save_errno = errno;
                                 69                 : 
                                 70               0 :         pfree(buf.data);
                                 71               0 :         errno = save_errno;
                                 72               0 :         return NULL;
                                 73                 :     }
                                 74                 : 
  945 tgl                        75 CBC           2 :     return buf.data;
                                 76                 : }
                                 77                 : 
                                 78                 : /*
                                 79                 :  * pg_get_line_buf()
                                 80                 :  *
                                 81                 :  * This has similar behavior to pg_get_line(), and thence to fgets(),
                                 82                 :  * except that the collected data is returned in a caller-supplied
                                 83                 :  * StringInfo buffer.  This is a convenient API for code that just
                                 84                 :  * wants to read and process one line at a time, without any artificial
                                 85                 :  * limit on line length.
                                 86                 :  *
                                 87                 :  * Returns true if a line was successfully collected (including the
                                 88                 :  * case of a non-newline-terminated line at EOF).  Returns false if
                                 89                 :  * there was an I/O error or no data was available before EOF.
                                 90                 :  * (Check ferror(stream) to distinguish these cases.)
                                 91                 :  *
                                 92                 :  * In the false-result case, buf is reset to empty.
                                 93                 :  */
                                 94                 : bool
  929                            95         5909939 : pg_get_line_buf(FILE *stream, StringInfo buf)
                                 96                 : {
                                 97                 :     /* We just need to drop any data from the previous call */
                                 98         5909939 :     resetStringInfo(buf);
  508                            99         5909939 :     return pg_get_line_append(stream, buf, NULL);
                                100                 : }
                                101                 : 
                                102                 : /*
                                103                 :  * pg_get_line_append()
                                104                 :  *
                                105                 :  * This has similar behavior to pg_get_line(), and thence to fgets(),
                                106                 :  * except that the collected data is appended to whatever is in *buf.
                                107                 :  * This is useful in preference to pg_get_line_buf() if the caller wants
                                108                 :  * to merge some lines together, e.g. to implement backslash continuation.
                                109                 :  *
                                110                 :  * Returns true if a line was successfully collected (including the
                                111                 :  * case of a non-newline-terminated line at EOF).  Returns false if
                                112                 :  * there was an I/O error or no data was available before EOF.
                                113                 :  * (Check ferror(stream) to distinguish these cases.)
                                114                 :  *
                                115                 :  * In the false-result case, the contents of *buf are logically unmodified,
                                116                 :  * though it's possible that the buffer has been resized.
                                117                 :  *
                                118                 :  * prompt_ctx can optionally be provided to allow this function to be
                                119                 :  * canceled via an existing SIGINT signal handler that will longjmp to the
                                120                 :  * specified place only when *(prompt_ctx->enabled) is true.  If canceled,
                                121                 :  * this function returns false, and prompt_ctx->canceled is set to true.
                                122                 :  */
                                123                 : bool
                                124         6037631 : pg_get_line_append(FILE *stream, StringInfo buf,
                                125                 :                    PromptInterruptContext *prompt_ctx)
                                126                 : {
  945                           127         6037631 :     int         orig_len = buf->len;
                                128                 : 
  508                           129         6037631 :     if (prompt_ctx && sigsetjmp(*((sigjmp_buf *) prompt_ctx->jmpbuf), 1) != 0)
                                130                 :     {
                                131                 :         /* Got here with longjmp */
  508 tgl                       132 UBC           0 :         prompt_ctx->canceled = true;
                                133                 :         /* Discard any data we collected before detecting error */
                                134               0 :         buf->len = orig_len;
                                135               0 :         buf->data[orig_len] = '\0';
                                136               0 :         return false;
                                137                 :     }
                                138                 : 
                                139                 :     /* Loop until newline or EOF/error */
                                140                 :     for (;;)
  508 tgl                       141 CBC           1 :     {
                                142                 :         char       *res;
                                143                 : 
                                144                 :         /* Enable longjmp while waiting for input */
                                145         6037632 :         if (prompt_ctx)
                                146               2 :             *(prompt_ctx->enabled) = true;
                                147                 : 
                                148                 :         /* Read some data, appending it to whatever we already have */
                                149         6037632 :         res = fgets(buf->data + buf->len, buf->maxlen - buf->len, stream);
                                150                 : 
                                151                 :         /* Disable longjmp again, then break if fgets failed */
                                152         6037632 :         if (prompt_ctx)
                                153               2 :             *(prompt_ctx->enabled) = false;
                                154                 : 
                                155         6037632 :         if (res == NULL)
                                156            4536 :             break;
                                157                 : 
                                158                 :         /* Got data, so update buf->len */
  945                           159         6033096 :         buf->len += strlen(buf->data + buf->len);
                                160                 : 
                                161                 :         /* Done if we have collected a newline */
                                162         6033096 :         if (buf->len > orig_len && buf->data[buf->len - 1] == '\n')
                                163         6033095 :             return true;
                                164                 : 
                                165                 :         /* Make some more room in the buffer, and loop to read more data */
                                166               1 :         enlargeStringInfo(buf, 128);
                                167                 :     }
                                168                 : 
                                169                 :     /* Check for I/O errors and EOF */
                                170            4536 :     if (ferror(stream) || buf->len == orig_len)
                                171                 :     {
                                172                 :         /* Discard any data we collected before detecting error */
                                173            4536 :         buf->len = orig_len;
                                174            4536 :         buf->data[orig_len] = '\0';
                                175            4536 :         return false;
                                176                 :     }
                                177                 : 
                                178                 :     /* No newline at EOF, but we did collect some data */
  945 tgl                       179 UBC           0 :     return true;
                                180                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a