mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Sync our copy of the timezone library with IANA tzcode master.
This patch absorbs some unreleased fixes for symlink manipulation bugs
introduced in tzcode 2016g.  Ordinarily I'd wait around for a released
version, but in this case it seems like we could do with extra testing,
in particular checking whether it works in EDB's VMware build environment.
This corresponds to commit aec59156abbf8472ba201b6c7ca2592f9c10e077 in
https://github.com/eggert/tz.
Per a report from Sandeep Thakkar, building in an environment where hard
links are not supported in the timezone data installation directory failed,
because upstream code refactoring had broken the case of symlinking from an
existing symlink.  Further experimentation also showed that the symlinks
were sometimes made incorrectly, with too many or too few "../"'s in the
symlink contents.
Back-patch of commit 1f87181e12.
Report: <CANFyU94_p6mqRQc2i26PFp5QAOQGB++AjGX=FO8LDpXw0GSTjw@mail.gmail.com>
Discussion: http://mm.icann.org/pipermail/tz/2016-November/024431.html
			
			
This commit is contained in:
		@@ -8,12 +8,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "postgres_fe.h"
 | 
					#include "postgres_fe.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
#ifdef HAVE_GETOPT_H
 | 
					#ifdef HAVE_GETOPT_H
 | 
				
			||||||
#include <getopt.h>
 | 
					#include <getopt.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#include <locale.h>
 | 
					#include <locale.h>
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int	optind;
 | 
					extern int	optind;
 | 
				
			||||||
extern char *optarg;
 | 
					extern char *optarg;
 | 
				
			||||||
@@ -44,14 +46,24 @@ typedef int64 zic_t;
 | 
				
			|||||||
#define MKDIR_UMASK 0755
 | 
					#define MKDIR_UMASK 0755
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifndef S_ISLNK
 | 
					#ifndef AT_SYMLINK_FOLLOW
 | 
				
			||||||
#define S_ISLNK(m) 0
 | 
					#define linkat(fromdir, from, todir, to, flag) \
 | 
				
			||||||
 | 
						(itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to))
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The maximum ptrdiff_t value, for pre-C99 platforms.  */
 | 
				
			||||||
 | 
					#ifndef PTRDIFF_MAX
 | 
				
			||||||
 | 
					static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The type and printf format for line numbers.  */
 | 
				
			||||||
 | 
					typedef int lineno;
 | 
				
			||||||
 | 
					#define PRIdLINENO "d"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct rule
 | 
					struct rule
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *r_filename;
 | 
						const char *r_filename;
 | 
				
			||||||
	int			r_linenum;
 | 
						lineno		r_linenum;
 | 
				
			||||||
	const char *r_name;
 | 
						const char *r_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	zic_t		r_loyear;		/* for example, 1986 */
 | 
						zic_t		r_loyear;		/* for example, 1986 */
 | 
				
			||||||
@@ -73,7 +85,7 @@ struct rule
 | 
				
			|||||||
	zic_t		r_stdoff;		/* offset from standard time */
 | 
						zic_t		r_stdoff;		/* offset from standard time */
 | 
				
			||||||
	const char *r_abbrvar;		/* variable part of abbreviation */
 | 
						const char *r_abbrvar;		/* variable part of abbreviation */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int			r_todo;			/* a rule to do (used in outzone) */
 | 
						bool		r_todo;			/* a rule to do (used in outzone) */
 | 
				
			||||||
	zic_t		r_temp;			/* used in outzone */
 | 
						zic_t		r_temp;			/* used in outzone */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -88,7 +100,7 @@ struct rule
 | 
				
			|||||||
struct zone
 | 
					struct zone
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *z_filename;
 | 
						const char *z_filename;
 | 
				
			||||||
	int			z_linenum;
 | 
						lineno		z_linenum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *z_name;
 | 
						const char *z_name;
 | 
				
			||||||
	zic_t		z_gmtoff;
 | 
						zic_t		z_gmtoff;
 | 
				
			||||||
@@ -99,7 +111,7 @@ struct zone
 | 
				
			|||||||
	zic_t		z_stdoff;
 | 
						zic_t		z_stdoff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct rule *z_rules;
 | 
						struct rule *z_rules;
 | 
				
			||||||
	int			z_nrules;
 | 
						ptrdiff_t	z_nrules;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct rule z_untilrule;
 | 
						struct rule z_untilrule;
 | 
				
			||||||
	zic_t		z_untiltime;
 | 
						zic_t		z_untiltime;
 | 
				
			||||||
@@ -131,20 +143,21 @@ static void inrule(char **fields, int nfields);
 | 
				
			|||||||
static bool inzcont(char **fields, int nfields);
 | 
					static bool inzcont(char **fields, int nfields);
 | 
				
			||||||
static bool inzone(char **fields, int nfields);
 | 
					static bool inzone(char **fields, int nfields);
 | 
				
			||||||
static bool inzsub(char **, int, bool);
 | 
					static bool inzsub(char **, int, bool);
 | 
				
			||||||
static int	itsdir(const char *name);
 | 
					static bool itsdir(char const *);
 | 
				
			||||||
 | 
					static bool itssymlink(char const *);
 | 
				
			||||||
static bool is_alpha(char a);
 | 
					static bool is_alpha(char a);
 | 
				
			||||||
static char lowerit(char);
 | 
					static char lowerit(char);
 | 
				
			||||||
