diff --git a/src/timezone/zic.c b/src/timezone/zic.c
index 6121337..d24d4d2 100644
--- a/src/timezone/zic.c
+++ b/src/timezone/zic.c
@@ -11,9 +11,11 @@
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #endif
+#include <fcntl.h>
 #include <locale.h>
 #include <sys/stat.h>
 #include <time.h>
+#include <unistd.h>
 
 extern int	optind;
 extern char *optarg;
@@ -44,14 +46,24 @@ typedef int64 zic_t;
 #define MKDIR_UMASK 0755
 #endif
 #endif
-#ifndef S_ISLNK
-#define S_ISLNK(m) 0
+#ifndef AT_SYMLINK_FOLLOW
+#define linkat(fromdir, from, todir, to, flag) \
+	(itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to))
 #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
 {
 	const char *r_filename;
-	int			r_linenum;
+	lineno		r_linenum;
 	const char *r_name;
 
 	zic_t		r_loyear;		/* for example, 1986 */
@@ -73,7 +85,7 @@ struct rule
 	zic_t		r_stdoff;		/* offset from standard time */
 	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 */
 };
 
@@ -88,7 +100,7 @@ struct rule
 struct zone
 {
 	const char *z_filename;
-	int			z_linenum;
+	lineno		z_linenum;
 
 	const char *z_name;
 	zic_t		z_gmtoff;
@@ -99,7 +111,7 @@ struct zone
 	zic_t		z_stdoff;
 
 	struct rule *z_rules;
-	int			z_nrules;
+	ptrdiff_t	z_nrules;
 
 	struct rule z_untilrule;
 	zic_t		z_untiltime;
@@ -131,20 +143,21 @@ static void inrule(char **fields, int nfields);
 static bool inzcont(char **fields, int nfields);
 static bool inzone(char **fields, int nfields);
 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 char lowerit(char);
 static void mkdirs(char const *, bool);
 static void newabbr(const char *abbr);
 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 void rulesub(struct rule * rp,
 		const char *loyearp, const char *hiyearp,
 		const char *typep, const char *monthp,
 		const char *dayp, const char *timep);
 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.  */
 enum
@@ -168,7 +181,7 @@ static int	leapcnt;
 static bool leapseen;
 static zic_t leapminyear;
 static zic_t leapmaxyear;
-static int	linenum;
+static lineno linenum;
 static int	max_abbrvar_len = PERCENT_Z_LEN_BOUND;
 static int	max_format_len;
 static zic_t max_year;
@@ -177,10 +190,10 @@ static bool noise;
 static bool print_abbrevs;
 static zic_t print_cutoff;
 static const char *rfilename;
-static int	rlinenum;
+static lineno rlinenum;
 static const char *progname;
-static int	timecnt;
-static int	timecnt_alloc;
+static ptrdiff_t timecnt;
+static ptrdiff_t timecnt_alloc;
 static int	typecnt;
 
 /*
@@ -265,24 +278,24 @@ static int	typecnt;
 #define YR_ONLY		2
 
 static struct rule *rules;
-static int	nrules;				/* number of rules */
-static int	nrules_alloc;
+static ptrdiff_t nrules;		/* number of rules */
+static ptrdiff_t nrules_alloc;
 
 static struct zone *zones;
-static int	nzones;				/* number of zones */
-static int	nzones_alloc;
+static ptrdiff_t nzones;		/* number of zones */
+static ptrdiff_t nzones_alloc;
 
 struct link
 {
 	const char *l_filename;
-	int			l_linenum;
+	lineno		l_linenum;
 	const char *l_from;
 	const char *l_to;
 };
 
 static struct link *links;
-static int	nlinks;
-static int	nlinks_alloc;
+static ptrdiff_t nlinks;
+static ptrdiff_t nlinks_alloc;
 
 struct lookup
 {
@@ -429,17 +442,18 @@ ecpyalloc(char const * str)
 }
 
 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)
 		return ptr;
 	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)
-			memory_exhausted(_("int overflow"));
-		*nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1;
+		if ((amax - 1) / 3 * 2 < *nitems_alloc)
+			memory_exhausted(_("integer overflow"));
+		*nitems_alloc += (*nitems_alloc >> 1) + 1;
 		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
