From 1d25779284fe1ba08ecd57e647292a9deb241376 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Tue, 3 Jan 2017 13:48:53 -0500 Subject: Update copyright via script for 2017 --- src/timezone/pgtz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/timezone/pgtz.c') diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c index 4fa3d0da89..826857d943 100644 --- a/src/timezone/pgtz.c +++ b/src/timezone/pgtz.c @@ -3,7 +3,7 @@ * pgtz.c * Timezone Library Integration Functions * - * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group * * IDENTIFICATION * src/timezone/pgtz.c -- cgit v1.2.3 From 6275f5d28a1577563f53f2171689d4f890a46881 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 11 Apr 2017 14:13:31 -0400 Subject: Fix new warnings from GCC 7 This addresses the new warning types -Wformat-truncation -Wformat-overflow that are part of -Wall, via -Wformat, in GCC 7. --- contrib/pg_standby/pg_standby.c | 6 +++--- src/backend/access/heap/rewriteheap.c | 4 ++-- src/backend/access/transam/xlog.c | 6 +++--- src/backend/postmaster/pgstat.c | 4 ++-- src/backend/replication/basebackup.c | 4 ++-- src/backend/replication/logical/reorderbuffer.c | 2 +- src/backend/replication/logical/snapbuild.c | 4 ++-- src/backend/replication/slot.c | 6 +++--- src/backend/storage/file/copydir.c | 10 +++++----- src/backend/storage/file/fd.c | 12 ++++++------ src/backend/storage/file/reinit.c | 8 ++++---- src/backend/storage/ipc/dsm.c | 4 ++-- src/backend/utils/adt/dbsize.c | 14 +++++++------- src/backend/utils/adt/genfile.c | 4 ++-- src/backend/utils/cache/relcache.c | 4 ++-- src/backend/utils/error/elog.c | 2 +- src/backend/utils/time/snapmgr.c | 4 ++-- src/bin/pg_archivecleanup/pg_archivecleanup.c | 4 ++-- src/bin/pg_basebackup/pg_receivewal.c | 4 ++-- src/bin/pg_resetwal/pg_resetwal.c | 12 ++++++------ src/bin/pg_rewind/copy_fetch.c | 10 +++++----- src/common/file_utils.c | 4 ++-- src/timezone/pgtz.c | 4 ++-- 23 files changed, 68 insertions(+), 68 deletions(-) (limited to 'src/timezone/pgtz.c') diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c index e4d057e18e..5703032397 100644 --- a/contrib/pg_standby/pg_standby.c +++ b/contrib/pg_standby/pg_standby.c @@ -57,7 +57,7 @@ char *xlogFilePath; /* where we are going to restore to */ char *nextWALFileName; /* the file we need to get from archive */ char *restartWALFileName; /* the file from which we can restart restore */ char *priorWALFileName; /* the file we need to get from archive */ -char WALFilePath[MAXPGPATH]; /* the file path including archive */ +char WALFilePath[MAXPGPATH * 2]; /* the file path including archive */ char restoreCommand[MAXPGPATH]; /* run this to restore */ char exclusiveCleanupFileName[MAXFNAMELEN]; /* the file we need to * get from archive */ @@ -259,9 +259,9 @@ CustomizableCleanupPriorWALFiles(void) strcmp(xlde->d_name + 8, exclusiveCleanupFileName + 8) < 0) { #ifdef WIN32 - snprintf(WALFilePath, MAXPGPATH, "%s\\%s", archiveLocation, xlde->d_name); + snprintf(WALFilePath, sizeof(WALFilePath), "%s\\%s", archiveLocation, xlde->d_name); #else - snprintf(WALFilePath, MAXPGPATH, "%s/%s", archiveLocation, xlde->d_name); + snprintf(WALFilePath, sizeof(WALFilePath), "%s/%s", archiveLocation, xlde->d_name); #endif if (debug) diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index d7f65a5e99..60dcb67a20 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -1203,7 +1203,7 @@ CheckPointLogicalRewriteHeap(void) XLogRecPtr redo; DIR *mappings_dir; struct dirent *mapping_de; - char path[MAXPGPATH]; + char path[MAXPGPATH + 20]; /* * We start of with a minimum of the last redo pointer. No new decoding @@ -1234,7 +1234,7 @@ CheckPointLogicalRewriteHeap(void) strcmp(mapping_de->d_name, "..") == 0) continue; - snprintf(path, MAXPGPATH, "pg_logical/mappings/%s", mapping_de->d_name); + snprintf(path, sizeof(path), "pg_logical/mappings/%s", mapping_de->d_name); if (lstat(path, &statbuf) == 0 && !S_ISREG(statbuf.st_mode)) continue; diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 45ed58ea34..c7667879c6 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -4102,7 +4102,7 @@ CleanupBackupHistory(void) { DIR *xldir; struct dirent *xlde; - char path[MAXPGPATH]; + char path[MAXPGPATH + sizeof(XLOGDIR)]; xldir = AllocateDir(XLOGDIR); if (xldir == NULL) @@ -4120,7 +4120,7 @@ CleanupBackupHistory(void) ereport(DEBUG2, (errmsg("removing transaction log backup history file \"%s\"", xlde->d_name))); - snprintf(path, MAXPGPATH, XLOGDIR "/%s", xlde->d_name); + snprintf(path, sizeof(path), XLOGDIR "/%s", xlde->d_name); unlink(path); XLogArchiveCleanup(xlde->d_name); } @@ -10389,7 +10389,7 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p, /* Collect information about all tablespaces */ while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL) { - char fullpath[MAXPGPATH]; + char fullpath[MAXPGPATH + 10]; char linkpath[MAXPGPATH]; char *relpath = NULL; int rllen; diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 235dc26405..15d06892d3 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -606,7 +606,7 @@ pgstat_reset_remove_files(const char *directory) { DIR *dir; struct dirent *entry; - char fname[MAXPGPATH]; + char fname[MAXPGPATH * 2]; dir = AllocateDir(directory); while ((entry = ReadDir(dir, directory)) != NULL) @@ -636,7 +636,7 @@ pgstat_reset_remove_files(const char *directory) strcmp(entry->d_name + nchars, "stat") != 0) continue; - snprintf(fname, MAXPGPATH, "%s/%s", directory, + snprintf(fname, sizeof(fname), "%s/%s", directory, entry->d_name); unlink(fname); } diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c index e3a7ad5e9a..3ee0dd5aa4 100644 --- a/src/backend/replication/basebackup.c +++ b/src/backend/replication/basebackup.c @@ -959,7 +959,7 @@ sendDir(char *path, int basepathlen, bool sizeonly, List *tablespaces, { DIR *dir; struct dirent *de; - char pathbuf[MAXPGPATH]; + char pathbuf[MAXPGPATH * 2]; struct stat statbuf; int64 size = 0; @@ -1011,7 +1011,7 @@ sendDir(char *path, int basepathlen, bool sizeonly, List *tablespaces, if (excludeFound) continue; - snprintf(pathbuf, MAXPGPATH, "%s/%s", path, de->d_name); + snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name); /* Skip pg_control here to back up it last */ if (strcmp(pathbuf, "./global/pg_control") == 0) diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index 12ebadca81..0c174be8ed 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -2613,7 +2613,7 @@ StartupReorderBuffer(void) while ((logical_de = ReadDir(logical_dir, "pg_replslot")) != NULL) { struct stat statbuf; - char path[MAXPGPATH]; + char path[MAXPGPATH * 2 + 12]; if (strcmp(logical_de->d_name, ".") == 0 || strcmp(logical_de->d_name, "..") == 0) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index 227960452d..358ec28932 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1868,7 +1868,7 @@ CheckPointSnapBuild(void) XLogRecPtr redo; DIR *snap_dir; struct dirent *snap_de; - char path[MAXPGPATH]; + char path[MAXPGPATH + 21]; /* * We start off with a minimum of the last redo pointer. No new replication @@ -1895,7 +1895,7 @@ CheckPointSnapBuild(void) strcmp(snap_de->d_name, "..") == 0) continue; - snprintf(path, MAXPGPATH, "pg_logical/snapshots/%s", snap_de->d_name); + snprintf(path, sizeof(path), "pg_logical/snapshots/%s", snap_de->d_name); if (lstat(path, &statbuf) == 0 && !S_ISREG(statbuf.st_mode)) { diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 6ac0ce69c6..e8ad0f7b39 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -1023,13 +1023,13 @@ StartupReplicationSlots(void) while ((replication_de = ReadDir(replication_dir, "pg_replslot")) != NULL) { struct stat statbuf; - char path[MAXPGPATH]; + char path[MAXPGPATH + 12]; if (strcmp(replication_de->d_name, ".") == 0 || strcmp(replication_de->d_name, "..") == 0) continue; - snprintf(path, MAXPGPATH, "pg_replslot/%s", replication_de->d_name); + snprintf(path, sizeof(path), "pg_replslot/%s", replication_de->d_name); /* we're only creating directories here, skip if it's not our's */ if (lstat(path, &statbuf) == 0 && !S_ISDIR(statbuf.st_mode)) @@ -1259,7 +1259,7 @@ RestoreSlotFromDisk(const char *name) { ReplicationSlotOnDisk cp; int i; - char path[MAXPGPATH]; + char path[MAXPGPATH + 22]; int fd; bool restored = false; int readBytes; diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c index dffe28376b..1e2691685a 100644 --- a/src/backend/storage/file/copydir.c +++ b/src/backend/storage/file/copydir.c @@ -38,8 +38,8 @@ copydir(char *fromdir, char *todir, bool recurse) { DIR *xldir; struct dirent *xlde; - char fromfile[MAXPGPATH]; - char tofile[MAXPGPATH]; + char fromfile[MAXPGPATH * 2]; + char tofile[MAXPGPATH * 2]; if (mkdir(todir, S_IRWXU) != 0) ereport(ERROR, @@ -63,8 +63,8 @@ copydir(char *fromdir, char *todir, bool recurse) strcmp(xlde->d_name, "..") == 0) continue; - snprintf(fromfile, MAXPGPATH, "%s/%s", fromdir, xlde->d_name); - snprintf(tofile, MAXPGPATH, "%s/%s", todir, xlde->d_name); + snprintf(fromfile, sizeof(fromfile), "%s/%s", fromdir, xlde->d_name); + snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name); if (lstat(fromfile, &fst) < 0) ereport(ERROR, @@ -103,7 +103,7 @@ copydir(char *fromdir, char *todir, bool recurse) strcmp(xlde->d_name, "..") == 0) continue; - snprintf(tofile, MAXPGPATH, "%s/%s", todir, xlde->d_name); + snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name); /* * We don't need to sync subdirectories here since the recursive diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index b14979496c..81d96a4cc0 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -2705,7 +2705,7 @@ CleanupTempFiles(bool isProcExit) void RemovePgTempFiles(void) { - char temp_path[MAXPGPATH]; + char temp_path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY) + sizeof(PG_TEMP_FILES_DIR)]; DIR *spc_dir; struct dirent *spc_de; @@ -2753,7 +2753,7 @@ RemovePgTempFilesInDir(const char *tmpdirname) { DIR *temp_dir; struct dirent *temp_de; - char rm_path[MAXPGPATH]; + char rm_path[MAXPGPATH * 2]; temp_dir = AllocateDir(tmpdirname); if (temp_dir == NULL) @@ -2794,7 +2794,7 @@ RemovePgTempRelationFiles(const char *tsdirname) { DIR *ts_dir; struct dirent *de; - char dbspace_path[MAXPGPATH]; + char dbspace_path[MAXPGPATH * 2]; ts_dir = AllocateDir(tsdirname); if (ts_dir == NULL) @@ -2835,7 +2835,7 @@ RemovePgTempRelationFilesInDbspace(const char *dbspacedirname) { DIR *dbspace_dir; struct dirent *de; - char rm_path[MAXPGPATH]; + char rm_path[MAXPGPATH * 2]; dbspace_dir = AllocateDir(dbspacedirname); if (dbspace_dir == NULL) @@ -3022,7 +3022,7 @@ walkdir(const char *path, while ((de = ReadDirExtended(dir, path, elevel)) != NULL) { - char subpath[MAXPGPATH]; + char subpath[MAXPGPATH * 2]; struct stat fst; int sret; @@ -3032,7 +3032,7 @@ walkdir(const char *path, strcmp(de->d_name, "..") == 0) continue; - snprintf(subpath, MAXPGPATH, "%s/%s", path, de->d_name); + snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name); if (process_symlinks) sret = stat(subpath, &fst); diff --git a/src/backend/storage/file/reinit.c b/src/backend/storage/file/reinit.c index b883dfc657..f331e7bc21 100644 --- a/src/backend/storage/file/reinit.c +++ b/src/backend/storage/file/reinit.c @@ -48,7 +48,7 @@ typedef struct void ResetUnloggedRelations(int op) { - char temp_path[MAXPGPATH]; + char temp_path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)]; DIR *spc_dir; struct dirent *spc_de; MemoryContext tmpctx, @@ -104,7 +104,7 @@ ResetUnloggedRelationsInTablespaceDir(const char *tsdirname, int op) { DIR *ts_dir; struct dirent *de; - char dbspace_path[MAXPGPATH]; + char dbspace_path[MAXPGPATH * 2]; ts_dir = AllocateDir(tsdirname); if (ts_dir == NULL) @@ -145,7 +145,7 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op) { DIR *dbspace_dir; struct dirent *de; - char rm_path[MAXPGPATH]; + char rm_path[MAXPGPATH * 2]; /* Caller must specify at least one operation. */ Assert((op & (UNLOGGED_RELATION_CLEANUP | UNLOGGED_RELATION_INIT)) != 0); @@ -308,7 +308,7 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op) ForkNumber forkNum; int oidchars; char oidbuf[OIDCHARS + 1]; - char srcpath[MAXPGPATH]; + char srcpath[MAXPGPATH * 2]; char dstpath[MAXPGPATH]; /* Skip anything that doesn't look like a relation data file. */ diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index b65b63b721..387849e22c 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -307,9 +307,9 @@ dsm_cleanup_for_mmap(void) if (strncmp(dent->d_name, PG_DYNSHMEM_MMAP_FILE_PREFIX, strlen(PG_DYNSHMEM_MMAP_FILE_PREFIX)) == 0) { - char buf[MAXPGPATH]; + char buf[MAXPGPATH + sizeof(PG_DYNSHMEM_DIR)]; - snprintf(buf, MAXPGPATH, PG_DYNSHMEM_DIR "/%s", dent->d_name); + snprintf(buf, sizeof(buf), PG_DYNSHMEM_DIR "/%s", dent->d_name); elog(DEBUG2, "removing file \"%s\"", buf); diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 6d56638208..b0418b18dc 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -41,7 +41,7 @@ db_dir_size(const char *path) int64 dirsize = 0; struct dirent *direntry; DIR *dirdesc; - char filename[MAXPGPATH]; + char filename[MAXPGPATH * 2]; dirdesc = AllocateDir(path); @@ -58,7 +58,7 @@ db_dir_size(const char *path) strcmp(direntry->d_name, "..") == 0) continue; - snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name); + snprintf(filename, sizeof(filename), "%s/%s", path, direntry->d_name); if (stat(filename, &fst) < 0) { @@ -86,7 +86,7 @@ calculate_database_size(Oid dbOid) DIR *dirdesc; struct dirent *direntry; char dirpath[MAXPGPATH]; - char pathname[MAXPGPATH]; + char pathname[MAXPGPATH + 12 + sizeof(TABLESPACE_VERSION_DIRECTORY)]; AclResult aclresult; /* @@ -104,7 +104,7 @@ calculate_database_size(Oid dbOid) /* Shared storage in pg_global is not counted */ /* Include pg_default storage */ - snprintf(pathname, MAXPGPATH, "base/%u", dbOid); + snprintf(pathname, sizeof(pathname), "base/%u", dbOid); totalsize = db_dir_size(pathname); /* Scan the non-default tablespaces */ @@ -124,7 +124,7 @@ calculate_database_size(Oid dbOid) strcmp(direntry->d_name, "..") == 0) continue; - snprintf(pathname, MAXPGPATH, "pg_tblspc/%s/%s/%u", + snprintf(pathname, sizeof(pathname), "pg_tblspc/%s/%s/%u", direntry->d_name, TABLESPACE_VERSION_DIRECTORY, dbOid); totalsize += db_dir_size(pathname); } @@ -172,7 +172,7 @@ static int64 calculate_tablespace_size(Oid tblspcOid) { char tblspcPath[MAXPGPATH]; - char pathname[MAXPGPATH]; + char pathname[MAXPGPATH * 2]; int64 totalsize = 0; DIR *dirdesc; struct dirent *direntry; @@ -215,7 +215,7 @@ calculate_tablespace_size(Oid tblspcOid) strcmp(direntry->d_name, "..") == 0) continue; - snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name); + snprintf(pathname, sizeof(pathname), "%s/%s", tblspcPath, direntry->d_name); if (stat(pathname, &fst) < 0) { diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c index 8d0a236e6d..32d6a66688 100644 --- a/src/backend/utils/adt/genfile.c +++ b/src/backend/utils/adt/genfile.c @@ -522,7 +522,7 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, char *dir) { Datum values[3]; bool nulls[3]; - char path[MAXPGPATH]; + char path[MAXPGPATH * 2]; struct stat attrib; HeapTuple tuple; @@ -531,7 +531,7 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, char *dir) continue; /* Get the file info */ - snprintf(path, MAXPGPATH, "%s/%s", fctx->location, de->d_name); + snprintf(path, sizeof(path), "%s/%s", fctx->location, de->d_name); if (stat(path, &attrib) < 0) ereport(ERROR, (errcode_for_file_access(), diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ddb948528b..5bf02d4c0e 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -6074,7 +6074,7 @@ RelationCacheInitFileRemove(void) const char *tblspcdir = "pg_tblspc"; DIR *dir; struct dirent *de; - char path[MAXPGPATH]; + char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)]; /* * We zap the shared cache file too. In theory it can't get out of sync @@ -6116,7 +6116,7 @@ RelationCacheInitFileRemoveInDir(const char *tblspcpath) { DIR *dir; struct dirent *de; - char initfilename[MAXPGPATH]; + char initfilename[MAXPGPATH * 2]; /* Scan the tablespace directory to find per-database directories */ dir = AllocateDir(tblspcpath); diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 6e83cbedab..22004cb819 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -2228,7 +2228,7 @@ static void setup_formatted_log_time(void) { pg_time_t stamp_time; - char msbuf[8]; + char msbuf[13]; if (!saved_timeval_set) { diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 3d92494e0b..3a3a25a0c3 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -1578,7 +1578,7 @@ XactHasExportedSnapshots(void) void DeleteAllExportedSnapshotFiles(void) { - char buf[MAXPGPATH]; + char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)]; DIR *s_dir; struct dirent *s_de; @@ -1599,7 +1599,7 @@ DeleteAllExportedSnapshotFiles(void) strcmp(s_de->d_name, "..") == 0) continue; - snprintf(buf, MAXPGPATH, SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name); + snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name); /* Again, unlink failure is not worthy of FATAL */ if (unlink(buf)) elog(LOG, "could not unlink file \"%s\": %m", buf); diff --git a/src/bin/pg_archivecleanup/pg_archivecleanup.c b/src/bin/pg_archivecleanup/pg_archivecleanup.c index f1651d4273..1760955586 100644 --- a/src/bin/pg_archivecleanup/pg_archivecleanup.c +++ b/src/bin/pg_archivecleanup/pg_archivecleanup.c @@ -32,7 +32,7 @@ char *additional_ext = NULL; /* Extension to remove from filenames */ char *archiveLocation; /* where to find the archive? */ char *restartWALFileName; /* the file from which we can restart restore */ -char WALFilePath[MAXPGPATH]; /* the file path including archive */ +char WALFilePath[MAXPGPATH * 2]; /* the file path including archive */ char exclusiveCleanupFileName[MAXFNAMELEN]; /* the oldest file we * want to remain in * archive */ @@ -133,7 +133,7 @@ CleanupPriorWALFiles(void) * extension that might have been chopped off before testing * the sequence. */ - snprintf(WALFilePath, MAXPGPATH, "%s/%s", + snprintf(WALFilePath, sizeof(WALFilePath), "%s/%s", archiveLocation, xlde->d_name); if (dryrun) diff --git a/src/bin/pg_basebackup/pg_receivewal.c b/src/bin/pg_basebackup/pg_receivewal.c index 15348ada58..1a9fe81be1 100644 --- a/src/bin/pg_basebackup/pg_receivewal.c +++ b/src/bin/pg_basebackup/pg_receivewal.c @@ -244,7 +244,7 @@ FindStreamingStart(uint32 *tli) if (!ispartial && !iscompress) { struct stat statbuf; - char fullpath[MAXPGPATH]; + char fullpath[MAXPGPATH * 2]; snprintf(fullpath, sizeof(fullpath), "%s/%s", basedir, dirent->d_name); if (stat(fullpath, &statbuf) != 0) @@ -267,7 +267,7 @@ FindStreamingStart(uint32 *tli) int fd; char buf[4]; int bytes_out; - char fullpath[MAXPGPATH]; + char fullpath[MAXPGPATH * 2]; snprintf(fullpath, sizeof(fullpath), "%s/%s", basedir, dirent->d_name); diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c index bcb9ed938f..73bd9fe6ec 100644 --- a/src/bin/pg_resetwal/pg_resetwal.c +++ b/src/bin/pg_resetwal/pg_resetwal.c @@ -958,7 +958,7 @@ KillExistingXLOG(void) { DIR *xldir; struct dirent *xlde; - char path[MAXPGPATH]; + char path[MAXPGPATH + sizeof(XLOGDIR)]; xldir = opendir(XLOGDIR); if (xldir == NULL) @@ -973,7 +973,7 @@ KillExistingXLOG(void) if (IsXLogFileName(xlde->d_name) || IsPartialXLogFileName(xlde->d_name)) { - snprintf(path, MAXPGPATH, "%s/%s", XLOGDIR, xlde->d_name); + snprintf(path, sizeof(path), "%s/%s", XLOGDIR, xlde->d_name); if (unlink(path) < 0) { fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"), @@ -1005,11 +1005,11 @@ KillExistingXLOG(void) static void KillExistingArchiveStatus(void) { +#define ARCHSTATDIR XLOGDIR "/archive_status" + DIR *xldir; struct dirent *xlde; - char path[MAXPGPATH]; - -#define ARCHSTATDIR XLOGDIR "/archive_status" + char path[MAXPGPATH + sizeof(ARCHSTATDIR)]; xldir = opendir(ARCHSTATDIR); if (xldir == NULL) @@ -1027,7 +1027,7 @@ KillExistingArchiveStatus(void) strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.ready") == 0 || strcmp(xlde->d_name + XLOG_FNAME_LEN, ".partial.done") == 0)) { - snprintf(path, MAXPGPATH, "%s/%s", ARCHSTATDIR, xlde->d_name); + snprintf(path, sizeof(path), "%s/%s", ARCHSTATDIR, xlde->d_name); if (unlink(path) < 0) { fprintf(stderr, _("%s: could not delete file \"%s\": %s\n"), diff --git a/src/bin/pg_rewind/copy_fetch.c b/src/bin/pg_rewind/copy_fetch.c index f8d3dfecfa..347d4e4d4c 100644 --- a/src/bin/pg_rewind/copy_fetch.c +++ b/src/bin/pg_rewind/copy_fetch.c @@ -65,14 +65,14 @@ recurse_dir(const char *datadir, const char *parentpath, while (errno = 0, (xlde = readdir(xldir)) != NULL) { struct stat fst; - char fullpath[MAXPGPATH]; - char path[MAXPGPATH]; + char fullpath[MAXPGPATH * 2]; + char path[MAXPGPATH * 2]; if (strcmp(xlde->d_name, ".") == 0 || strcmp(xlde->d_name, "..") == 0) continue; - snprintf(fullpath, MAXPGPATH, "%s/%s", fullparentpath, xlde->d_name); + snprintf(fullpath, sizeof(fullpath), "%s/%s", fullparentpath, xlde->d_name); if (lstat(fullpath, &fst) < 0) { @@ -93,9 +93,9 @@ recurse_dir(const char *datadir, const char *parentpath, } if (parentpath) - snprintf(path, MAXPGPATH, "%s/%s", parentpath, xlde->d_name); + snprintf(path, sizeof(path), "%s/%s", parentpath, xlde->d_name); else - snprintf(path, MAXPGPATH, "%s", xlde->d_name); + snprintf(path, sizeof(path), "%s", xlde->d_name); if (S_ISREG(fst.st_mode)) callback(path, FILE_TYPE_REGULAR, fst.st_size, NULL); diff --git a/src/common/file_utils.c b/src/common/file_utils.c index 72b0565c71..218b83f391 100644 --- a/src/common/file_utils.c +++ b/src/common/file_utils.c @@ -166,7 +166,7 @@ walkdir(const char *path, while (errno = 0, (de = readdir(dir)) != NULL) { - char subpath[MAXPGPATH]; + char subpath[MAXPGPATH * 2]; struct stat fst; int sret; @@ -174,7 +174,7 @@ walkdir(const char *path, strcmp(de->d_name, "..") == 0) continue; - snprintf(subpath, MAXPGPATH, "%s/%s", path, de->d_name); + snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name); if (process_symlinks) sret = stat(subpath, &fst); diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c index 826857d943..b7cfc5f5ac 100644 --- a/src/timezone/pgtz.c +++ b/src/timezone/pgtz.c @@ -412,7 +412,7 @@ pg_tzenumerate_next(pg_tzenum *dir) while (dir->depth >= 0) { struct dirent *direntry; - char fullname[MAXPGPATH]; + char fullname[MAXPGPATH * 2]; struct stat statbuf; direntry = ReadDir(dir->dirdesc[dir->depth], dir->dirname[dir->depth]); @@ -429,7 +429,7 @@ pg_tzenumerate_next(pg_tzenum *dir) if (direntry->d_name[0] == '.') continue; - snprintf(fullname, MAXPGPATH, "%s/%s", + snprintf(fullname, sizeof(fullname), "%s/%s", dir->dirname[dir->depth], direntry->d_name); if (stat(fullname, &statbuf) != 0) ereport(ERROR, -- cgit v1.2.3 From e18b2c480da478f62781e06488cda56fe1b4e919 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 30 Apr 2017 15:13:51 -0400 Subject: Sync our copy of the timezone library with IANA release tzcode2017b. zic no longer mishandles some transitions in January 2038 when it attempts to work around Qt bug 53071. This fixes a bug affecting Pacific/Tongatapu that was introduced in zic 2016e. localtime.c now contains a workaround, useful when loading a file generated by a buggy zic. There are assorted cosmetic changes as well, notably relocation of a bunch of #defines. --- src/timezone/README | 2 +- src/timezone/localtime.c | 73 +++++++++++++++++++++++++++++++++++----------- src/timezone/pgtz.c | 9 +++--- src/timezone/private.h | 76 ++++++++++++++++++++++++++++++++++++------------ src/timezone/strftime.c | 11 +++++-- src/timezone/tzfile.h | 52 --------------------------------- src/timezone/zic.c | 15 ++++++++-- 7 files changed, 139 insertions(+), 99 deletions(-) (limited to 'src/timezone/pgtz.c') diff --git a/src/timezone/README b/src/timezone/README index a82d77c7ba..2544230c4c 100644 --- a/src/timezone/README +++ b/src/timezone/README @@ -50,7 +50,7 @@ match properly on the old version. Time Zone code ============== -The code in this directory is currently synced with tzcode release 2016j. +The code in this directory is currently synced with tzcode release 2017b. There are many cosmetic (and not so cosmetic) differences from the original tzcode library, but diffs in the upstream version should usually be propagated to our version. Here are some notes about that. diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c index e6c1beaf96..154124e49c 100644 --- a/src/timezone/localtime.c +++ b/src/timezone/localtime.c @@ -17,8 +17,9 @@ #include #include "datatype/timestamp.h" -#include "private.h" #include "pgtz.h" + +#include "private.h" #include "tzfile.h" @@ -414,10 +415,10 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend, { /* * Attempt to reuse existing abbreviations. Without this, - * America/Anchorage would stop working after 2037 when - * TZ_MAX_CHARS is 50, as sp->charcnt equals 42 (for LMT CAT CAWT - * CAPT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for - * AKST AKDT). Reusing means sp->charcnt can stay 42 in this + * America/Anchorage would be right on the edge after 2037 when + * TZ_MAX_CHARS is 50, as sp->charcnt equals 40 (for LMT AST AWT + * APT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for + * AKST AKDT). Reusing means sp->charcnt can stay 40 in this * example. */ int gotabbr = 0; @@ -451,6 +452,17 @@ tzloadbody(char const * name, char *canonname, struct state * sp, bool doextend, if (gotabbr == 2) { sp->charcnt = charcnt; + + /* + * Ignore any trailing, no-op transitions generated by zic as + * they don't help here and can run afoul of bugs in zic 2016j + * or earlier. + */ + while (1 < sp->timecnt + && (sp->types[sp->timecnt - 1] + == sp->types[sp->timecnt - 2])) + sp->timecnt--; + for (i = 0; i < ts->timecnt; i++) if (sp->ats[sp->timecnt - 1] < ts->ats[i]) break; @@ -974,6 +986,8 @@ tzparse(const char *name, struct state * sp, bool lastditch) int yearlim; int timecnt; pg_time_t janfirst; + int32 janoffset = 0; + int yearbeg; ++name; if ((name = getrule(name, &start)) == NULL) @@ -994,8 +1008,23 @@ tzparse(const char *name, struct state * sp, bool lastditch) sp->defaulttype = 0; timecnt = 0; janfirst = 0; - yearlim = EPOCH_YEAR + YEARSPERREPEAT; - for (year = EPOCH_YEAR; year < yearlim; year++) + yearbeg = EPOCH_YEAR; + + do + { + int32 yearsecs + = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY; + + yearbeg--; + if (increment_overflow_time(&janfirst, -yearsecs)) + { + janoffset = -yearsecs; + break; + } + } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg); + + yearlim = yearbeg + YEARSPERREPEAT + 1; + for (year = yearbeg; year < yearlim; year++) { int32 starttime = transtime(year, &start, stdoffset), @@ -1020,24 +1049,34 @@ tzparse(const char *name, struct state * sp, bool lastditch) { if (TZ_MAX_TIMES - 2 < timecnt) break; - yearlim = year + YEARSPERREPEAT + 1; sp->ats[timecnt] = janfirst; - if (increment_overflow_time - (&sp->ats[timecnt], starttime)) - break; - sp->types[timecnt++] = reversed; + if (!increment_overflow_time + (&sp->ats[timecnt], + janoffset + starttime)) + sp->types[timecnt++] = reversed; + else if (janoffset) + sp->defaulttype = reversed; sp->ats[timecnt] = janfirst; - if (increment_overflow_time - (&sp->ats[timecnt], endtime)) - break; - sp->types[timecnt++] = !reversed; + if (!increment_overflow_time + (&sp->ats[timecnt], + janoffset + endtime)) + { + sp->types[timecnt++] = !reversed; + yearlim = year + YEARSPERREPEAT + 1; + } + else if (janoffset) + sp->defaulttype = !reversed; } - if (increment_overflow_time(&janfirst, yearsecs)) + if (increment_overflow_time + (&janfirst, janoffset + yearsecs)) break; + janoffset = 0; } sp->timecnt = timecnt; if (!timecnt) sp->typecnt = 1; /* Perpetual DST. */ + else if (YEARSPERREPEAT < year - yearbeg) + sp->goback = sp->goahead = true; } else { diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c index b7cfc5f5ac..13ce399033 100644 --- a/src/timezone/pgtz.c +++ b/src/timezone/pgtz.c @@ -17,6 +17,7 @@ #include #include +#include "datatype/timestamp.h" #include "miscadmin.h" #include "pgtz.h" #include "storage/fd.h" @@ -308,14 +309,14 @@ pg_tzset_offset(long gmtoffset) char tzname[128]; snprintf(offsetstr, sizeof(offsetstr), - "%02ld", absoffset / SECSPERHOUR); - absoffset %= SECSPERHOUR; + "%02ld", absoffset / SECS_PER_HOUR); + absoffset %= SECS_PER_HOUR; if (absoffset != 0) { snprintf(offsetstr + strlen(offsetstr), sizeof(offsetstr) - strlen(offsetstr), - ":%02ld", absoffset / SECSPERMIN); - absoffset %= SECSPERMIN; + ":%02ld", absoffset / SECS_PER_MINUTE); + absoffset %= SECS_PER_MINUTE; if (absoffset != 0) snprintf(offsetstr + strlen(offsetstr), sizeof(offsetstr) - strlen(offsetstr), diff --git a/src/timezone/private.h b/src/timezone/private.h index b8533d51e8..f031b17b7e 100644 --- a/src/timezone/private.h +++ b/src/timezone/private.h @@ -67,14 +67,8 @@ extern int unlink(const char *filename); * Finally, some convenience items. */ -#ifndef TYPE_BIT #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) -#endif /* !defined TYPE_BIT */ - -#ifndef TYPE_SIGNED #define TYPE_SIGNED(type) (((type) -1) < 0) -#endif /* !defined TYPE_SIGNED */ - #define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0) /* @@ -88,7 +82,6 @@ extern int unlink(const char *filename); #define MINVAL(t, b) \ ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0)) -#ifndef INT_STRLEN_MAXIMUM /* * 302 / 1000 is log10(2.0) rounded up. * Subtract one for the sign bit if the type is signed; @@ -98,7 +91,6 @@ extern int unlink(const char *filename); #define INT_STRLEN_MAXIMUM(type) \ ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ 1 + TYPE_SIGNED(type)) -#endif /* !defined INT_STRLEN_MAXIMUM */ /* * INITIALIZE(x) @@ -108,24 +100,70 @@ extern int unlink(const char *filename); #undef _ #define _(msgid) (msgid) -#ifndef YEARSPERREPEAT +/* Handy macros that are independent of tzfile implementation. */ + #define YEARSPERREPEAT 400 /* years before a Gregorian repeat */ -#endif /* !defined YEARSPERREPEAT */ + +#define SECSPERMIN 60 +#define MINSPERHOUR 60 +#define HOURSPERDAY 24 +#define DAYSPERWEEK 7 +#define DAYSPERNYEAR 365 +#define DAYSPERLYEAR 366 +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY ((int32) SECSPERHOUR * HOURSPERDAY) +#define MONSPERYEAR 12 + +#define TM_SUNDAY 0 +#define TM_MONDAY 1 +#define TM_TUESDAY 2 +#define TM_WEDNESDAY 3 +#define TM_THURSDAY 4 +#define TM_FRIDAY 5 +#define TM_SATURDAY 6 + +#define TM_JANUARY 0 +#define TM_FEBRUARY 1 +#define TM_MARCH 2 +#define TM_APRIL 3 +#define TM_MAY 4 +#define TM_JUNE 5 +#define TM_JULY 6 +#define TM_AUGUST 7 +#define TM_SEPTEMBER 8 +#define TM_OCTOBER 9 +#define TM_NOVEMBER 10 +#define TM_DECEMBER 11 + +#define TM_YEAR_BASE 1900 + +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY TM_THURSDAY + +#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) /* - * The Gregorian year averages 365.2425 days, which is 31556952 seconds. + * Since everything in isleap is modulo 400 (or a factor of 400), we know that + * isleap(y) == isleap(y % 400) + * and so + * isleap(a + b) == isleap((a + b) % 400) + * or + * isleap(a + b) == isleap(a % 400 + b % 400) + * This is true even if % means modulo rather than Fortran remainder + * (which is allowed by C89 but not C99). + * We use this to avoid addition overflow problems. */ -#ifndef AVGSECSPERYEAR -#define AVGSECSPERYEAR 31556952L -#endif /* !defined AVGSECSPERYEAR */ +#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) -#ifndef SECSPERREPEAT -#define SECSPERREPEAT ((int64) YEARSPERREPEAT * (int64) AVGSECSPERYEAR) -#endif /* !defined SECSPERREPEAT */ -#ifndef SECSPERREPEAT_BITS +/* + * The Gregorian year averages 365.2425 days, which is 31556952 seconds. + */ + +#define AVGSECSPERYEAR 31556952L +#define SECSPERREPEAT \ + ((int64) YEARSPERREPEAT * (int64) AVGSECSPERYEAR) #define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */ -#endif /* !defined SECSPERREPEAT_BITS */ #endif /* !defined PRIVATE_H */ diff --git a/src/timezone/strftime.c b/src/timezone/strftime.c index acaba86881..d9a18d49a8 100644 --- a/src/timezone/strftime.c +++ b/src/timezone/strftime.c @@ -1,4 +1,4 @@ -/* Convert a broken-down time stamp to a string. */ +/* Convert a broken-down timestamp to a string. */ /* * Copyright 1989 The Regents of the University of California. @@ -43,7 +43,6 @@ #include #include "private.h" -#include "tzfile.h" struct lc_time_T @@ -451,11 +450,17 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim, { long diff; char const *sign; + bool negative; if (t->tm_isdst < 0) continue; diff = t->tm_gmtoff; - if (diff < 0) + negative = diff < 0; + if (diff == 0) + { + negative = t->tm_zone[0] == '-'; + } + if (negative) { sign = "-"; diff = -diff; diff --git a/src/timezone/tzfile.h b/src/timezone/tzfile.h index 32d237b827..56a5b43472 100644 --- a/src/timezone/tzfile.h +++ b/src/timezone/tzfile.h @@ -100,56 +100,4 @@ struct tzhead #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ -#define SECSPERMIN 60 -#define MINSPERHOUR 60 -#define HOURSPERDAY 24 -#define DAYSPERWEEK 7 -#define DAYSPERNYEAR 365 -#define DAYSPERLYEAR 366 -#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) -#define SECSPERDAY ((int32) SECSPERHOUR * HOURSPERDAY) -#define MONSPERYEAR 12 - -#define TM_SUNDAY 0 -#define TM_MONDAY 1 -#define TM_TUESDAY 2 -#define TM_WEDNESDAY 3 -#define TM_THURSDAY 4 -#define TM_FRIDAY 5 -#define TM_SATURDAY 6 - -#define TM_JANUARY 0 -#define TM_FEBRUARY 1 -#define TM_MARCH 2 -#define TM_APRIL 3 -#define TM_MAY 4 -#define TM_JUNE 5 -#define TM_JULY 6 -#define TM_AUGUST 7 -#define TM_SEPTEMBER 8 -#define TM_OCTOBER 9 -#define TM_NOVEMBER 10 -#define TM_DECEMBER 11 - -#define TM_YEAR_BASE 1900 - -#define EPOCH_YEAR 1970 -#define EPOCH_WDAY TM_THURSDAY - -#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) - -/* - * Since everything in isleap is modulo 400 (or a factor of 400), we know that - * isleap(y) == isleap(y % 400) - * and so - * isleap(a + b) == isleap((a + b) % 400) - * or - * isleap(a + b) == isleap(a % 400 + b % 400) - * This is true even if % means modulo rather than Fortran remainder - * (which is allowed by C89 but not C99). - * We use this to avoid addition overflow problems. - */ - -#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) - #endif /* !defined TZFILE_H */ diff --git a/src/timezone/zic.c b/src/timezone/zic.c index e1875585df..5fa0a81262 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -2671,6 +2671,9 @@ outzone(const struct zone * zpfirst, ptrdiff_t zonecount) bool do_extend; char version; ptrdiff_t lastatmax = -1; + zic_t one = 1; + zic_t y2038_boundary = one << 31; + zic_t max_year0; max_abbr_len = 2 + max_format_len + max_abbrvar_len; max_envvar_len = 2 * max_abbr_len + 5 * 9; @@ -2780,12 +2783,13 @@ outzone(const struct zone * zpfirst, ptrdiff_t zonecount) } /* - * For the benefit of older systems, generate data from 1900 through 2037. + * For the benefit of older systems, generate data from 1900 through 2038. */ if (min_year > 1900) min_year = 1900; - if (max_year < 2037) - max_year = 2037; + max_year0 = max_year; + if (max_year < 2038) + max_year = 2038; for (i = 0; i < zonecount; ++i) { /* @@ -2835,7 +2839,12 @@ outzone(const struct zone * zpfirst, ptrdiff_t zonecount) year <= rp->r_hiyear && yearistype(year, rp->r_yrtype); if (rp->r_todo) + { rp->r_temp = rpytime(rp, year); + rp->r_todo + = (rp->r_temp < y2038_boundary + || year <= max_year0); + } } for (;;) { -- cgit v1.2.3 From af2c5aa88d38573724e40fa029499b4db20b0eb2 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 2 May 2017 21:50:35 -0400 Subject: Improve performance of timezone loading, especially pg_timezone_names view. tzparse() would attempt to load the "posixrules" timezone database file on each call. That might seem like it would only be an issue when selecting a POSIX-style zone name rather than a zone defined in the timezone database, but it turns out that each zone definition file contains a POSIX-style zone string and tzload() will call tzparse() to parse that. Thus, when scanning the whole timezone file tree as we do in the pg_timezone_names view, "posixrules" was read repetitively for each zone definition file. Fix that by caching the file on first use within any given process. (We cache other zone definitions for the life of the process, so there seems little reason not to cache this one as well.) This probably won't help much in processes that never run pg_timezone_names, but even one additional SET of the timezone GUC would come out ahead. An even worse problem for pg_timezone_names is that pg_open_tzfile() has an inefficient way of identifying the canonical case of a zone name: it basically re-descends the directory tree to the zone file. That's not awful for an individual "SET timezone" operation, but it's pretty horrid when we're inspecting every zone in the database. And it's pointless too because we already know the canonical spelling, having just read it from the filesystem. Fix by teaching pg_open_tzfile() to avoid the directory search if it's not asked for the canonical name, and backfilling the proper result in pg_tzenumerate_next(). In combination these changes seem to make the pg_timezone_names view about 3x faster to read, for me. Since a scan of pg_timezone_names has up to now been one of the slowest queries in the regression tests, this should help some little bit for buildfarm cycle times. Back-patch to all supported branches, not so much because it's likely that users will care much about the view's performance as because tracking changes in the upstream IANA timezone code is really painful if we don't keep all the branches in sync. Discussion: https://postgr.es/m/27962.1493671706@sss.pgh.pa.us --- src/timezone/README | 3 +++ src/timezone/localtime.c | 23 ++++++++++++++++++++++- src/timezone/pgtz.c | 42 +++++++++++++++++++++++++++++++++++------- 3 files changed, 60 insertions(+), 8 deletions(-) (limited to 'src/timezone/pgtz.c') diff --git a/src/timezone/README b/src/timezone/README index 2544230c4c..912e0c1b39 100644 --- a/src/timezone/README +++ b/src/timezone/README @@ -79,6 +79,9 @@ other exposed names. slightly modified the API of the former, in part because it now relies on our own pg_open_tzfile() rather than opening files for itself. +* tzparse() is adjusted to cache the result of loading the TZDEFRULES +zone, so that that's not repeated more than once per process. + * There's a fair amount of code we don't need and have removed, including all the nonstandard optional APIs. We have also added a few functions of our own at the bottom of localtime.c. diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c index 154124e49c..a2faa82ac8 100644 --- a/src/timezone/localtime.c +++ b/src/timezone/localtime.c @@ -54,6 +54,13 @@ static const char gmt[] = "GMT"; static const pg_time_t time_t_min = MINVAL(pg_time_t, TYPE_BIT(pg_time_t)); static const pg_time_t time_t_max = MAXVAL(pg_time_t, TYPE_BIT(pg_time_t)); +/* + * We cache the result of trying to load the TZDEFRULES zone here. + * tzdefrules_loaded is 0 if not tried yet, +1 if good, -1 if failed. + */ +static struct state tzdefrules_s; +static int tzdefrules_loaded = 0; + /* * The DST rules to use if TZ has no rules and we can't load TZDEFRULES. * We default to US rules as of 1999-08-17. @@ -942,7 +949,21 @@ tzparse(const char *name, struct state * sp, bool lastditch) charcnt = stdlen + 1; if (sizeof sp->chars < charcnt) return false; - load_ok = tzload(TZDEFRULES, NULL, sp, false) == 0; + + /* + * This bit also differs from the IANA code, which doesn't make any + * attempt to avoid repetitive loadings of the TZDEFRULES zone. + */ + if (tzdefrules_loaded == 0) + { + if (tzload(TZDEFRULES, NULL, &tzdefrules_s, false) == 0) + tzdefrules_loaded = 1; + else + tzdefrules_loaded = -1; + } + load_ok = (tzdefrules_loaded > 0); + if (load_ok) + memcpy(sp, &tzdefrules_s, sizeof(struct state)); } if (!load_ok) sp->leapcnt = 0; /* so, we're off a little */ diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c index 13ce399033..31dbf8993b 100644 --- a/src/timezone/pgtz.c +++ b/src/timezone/pgtz.c @@ -80,12 +80,37 @@ pg_open_tzfile(const char *name, char *canonname) int fullnamelen; int orignamelen; + /* Initialize fullname with base name of tzdata directory */ + strlcpy(fullname, pg_TZDIR(), sizeof(fullname)); + orignamelen = fullnamelen = strlen(fullname); + + if (fullnamelen + 1 + strlen(name) >= MAXPGPATH) + return -1; /* not gonna fit */ + + /* + * If the caller doesn't need the canonical spelling, first just try to + * open the name as-is. This can be expected to succeed if the given name + * is already case-correct, or if the filesystem is case-insensitive; and + * we don't need to distinguish those situations if we aren't tasked with + * reporting the canonical spelling. + */ + if (canonname == NULL) + { + int result; + + fullname[fullnamelen] = '/'; + /* test above ensured this will fit: */ + strcpy(fullname + fullnamelen + 1, name); + result = open(fullname, O_RDONLY | PG_BINARY, 0); + if (result >= 0) + return result; + /* If that didn't work, fall through to do it the hard way */ + } + /* * Loop to split the given name into directory levels; for each level, * search using scan_directory_ci(). */ - strlcpy(fullname, pg_TZDIR(), sizeof(fullname)); - orignamelen = fullnamelen = strlen(fullname); fname = name; for (;;) { @@ -97,8 +122,6 @@ pg_open_tzfile(const char *name, char *canonname) fnamelen = slashptr - fname; else fnamelen = strlen(fname); - if (fullnamelen + 1 + fnamelen >= MAXPGPATH) - return -1; /* not gonna fit */ if (!scan_directory_ci(fullname, fname, fnamelen, fullname + fullnamelen + 1, MAXPGPATH - fullnamelen - 1)) @@ -458,10 +481,11 @@ pg_tzenumerate_next(pg_tzenum *dir) /* * Load this timezone using tzload() not pg_tzset(), so we don't fill - * the cache + * the cache. Also, don't ask for the canonical spelling: we already + * know it, and pg_open_tzfile's way of finding it out is pretty + * inefficient. */ - if (tzload(fullname + dir->baselen, dir->tz.TZname, &dir->tz.state, - true) != 0) + if (tzload(fullname + dir->baselen, NULL, &dir->tz.state, true) != 0) { /* Zone could not be loaded, ignore it */ continue; @@ -473,6 +497,10 @@ pg_tzenumerate_next(pg_tzenum *dir) continue; } + /* OK, return the canonical zone name spelling. */ + strlcpy(dir->tz.TZname, fullname + dir->baselen, + sizeof(dir->tz.TZname)); + /* Timezone loaded OK. */ return &dir->tz; } -- cgit v1.2.3 From 5788a5670e4a58049b8adc82c4fef97a2c3be327 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 7 May 2017 11:34:31 -0400 Subject: Restore fullname[] contents before falling through in pg_open_tzfile(). Fix oversight in commit af2c5aa88: if the shortcut open() doesn't work, we need to reset fullname[] to be just the name of the toplevel tzdata directory before we fall through into the pre-existing code. This failed to be exposed in my (tgl's) testing because the fall-through path is actually never taken under normal circumstances. David Rowley, per report from Amit Kapila Discussion: https://postgr.es/m/CAA4eK1LC7CaNhRAQ__C3ht1JVrPzaAXXhEJRnR5L6bfYHiLmWw@mail.gmail.com --- src/timezone/pgtz.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/timezone/pgtz.c') diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c index 31dbf8993b..846f8898ff 100644 --- a/src/timezone/pgtz.c +++ b/src/timezone/pgtz.c @@ -105,6 +105,7 @@ pg_open_tzfile(const char *name, char *canonname) if (result >= 0) return result; /* If that didn't work, fall through to do it the hard way */ + fullname[fullnamelen] = '\0'; } /* -- cgit v1.2.3