static void mkdirs(char const *, bool);
 | 
					static void mkdirs(char const *, bool);
 | 
				
			||||||
static void newabbr(const char *abbr);
 | 
					static void newabbr(const char *abbr);
 | 
				
			||||||
static zic_t oadd(zic_t t1, zic_t t2);
 | 
					static zic_t oadd(zic_t t1, zic_t t2);
 | 
				
			||||||
static void outzone(const struct zone * zp, int ntzones);
 | 
					static void outzone(const struct zone * zp, ptrdiff_t ntzones);
 | 
				
			||||||
static zic_t rpytime(const struct rule * rp, zic_t wantedy);
 | 
					static zic_t rpytime(const struct rule * rp, zic_t wantedy);
 | 
				
			||||||
static void rulesub(struct rule * rp,
 | 
					static void rulesub(struct rule * rp,
 | 
				
			||||||
		const char *loyearp, const char *hiyearp,
 | 
							const char *loyearp, const char *hiyearp,
 | 
				
			||||||
		const char *typep, const char *monthp,
 | 
							const char *typep, const char *monthp,
 | 
				
			||||||
		const char *dayp, const char *timep);
 | 
							const char *dayp, const char *timep);
 | 
				
			||||||
static zic_t tadd(zic_t t1, zic_t t2);
 | 
					static zic_t tadd(zic_t t1, zic_t t2);
 | 
				
			||||||