-eats(const char *name, int num, const char *rname, int rnum)
+eats(char const * name, lineno num, char const * rname, lineno rnum)
 {
 	filename = name;
 	linenum = num;
@@ -458,7 +472,7 @@ eats(const char *name, int num, const char *rname, int rnum)
 }
 
 static void
-eat(const char *name, int num)
+eat(char const * name, lineno num)
 {
 	eats(name, num, NULL, -1);
 }
@@ -471,10 +485,10 @@ verror(const char *string, va_list args)
 	 * "*" -v on BSD systems.
 	 */
 	if (filename)
-		fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
+		fprintf(stderr, _("\"%s\", line %" PRIdLINENO ": "), filename, linenum);
 	vfprintf(stderr, string, args);
 	if (rfilename != NULL)
-		fprintf(stderr, _(" (rule from \"%s\", line %d)"),
+		fprintf(stderr, _(" (rule from \"%s\", line %" PRIdLINENO ")"),
 				rfilename, rlinenum);
 	fprintf(stderr, "\n");
 }
@@ -565,9 +579,10 @@ static const char *yitcommand;
 int
 main(int argc, char *argv[])
 {
-	int			i;
-	int			j;
-	int			c;
+	int			c,
+				k;
+	ptrdiff_t	i,
+				j;
 
 #ifndef WIN32
 	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"));
 		return EXIT_FAILURE;
 	}
-	for (i = 1; i < argc; ++i)
-		if (strcmp(argv[i], "--version") == 0)
+	for (k = 1; k < argc; k++)
+		if (strcmp(argv[k], "--version") == 0)
 		{
 			printf("zic %s\n", PG_VERSION);
 			close_file(stdout, NULL, NULL);
 			return EXIT_SUCCESS;
 		}
-		else if (strcmp(argv[i], "--help") == 0)
+		else if (strcmp(argv[k], "--help") == 0)
 		{
 			usage(stdout, EXIT_SUCCESS);
 		}
@@ -674,8 +689,8 @@ main(int argc, char *argv[])
 		adjleap();
 	}
 
-	for (i = optind; i < argc; ++i)
-		infile(argv[i]);
+	for (k = optind; k < argc; k++)
+		infile(argv[k]);
 	if (errors)
 		return EXIT_FAILURE;
 	associate();
@@ -725,7 +740,7 @@ componentcheck(char const * name, char const * component,
 	enum
 	{
 	component_len_max = 14};
-	size_t		component_len = component_end - component;
+	ptrdiff_t	component_len = component_end - component;
 
 	if (component_len == 0)
 	{
@@ -743,8 +758,10 @@ componentcheck(char const * name, char const * component,
 	if (0 < component_len && component_len <= 2
 		&& component[0] == '.' && component_end[-1] == '.')
 	{
+		int			len = component_len;
+
 		error(_("file name '%s' contains '%.*s' component"),
-			  name, (int) component_len, component);
+			  name, len, component);
 		return false;
 	}
 	if (noise)
@@ -835,9 +852,9 @@ relname(char const * from, char const * to)
 	for (i = 0; f[i] && f[i] == to[i]; i++)
 		if (f[i] == '/')
 			dir_len = i + 1;
-	for (; f[i]; i++)
-		dotdots += f[i] == '/' && f[i - 1] != '/';
-	taillen = i - dir_len;
+	for (; to[i]; i++)
+		dotdots += to[i] == '/' && to[i - 1] != '/';
+	taillen = strlen(f + dir_len);
 	dotdotetcsize = 3 * dotdots + taillen + 1;
 	if (dotdotetcsize <= linksize)
 	{
@@ -851,10 +868,19 @@ relname(char const * from, char const * to)
 }
 #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
 dolink(char const * fromfield, char const * tofield, bool staysymlink)
 {
-	int			fromisdir;
 	bool		todirs_made = false;
 	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
 	 * us.
 	 */
-	fromisdir = itsdir(fromfield);
-	if (fromisdir)
+	if (itsdir(fromfield))
 	{
-		char const *e = strerror(fromisdir < 0 ? errno : EPERM);
-
 		fprintf(stderr, _("%s: link from %s/%s failed: %s\n"),
-				progname, directory, fromfield, e);
+				progname, directory, fromfield, strerror(EPERM));
 		exit(EXIT_FAILURE);
 	}
 	if (staysymlink)
-		staysymlink = itsdir(tofield) == 2;
+		staysymlink = itssymlink(tofield);
 	if (remove(tofield) == 0)
 		todirs_made = true;
 	else if (errno != ENOENT)
@@ -883,13 +906,12 @@ dolink(char const * fromfield, char const * tofield, bool staysymlink)
 				progname, directory, tofield, e);
 		exit(EXIT_FAILURE);
 	}
