LCOV - differential code coverage report
Current view: top level - src/backend/storage/file - reinit.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 88.0 % 125 110 15 110
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 4 4 4
Baseline: lcov-20250906-005545-baseline Branches: 63.9 % 108 69 39 69
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(360..) days: 88.0 % 125 110 15 110
Function coverage date bins:
(360..) days: 100.0 % 4 4 4
Branch coverage date bins:
(360..) days: 63.9 % 108 69 39 69

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * reinit.c
                                  4                 :                :  *    Reinitialization of unlogged relations
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  * IDENTIFICATION
                                 10                 :                :  *    src/backend/storage/file/reinit.c
                                 11                 :                :  *
                                 12                 :                :  *-------------------------------------------------------------------------
                                 13                 :                :  */
                                 14                 :                : 
                                 15                 :                : #include "postgres.h"
                                 16                 :                : 
                                 17                 :                : #include <unistd.h>
                                 18                 :                : 
                                 19                 :                : #include "common/relpath.h"
                                 20                 :                : #include "postmaster/startup.h"
                                 21                 :                : #include "storage/copydir.h"
                                 22                 :                : #include "storage/fd.h"
                                 23                 :                : #include "storage/reinit.h"
                                 24                 :                : #include "utils/hsearch.h"
                                 25                 :                : #include "utils/memutils.h"
                                 26                 :                : 
                                 27                 :                : static void ResetUnloggedRelationsInTablespaceDir(const char *tsdirname,
                                 28                 :                :                                                   int op);
                                 29                 :                : static void ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname,
                                 30                 :                :                                                int op);
                                 31                 :                : 
                                 32                 :                : typedef struct
                                 33                 :                : {
                                 34                 :                :     RelFileNumber relnumber;    /* hash key */
                                 35                 :                : } unlogged_relation_entry;
                                 36                 :                : 
                                 37                 :                : /*
                                 38                 :                :  * Reset unlogged relations from before the last restart.
                                 39                 :                :  *
                                 40                 :                :  * If op includes UNLOGGED_RELATION_CLEANUP, we remove all forks of any
                                 41                 :                :  * relation with an "init" fork, except for the "init" fork itself.
                                 42                 :                :  *
                                 43                 :                :  * If op includes UNLOGGED_RELATION_INIT, we copy the "init" fork to the main
                                 44                 :                :  * fork.
                                 45                 :                :  */
                                 46                 :                : void
 5365 rhaas@postgresql.org       47                 :CBC         353 : ResetUnloggedRelations(int op)
                                 48                 :                : {
                                 49                 :                :     char        temp_path[MAXPGPATH + sizeof(PG_TBLSPC_DIR) + sizeof(TABLESPACE_VERSION_DIRECTORY)];
                                 50                 :                :     DIR        *spc_dir;
                                 51                 :                :     struct dirent *spc_de;
                                 52                 :                :     MemoryContext tmpctx,
                                 53                 :                :                 oldctx;
                                 54                 :                : 
                                 55                 :                :     /* Log it. */
 5163 peter_e@gmx.net            56         [ +  + ]:            353 :     elog(DEBUG1, "resetting unlogged relations: cleanup %d init %d",
                                 57                 :                :          (op & UNLOGGED_RELATION_CLEANUP) != 0,
                                 58                 :                :          (op & UNLOGGED_RELATION_INIT) != 0);
                                 59                 :                : 
                                 60                 :                :     /*
                                 61                 :                :      * Just to be sure we don't leak any memory, let's create a temporary
                                 62                 :                :      * memory context for this operation.
                                 63                 :                :      */
 5365 rhaas@postgresql.org       64                 :            353 :     tmpctx = AllocSetContextCreate(CurrentMemoryContext,
                                 65                 :                :                                    "ResetUnloggedRelations",
                                 66                 :                :                                    ALLOCSET_DEFAULT_SIZES);
                                 67                 :            353 :     oldctx = MemoryContextSwitchTo(tmpctx);
                                 68                 :                : 
                                 69                 :                :     /* Prepare to report progress resetting unlogged relations. */
 1412                            70                 :            353 :     begin_startup_progress_phase();
                                 71                 :                : 
                                 72                 :                :     /*
                                 73                 :                :      * First process unlogged files in pg_default ($PGDATA/base)
                                 74                 :                :      */
 5365                            75                 :            353 :     ResetUnloggedRelationsInTablespaceDir("base", op);
                                 76                 :                : 
                                 77                 :                :     /*
                                 78                 :                :      * Cycle through directories for all non-default tablespaces.
                                 79                 :                :      */
  368 michael@paquier.xyz        80                 :            353 :     spc_dir = AllocateDir(PG_TBLSPC_DIR);
                                 81                 :                : 
                                 82         [ +  + ]:           1146 :     while ((spc_de = ReadDir(spc_dir, PG_TBLSPC_DIR)) != NULL)
                                 83                 :                :     {
 5365 rhaas@postgresql.org       84         [ +  + ]:            793 :         if (strcmp(spc_de->d_name, ".") == 0 ||
                                 85         [ +  + ]:            440 :             strcmp(spc_de->d_name, "..") == 0)
                                 86                 :            706 :             continue;
                                 87                 :                : 
  368 michael@paquier.xyz        88                 :             87 :         snprintf(temp_path, sizeof(temp_path), "%s/%s/%s",
                                 89                 :             87 :                  PG_TBLSPC_DIR, spc_de->d_name, TABLESPACE_VERSION_DIRECTORY);
 5365 rhaas@postgresql.org       90                 :             87 :         ResetUnloggedRelationsInTablespaceDir(temp_path, op);
                                 91                 :                :     }
                                 92                 :                : 
                                 93                 :            353 :     FreeDir(spc_dir);
                                 94                 :                : 
                                 95                 :                :     /*
                                 96                 :                :      * Restore memory context.
                                 97                 :                :      */
                                 98                 :            353 :     MemoryContextSwitchTo(oldctx);
                                 99                 :            353 :     MemoryContextDelete(tmpctx);
                                100                 :            353 : }
                                101                 :                : 
                                102                 :                : /*
                                103                 :                :  * Process one tablespace directory for ResetUnloggedRelations
                                104                 :                :  */
                                105                 :                : static void
                                106                 :            440 : ResetUnloggedRelationsInTablespaceDir(const char *tsdirname, int op)
                                107                 :                : {
                                108                 :                :     DIR        *ts_dir;
                                109                 :                :     struct dirent *de;
                                110                 :                :     char        dbspace_path[MAXPGPATH * 2];
                                111                 :                : 
                                112                 :            440 :     ts_dir = AllocateDir(tsdirname);
                                113                 :                : 
                                114                 :                :     /*
                                115                 :                :      * If we get ENOENT on a tablespace directory, log it and return.  This
                                116                 :                :      * can happen if a previous DROP TABLESPACE crashed between removing the
                                117                 :                :      * tablespace directory and removing the symlink in pg_tblspc.  We don't
                                118                 :                :      * really want to prevent database startup in that scenario, so let it
                                119                 :                :      * pass instead.  Any other type of error will be reported by ReadDir
                                120                 :                :      * (causing a startup failure).
                                121                 :                :      */
 2833 tgl@sss.pgh.pa.us         122   [ -  +  -  - ]:            440 :     if (ts_dir == NULL && errno == ENOENT)
                                123                 :                :     {
 2833 tgl@sss.pgh.pa.us         124         [ #  # ]:UBC           0 :         ereport(LOG,
                                125                 :                :                 (errcode_for_file_access(),
                                126                 :                :                  errmsg("could not open directory \"%s\": %m",
                                127                 :                :                         tsdirname)));
 5365 rhaas@postgresql.org      128                 :              0 :         return;
                                129                 :                :     }
                                130                 :                : 
 5365 rhaas@postgresql.org      131         [ +  + ]:CBC        2597 :     while ((de = ReadDir(ts_dir, tsdirname)) != NULL)
                                132                 :                :     {
                                133                 :                :         /*
                                134                 :                :          * We're only interested in the per-database directories, which have
                                135                 :                :          * numeric names.  Note that this code will also (properly) ignore "."
                                136                 :                :          * and "..".
                                137                 :                :          */
 2833 tgl@sss.pgh.pa.us         138         [ +  + ]:           2157 :         if (strspn(de->d_name, "0123456789") != strlen(de->d_name))
 5365 rhaas@postgresql.org      139                 :            944 :             continue;
                                140                 :                : 
                                141                 :           1213 :         snprintf(dbspace_path, sizeof(dbspace_path), "%s/%s",
                                142                 :           1213 :                  tsdirname, de->d_name);
                                143                 :                : 
 1412                           144         [ +  + ]:           1213 :         if (op & UNLOGGED_RELATION_INIT)
                                145   [ -  +  -  - ]:            510 :             ereport_startup_progress("resetting unlogged relations (init), elapsed time: %ld.%02d s, current path: %s",
                                146                 :                :                                      dbspace_path);
                                147         [ +  - ]:            703 :         else if (op & UNLOGGED_RELATION_CLEANUP)
                                148   [ -  +  -  - ]:            703 :             ereport_startup_progress("resetting unlogged relations (cleanup), elapsed time: %ld.%02d s, current path: %s",
                                149                 :                :                                      dbspace_path);
                                150                 :                : 
 5365                           151                 :           1213 :         ResetUnloggedRelationsInDbspaceDir(dbspace_path, op);
                                152                 :                :     }
                                153                 :                : 
                                154                 :            440 :     FreeDir(ts_dir);
                                155                 :                : }
                                156                 :                : 
                                157                 :                : /*
                                158                 :                :  * Process one per-dbspace directory for ResetUnloggedRelations
                                159                 :                :  */
                                160                 :                : static void
                                161                 :           1213 : ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
                                162                 :                : {
                                163                 :                :     DIR        *dbspace_dir;
                                164                 :                :     struct dirent *de;
                                165                 :                :     char        rm_path[MAXPGPATH * 2];
                                166                 :                : 
                                167                 :                :     /* Caller must specify at least one operation. */
                                168         [ -  + ]:           1213 :     Assert((op & (UNLOGGED_RELATION_CLEANUP | UNLOGGED_RELATION_INIT)) != 0);
                                169                 :                : 
                                170                 :                :     /*
                                171                 :                :      * Cleanup is a two-pass operation.  First, we go through and identify all
                                172                 :                :      * the files with init forks.  Then, we go through again and nuke
                                173                 :                :      * everything with the same OID except the init fork.
                                174                 :                :      */
                                175         [ +  + ]:           1213 :     if ((op & UNLOGGED_RELATION_CLEANUP) != 0)
                                176                 :                :     {
                                177                 :                :         HTAB       *hash;
                                178                 :                :         HASHCTL     ctl;
                                179                 :                : 
                                180                 :                :         /*
                                181                 :                :          * It's possible that someone could create a ton of unlogged relations
                                182                 :                :          * in the same database & tablespace, so we'd better use a hash table
                                183                 :                :          * rather than an array or linked list to keep track of which files
                                184                 :                :          * need to be reset.  Otherwise, this cleanup operation would be
                                185                 :                :          * O(n^2).
                                186                 :                :          */
 1074                           187                 :            703 :         ctl.keysize = sizeof(Oid);
 5365                           188                 :            703 :         ctl.entrysize = sizeof(unlogged_relation_entry);
 1726 tgl@sss.pgh.pa.us         189                 :            703 :         ctl.hcxt = CurrentMemoryContext;
 1074 rhaas@postgresql.org      190                 :            703 :         hash = hash_create("unlogged relation OIDs", 32, &ctl,
                                191                 :                :                            HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
                                192                 :                : 
                                193                 :                :         /* Scan the directory. */
 2833 tgl@sss.pgh.pa.us         194                 :            703 :         dbspace_dir = AllocateDir(dbspacedirname);
 5365 rhaas@postgresql.org      195         [ +  + ]:         201636 :         while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
                                196                 :                :         {
                                197                 :                :             ForkNumber  forkNum;
                                198                 :                :             unsigned    segno;
                                199                 :                :             unlogged_relation_entry ent;
                                200                 :                : 
                                201                 :                :             /* Skip anything that doesn't look like a relation data file. */
  684                           202         [ +  + ]:         200933 :             if (!parse_filename_for_nontemp_relation(de->d_name,
                                203                 :                :                                                      &ent.relnumber,
                                204                 :                :                                                      &forkNum, &segno))
 5365                           205                 :         200925 :                 continue;
                                206                 :                : 
                                207                 :                :             /* Also skip it unless this is the init fork. */
                                208         [ +  + ]:         198207 :             if (forkNum != INIT_FORKNUM)
                                209                 :         198199 :                 continue;
                                210                 :                : 
                                211                 :                :             /*
                                212                 :                :              * Put the RelFileNumber into the hash table, if it isn't already.
                                213                 :                :              */
 1726 tgl@sss.pgh.pa.us         214                 :              8 :             (void) hash_search(hash, &ent, HASH_ENTER, NULL);
                                215                 :                :         }
                                216                 :                : 
                                217                 :                :         /* Done with the first pass. */
 5365 rhaas@postgresql.org      218                 :            703 :         FreeDir(dbspace_dir);
                                219                 :                : 
                                220                 :                :         /*
                                221                 :                :          * If we didn't find any init forks, there's no point in continuing;
                                222                 :                :          * we can bail out now.
                                223                 :                :          */
                                224         [ +  + ]:            703 :         if (hash_get_num_entries(hash) == 0)
                                225                 :                :         {
                                226                 :            699 :             hash_destroy(hash);
                                227                 :            699 :             return;
                                228                 :                :         }
                                229                 :                : 
                                230                 :                :         /*
                                231                 :                :          * Now, make a second pass and remove anything that matches.
                                232                 :                :          */
                                233                 :              4 :         dbspace_dir = AllocateDir(dbspacedirname);
                                234         [ +  + ]:            937 :         while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
                                235                 :                :         {
                                236                 :                :             ForkNumber  forkNum;
                                237                 :                :             unsigned    segno;
                                238                 :                :             unlogged_relation_entry ent;
                                239                 :                : 
                                240                 :                :             /* Skip anything that doesn't look like a relation data file. */
  684                           241         [ +  + ]:            933 :             if (!parse_filename_for_nontemp_relation(de->d_name,
                                242                 :                :                                                      &ent.relnumber,
                                243                 :                :                                                      &forkNum, &segno))
 5365                           244                 :             22 :                 continue;
                                245                 :                : 
                                246                 :                :             /* We never remove the init fork. */
                                247         [ +  + ]:            919 :             if (forkNum == INIT_FORKNUM)
                                248                 :              8 :                 continue;
                                249                 :                : 
                                250                 :                :             /*
                                251                 :                :              * See whether the OID portion of the name shows up in the hash
                                252                 :                :              * table.  If so, nuke it!
                                253                 :                :              */
 1726 tgl@sss.pgh.pa.us         254         [ +  + ]:            911 :             if (hash_search(hash, &ent, HASH_FIND, NULL))
                                255                 :                :             {
 5365 rhaas@postgresql.org      256                 :              7 :                 snprintf(rm_path, sizeof(rm_path), "%s/%s",
 5263 bruce@momjian.us          257                 :              7 :                          dbspacedirname, de->d_name);
 2833 tgl@sss.pgh.pa.us         258         [ -  + ]:              7 :                 if (unlink(rm_path) < 0)
 2833 tgl@sss.pgh.pa.us         259         [ #  # ]:UBC           0 :                     ereport(ERROR,
                                260                 :                :                             (errcode_for_file_access(),
                                261                 :                :                              errmsg("could not remove file \"%s\": %m",
                                262                 :                :                                     rm_path)));
                                263                 :                :                 else
 5365 rhaas@postgresql.org      264         [ -  + ]:CBC           7 :                     elog(DEBUG2, "unlinked file \"%s\"", rm_path);
                                265                 :                :             }
                                266                 :                :         }
                                267                 :                : 
                                268                 :                :         /* Cleanup is complete. */
                                269                 :              4 :         FreeDir(dbspace_dir);
                                270                 :              4 :         hash_destroy(hash);
                                271                 :                :     }
                                272                 :                : 
                                273                 :                :     /*
                                274                 :                :      * Initialization happens after cleanup is complete: we copy each init
                                275                 :                :      * fork file to the corresponding main fork file.  Note that if we are
                                276                 :                :      * asked to do both cleanup and init, we may never get here: if the
                                277                 :                :      * cleanup code determines that there are no init forks in this dbspace,
                                278                 :                :      * it will return before we get to this point.
                                279                 :                :      */
                                280         [ +  + ]:            514 :     if ((op & UNLOGGED_RELATION_INIT) != 0)
                                281                 :                :     {
                                282                 :                :         /* Scan the directory. */
 2833 tgl@sss.pgh.pa.us         283                 :            510 :         dbspace_dir = AllocateDir(dbspacedirname);
 5365 rhaas@postgresql.org      284         [ +  + ]:         143062 :         while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
                                285                 :                :         {
                                286                 :                :             ForkNumber  forkNum;
                                287                 :                :             RelFileNumber relNumber;
                                288                 :                :             unsigned    segno;
                                289                 :                :             char        srcpath[MAXPGPATH * 2];
                                290                 :                :             char        dstpath[MAXPGPATH];
                                291                 :                : 
                                292                 :                :             /* Skip anything that doesn't look like a relation data file. */
  684                           293         [ +  + ]:         142552 :             if (!parse_filename_for_nontemp_relation(de->d_name, &relNumber,
                                294                 :                :                                                      &forkNum, &segno))
 5365                           295                 :         142545 :                 continue;
                                296                 :                : 
                                297                 :                :             /* Also skip it unless this is the init fork. */
                                298         [ +  + ]:         140580 :             if (forkNum != INIT_FORKNUM)
                                299                 :         140573 :                 continue;
                                300                 :                : 
                                301                 :                :             /* Construct source pathname. */
                                302                 :              7 :             snprintf(srcpath, sizeof(srcpath), "%s/%s",
                                303                 :              7 :                      dbspacedirname, de->d_name);
                                304                 :                : 
                                305                 :                :             /* Construct destination pathname. */
  684                           306         [ +  - ]:              7 :             if (segno == 0)
                                307                 :              7 :                 snprintf(dstpath, sizeof(dstpath), "%s/%u",
                                308                 :                :                          dbspacedirname, relNumber);
                                309                 :                :             else
  684 rhaas@postgresql.org      310                 :UBC           0 :                 snprintf(dstpath, sizeof(dstpath), "%s/%u.%u",
                                311                 :                :                          dbspacedirname, relNumber, segno);
                                312                 :                : 
                                313                 :                :             /* OK, we're ready to perform the actual copy. */
 5365 rhaas@postgresql.org      314         [ -  + ]:CBC           7 :             elog(DEBUG2, "copying %s to %s", srcpath, dstpath);
                                315                 :              7 :             copy_file(srcpath, dstpath);
                                316                 :                :         }
                                317                 :                : 
                                318                 :            510 :         FreeDir(dbspace_dir);
                                319                 :                : 
                                320                 :                :         /*
                                321                 :                :          * copy_file() above has already called pg_flush_data() on the files
                                322                 :                :          * it created. Now we need to fsync those files, because a checkpoint
                                323                 :                :          * won't do it for us while we're in recovery. We do this in a
                                324                 :                :          * separate pass to allow the kernel to perform all the flushes
                                325                 :                :          * (especially the metadata ones) at once.
                                326                 :                :          */
 3949 andres@anarazel.de        327                 :            510 :         dbspace_dir = AllocateDir(dbspacedirname);
                                328         [ +  + ]:         143069 :         while ((de = ReadDir(dbspace_dir, dbspacedirname)) != NULL)
                                329                 :                :         {
                                330                 :                :             RelFileNumber relNumber;
                                331                 :                :             ForkNumber  forkNum;
                                332                 :                :             unsigned    segno;
                                333                 :                :             char        mainpath[MAXPGPATH];
                                334                 :                : 
                                335                 :                :             /* Skip anything that doesn't look like a relation data file. */
  684 rhaas@postgresql.org      336         [ +  + ]:         142559 :             if (!parse_filename_for_nontemp_relation(de->d_name, &relNumber,
                                337                 :                :                                                      &forkNum, &segno))
 3949 andres@anarazel.de        338                 :         142552 :                 continue;
                                339                 :                : 
                                340                 :                :             /* Also skip it unless this is the init fork. */
                                341         [ +  + ]:         140587 :             if (forkNum != INIT_FORKNUM)
                                342                 :         140580 :                 continue;
                                343                 :                : 
                                344                 :                :             /* Construct main fork pathname. */
  684 rhaas@postgresql.org      345         [ +  - ]:              7 :             if (segno == 0)
                                346                 :              7 :                 snprintf(mainpath, sizeof(mainpath), "%s/%u",
                                347                 :                :                          dbspacedirname, relNumber);
                                348                 :                :             else
  684 rhaas@postgresql.org      349                 :UBC           0 :                 snprintf(mainpath, sizeof(mainpath), "%s/%u.%u",
                                350                 :                :                          dbspacedirname, relNumber, segno);
                                351                 :                : 
 3949 andres@anarazel.de        352                 :CBC           7 :             fsync_fname(mainpath, false);
                                353                 :                :         }
                                354                 :                : 
                                355                 :            510 :         FreeDir(dbspace_dir);
                                356                 :                : 
                                357                 :                :         /*
                                358                 :                :          * Lastly, fsync the database directory itself, ensuring the
                                359                 :                :          * filesystem remembers the file creations and deletions we've done.
                                360                 :                :          * We don't bother with this during a call that does only
                                361                 :                :          * UNLOGGED_RELATION_CLEANUP, because if recovery crashes before we
                                362                 :                :          * get to doing UNLOGGED_RELATION_INIT, we'll redo the cleanup step
                                363                 :                :          * too at the next startup attempt.
                                364                 :                :          */
 3468                           365                 :            510 :         fsync_fname(dbspacedirname, true);
                                366                 :                :     }
                                367                 :                : }
                                368                 :                : 
                                369                 :                : /*
                                370                 :                :  * Basic parsing of putative relation filenames.
                                371                 :                :  *
                                372                 :                :  * This function returns true if the file appears to be in the correct format
                                373                 :                :  * for a non-temporary relation and false otherwise.
                                374                 :                :  *
                                375                 :                :  * If it returns true, it sets *relnumber, *fork, and *segno to the values
                                376                 :                :  * extracted from the filename. If it returns false, these values are set to
                                377                 :                :  * InvalidRelFileNumber, InvalidForkNumber, and 0, respectively.
                                378                 :                :  */
                                379                 :                : bool
  684 rhaas@postgresql.org      380                 :         806896 : parse_filename_for_nontemp_relation(const char *name, RelFileNumber *relnumber,
                                381                 :                :                                     ForkNumber *fork, unsigned *segno)
                                382                 :                : {
                                383                 :                :     unsigned long n,
                                384                 :                :                 s;
                                385                 :                :     ForkNumber  f;
                                386                 :                :     char       *endp;
                                387                 :                : 
                                388                 :         806896 :     *relnumber = InvalidRelFileNumber;
                                389                 :         806896 :     *fork = InvalidForkNumber;
                                390                 :         806896 :     *segno = 0;
                                391                 :                : 
                                392                 :                :     /*
                                393                 :                :      * Relation filenames should begin with a digit that is not a zero. By
                                394                 :                :      * rejecting cases involving leading zeroes, the caller can assume that
                                395                 :                :      * there's only one possible string of characters that could have produced
                                396                 :                :      * any given value for *relnumber.
                                397                 :                :      *
                                398                 :                :      * (To be clear, we don't expect files with names like 0017.3 to exist at
                                399                 :                :      * all -- but if 0017.3 does exist, it's a non-relation file, not part of
                                400                 :                :      * the main fork for relfilenode 17.)
                                401                 :                :      */
                                402   [ +  +  +  + ]:         806896 :     if (name[0] < '1' || name[0] > '9')
                                403                 :           9377 :         return false;
                                404                 :                : 
                                405                 :                :     /*
                                406                 :                :      * Parse the leading digit string. If the value is out of range, we
                                407                 :                :      * conclude that this isn't a relation file at all.
                                408                 :                :      */
                                409                 :         797519 :     errno = 0;
                                410                 :         797519 :     n = strtoul(name, &endp, 10);
                                411   [ +  -  +  -  :         797519 :     if (errno || name == endp || n <= 0 || n > PG_UINT32_MAX)
                                        +  -  -  + ]
 5365 rhaas@postgresql.org      412                 :UBC           0 :         return false;
  684 rhaas@postgresql.org      413                 :CBC      797519 :     name = endp;
                                414                 :                : 
                                415                 :                :     /* Check for a fork name. */
                                416         [ +  + ]:         797519 :     if (*name != '_')
                                417                 :         601383 :         f = MAIN_FORKNUM;
                                418                 :                :     else
                                419                 :                :     {
                                420                 :                :         int         forkchar;
                                421                 :                : 
                                422                 :         196136 :         forkchar = forkname_chars(name + 1, &f);
 5365                           423         [ -  + ]:         196136 :         if (forkchar <= 0)
 5365 rhaas@postgresql.org      424                 :UBC           0 :             return false;
  684 rhaas@postgresql.org      425                 :CBC      196136 :         name += forkchar + 1;
                                426                 :                :     }
                                427                 :                : 
                                428                 :                :     /* Check for a segment number. */
                                429         [ +  - ]:         797519 :     if (*name != '.')
                                430                 :         797519 :         s = 0;
                                431                 :                :     else
                                432                 :                :     {
                                433                 :                :         /* Reject leading zeroes, just like we do for RelFileNumber. */
  627 rhaas@postgresql.org      434   [ #  #  #  # ]:UBC           0 :         if (name[1] < '1' || name[1] > '9')
  684                           435                 :              0 :             return false;
                                436                 :                : 
                                437                 :              0 :         errno = 0;
                                438                 :              0 :         s = strtoul(name + 1, &endp, 10);
                                439   [ #  #  #  #  :              0 :         if (errno || name + 1 == endp || s <= 0 || s > PG_UINT32_MAX)
                                        #  #  #  # ]
 5365                           440                 :              0 :             return false;
  684                           441                 :              0 :         name = endp;
                                442                 :                :     }
                                443                 :                : 
                                444                 :                :     /* Now we should be at the end. */
  684 rhaas@postgresql.org      445         [ -  + ]:CBC      797519 :     if (*name != '\0')
 5365 rhaas@postgresql.org      446                 :UBC           0 :         return false;
                                447                 :                : 
                                448                 :                :     /* Set out parameters and return. */
  684 rhaas@postgresql.org      449                 :CBC      797519 :     *relnumber = (RelFileNumber) n;
                                450                 :         797519 :     *fork = f;
                                451                 :         797519 :     *segno = (unsigned) s;
 5365                           452                 :         797519 :     return true;
                                453                 :                : }
        

Generated by: LCOV version 2.4-beta