LCOV - code coverage report
Current view: top level - src/bin/pg_upgrade - util.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 123 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 12 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  *      util.c
       3              :  *
       4              :  *      utility functions
       5              :  *
       6              :  *      Copyright (c) 2010-2026, 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
      32            0 : report_status(eLogType type, const char *fmt,...)
      33              : {
      34            0 :         va_list         args;
      35              : 
      36            0 :         va_start(args, fmt);
      37            0 :         pg_log_v(type, fmt, args);
      38            0 :         va_end(args);
      39            0 : }
      40              : 
      41              : 
      42              : void
      43            0 : end_progress_output(void)
      44              : {
      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              :          */
      50            0 :         if (log_opts.isatty)
      51              :         {
      52            0 :                 printf("\r");
      53            0 :                 pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, "");
      54            0 :         }
      55            0 :         else if (log_opts.verbose)
      56            0 :                 pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, "");
      57            0 : }
      58              : 
      59              : /*
      60              :  * Remove any logs generated internally.  To be used once when exiting.
      61              :  */
      62              : void
      63            0 : cleanup_output_dirs(void)
      64              : {
      65            0 :         fclose(log_opts.internal);
      66              : 
      67              :         /* Remove dump and log files? */
      68            0 :         if (log_opts.retain)
      69            0 :                 return;
      70              : 
      71              :         /*
      72              :          * Try twice.  The second time might wait for files to finish being
      73              :          * unlinked, on Windows.
      74              :          */
      75            0 :         if (!rmtree(log_opts.basedir, true))
      76            0 :                 rmtree(log_opts.basedir, true);
      77              : 
      78              :         /* Remove pg_upgrade_output.d only if empty */
      79            0 :         switch (pg_check_dir(log_opts.rootdir))
      80              :         {
      81              :                 case 0:                                 /* non-existent */
      82              :                 case 3:                                 /* exists and contains a mount point */
      83            0 :                         Assert(false);
      84              :                         break;
      85              : 
      86              :                 case 1:                                 /* exists and empty */
      87              :                 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              :                          */
      93            0 :                         if (!rmtree(log_opts.rootdir, true))
      94            0 :                                 rmtree(log_opts.rootdir, true);
      95            0 :                         break;
      96              : 
      97              :                 case 4:                                 /* exists */
      98              : 
      99              :                         /*
     100              :                          * Keep the root directory as this includes some past log
     101              :                          * activity.
     102              :                          */
     103              :                         break;
     104              : 
     105              :                 default:
     106              :                         /* different failure, just report it */
     107            0 :                         pg_log(PG_WARNING, "could not access directory \"%s\": %m",
     108            0 :                                    log_opts.rootdir);
     109            0 :                         break;
     110              :         }
     111            0 : }
     112              : 
     113              : /*
     114              :  * prep_status
     115              :  *
     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
     129            0 : prep_status(const char *fmt,...)
     130              : {
     131            0 :         va_list         args;
     132            0 :         char            message[MAX_STRING];
     133              : 
     134            0 :         va_start(args, fmt);
     135            0 :         vsnprintf(message, sizeof(message), fmt, args);
     136            0 :         va_end(args);
     137              : 
     138              :         /* trim strings */
     139            0 :         pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, message);
     140            0 : }
     141              : 
     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
     156            0 : prep_status_progress(const char *fmt,...)
     157              : {
     158            0 :         va_list         args;
     159            0 :         char            message[MAX_STRING];
     160              : 
     161            0 :         va_start(args, fmt);
     162            0 :         vsnprintf(message, sizeof(message), fmt, args);
     163            0 :         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.
     168              :          */
     169            0 :         if (log_opts.isatty || log_opts.verbose)
     170            0 :                 pg_log(PG_REPORT, "%-*s", MESSAGE_WIDTH, message);
     171              :         else
     172            0 :                 pg_log(PG_REPORT_NONL, "%-*s", MESSAGE_WIDTH, message);
     173            0 : }
     174              : 
     175              : static void
     176            0 : pg_log_v(eLogType type, const char *fmt, va_list ap)
     177              : {
     178            0 :         char            message[QUERY_ALLOC];
     179              : 
     180              :         /* No incoming message should end in newline; we add that here. */
     181            0 :         Assert(fmt);
     182            0 :         Assert(fmt[0] == '\0' || fmt[strlen(fmt) - 1] != '\n');
     183              : 
     184            0 :         vsnprintf(message, sizeof(message), _(fmt), ap);
     185              : 
     186              :         /* PG_VERBOSE and PG_STATUS are only output in verbose mode */
     187              :         /* fopen() on log_opts.internal might have failed, so check it */
     188            0 :         if (((type != PG_VERBOSE && type != PG_STATUS) || log_opts.verbose) &&
     189            0 :                 log_opts.internal != NULL)
     190              :         {
     191            0 :                 if (type == PG_STATUS)
     192              :                         /* status messages get two leading spaces, see below */
     193            0 :                         fprintf(log_opts.internal, "  %s\n", message);
     194            0 :                 else if (type == PG_REPORT_NONL)
     195            0 :                         fprintf(log_opts.internal, "%s", message);
     196              :                 else
     197            0 :                         fprintf(log_opts.internal, "%s\n", message);
     198            0 :                 fflush(log_opts.internal);
     199            0 :         }
     200              : 
     201            0 :         switch (type)
     202              :         {
     203              :                 case PG_VERBOSE:
     204            0 :                         if (log_opts.verbose)
     205            0 :                                 printf("%s\n", message);
     206            0 :                         break;
     207              : 
     208              :                 case PG_STATUS:
     209              : 
     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).
     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              :                          */
     220            0 :                         if (log_opts.isatty)
     221              :                         {
     222            0 :                                 bool            itfits = (strlen(message) <= MESSAGE_WIDTH - 2);
     223              : 
     224              :                                 /* prefix with "..." if we do leading truncation */
     225            0 :                                 printf("  %s%-*.*s\r",
     226              :                                            itfits ? "" : "...",
     227              :                                            MESSAGE_WIDTH - 2, MESSAGE_WIDTH - 2,
     228              :                                            itfits ? message :
     229              :                                            message + strlen(message) - MESSAGE_WIDTH + 3 + 2);
     230            0 :                         }
     231            0 :                         else if (log_opts.verbose)
     232            0 :                                 printf("  %s\n", message);
     233            0 :                         break;
     234              : 
     235              :                 case PG_REPORT_NONL:
     236              :                         /* This option is for use by prep_status and friends */
     237            0 :                         printf("%s", message);
     238            0 :                         break;
     239              : 
     240              :                 case PG_REPORT:
     241              :                 case PG_WARNING:
     242            0 :                         printf("%s\n", message);
     243            0 :                         break;
     244              : 
     245              :                 case PG_FATAL:
     246              :                         /* Extra newline in case we're interrupting status output */
     247            0 :                         printf("\n%s\n", message);
     248            0 :                         printf(_("Failure, exiting\n"));
     249            0 :                         exit(1);
     250              :                         break;
     251              : 
     252              :                         /* No default:, we want a warning for omitted cases */
     253              :         }
     254            0 :         fflush(stdout);
     255            0 : }
     256              : 
     257              : 
     258              : void
     259            0 : pg_log(eLogType type, const char *fmt,...)
     260              : {
     261            0 :         va_list         args;
     262              : 
     263            0 :         va_start(args, fmt);
     264            0 :         pg_log_v(type, fmt, args);
     265            0 :         va_end(args);
     266            0 : }
     267              : 
     268              : 
     269              : void
     270            0 : pg_fatal(const char *fmt,...)
     271              : {
     272            0 :         va_list         args;
     273              : 
     274            0 :         va_start(args, fmt);
     275            0 :         pg_log_v(PG_FATAL, fmt, args);
     276            0 :         va_end(args);
     277              :         /* NOTREACHED */
     278            0 :         printf(_("Failure, exiting\n"));
     279            0 :         exit(1);
     280              : }
     281              : 
     282              : 
     283              : void
     284            0 : check_ok(void)
     285              : {
     286              :         /* all seems well */
     287            0 :         report_status(PG_REPORT, "ok");
     288            0 : }
     289              : 
     290              : 
     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.
     297              :  */
     298              : char *
     299            0 : quote_identifier(const char *s)
     300              : {
     301            0 :         char       *result = pg_malloc(strlen(s) * 2 + 3);
     302            0 :         char       *r = result;
     303              : 
     304            0 :         *r++ = '"';
     305            0 :         while (*s)
     306              :         {
     307            0 :                 if (*s == '"')
     308            0 :                         *r++ = *s;
     309            0 :                 *r++ = *s;
     310            0 :                 s++;
     311              :         }
     312            0 :         *r++ = '"';
     313            0 :         *r++ = '\0';
     314              : 
     315            0 :         return result;
     316            0 : }
     317              : 
     318              : 
     319              : /*
     320              :  * get_user_info()
     321              :  */
     322              : int
     323            0 : get_user_info(char **user_name_p)
     324              : {
     325            0 :         int                     user_id;
     326            0 :         const char *user_name;
     327            0 :         char       *errstr;
     328              : 
     329              : #ifndef WIN32
     330            0 :         user_id = geteuid();
     331              : #else
     332              :         user_id = 1;
     333              : #endif
     334              : 
     335            0 :         user_name = get_user_name(&errstr);
     336            0 :         if (!user_name)
     337            0 :                 pg_fatal("%s", errstr);
     338              : 
     339              :         /* make a copy */
     340            0 :         *user_name_p = pg_strdup(user_name);
     341              : 
     342            0 :         return user_id;
     343            0 : }
     344              : 
     345              : 
     346              : /*
     347              :  *      str2uint()
     348              :  *
     349              :  *      convert string to oid
     350              :  */
     351              : unsigned int
     352            0 : str2uint(const char *str)
     353              : {
     354            0 :         return strtoul(str, NULL, 10);
     355              : }
        

Generated by: LCOV version 2.3.2-1