-	link_errno = (staysymlink ? ENOTSUP
-				  : link(fromfield, tofield) == 0 ? 0 : errno);
+	link_errno = staysymlink ? ENOTSUP : hardlinkerr(fromfield, tofield);
 	if (link_errno == ENOENT && !todirs_made)
 	{
 		mkdirs(tofield, true);
 		todirs_made = true;
-		link_errno = link(fromfield, tofield) == 0 ? 0 : errno;
+		link_errno = hardlinkerr(fromfield, tofield);
 	}
 	if (link_errno != 0)
 	{
@@ -997,31 +1019,42 @@ static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332
 								 ? BIG_BANG
 								 : MINVAL(zic_t, TIME_T_BITS_IN_FILE));
 
-/* Return 1 if NAME is a directory, 2 if a symbolic link, 0 if
-   something else, -1 (setting errno) if trouble.  */
-static int
+/* Return true if NAME is a directory.  */
+static bool
 itsdir(char const * name)
 {
 	struct stat st;
-	int			res = lstat(name, &st);
-
+	int			res = stat(name, &st);
+#ifdef S_ISDIR
 	if (res == 0)
+		return S_ISDIR(st.st_mode) != 0;
+#endif
+	if (res == 0 || errno == EOVERFLOW)
 	{
-#ifdef S_ISDIR
-		return S_ISDIR(st.st_mode) ? 1 : S_ISLNK(st.st_mode) ? 2 : 0;
-#else
 		size_t		n = strlen(name);
 		char	   *nameslashdot = emalloc(n + 3);
 		bool		dir;
 
 		memcpy(nameslashdot, name, n);
 		strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]);
-		dir = lstat(nameslashdot, &st) == 0;
+		dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
 		free(nameslashdot);
 		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
 }
 
 /*
@@ -1044,10 +1077,10 @@ associate(void)
 {
 	struct zone *zp;
 	struct rule *rp;
-	int			base,
+	ptrdiff_t	i,
+				j,
+				base,
 				out;
-	int			i,
-				j;
 
 	if (nrules != 0)
 	{
@@ -1134,7 +1167,7 @@ infile(const char *name)
 	const struct lookup *lp;
 	int			nfields;
 	bool		wantcont;
-	int			num;
+	lineno		num;
 	char		buf[BUFSIZ];
 
 	if (strcmp(name, "-") == 0)
@@ -1185,7 +1218,7 @@ infile(const char *name)
 			if (lp == NULL)
 				error(_("input line of unknown type"));
 			else
-				switch ((int) (lp->l_value))
+				switch (lp->l_value)
 				{
 					case LC_RULE:
 						inrule(fields, nfields);
@@ -1312,7 +1345,7 @@ inrule(char **fields, int nfields)
 static bool
 inzone(char **fields, int nfields)
 {
-	int			i;
+	ptrdiff_t	i;
 
 	if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS)
 	{
@@ -1337,8 +1370,8 @@ inzone(char **fields, int nfields)
 		if (zones[i].z_name != NULL &&
 			strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
 		{
-			error(
-				  _("duplicate zone name %s (file \"%s\", line %d)"),
+			error(_("duplicate zone name %s"
+					" (file \"%s\", line %" PRIdLINENO ")"),
 				  fields[ZF_NAME],
 				  zones[i].z_filename,
 				  zones[i].z_linenum);
@@ -1462,7 +1495,7 @@ inleap(char **fields, int nfields)
 {
 	const char *cp;
 	const struct lookup *lp;
-	int			i,
+	zic_t		i,
 				j;
 
 	/* PG: make year be int not zic_t to avoid sscanf portability issues */