static bool yearistype(int year, const char *type);
 | 
					static bool yearistype(zic_t year, const char *type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Bound on length of what %z can expand to.  */
 | 
					/* Bound on length of what %z can expand to.  */
 | 
				
			||||||
enum
 | 
					enum
 | 
				
			||||||
@@ -168,7 +181,7 @@ static int	leapcnt;
 | 
				
			|||||||
static bool leapseen;
 | 
					static bool leapseen;
 | 
				
			||||||
static zic_t leapminyear;
 | 
					static zic_t leapminyear;
 | 
				
			||||||
static zic_t leapmaxyear;
 | 
					static zic_t leapmaxyear;
 | 
				
			||||||
static int	linenum;
 | 
					static lineno linenum;
 | 
				
			||||||
static int	max_abbrvar_len = PERCENT_Z_LEN_BOUND;
 | 
					static int	max_abbrvar_len = PERCENT_Z_LEN_BOUND;
 | 
				
			||||||
static int	max_format_len;
 | 
					static int	max_format_len;
 | 
				
			||||||
static zic_t max_year;
 | 
					static zic_t max_year;
 | 
				
			||||||
@@ -177,10 +190,10 @@ static bool noise;
 | 
				
			|||||||
static bool print_abbrevs;
 | 
					static bool print_abbrevs;
 | 
				
			||||||
static zic_t print_cutoff;
 | 
					static zic_t print_cutoff;
 | 
				
			||||||
static const char *rfilename;
 | 
					static const char *rfilename;
 | 
				
			||||||
static int	rlinenum;
 | 
					static lineno rlinenum;
 | 
				
			||||||
static const char *progname;
 | 
					static const char *progname;
 | 
				
			||||||
static int	timecnt;
 | 
					static ptrdiff_t timecnt;
 | 
				
			||||||
static int	timecnt_alloc;
 | 
					static ptrdiff_t timecnt_alloc;
 | 
				
			||||||
static int	typecnt;
 | 
					static int	typecnt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -265,24 +278,24 @@ static int	typecnt;
 | 
				
			|||||||
#define YR_ONLY		2
 | 
					#define YR_ONLY		2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct rule *rules;
 | 
					static struct rule *rules;
 | 
				
			||||||
static int	nrules;				/* number of rules */
 | 
					static ptrdiff_t nrules;		/* number of rules */
 | 
				
			||||||
static int	nrules_alloc;
 | 
					static ptrdiff_t nrules_alloc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct zone *zones;
 | 
					static struct zone *zones;
 | 
				
			||||||
static int	nzones;				/* number of zones */
 | 
					static ptrdiff_t nzones;		/* number of zones */
 | 
				
			||||||
static int	nzones_alloc;
 | 
					static ptrdiff_t nzones_alloc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct link
 | 
					struct link
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char *l_filename;
 | 
						const char *l_filename;
 | 
				
			||||||
	int			l_linenum;
 | 
						lineno		l_linenum;
 | 
				
			||||||
	const char *l_from;
 | 
						const char *l_from;
 | 
				
			||||||
	const char *l_to;
 | 
						const char *l_to;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct link *links;
 | 
					static struct link *links;
 | 
				
			||||||
static int	nlinks;
 | 
					static ptrdiff_t nlinks;
 | 
				
			||||||
static int	nlinks_alloc;
 | 
					static ptrdiff_t nlinks_alloc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct lookup
 | 
					struct lookup
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -429,17 +442,18 @@ ecpyalloc(char const * str)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *
 | 
					static void *
 | 
				
			||||||
growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
 | 
					growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t * nitems_alloc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (nitems < *nitems_alloc)
 | 
						if (nitems < *nitems_alloc)
 | 
				
			||||||
		return ptr;
 | 
							return ptr;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int			nitems_max = INT_MAX - WORK_AROUND_QTBUG_53071;
 | 
							ptrdiff_t	nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
 | 
				
			||||||
 | 
							ptrdiff_t	amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((nitems_max - 1) / 3 * 2 < *nitems_alloc)
 | 
							if ((amax - 1) / 3 * 2 < *nitems_alloc)
 | 
				
			||||||
			memory_exhausted(_("int overflow"));
 | 
								memory_exhausted(_("integer overflow"));
 | 
				
			||||||
		*nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1;
 | 
							*nitems_alloc += (*nitems_alloc >> 1) + 1;
 | 
				
			||||||
		return erealloc(ptr, size_product(*nitems_alloc, itemsize));
 | 
							return erealloc(ptr, size_product(*nitems_alloc, itemsize));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -449,7 +463,7 @@ growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
eats(const char *name, int num, const char *rname, int rnum)
 | 
					eats(char const * name, lineno num, char const * rname, lineno rnum)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	filename = name;
 | 
						filename = name;
 | 
				
			||||||
	linenum = num;
 | 
						linenum = num;
 | 
				
			||||||
@@ -458,7 +472,7 @@ eats(const char *name, int num, const char *rname, int rnum)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
eat(const char *name, int num)
 | 
					eat(char const * name, lineno num)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	eats(name, num, NULL, -1);
 | 
						eats(name, num, NULL, -1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -471,10 +485,10 @@ verror(const char *string, va_list args)
 | 
				
			|||||||
	 * "*" -v on BSD systems.
 | 
						 * "*" -v on BSD systems.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (filename)
 | 
						if (filename)
 | 
				
			||||||
		fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
 | 
							fprintf(stderr, _("\"%s\", line %" PRIdLINENO ": "), filename, linenum);
 | 
				
			||||||
	vfprintf(stderr, string, args);
 | 
						vfprintf(stderr, string, args);
 | 
				
			||||||
	if (rfilename != NULL)
 | 
						if (rfilename != NULL)
 | 
				
			||||||
		fprintf(stderr, _(" (rule from \"%s\", line %d)"),
 | 
							fprintf(stderr, _(" (rule from \"%s\", line %" PRIdLINENO ")"),
 | 
				
			||||||
				rfilename, rlinenum);
 | 
									rfilename, rlinenum);
 | 
				
			||||||
	fprintf(stderr, "\n");
 | 
						fprintf(stderr, "\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -565,9 +579,10 @@ static const char *yitcommand;
 | 
				
			|||||||
int
 | 
					int
 | 
				
			||||||
main(int argc, char *argv[])
 | 
					main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int			i;
 | 
						int			c,
 | 
				
			||||||
	int			j;
 | 
									k;
 | 
				
			||||||
	int			c;
 | 
						ptrdiff_t	i,
 | 
				
			||||||
 | 
									j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef WIN32
 | 
					#ifndef WIN32
 | 
				
			||||||
	umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
 | 
						umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
 | 
				
			||||||
@@ -579,14 +594,14 @@ main(int argc, char *argv[])
 | 
				
			|||||||
				_("wild compilation-time specification of zic_t"));
 | 
									_("wild compilation-time specification of zic_t"));
 | 
				
			||||||
		return EXIT_FAILURE;
 | 
							return EXIT_FAILURE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for (i = 1; i < argc; ++i)
 | 
						for (k = 1; k < argc; k++)
 | 
				
			||||||
		if (strcmp(argv[i], "--version") == 0)
 | 
							if (strcmp(argv[k], "--version") == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			printf("zic %s\n", PG_VERSION);
 | 
								printf("zic %s\n", PG_VERSION);
 | 
				
			||||||
			close_file(stdout, NULL, NULL);
 | 
								close_file(stdout, NULL, NULL);
 | 
				
			||||||
			return EXIT_SUCCESS;
 | 
								return EXIT_SUCCESS;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (strcmp(argv[i], "--help") == 0)
 | 
							else if (strcmp(argv[k], "--help") == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			usage(stdout, EXIT_SUCCESS);
 | 
								usage(stdout, EXIT_SUCCESS);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -674,8 +689,8 @@ main(int argc, char *argv[])
 | 
				
			|||||||
		adjleap();
 | 
							adjleap();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = optind; i < argc; ++i)
 | 
						for (k = optind; k < argc; k++)
 | 
				
			||||||
		infile(argv[i]);
 | 
							infile(argv[k]);
 | 
				
			||||||
	if (errors)
 | 
						if (errors)
 | 
				
			||||||
		return EXIT_FAILURE;
 | 
							return EXIT_FAILURE;
 | 
				
			||||||
	associate();
 | 
						associate();
 | 
				
			||||||
@@ -725,7 +740,7 @@ componentcheck(char const * name, char const * component,
 | 
				
			|||||||
	enum
 | 
						enum
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	component_len_max = 14};
 | 
						component_len_max = 14};
 | 
				
			||||||
	size_t		component_len = component_end - component;
 | 
						ptrdiff_t	component_len = component_end - component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (component_len == 0)
 | 
						if (component_len == 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -743,8 +758,10 @@ componentcheck(char const * name, char const * component,
 | 
				
			|||||||
	if (0 < component_len && component_len <= 2
 | 
						if (0 < component_len && component_len <= 2
 | 
				
			||||||
		&& component[0] == '.' && component_end[-1] == '.')
 | 
							&& component[0] == '.' && component_end[-1] == '.')
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							int			len = component_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		error(_("file name '%s' contains '%.*s' component"),
 | 
							error(_("file name '%s' contains '%.*s' component"),
 | 
				
			||||||
			  name, (int) component_len, component);
 | 
								  name, len, component);
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (noise)
 | 
						if (noise)
 | 
				
			||||||
@@ -835,9 +852,9 @@ relname(char const * from, char const * to)
 | 
				
			|||||||
	for (i = 0; f[i] && f[i] == to[i]; i++)
 | 
						for (i = 0; f[i] && f[i] == to[i]; i++)
 | 
				
			||||||
		if (f[i] == '/')
 | 
							if (f[i] == '/')
 | 
				
			||||||
			dir_len = i + 1;
 | 
								dir_len = i + 1;
 | 
				
			||||||
	for (; f[i]; i++)
 | 
						for (; to[i]; i++)
 | 
				
			||||||
		dotdots += f[i] == '/' && f[i - 1] != '/';
 | 
							dotdots += to[i] == '/' && to[i - 1] != '/';
 | 
				
			||||||
	taillen = i - dir_len;
 | 
						taillen = strlen(f + dir_len);
 | 
				
			||||||
	dotdotetcsize = 3 * dotdots + taillen + 1;
 | 
						dotdotetcsize = 3 * dotdots + taillen + 1;
 | 
				
			||||||
	if (dotdotetcsize <= linksize)
 | 
						if (dotdotetcsize <= linksize)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -851,10 +868,19 @@ relname(char const * from, char const * to)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif   /* HAVE_SYMLINK */
 | 
					#endif   /* HAVE_SYMLINK */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Hard link FROM to TO, following any symbolic links.
 | 
				
			||||||
 | 
					   Return 0 if successful, an error number otherwise.  */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					hardlinkerr(char const * from, char const * to)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int			r = linkat(AT_FDCWD, from, AT_FDCWD, to, AT_SYMLINK_FOLLOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return r == 0 ? 0 : errno;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
dolink(char const * fromfield, char const * tofield, bool staysymlink)
 | 
					dolink(char const * fromfield, char const * tofield, bool staysymlink)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int			fromisdir;
 | 
					 | 
				
			||||||
	bool		todirs_made = false;
 | 
						bool		todirs_made = false;
 | 
				
			||||||
	int			link_errno;
 | 
						int			link_errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -862,17 +888,14 @@ dolink(char const * fromfield, char const * tofield, bool staysymlink)
 | 
				
			|||||||
	 * We get to be careful here since there's a fair chance of root running
 | 
						 * We get to be careful here since there's a fair chance of root running
 | 
				
			||||||
	 * us.
 | 
						 * us.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	fromisdir = itsdir(fromfield);
 | 
						if (itsdir(fromfield))
 | 
				
			||||||
	if (fromisdir)
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		char const *e = strerror(fromisdir < 0 ? errno : EPERM);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		fprintf(stderr, _("%s: link from %s/%s failed: %s\n"),
 | 
							fprintf(stderr, _("%s: link from %s/%s failed: %s\n"),
 | 
				
			||||||
				progname, directory, fromfield, e);
 | 
									progname, directory, fromfield, strerror(EPERM));
 | 
				
			||||||
		exit(EXIT_FAILURE);
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (staysymlink)
 | 
						if (staysymlink)
 | 
				
			||||||
		staysymlink = itsdir(tofield) == 2;
 | 
							staysymlink = itssymlink(tofield);
 | 
				
			||||||
	if (remove(tofield) == 0)
 | 
						if (remove(tofield) == 0)
 | 
				
			||||||
		todirs_made = true;
 | 
							todirs_made = true;
 | 
				
			||||||
	else if (errno != ENOENT)
 | 
						else if (errno != ENOENT)
 | 
				
			||||||
@@ -883,13 +906,12 @@ dolink(char const * fromfield, char const * tofield, bool staysymlink)
 | 
				
			|||||||
				progname, directory, tofield, e);
 | 
									progname, directory, tofield, e);
 | 
				
			||||||
		exit(EXIT_FAILURE);
 | 
							exit(EXIT_FAILURE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	link_errno = (staysymlink ? ENOTSUP
 | 
						link_errno = staysymlink ? ENOTSUP : hardlinkerr(fromfield, tofield);
 | 
				
			||||||
				  : link(fromfield, tofield) == 0 ? 0 : errno);
 | 
					 | 
				
			||||||
	if (link_errno == ENOENT && !todirs_made)
 | 
						if (link_errno == ENOENT && !todirs_made)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		mkdirs(tofield, true);
 | 
							mkdirs(tofield, true);
 | 
				
			||||||
		todirs_made = true;
 | 
							todirs_made = true;
 | 
				
			||||||
		link_errno = link(fromfield, tofield) == 0 ? 0 : errno;
 | 
							link_errno = hardlinkerr(fromfield, tofield);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (link_errno != 0)
 | 
						if (link_errno != 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -999,31 +1021,42 @@ static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332
 | 
				
			|||||||
								 ? BIG_BANG
 | 
													 ? BIG_BANG
 | 
				
			||||||
								 : MINVAL(zic_t, TIME_T_BITS_IN_FILE));
 | 
													 : MINVAL(zic_t, TIME_T_BITS_IN_FILE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Return 1 if NAME is a directory, 2 if a symbolic link, 0 if
 | 
					/* Return true if NAME is a directory.  */
 | 
				
			||||||
   something else, -1 (setting errno) if trouble.  */
 | 
					static bool
 | 
				
			||||||
static int
 | 
					 | 
				
			||||||
itsdir(char const * name)
 | 
					itsdir(char const * name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct stat st;
 | 
						struct stat st;
 | 
				
			||||||
	int			res = lstat(name, &st);
 | 
						int			res = stat(name, &st);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (res == 0)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
#ifdef S_ISDIR
 | 
					#ifdef S_ISDIR
 | 
				
			||||||
		return S_ISDIR(st.st_mode) ? 1 : S_ISLNK(st.st_mode) ? 2 : 0;
 | 
						if (res == 0)
 | 
				
			||||||
#else
 | 
							return S_ISDIR(st.st_mode) != 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						if (res == 0 || errno == EOVERFLOW)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		size_t		n = strlen(name);
 | 
							size_t		n = strlen(name);
 | 
				
			||||||
		char	   *nameslashdot = emalloc(n + 3);
 | 
							char	   *nameslashdot = emalloc(n + 3);
 | 
				
			||||||
		bool		dir;
 | 
							bool		dir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		memcpy(nameslashdot, name, n);
 | 
							memcpy(nameslashdot, name, n);
 | 
				
			||||||
		strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]);
 | 
							strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]);
 | 
				
			||||||
		dir = lstat(nameslashdot, &st) == 0;
 | 
							dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
 | 
				
			||||||
		free(nameslashdot);
 | 
							free(nameslashdot);
 | 
				
			||||||
		return dir;
 | 
							return dir;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return -1;
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Return true if NAME is a symbolic link.  */
 | 
				
			||||||
 | 
					static bool
 | 
				
			||||||
 | 
					itssymlink(char const * name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifdef HAVE_SYMLINK
 | 
				
			||||||
 | 
						char		c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0 <= readlink(name, &c, 1);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -1046,10 +1079,10 @@ associate(void)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct zone *zp;
 | 
						struct zone *zp;
 | 
				
			||||||
	struct rule *rp;
 | 
						struct rule *rp;
 | 
				
			||||||
	int			base,
 | 
						ptrdiff_t	i,
 | 
				
			||||||
 | 
									j,
 | 
				
			||||||
 | 
									base,
 | 
				
			||||||
				out;
 | 
									out;
 | 
				
			||||||
	int			i,
 | 
					 | 
				
			||||||
				j;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nrules != 0)
 | 
						if (nrules != 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -1136,7 +1169,7 @@ infile(const char *name)
 | 
				
			|||||||
	const struct lookup *lp;
 | 
						const struct lookup *lp;
 | 
				
			||||||
	int			nfields;
 | 
						int			nfields;
 | 
				
			||||||
	bool		wantcont;
 | 
						bool		wantcont;
 | 
				
			||||||
	int			num;
 | 
						lineno		num;
 | 
				
			||||||
	char		buf[BUFSIZ];
 | 
						char		buf[BUFSIZ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (strcmp(name, "-") == 0)
 | 
						if (strcmp(name, "-") == 0)
 | 
				
			||||||
@@ -1187,7 +1220,7 @@ infile(const char *name)
 | 
				
			|||||||
			if (lp == NULL)
 | 
								if (lp == NULL)
 | 
				
			||||||
				error(_("input line of unknown type"));
 | 
									error(_("input line of unknown type"));
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				switch ((int) (lp->l_value))
 | 
									switch (lp->l_value)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					case LC_RULE:
 | 
										case LC_RULE:
 | 
				
			||||||
						inrule(fields, nfields);
 | 
											inrule(fields, nfields);
 | 
				
			||||||
@@ -1314,7 +1347,7 @@ inrule(char **fields, int nfields)
 | 
				
			|||||||
static bool
 | 
					static bool
 | 
				
			||||||
inzone(char **fields, int nfields)
 | 
					inzone(char **fields, int nfields)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int			i;
 | 
						ptrdiff_t	i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS)
 | 
						if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -1339,8 +1372,8 @@ inzone(char **fields, int nfields)
 | 
				
			|||||||
		if (zones[i].z_name != NULL &&
 | 
							if (zones[i].z_name != NULL &&
 | 
				
			||||||
			strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
 | 
								strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			error(
 | 
								error(_("duplicate zone name %s"
 | 
				
			||||||
				  _("duplicate zone name %s (file \"%s\", line %d)"),
 | 
										" (file \"%s\", line %" PRIdLINENO ")"),
 | 
				
			||||||
				  fields[ZF_NAME],
 | 
									  fields[ZF_NAME],
 | 
				
			||||||
				  zones[i].z_filename,
 | 
									  zones[i].z_filename,
 | 
				
			||||||
				  zones[i].z_linenum);
 | 
									  zones[i].z_linenum);
 | 
				
			||||||
@@ -1464,7 +1497,7 @@ inleap(char **fields, int nfields)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	const char *cp;
 | 
						const char *cp;
 | 
				
			||||||
	const struct lookup *lp;
 | 
						const struct lookup *lp;
 | 
				
			||||||
	int			i,
 | 
						zic_t		i,
 | 
				
			||||||
				j;
 | 
									j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* PG: make year be int not zic_t to avoid sscanf portability issues */
 | 
						/* PG: make year be int not zic_t to avoid sscanf portability issues */
 | 
				
			||||||
@@ -1671,7 +1704,7 @@ rulesub(struct rule * rp, const char *loyearp, const char *hiyearp,
 | 
				
			|||||||
	lp = byword(cp, begin_years);
 | 
						lp = byword(cp, begin_years);
 | 
				
			||||||
	rp->r_lowasnum = lp == NULL;
 | 
						rp->r_lowasnum = lp == NULL;
 | 
				
			||||||
	if (!rp->r_lowasnum)
 | 
						if (!rp->r_lowasnum)
 | 
				
			||||||
		switch ((int) lp->l_value)
 | 
							switch (lp->l_value)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			case YR_MINIMUM:
 | 
								case YR_MINIMUM:
 | 
				
			||||||
				rp->r_loyear = ZIC_MIN;
 | 
									rp->r_loyear = ZIC_MIN;
 | 
				
			||||||
@@ -1696,7 +1729,7 @@ rulesub(struct rule * rp, const char *loyearp, const char *hiyearp,
 | 
				
			|||||||
	lp = byword(cp, end_years);
 | 
						lp = byword(cp, end_years);
 | 
				
			||||||
	rp->r_hiwasnum = lp == NULL;
 | 
						rp->r_hiwasnum = lp == NULL;
 | 
				
			||||||
	if (!rp->r_hiwasnum)
 | 
						if (!rp->r_hiwasnum)
 | 
				
			||||||
		switch ((int) lp->l_value)
 | 
							switch (lp->l_value)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			case YR_MINIMUM:
 | 
								case YR_MINIMUM:
 | 
				
			||||||
				rp->r_hiyear = ZIC_MIN;
 | 
									rp->r_hiyear = ZIC_MIN;
 | 
				
			||||||
@@ -1846,11 +1879,11 @@ static void
 | 
				
			|||||||
writezone(const char *const name, const char *const string, char version)
 | 
					writezone(const char *const name, const char *const string, char version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	FILE	   *fp;
 | 
						FILE	   *fp;
 | 
				
			||||||
	int			i,
 | 
						ptrdiff_t	i,
 | 
				
			||||||
				j;
 | 
									j;
 | 
				
			||||||
	int			leapcnt32,
 | 
						int			leapcnt32,
 | 
				
			||||||
				leapi32;
 | 
									leapi32;
 | 
				
			||||||
	int			timecnt32,
 | 
						ptrdiff_t	timecnt32,
 | 
				
			||||||
				timei32;
 | 
									timei32;
 | 
				
			||||||
	int			pass;
 | 
						int			pass;
 | 
				
			||||||
	static const struct tzhead tzh0;
 | 
						static const struct tzhead tzh0;
 | 
				
			||||||
@@ -1858,7 +1891,7 @@ writezone(const char *const name, const char *const string, char version)
 | 
				
			|||||||
	bool		dir_checked = false;
 | 
						bool		dir_checked = false;
 | 
				
			||||||
	zic_t		one = 1;
 | 
						zic_t		one = 1;
 | 
				
			||||||
	zic_t		y2038_boundary = one << 31;
 | 
						zic_t		y2038_boundary = one << 31;
 | 
				
			||||||
	int			nats = timecnt + WORK_AROUND_QTBUG_53071;
 | 
						ptrdiff_t	nats = timecnt + WORK_AROUND_QTBUG_53071;
 | 
				
			||||||
	zic_t	   *ats = emalloc(size_product(nats, sizeof *ats + 1));
 | 
						zic_t	   *ats = emalloc(size_product(nats, sizeof *ats + 1));
 | 
				
			||||||
	void	   *typesptr = ats + nats;
 | 
						void	   *typesptr = ats + nats;
 | 
				
			||||||
	unsigned char *types = typesptr;
 | 
						unsigned char *types = typesptr;
 | 
				
			||||||
@@ -1873,8 +1906,8 @@ writezone(const char *const name, const char *const string, char version)
 | 
				
			|||||||
	 * Optimize.
 | 
						 * Optimize.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int			fromi;
 | 
							ptrdiff_t	fromi,
 | 
				
			||||||
		int			toi;
 | 
										toi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		toi = 0;
 | 
							toi = 0;
 | 
				
			||||||
		fromi = 0;
 | 
							fromi = 0;
 | 
				
			||||||
@@ -1898,9 +1931,17 @@ writezone(const char *const name, const char *const string, char version)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		timecnt = toi;
 | 
							timecnt = toi;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (noise && timecnt > 1200)
 | 
						if (noise && timecnt > 1200)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (timecnt > TZ_MAX_TIMES)
 | 
				
			||||||
 | 
								warning(_("reference clients mishandle"
 | 
				
			||||||
 | 
										  " more than %d transition times"),
 | 
				
			||||||
 | 
										TZ_MAX_TIMES);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
			warning(_("pre-2014 clients may mishandle"
 | 
								warning(_("pre-2014 clients may mishandle"
 | 
				
			||||||
					  " more than 1200 transition times"));
 | 
										  " more than 1200 transition times"));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Transfer.
 | 
						 * Transfer.
 | 
				
			||||||
@@ -2003,23 +2044,25 @@ writezone(const char *const name, const char *const string, char version)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	for (pass = 1; pass <= 2; ++pass)
 | 
						for (pass = 1; pass <= 2; ++pass)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int			thistimei,
 | 
							ptrdiff_t	thistimei,
 | 
				
			||||||
					thistimecnt;
 | 
										thistimecnt,
 | 
				
			||||||
 | 
										thistimelim;
 | 
				
			||||||
		int			thisleapi,
 | 
							int			thisleapi,
 | 
				
			||||||
					thisleapcnt;
 | 
										thisleapcnt,
 | 
				
			||||||
		int			thistimelim,
 | 
					 | 
				
			||||||
					thisleaplim;
 | 
										thisleaplim;
 | 
				
			||||||
		int			writetype[TZ_MAX_TYPES];
 | 
							int			writetype[TZ_MAX_TYPES];
 | 
				
			||||||
		int			typemap[TZ_MAX_TYPES];
 | 
							int			typemap[TZ_MAX_TYPES];
 | 
				
			||||||
		int			thistypecnt;
 | 
							int			thistypecnt;
 | 
				
			||||||
		char		thischars[TZ_MAX_CHARS];
 | 
							char		thischars[TZ_MAX_CHARS];
 | 
				
			||||||
		char		thischarcnt;
 | 
							int			thischarcnt;
 | 
				
			||||||
 | 
							bool		toomanytimes;
 | 
				
			||||||
		int			indmap[TZ_MAX_CHARS];
 | 
							int			indmap[TZ_MAX_CHARS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (pass == 1)
 | 
							if (pass == 1)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			thistimei = timei32;
 | 
								thistimei = timei32;
 | 
				
			||||||
			thistimecnt = timecnt32;
 | 
								thistimecnt = timecnt32;
 | 
				
			||||||
 | 
								toomanytimes = thistimecnt >> 31 >> 1 != 0;
 | 
				
			||||||
			thisleapi = leapi32;
 | 
								thisleapi = leapi32;
 | 
				
			||||||
			thisleapcnt = leapcnt32;
 | 
								thisleapcnt = leapcnt32;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -2027,9 +2070,12 @@ writezone(const char *const name, const char *const string, char version)
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			thistimei = 0;
 | 
								thistimei = 0;
 | 
				
			||||||
			thistimecnt = timecnt;
 | 
								thistimecnt = timecnt;
 | 
				
			||||||
 | 
								toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
 | 
				
			||||||
			thisleapi = 0;
 | 
								thisleapi = 0;
 | 
				
			||||||
			thisleapcnt = leapcnt;
 | 
								thisleapcnt = leapcnt;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if (toomanytimes)
 | 
				
			||||||
 | 
								error(_("too many transition times"));
 | 
				
			||||||
		thistimelim = thistimei + thistimecnt;
 | 
							thistimelim = thistimei + thistimecnt;
 | 
				
			||||||
		thisleaplim = thisleapi + thisleapcnt;
 | 
							thisleaplim = thisleapi + thisleapcnt;
 | 
				
			||||||
		for (i = 0; i < typecnt; ++i)
 | 
							for (i = 0; i < typecnt; ++i)
 | 
				
			||||||
@@ -2130,8 +2176,7 @@ writezone(const char *const name, const char *const string, char version)
 | 
				
			|||||||
					break;
 | 
										break;
 | 
				
			||||||
			if (j == thischarcnt)
 | 
								if (j == thischarcnt)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				strcpy(&thischars[(int) thischarcnt],
 | 
									strcpy(&thischars[thischarcnt], thisabbr);
 | 
				
			||||||
					   thisabbr);
 | 
					 | 
				
			||||||
				thischarcnt += strlen(thisabbr) + 1;
 | 
									thischarcnt += strlen(thisabbr) + 1;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			indmap[abbrinds[i]] = j;
 | 
								indmap[abbrinds[i]] = j;
 | 
				
			||||||
@@ -2478,13 +2523,13 @@ enum
 | 
				
			|||||||
YEAR_BY_YEAR_ZONE = 1};
 | 
					YEAR_BY_YEAR_ZONE = 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
stringzone(char *result, const struct zone * const zpfirst, const int zonecount)
 | 
					stringzone(char *result, struct zone const * zpfirst, ptrdiff_t zonecount)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct zone *zp;
 | 
						const struct zone *zp;
 | 
				
			||||||
	struct rule *rp;
 | 
						struct rule *rp;
 | 
				
			||||||
	struct rule *stdrp;
 | 
						struct rule *stdrp;
 | 
				
			||||||
	struct rule *dstrp;
 | 
						struct rule *dstrp;
 | 
				
			||||||
	int			i;
 | 
						ptrdiff_t	i;
 | 
				
			||||||
	const char *abbrvar;
 | 
						const char *abbrvar;
 | 
				
			||||||
	int			compat = 0;
 | 
						int			compat = 0;
 | 
				
			||||||
	int			c;
 | 
						int			c;
 | 
				
			||||||
@@ -2613,11 +2658,11 @@ stringzone(char *result, const struct zone * const zpfirst, const int zonecount)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
outzone(const struct zone * zpfirst, int zonecount)
 | 
					outzone(const struct zone * zpfirst, ptrdiff_t zonecount)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct zone *zp;
 | 
						const struct zone *zp;
 | 
				
			||||||
	struct rule *rp;
 | 
						struct rule *rp;
 | 
				
			||||||
	int			i,
 | 
						ptrdiff_t	i,
 | 
				
			||||||
				j;
 | 
									j;
 | 
				
			||||||
	bool		usestart,
 | 
						bool		usestart,
 | 
				
			||||||
				useuntil;
 | 
									useuntil;
 | 
				
			||||||
@@ -2639,7 +2684,7 @@ outzone(const struct zone * zpfirst, int zonecount)
 | 
				
			|||||||
	int			compat;
 | 
						int			compat;
 | 
				
			||||||
	bool		do_extend;
 | 
						bool		do_extend;
 | 
				
			||||||
	char		version;
 | 
						char		version;
 | 
				
			||||||
	int			lastatmax = -1;
 | 
						ptrdiff_t	lastatmax = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	max_abbr_len = 2 + max_format_len + max_abbrvar_len;
 | 
						max_abbr_len = 2 + max_format_len + max_abbrvar_len;
 | 
				
			||||||
	max_envvar_len = 2 * max_abbr_len + 5 * 9;
 | 
						max_envvar_len = 2 * max_abbr_len + 5 * 9;
 | 
				
			||||||
@@ -2808,7 +2853,7 @@ outzone(const struct zone * zpfirst, int zonecount)
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				for (;;)
 | 
									for (;;)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					int			k;
 | 
										ptrdiff_t	k;
 | 
				
			||||||
					zic_t		jtime,
 | 
										zic_t		jtime,
 | 
				
			||||||
								ktime = 0;
 | 
													ktime = 0;
 | 
				
			||||||
					zic_t		offset;
 | 
										zic_t		offset;
 | 
				
			||||||
@@ -3103,29 +3148,51 @@ adjleap(void)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool
 | 
					static char *
 | 
				
			||||||
yearistype(int year, const char *type)
 | 
					shellquote(char *b, char const * s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static char *buf;
 | 
						*b++ = '\'';
 | 
				
			||||||
 | 
						while (*s)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (*s == '\'')
 | 
				
			||||||
 | 
								*b++ = '\'', *b++ = '\\', *b++ = '\'';
 | 
				
			||||||
 | 
							*b++ = *s++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*b++ = '\'';
 | 
				
			||||||
 | 
						return b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool
 | 
				
			||||||
 | 
					yearistype(zic_t year, const char *type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char	   *buf;
 | 
				
			||||||
 | 
						char	   *b;
 | 
				
			||||||
	int			result;
 | 
						int			result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (type == NULL || *type == '\0')
 | 
						if (type == NULL || *type == '\0')
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type));
 | 
						buf = emalloc(1 + 4 * strlen(yitcommand) + 2
 | 
				
			||||||
	sprintf(buf, "%s %d %s", yitcommand, year, type);
 | 
									  + INT_STRLEN_MAXIMUM(zic_t) +2 + 4 * strlen(type) + 2);
 | 
				
			||||||
 | 
						b = shellquote(buf, yitcommand);
 | 
				
			||||||
 | 
						*b++ = ' ';
 | 
				
			||||||
 | 
						b += sprintf(b, INT64_FORMAT, year);
 | 
				
			||||||
 | 
						*b++ = ' ';
 | 
				
			||||||
 | 
						b = shellquote(b, type);
 | 
				
			||||||
 | 
						*b = '\0';
 | 
				
			||||||
	result = system(buf);
 | 
						result = system(buf);
 | 
				
			||||||
	if (WIFEXITED(result))
 | 
						if (WIFEXITED(result))
 | 
				
			||||||
		switch (WEXITSTATUS(result))
 | 
					 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
			case 0:
 | 
							int			status = WEXITSTATUS(result);
 | 
				
			||||||
				return true;
 | 
					
 | 
				
			||||||
			case 1:
 | 
							if (status <= 1)
 | 
				
			||||||
				return false;
 | 
							{
 | 
				
			||||||
 | 
								free(buf);
 | 
				
			||||||
 | 
								return status == 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	error(_("Wild result from command execution"));
 | 
						error(_("Wild result from command execution"));
 | 
				
			||||||
	fprintf(stderr, _("%s: command was '%s', result was %d\n"),
 | 
						fprintf(stderr, _("%s: command was '%s', result was %d\n"),
 | 
				
			||||||
			progname, buf, result);
 | 
								progname, buf, result);
 | 
				
			||||||
	for (;;)
 | 
					 | 
				
			||||||
	exit(EXIT_FAILURE);
 | 
						exit(EXIT_FAILURE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -3360,7 +3427,7 @@ getfields(char *cp)
 | 
				
			|||||||
					else
 | 
										else
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						error(_("Odd number of quotation marks"));
 | 
											error(_("Odd number of quotation marks"));
 | 
				
			||||||
						exit(1);
 | 
											exit(EXIT_FAILURE);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
		} while (*cp && *cp != '#' && !is_space(*cp));
 | 
							} while (*cp && *cp != '#' && !is_space(*cp));
 | 
				
			||||||
		if (is_space(*cp))
 | 
							if (is_space(*cp))
 | 
				
			||||||
@@ -3549,7 +3616,8 @@ newabbr(const char *string)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Ensure that the directories of ARGNAME exist, by making any missing
 | 
					/* Ensure that the directories of ARGNAME exist, by making any missing
 | 
				
			||||||
   ones.  If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
 | 
					   ones.  If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
 | 
				
			||||||
   do it for ARGNAME too.  Exit with failure if there is trouble.  */
 | 
					   do it for ARGNAME too.  Exit with failure if there is trouble.
 | 
				
			||||||
 | 
					   Do not consider an existing non-directory to be trouble.  */
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
mkdirs(char const * argname, bool ancestors)
 | 
					mkdirs(char const * argname, bool ancestors)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -3581,7 +3649,7 @@ mkdirs(char const * argname, bool ancestors)
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			int			err = errno;
 | 
								int			err = errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (err != EEXIST && itsdir(name) < 0)
 | 
								if (err != EEXIST && !itsdir(name))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				error(_("%s: Cannot create directory %s: %s"),
 | 
									error(_("%s: Cannot create directory %s: %s"),
 | 
				
			||||||
					  progname, name, strerror(err));
 | 
										  progname, name, strerror(err));
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user