LCOV - differential code coverage report
Current view: top level - src/bin/pg_upgrade - util.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 76.5 % 115 88 9 7 10 1 7 54 14 13 14 58 5 10
Current Date: 2023-04-08 17:13:01 Functions: 91.7 % 12 11 1 11 1 10 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 50.0 % 4 2 2 2
Legend: Lines: hit not hit (240..) days: 77.5 % 111 86 7 7 10 1 7 54 12 13 13 51
Function coverage date bins:
(240..) days: 50.0 % 22 11 1 11 1 9

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  *  util.c
                                  3                 :  *
                                  4                 :  *  utility functions
                                  5                 :  *
                                  6                 :  *  Copyright (c) 2010-2023, PostgreSQL Global Development Group
                                  7                 :  *  src/bin/pg_upgrade/util.c
                                  8                 :  */
                                  9                 : 
                                 10                 : #include "postgres_fe.h"
                                 11                 : 
                                 12                 : #include <signal.h>
                                 13                 : 
                                 14                 : #include "common/username.h"
                                 15                 : #include "pg_upgrade.h"
                                 16                 : 
                                 17                 : LogOpts     log_opts;
                                 18                 : 
                                 19                 : static void pg_log_v(eLogType type, const char *fmt, va_list ap) pg_attribute_printf(2, 0);
                                 20                 : 
                                 21                 : 
                                 22                 : /*
                                 23                 :  * report_status()
                                 24                 :  *
                                 25                 :  *  Displays the result of an operation (ok, failed, error message,...)
                                 26                 :  *
                                 27                 :  *  This is no longer functionally different from pg_log(), but we keep
                                 28                 :  *  it around to maintain a notational distinction between operation
                                 29                 :  *  results and other messages.
                                 30                 :  */
                                 31                 : void
 4555 bruce                      32 GIC          45 : report_status(eLogType type, const char *fmt,...)
                                 33                 : {
                                 34                 :     va_list     args;
 4715 bruce                      35 ECB             : 
 4715 bruce                      36 GIC          45 :     va_start(args, fmt);
  271 tgl                        37 GNC          45 :     pg_log_v(type, fmt, args);
 4715 bruce                      38 GIC          44 :     va_end(args);
 4715 bruce                      39 CBC          44 : }
 4715 bruce                      40 ECB             : 
                                 41                 : 
                                 42                 : void
 3782 bruce                      43 GIC           3 : end_progress_output(void)
 3782 bruce                      44 ECB             : {
                                 45                 :     /*
                                 46                 :      * For output to a tty, erase prior contents of progress line. When either
                                 47                 :      * tty or verbose, indent so that report_status() output will align
                                 48                 :      * nicely.
                                 49                 :      */
  412 andres                     50 GIC           3 :     if (log_opts.isatty)
  321 peter                      51 ECB             :     {
  321 peter                      52 UIC           0 :         printf("\r");
  271 tgl                        53 UNC           0 :         pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, "");
  321 peter                      54 EUB             :     }
  412 andres                     55 GIC           3 :     else if (log_opts.verbose)
  271 tgl                        56 UNC           0 :         pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, "");
 3782 bruce                      57 GBC           3 : }
 3782 bruce                      58 ECB             : 
                                 59                 : /*
                                 60                 :  * Remove any logs generated internally.  To be used once when exiting.
                                 61                 :  */
                                 62                 : void
  305 michael                    63 GIC           2 : cleanup_output_dirs(void)
  305 michael                    64 ECB             : {
  305 michael                    65 GIC           2 :     fclose(log_opts.internal);
  305 michael                    66 ECB             : 
                                 67                 :     /* Remove dump and log files? */
  305 michael                    68 GIC           2 :     if (log_opts.retain)
  305 michael                    69 LBC           0 :         return;
  305 michael                    70 EUB             : 
                                 71                 :     /*
                                 72                 :      * Try twice.  The second time might wait for files to finish being
                                 73                 :      * unlinked, on Windows.
                                 74                 :      */
   67 tmunro                     75 GNC           2 :     if (!rmtree(log_opts.basedir, true))
   67 tmunro                     76 UNC           0 :         rmtree(log_opts.basedir, true);
                                 77                 : 
                                 78                 :     /* Remove pg_upgrade_output.d only if empty */
  305 michael                    79 GIC           2 :     switch (pg_check_dir(log_opts.rootdir))
                                 80                 :     {
  305 michael                    81 LBC           0 :         case 0:                 /* non-existent */
  305 michael                    82 EUB             :         case 3:                 /* exists and contains a mount point */
  305 michael                    83 UIC           0 :             Assert(false);
                                 84                 :             break;
  305 michael                    85 ECB             : 
  305 michael                    86 GIC           2 :         case 1:                 /* exists and empty */
  305 michael                    87 EUB             :         case 2:                 /* exists and contains only dot files */
                                 88                 : 
                                 89                 :             /*
                                 90                 :              * Try twice.  The second time might wait for files to finish
                                 91                 :              * being unlinked, on Windows.
                                 92                 :              */
   67 tmunro                     93 GNC           2 :             if (!rmtree(log_opts.rootdir, true))
   67 tmunro                     94 UNC           0 :                 rmtree(log_opts.rootdir, true);
  305 michael                    95 GBC           2 :             break;
                                 96                 : 
  305 michael                    97 UIC           0 :         case 4:                 /* exists */
  305 michael                    98 ECB             : 
                                 99                 :             /*
                                100                 :              * Keep the root directory as this includes some past log
                                101                 :              * activity.
                                102                 :              */
  305 michael                   103 UIC           0 :             break;
                                104                 : 
  305 michael                   105 LBC           0 :         default:
  305 michael                   106 EUB             :             /* different failure, just report it */
  271 tgl                       107 UNC           0 :             pg_log(PG_WARNING, "could not access directory \"%s\": %m",
                                108                 :                    log_opts.rootdir);
  305 michael                   109 UBC           0 :             break;
                                110                 :     }
                                111                 : }
                                112                 : 
                                113                 : /*
                                114                 :  * prep_status
 4715 bruce                     115 EUB             :  *
                                116                 :  *  Displays a message that describes an operation we are about to begin.
                                117                 :  *  We pad the message out to MESSAGE_WIDTH characters so that all of the
                                118                 :  *  "ok" and "failed" indicators line up nicely.  (Overlength messages
                                119                 :  *  will be truncated, so don't get too verbose.)
                                120                 :  *
                                121                 :  *  A typical sequence would look like this:
                                122                 :  *      prep_status("about to flarb the next %d files", fileCount);
                                123                 :  *      if ((message = flarbFiles(fileCount)) == NULL)
                                124                 :  *        report_status(PG_REPORT, "ok");
                                125                 :  *      else
                                126                 :  *        pg_log(PG_FATAL, "failed: %s", message);
                                127                 :  */
                                128                 : void
 4555 bruce                     129 GIC          41 : prep_status(const char *fmt,...)
                                130                 : {
                                131                 :     va_list     args;
                                132                 :     char        message[MAX_STRING];
                                133                 : 
 4715                           134              41 :     va_start(args, fmt);
                                135              41 :     vsnprintf(message, sizeof(message), fmt, args);
                                136              41 :     va_end(args);
                                137                 : 
                                138                 :     /* trim strings */
  271 tgl                       139 GNC          41 :     pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, message);
  412 andres                    140 GIC          41 : }
  412 andres                    141 ECB             : 
                                142                 : /*
                                143                 :  * prep_status_progress
                                144                 :  *
                                145                 :  *   Like prep_status(), but for potentially longer running operations.
                                146                 :  *   Details about what item is currently being processed can be displayed
                                147                 :  *   with pg_log(PG_STATUS, ...). A typical sequence would look like this:
                                148                 :  *
                                149                 :  *   prep_status_progress("copying files");
                                150                 :  *   for (...)
                                151                 :  *     pg_log(PG_STATUS, "%s", filename);
                                152                 :  *   end_progress_output();
                                153                 :  *   report_status(PG_REPORT, "ok");
                                154                 :  */
                                155                 : void
  412 andres                    156 GIC           3 : prep_status_progress(const char *fmt,...)
                                157                 : {
                                158                 :     va_list     args;
                                159                 :     char        message[MAX_STRING];
                                160                 : 
                                161               3 :     va_start(args, fmt);
                                162               3 :     vsnprintf(message, sizeof(message), fmt, args);
                                163               3 :     va_end(args);
                                164                 : 
                                165                 :     /*
                                166                 :      * If outputting to a tty or in verbose, append newline. pg_log_v() will
                                167                 :      * put the individual progress items onto the next line.
  412 andres                    168 ECB             :      */
  412 andres                    169 GIC           3 :     if (log_opts.isatty || log_opts.verbose)
 3775 bruce                     170 UIC           0 :         pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message);
                                171                 :     else
  271 tgl                       172 GNC           3 :         pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, message);
 4715 bruce                     173 CBC           3 : }
 4715 bruce                     174 ECB             : 
 2936 tgl                       175                 : static void
 3477 peter_e                   176 GIC        3609 : pg_log_v(eLogType type, const char *fmt, va_list ap)
                                177                 : {
                                178                 :     char        message[QUERY_ALLOC];
                                179                 : 
                                180                 :     /* No incoming message should end in newline; we add that here. */
  271 tgl                       181 GNC        3609 :     Assert(fmt);
                                182            3609 :     Assert(fmt[0] == '\0' || fmt[strlen(fmt) - 1] != '\n');
                                183                 : 
 2344 peter_e                   184 GIC        3609 :     vsnprintf(message, sizeof(message), _(fmt), ap);
 4715 bruce                     185 ECB             : 
 3775 bruce                     186 EUB             :     /* PG_VERBOSE and PG_STATUS are only output in verbose mode */
                                187                 :     /* fopen() on log_opts.internal might have failed, so check it */
 3775 bruce                     188 CBC        3609 :     if (((type != PG_VERBOSE && type != PG_STATUS) || log_opts.verbose) &&
                                189              97 :         log_opts.internal != NULL)
                                190                 :     {
 3775 bruce                     191 GIC          97 :         if (type == PG_STATUS)
                                192                 :             /* status messages get two leading spaces, see below */
 3775 bruce                     193 UIC           0 :             fprintf(log_opts.internal, "  %s\n", message);
  271 tgl                       194 GNC          97 :         else if (type == PG_REPORT_NONL)
 3775 bruce                     195 GIC          44 :             fprintf(log_opts.internal, "%s", message);
                                196                 :         else
  271 tgl                       197 GNC          53 :             fprintf(log_opts.internal, "%s\n", message);
 4045 bruce                     198 GIC          97 :         fflush(log_opts.internal);
 4715 bruce                     199 ECB             :     }
                                200                 : 
 4715 bruce                     201 GIC        3609 :     switch (type)
 4715 bruce                     202 ECB             :     {
 4045 bruce                     203 GIC        1939 :         case PG_VERBOSE:
 4554                           204            1939 :             if (log_opts.verbose)
  271 tgl                       205 UNC           0 :                 printf("%s\n", message);
 4715 bruce                     206 CBC        1939 :             break;
 4715 bruce                     207 ECB             : 
 3775 bruce                     208 GIC        1573 :         case PG_STATUS:
  332 tgl                       209 ECB             : 
                                210                 :             /*
                                211                 :              * For output to a terminal, we add two leading spaces and no
                                212                 :              * newline; instead append \r so that the next message is output
                                213                 :              * on the same line.  Truncate on the left to fit into
                                214                 :              * MESSAGE_WIDTH (counting the spaces as part of that).
  412 andres                    215                 :              *
                                216                 :              * If going to non-interactive output, only display progress if
                                217                 :              * verbose is enabled. Otherwise the output gets unreasonably
                                218                 :              * large by default.
                                219                 :              */
  412 andres                    220 GIC        1573 :             if (log_opts.isatty)
                                221                 :             {
  271 tgl                       222 UNC           0 :                 bool        itfits = (strlen(message) <= MESSAGE_WIDTH - 2);
                                223                 : 
 3602 bruce                     224 ECB             :                 /* prefix with "..." if we do leading truncation */
  271 tgl                       225 UNC           0 :                 printf("  %s%-*.*s\r",
                                226                 :                        itfits ? "" : "...",
 3602 bruce                     227 EUB             :                        MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2,
                                228                 :                        itfits ? message :
 3602 bruce                     229 ECB             :                        message + strlen(message) - MESSAGE_WIDTH + 3 + 2);
                                230                 :             }
  412 andres                    231 GIC        1573 :             else if (log_opts.verbose)
 2344 peter_e                   232 UIC           0 :                 printf("  %s\n", message);
 3775 bruce                     233 GIC        1573 :             break;
                                234                 : 
  271 tgl                       235 GNC          44 :         case PG_REPORT_NONL:
                                236                 :             /* This option is for use by prep_status and friends */
  271 tgl                       237 GIC          44 :             printf("%s", message);
                                238              44 :             break;
                                239                 : 
 4715 bruce                     240 GNC          52 :         case PG_REPORT:
                                241                 :         case PG_WARNING:
  271 tgl                       242              52 :             printf("%s\n", message);
 4715 bruce                     243              52 :             break;
                                244                 : 
 4715 bruce                     245 GIC           1 :         case PG_FATAL:
                                246                 :             /* Extra newline in case we're interrupting status output */
  271 tgl                       247 GNC           1 :             printf("\n%s\n", message);
 2368 peter_e                   248 CBC           1 :             printf(_("Failure, exiting\n"));
 3378 peter_e                   249 GIC           1 :             exit(1);
 4715 bruce                     250 EUB             :             break;
                                251                 : 
                                252                 :             /* No default:, we want a warning for omitted cases */
                                253                 :     }
 4715 bruce                     254 GIC        3608 :     fflush(stdout);
                                255            3608 : }
                                256                 : 
                                257                 : 
 3477 peter_e                   258 ECB             : void
 3477 peter_e                   259 GBC        3564 : pg_log(eLogType type, const char *fmt,...)
 3477 peter_e                   260 ECB             : {
                                261                 :     va_list     args;
                                262                 : 
 3477 peter_e                   263 GIC        3564 :     va_start(args, fmt);
 3477 peter_e                   264 CBC        3564 :     pg_log_v(type, fmt, args);
                                265            3564 :     va_end(args);
 3477 peter_e                   266 GIC        3564 : }
 3477 peter_e                   267 ECB             : 
                                268                 : 
                                269                 : void
 3477 peter_e                   270 LBC           0 : pg_fatal(const char *fmt,...)
                                271                 : {
 3477 peter_e                   272 ECB             :     va_list     args;
                                273                 : 
 3477 peter_e                   274 LBC           0 :     va_start(args, fmt);
                                275               0 :     pg_log_v(PG_FATAL, fmt, args);
                                276               0 :     va_end(args);
                                277                 :     /* NOTREACHED */
 2368 peter_e                   278 UIC           0 :     printf(_("Failure, exiting\n"));
 3477                           279               0 :     exit(1);
                                280                 : }
                                281                 : 
 3477 peter_e                   282 ECB             : 
 4715 bruce                     283                 : void
 4555 bruce                     284 GIC          44 : check_ok(void)
                                285                 : {
                                286                 :     /* all seems well */
 4555 bruce                     287 CBC          44 :     report_status(PG_REPORT, "ok");
 4715 bruce                     288 GIC          44 : }
                                289                 : 
 4715 bruce                     290 ECB             : 
                                291                 : /*
                                292                 :  * quote_identifier()
                                293                 :  *      Properly double-quote a SQL identifier.
                                294                 :  *
                                295                 :  * The result should be pg_free'd, but most callers don't bother because
                                296                 :  * memory leakage is not a big deal in this program.
 4715 bruce                     297 EUB             :  */
                                298                 : char *
 4555 bruce                     299 GIC           2 : quote_identifier(const char *s)
                                300                 : {
 4555 bruce                     301 GBC           2 :     char       *result = pg_malloc(strlen(s) * 2 + 3);
 4715                           302               2 :     char       *r = result;
 4715 bruce                     303 EUB             : 
 4715 bruce                     304 GIC           2 :     *r++ = '"';
 4715 bruce                     305 GBC          20 :     while (*s)
 4715 bruce                     306 EUB             :     {
 4715 bruce                     307 GIC          18 :         if (*s == '"')
 4715 bruce                     308 UIC           0 :             *r++ = *s;
 4715 bruce                     309 GIC          18 :         *r++ = *s;
                                310              18 :         s++;
 4715 bruce                     311 ECB             :     }
 4715 bruce                     312 GIC           2 :     *r++ = '"';
                                313               2 :     *r++ = '\0';
 4715 bruce                     314 ECB             : 
 4715 bruce                     315 CBC           2 :     return result;
                                316                 : }
                                317                 : 
                                318                 : 
                                319                 : /*
                                320                 :  * get_user_info()
                                321                 :  */
                                322                 : int
 3399 rhaas                     323 GIC           6 : get_user_info(char **user_name_p)
                                324                 : {
                                325                 :     int         user_id;
 3399 rhaas                     326 ECB             :     const char *user_name;
                                327                 :     char       *errstr;
 4660 bruce                     328                 : 
 4715                           329                 : #ifndef WIN32
 4715 bruce                     330 GIC           6 :     user_id = geteuid();
 3399 bruce                     331 ECB             : #else
 4715                           332                 :     user_id = 1;
                                333                 : #endif
                                334                 : 
 3399 rhaas                     335 GBC           6 :     user_name = get_user_name(&errstr);
 3399 rhaas                     336 CBC           6 :     if (!user_name)
  271 tgl                       337 UNC           0 :         pg_fatal("%s", errstr);
                                338                 : 
 3399 bruce                     339 ECB             :     /* make a copy */
 3399 rhaas                     340 CBC           6 :     *user_name_p = pg_strdup(user_name);
                                341                 : 
 4715 bruce                     342               6 :     return user_id;
                                343                 : }
                                344                 : 
                                345                 : 
                                346                 : /*
                                347                 :  *  str2uint()
                                348                 :  *
                                349                 :  *  convert string to oid
 4576 bruce                     350 ECB             :  */
                                351                 : unsigned int
 4576 bruce                     352 GIC          80 : str2uint(const char *str)
                                353                 : {
 4575                           354              80 :     return strtoul(str, NULL, 10);
                                355                 : }
        

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