@@ -1669,7 +1702,7 @@ rulesub(struct rule * rp, const char *loyearp, const char *hiyearp,
 	lp = byword(cp, begin_years);
 	rp->r_lowasnum = lp == NULL;
 	if (!rp->r_lowasnum)
-		switch ((int) lp->l_value)
+		switch (lp->l_value)
 		{
 			case YR_MINIMUM:
 				rp->r_loyear = ZIC_MIN;
@@ -1694,7 +1727,7 @@ rulesub(struct rule * rp, const char *loyearp, const char *hiyearp,
 	lp = byword(cp, end_years);
 	rp->r_hiwasnum = lp == NULL;
 	if (!rp->r_hiwasnum)
-		switch ((int) lp->l_value)
+		switch (lp->l_value)
 		{
 			case YR_MINIMUM:
 				rp->r_hiyear = ZIC_MIN;
@@ -1844,11 +1877,11 @@ static void
 writezone(const char *const name, const char *const string, char version)
 {
 	FILE	   *fp;
-	int			i,
+	ptrdiff_t	i,
 				j;
 	int			leapcnt32,
 				leapi32;
-	int			timecnt32,
+	ptrdiff_t	timecnt32,
 				timei32;
 	int			pass;
 	static const struct tzhead tzh0;
@@ -1856,7 +1889,7 @@ writezone(const char *const name, const char *const string, char version)
 	bool		dir_checked = false;
 	zic_t		one = 1;
 	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));
 	void	   *typesptr = ats + nats;
 	unsigned char *types = typesptr;
@@ -1871,8 +1904,8 @@ writezone(const char *const name, const char *const string, char version)
 	 * Optimize.
 	 */
 	{
-		int			fromi;
-		int			toi;
+		ptrdiff_t	fromi,
+					toi;
 
 		toi = 0;
 		fromi = 0;
@@ -1896,9 +1929,17 @@ writezone(const char *const name, const char *const string, char version)
 		}
 		timecnt = toi;
 	}
+
 	if (noise && timecnt > 1200)
-		warning(_("pre-2014 clients may mishandle"
-				  " more than 1200 transition times"));
+	{
+		if (timecnt > TZ_MAX_TIMES)
+			warning(_("reference clients mishandle"
+					  " more than %d transition times"),
+					TZ_MAX_TIMES);
+		else
+			warning(_("pre-2014 clients may mishandle"
+					  " more than 1200 transition times"));
+	}
 
 	/*
 	 * Transfer.
@@ -2001,23 +2042,25 @@ writezone(const char *const name, const char *const string, char version)
 	}
 	for (pass = 1; pass <= 2; ++pass)
 	{
-		int			thistimei,
-					thistimecnt;
+		ptrdiff_t	thistimei,
+					thistimecnt,
+					thistimelim;
 		int			thisleapi,
-					thisleapcnt;
-		int			thistimelim,
+					thisleapcnt,
 					thisleaplim;
 		int			writetype[TZ_MAX_TYPES];
 		int			typemap[TZ_MAX_TYPES];
 		int			thistypecnt;
 		char		thischars[TZ_MAX_CHARS];
-		char		thischarcnt;
+		int			thischarcnt;
+		bool		toomanytimes;
 		int			indmap[TZ_MAX_CHARS];
 
 		if (pass == 1)
 		{
 			thistimei = timei32;
 			thistimecnt = timecnt32;
+			toomanytimes = thistimecnt >> 31 >> 1 != 0;
 			thisleapi = leapi32;
 			thisleapcnt = leapcnt32;
 		}
@@ -2025,9 +2068,12 @@ writezone(const char *const name, const char *const string, char version)
 		{
 			thistimei = 0;
 			thistimecnt = timecnt;
+			toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
 			thisleapi = 0;
 			thisleapcnt = leapcnt;
 		}
+		if (toomanytimes)
+			error(_("too many transition times"));
 		thistimelim = thistimei + thistimecnt;
 		thisleaplim = thisleapi + thisleapcnt;
 		for (i = 0; i < typecnt; ++i)
@@ -2128,8 +2174,7 @@ writezone(const char *const name, const char *const string, char version)
 					break;
 			if (j == thischarcnt)
 			{
-				strcpy(&thischars[(int) thischarcnt],
-					   thisabbr);
+				strcpy(&thischars[thischarcnt], thisabbr);
 				thischarcnt += strlen(thisabbr) + 1;
 			}
 			indmap[abbrinds[i]] = j;
@@ -2476,13 +2521,13 @@ enum
 YEAR_BY_YEAR_ZONE = 1};
 
 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;
 	struct rule *rp;
 	struct rule *stdrp;
 	struct rule *dstrp;
-	int			i;
+	ptrdiff_t	i;
 	const char *abbrvar;
 	int			compat = 0;
 	int			c;
@@ -2611,11 +2656,11 @@ stringzone(char *result, const struct zone * const zpfirst, const int zonecount)
 }
 
 static void
-outzone(const struct zone * zpfirst, int zonecount)
+outzone(const struct zone * zpfirst, ptrdiff_t zonecount)
 {
 	const struct zone *zp;
 	struct rule *rp;
-	int			i,
+	ptrdiff_t	i,
 				j;
 	bool		usestart,
 				useuntil;
@@ -2637,7 +2682,7 @@ outzone(const struct zone * zpfirst, int zonecount)
 	int			compat;
 	bool		do_extend;
 	char		version;
-	int			lastatmax = -1;
+	ptrdiff_t	lastatmax = -1;
 
 	max_abbr_len = 2 + max_format_len + max_abbrvar_len;
 	max_envvar_len = 2 * max_abbr_len + 5 * 9;
@@ -2806,7 +2851,7 @@ outzone(const struct zone * zpfirst, int zonecount)
 				}
 				for (;;)
 				{
-					int			k;
+					ptrdiff_t	k;
 					zic_t		jtime,
 								ktime = 0;
 					zic_t		offset;
@@ -3101,30 +3146,52 @@ adjleap(void)
 	}
 }
 
+static char *
+shellquote(char *b, char const * s)
+{
+	*b++ = '\'';
+	while (*s)
+	{
+		if (*s == '\'')
+			*b++ = '\'', *b++ = '\\', *b++ = '\'';
+		*b++ = *s++;
+	}
+	*b++ = '\'';
+	return b;
+}
+
 static bool
-yearistype(int year, const char *type)
+yearistype(zic_t year, const char *type)
 {
-	static char *buf;
+	char	   *buf;
+	char	   *b;
 	int			result;
 
 	if (type == NULL || *type == '\0')
 		return true;
-	buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type));
-	sprintf(buf, "%s %d %s", yitcommand, year, type);
+	buf = emalloc(1 + 4 * strlen(yitcommand) + 2
+				  + 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);
 	if (WIFEXITED(result))
-		switch (WEXITSTATUS(result))
+	{
+		int			status = WEXITSTATUS(result);
+
+		if (status <= 1)
 		{
-			case 0:
-				return true;
-			case 1:
-				return false;
+			free(buf);
+			return status == 0;
 		}
+	}
 	error(_("Wild result from command execution"));
 	fprintf(stderr, _("%s: command was '%s', result was %d\n"),
 			progname, buf, result);
-	for (;;)
-		exit(EXIT_FAILURE);
+	exit(EXIT_FAILURE);
 }
 
 /* Is A a space character in the C locale?	*/
@@ -3358,7 +3425,7 @@ getfields(char *cp)
 					else
 					{
 						error(_("Odd number of quotation marks"));
-						exit(1);
+						exit(EXIT_FAILURE);
 					}
 		} while (*cp && *cp != '#' && !is_space(*cp));
 		if (is_space(*cp))
@@ -3547,7 +3614,8 @@ newabbr(const char *string)
 
 /* Ensure that the directories of ARGNAME exist, by making any missing
    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
 mkdirs(char const * argname, bool ancestors)
 {
@@ -3579,7 +3647,7 @@ mkdirs(char const * argname, bool ancestors)
 		{
 			int			err = errno;
 
-			if (err != EEXIST && itsdir(name) < 0)
+			if (err != EEXIST && !itsdir(name))
 			{
 				error(_("%s: Cannot create directory %s: %s"),
 					  progname, name, strerror(err));
