Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1f87181

Browse files
committedNov 4, 2016
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. This should get back-patched, but first let's see what the buildfarm makes of it. I'm not too sure about the new dependency on linkat(2). Report: <CANFyU94_p6mqRQc2i26PFp5QAOQGB++AjGX=FO8LDpXw0GSTjw@mail.gmail.com> Discussion: http://mm.icann.org/pipermail/tz/2016-November/024431.html
1 parent a0f357e commit 1f87181

File tree

1 file changed

+176
-108
lines changed

1 file changed

+176
-108
lines changed
 

‎src/timezone/zic.c

Lines changed: 176 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
#include "postgres_fe.h"
1010

11+
#include <fcntl.h>
1112
#include <locale.h>
1213
#include <sys/stat.h>
1314
#include <time.h>
15+
#include <unistd.h>
1416

1517
#include "pg_getopt.h"
1618

@@ -35,14 +37,24 @@ typedef int64 zic_t;
3537
#define MKDIR_UMASK 0755
3638
#endif
3739
#endif
38-
#ifndef S_ISLNK
39-
#define S_ISLNK(m) 0
40+
#ifndef AT_SYMLINK_FOLLOW
41+
#define linkat(fromdir, from, todir, to, flag) \
42+
(itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to))
4043
#endif
4144

45+
/* The maximum ptrdiff_t value, for pre-C99 platforms. */
46+
#ifndef PTRDIFF_MAX
47+
static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
48+
#endif
49+
50+
/* The type and printf format for line numbers. */
51+
typedef int lineno;
52+
#define PRIdLINENO "d"
53+
4254
struct rule
4355
{
4456
const char *r_filename;
45-
int r_linenum;
57+
lineno r_linenum;
4658
const char *r_name;
4759

4860
zic_t r_loyear; /* for example, 1986 */
@@ -64,7 +76,7 @@ struct rule
6476
zic_t r_stdoff; /* offset from standard time */
6577
const char *r_abbrvar; /* variable part of abbreviation */
6678

67-
int r_todo; /* a rule to do (used in outzone) */
79+
bool r_todo; /* a rule to do (used in outzone) */
6880
zic_t r_temp; /* used in outzone */
6981
};
7082

@@ -79,7 +91,7 @@ struct rule
7991
struct zone
8092
{
8193
const char *z_filename;
82-
int z_linenum;
94+
lineno z_linenum;
8395

8496
const char *z_name;
8597
zic_t z_gmtoff;
@@ -90,7 +102,7 @@ struct zone
90102
zic_t z_stdoff;
91103

92104
struct rule *z_rules;
93-
int z_nrules;
105+
ptrdiff_t z_nrules;
94106

95107
struct rule z_untilrule;
96108
zic_t z_untiltime;
@@ -119,20 +131,21 @@ static void inrule(char **fields, int nfields);
119131
static bool inzcont(char **fields, int nfields);
120132
static bool inzone(char **fields, int nfields);
121133
static bool inzsub(char **, int, bool);
122-
static int itsdir(const char *name);
134+
static bool itsdir(char const *);
135+
static bool itssymlink(char const *);
123136
static bool is_alpha(char a);
124137
static char lowerit(char);
125138
static void mkdirs(char const *, bool);
126139
static void newabbr(const char *abbr);
127140
static zic_t oadd(zic_t t1, zic_t t2);
128-
static void outzone(const struct zone * zp, int ntzones);
141+
static void outzone(const struct zone * zp, ptrdiff_t ntzones);
129142
static zic_t rpytime(const struct rule * rp, zic_t wantedy);
130143
static void rulesub(struct rule * rp,
131144
const char *loyearp, const char *hiyearp,
132145
const char *typep, const char *monthp,
133146
const char *dayp, const char *timep);
134147
static zic_t tadd(zic_t t1, zic_t t2);
135-
static bool yearistype(int year, const char *type);
148+
static bool yearistype(zic_t year, const char *type);
136149

137150
/* Bound on length of what %z can expand to. */
138151
enum
@@ -156,7 +169,7 @@ static int leapcnt;
156169
static bool leapseen;
157170
static zic_t leapminyear;
158171
static zic_t leapmaxyear;
159-
static int linenum;
172+
static lineno linenum;
160173
static int max_abbrvar_len = PERCENT_Z_LEN_BOUND;
161174
static int max_format_len;
162175
static zic_t max_year;
@@ -165,10 +178,10 @@ static bool noise;
165178
static bool print_abbrevs;
166179
static zic_t print_cutoff;
167180
static const char *rfilename;
168-
static int rlinenum;
181+
static lineno rlinenum;
169182
static const char *progname;
170-
static int timecnt;
171-
static int timecnt_alloc;
183+
static ptrdiff_t timecnt;
184+
static ptrdiff_t timecnt_alloc;
172185
static int typecnt;
173186

174187
/*
@@ -253,24 +266,24 @@ static int typecnt;
253266
#define YR_ONLY 2
254267

255268
static struct rule *rules;
256-
static int nrules; /* number of rules */
257-
static int nrules_alloc;
269+
static ptrdiff_t nrules; /* number of rules */
270+
static ptrdiff_t nrules_alloc;
258271

259272
static struct zone *zones;
260-
static int nzones; /* number of zones */
261-
static int nzones_alloc;
273+
static ptrdiff_t nzones; /* number of zones */
274+
static ptrdiff_t nzones_alloc;
262275

263276
struct link
264277
{
265278
const char *l_filename;
266-
int l_linenum;
279+
lineno l_linenum;
267280
const char *l_from;
268281
const char *l_to;
269282
};
270283

271284
static struct link *links;
272-
static int nlinks;
273-
static int nlinks_alloc;
285+
static ptrdiff_t nlinks;
286+
static ptrdiff_t nlinks_alloc;
274287

275288
struct lookup
276289
{
@@ -417,17 +430,18 @@ ecpyalloc(char const * str)
417430
}
418431

419432
static void *
420-
growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
433+
growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t * nitems_alloc)
421434
{
422435
if (nitems < *nitems_alloc)
423436
return ptr;
424437
else
425438
{
426-
int nitems_max = INT_MAX - WORK_AROUND_QTBUG_53071;
439+
ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
440+
ptrdiff_t amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
427441

428-
if ((nitems_max - 1) / 3 * 2 < *nitems_alloc)
429-
memory_exhausted(_("int overflow"));
430-
*nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1;
442+
if ((amax - 1) / 3 * 2 < *nitems_alloc)
443+
memory_exhausted(_("integer overflow"));
444+
*nitems_alloc += (*nitems_alloc >> 1) + 1;
431445
return erealloc(ptr, size_product(*nitems_alloc, itemsize));
432446
}
433447
}
@@ -437,7 +451,7 @@ growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
437451
*/
438452

439453
static void
440-
eats(const char *name, int num, const char *rname, int rnum)
454+
eats(char const * name, lineno num, char const * rname, lineno rnum)
441455
{
442456
filename = name;
443457
linenum = num;
@@ -446,7 +460,7 @@ eats(const char *name, int num, const char *rname, int rnum)
446460
}
447461

448462
static void
449-
eat(const char *name, int num)
463+
eat(char const * name, lineno num)
450464
{
451465
eats(name, num, NULL, -1);
452466
}
@@ -459,10 +473,10 @@ verror(const char *string, va_list args)
459473
* "*" -v on BSD systems.
460474
*/
461475
if (filename)
462-
fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
476+
fprintf(stderr, _("\"%s\", line %" PRIdLINENO ": "), filename, linenum);
463477
vfprintf(stderr, string, args);
464478
if (rfilename != NULL)
465-
fprintf(stderr, _(" (rule from \"%s\", line %d)"),
479+
fprintf(stderr, _(" (rule from \"%s\", line %" PRIdLINENO ")"),
466480
rfilename, rlinenum);
467481
fprintf(stderr, "\n");
468482
}
@@ -553,9 +567,10 @@ static const char *yitcommand;
553567
int
554568
main(int argc, char *argv[])
555569
{
556-
int i;
557-
int j;
558-
int c;
570+
int c,
571+
k;
572+
ptrdiff_t i,
573+
j;
559574

560575
#ifndef WIN32
561576
umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
@@ -567,14 +582,14 @@ main(int argc, char *argv[])
567582
_("wild compilation-time specification of zic_t"));
568583
return EXIT_FAILURE;
569584
}
570-
for (i = 1; i < argc; ++i)
571-
if (strcmp(argv[i], "--version") == 0)
585+
for (k = 1; k < argc; k++)
586+
if (strcmp(argv[k], "--version") == 0)
572587
{
573588
printf("zic %s\n", PG_VERSION);
574589
close_file(stdout, NULL, NULL);
575590
return EXIT_SUCCESS;
576591
}
577-
else if (strcmp(argv[i], "--help") == 0)
592+
else if (strcmp(argv[k], "--help") == 0)
578593
{
579594
usage(stdout, EXIT_SUCCESS);
580595
}
@@ -662,8 +677,8 @@ main(int argc, char *argv[])
662677
adjleap();
663678
}
664679

665-
for (i = optind; i < argc; ++i)
666-
infile(argv[i]);
680+
for (k = optind; k < argc; k++)
681+
infile(argv[k]);
667682
if (errors)
668683
return EXIT_FAILURE;
669684
associate();
@@ -713,7 +728,7 @@ componentcheck(char const * name, char const * component,
713728
enum
714729
{
715730
component_len_max = 14};
716-
size_t component_len = component_end - component;
731+
ptrdiff_t component_len = component_end - component;
717732

718733
if (component_len == 0)
719734
{
@@ -731,8 +746,10 @@ componentcheck(char const * name, char const * component,
731746
if (0 < component_len && component_len <= 2
732747
&& component[0] == '.' && component_end[-1] == '.')
733748
{
749+
int len = component_len;
750+
734751
error(_("file name '%s' contains '%.*s' component"),
735-
name, (int) component_len, component);
752+
name, len, component);
736753
return false;
737754
}
738755
if (noise)
@@ -823,9 +840,9 @@ relname(char const * from, char const * to)
823840
for (i = 0; f[i] && f[i] == to[i]; i++)
824841
if (f[i] == '/')
825842
dir_len = i + 1;
826-
for (; f[i]; i++)
827-
dotdots += f[i] == '/' && f[i - 1] != '/';
828-
taillen = i - dir_len;
843+
for (; to[i]; i++)
844+
dotdots += to[i] == '/' && to[i - 1] != '/';
845+
taillen = strlen(f + dir_len);
829846
dotdotetcsize = 3 * dotdots + taillen + 1;
830847
if (dotdotetcsize <= linksize)
831848
{
@@ -839,28 +856,34 @@ relname(char const * from, char const * to)
839856
}
840857
#endif /* HAVE_SYMLINK */
841858

859+
/* Hard link FROM to TO, following any symbolic links.
860+
Return 0 if successful, an error number otherwise. */
861+
static int
862+
hardlinkerr(char const * from, char const * to)
863+
{
864+
int r = linkat(AT_FDCWD, from, AT_FDCWD, to, AT_SYMLINK_FOLLOW);
865+
866+
return r == 0 ? 0 : errno;
867+
}
868+
842869
static void
843870
dolink(char const * fromfield, char const * tofield, bool staysymlink)
844871
{
845-
int fromisdir;
846872
bool todirs_made = false;
847873
int link_errno;
848874

849875
/*
850876
* We get to be careful here since there's a fair chance of root running
851877
* us.
852878
*/
853-
fromisdir = itsdir(fromfield);
854-
if (fromisdir)
879+
if (itsdir(fromfield))
855880
{
856-
char const *e = strerror(fromisdir < 0 ? errno : EPERM);
857-
858881
fprintf(stderr, _("%s: link from %s/%s failed: %s\n"),
859-
progname, directory, fromfield, e);
882+
progname, directory, fromfield, strerror(EPERM));
860883
exit(EXIT_FAILURE);
861884
}
862885
if (staysymlink)
863-
staysymlink = itsdir(tofield) == 2;
886+
staysymlink = itssymlink(tofield);
864887
if (remove(tofield) == 0)
865888
todirs_made = true;
866889
else if (errno != ENOENT)
@@ -871,13 +894,12 @@ dolink(char const * fromfield, char const * tofield, bool staysymlink)
871894
progname, directory, tofield, e);
872895
exit(EXIT_FAILURE);
873896
}
874-
link_errno = (staysymlink ? ENOTSUP
875-
: link(fromfield, tofield) == 0 ? 0 : errno);
897+
link_errno = staysymlink ? ENOTSUP : hardlinkerr(fromfield, tofield);
876898
if (link_errno == ENOENT && !todirs_made)
877899
{
878900
mkdirs(tofield, true);
879901
todirs_made = true;
880-
link_errno = link(fromfield, tofield) == 0 ? 0 : errno;
902+
link_errno = hardlinkerr(fromfield, tofield);
881903
}
882904
if (link_errno != 0)
883905
{
@@ -987,31 +1009,42 @@ static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332
9871009
? BIG_BANG
9881010
: MINVAL(zic_t, TIME_T_BITS_IN_FILE));
9891011

990-
/* Return 1 if NAME is a directory, 2 if a symbolic link, 0 if
991-
something else, -1 (setting errno) if trouble. */
992-
static int
1012+
/* Return true if NAME is a directory. */
1013+
static bool
9931014
itsdir(char const * name)
9941015
{
9951016
struct stat st;
996-
int res = lstat(name, &st);
997-
1017+
int res = stat(name, &st);
1018+
#ifdef S_ISDIR
9981019
if (res == 0)
1020+
return S_ISDIR(st.st_mode) != 0;
1021+
#endif
1022+
if (res == 0 || errno == EOVERFLOW)
9991023
{
1000-
#ifdef S_ISDIR
1001-
return S_ISDIR(st.st_mode) ? 1 : S_ISLNK(st.st_mode) ? 2 : 0;
1002-
#else
10031024
size_t n = strlen(name);
10041025
char *nameslashdot = emalloc(n + 3);
10051026
bool dir;
10061027

10071028
memcpy(nameslashdot, name, n);
10081029
strcpy(&nameslashdot[n], &"/."[!(n && name[n - 1] != '/')]);
1009-
dir = lstat(nameslashdot, &st) == 0;
1030+
dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
10101031
free(nameslashdot);
10111032
return dir;
1012-
#endif
10131033
}
1014-
return -1;
1034+
return false;
1035+
}
1036+
1037+
/* Return true if NAME is a symbolic link. */
1038+
static bool
1039+
itssymlink(char const * name)
1040+
{
1041+
#ifdef HAVE_SYMLINK
1042+
char c;
1043+
1044+
return 0 <= readlink(name, &c, 1);
1045+
#else
1046+
return false;
1047+
#endif
10151048
}
10161049

10171050
/*
@@ -1034,10 +1067,10 @@ associate(void)
10341067
{
10351068
struct zone *zp;
10361069
struct rule *rp;
1037-
int base,
1070+
ptrdiff_t i,
1071+
j,
1072+
base,
10381073
out;
1039-
int i,
1040-
j;
10411074

10421075
if (nrules != 0)
10431076
{
@@ -1124,7 +1157,7 @@ infile(const char *name)
11241157
const struct lookup *lp;
11251158
int nfields;
11261159
bool wantcont;
1127-
int num;
1160+
lineno num;
11281161
char buf[BUFSIZ];
11291162

11301163
if (strcmp(name, "-") == 0)
@@ -1175,7 +1208,7 @@ infile(const char *name)
11751208
if (lp == NULL)
11761209
error(_("input line of unknown type"));
11771210
else
1178-
switch ((int) (lp->l_value))
1211+
switch (lp->l_value)
11791212
{
11801213
case LC_RULE:
11811214
inrule(fields, nfields);
@@ -1302,7 +1335,7 @@ inrule(char **fields, int nfields)
13021335
static bool
13031336
inzone(char **fields, int nfields)
13041337
{
1305-
int i;
1338+
ptrdiff_t i;
13061339

13071340
if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS)
13081341
{
@@ -1327,8 +1360,8 @@ inzone(char **fields, int nfields)
13271360
if (zones[i].z_name != NULL &&
13281361
strcmp(zones[i].z_name, fields[ZF_NAME]) == 0)
13291362
{
1330-
error(
1331-
_("duplicate zone name %s (file \"%s\", line %d)"),
1363+
error(_("duplicate zone name %s"
1364+
" (file \"%s\", line %" PRIdLINENO ")"),
13321365
fields[ZF_NAME],
13331366
zones[i].z_filename,
13341367
zones[i].z_linenum);
@@ -1452,7 +1485,7 @@ inleap(char **fields, int nfields)
14521485
{
14531486
const char *cp;
14541487
const struct lookup *lp;
1455-
int i,
1488+
zic_t i,
14561489
j;
14571490

14581491
/* PG: make year be int not zic_t to avoid sscanf portability issues */
@@ -1659,7 +1692,7 @@ rulesub(struct rule * rp, const char *loyearp, const char *hiyearp,
16591692
lp = byword(cp, begin_years);
16601693
rp->r_lowasnum = lp == NULL;
16611694
if (!rp->r_lowasnum)
1662-
switch ((int) lp->l_value)
1695+
switch (lp->l_value)
16631696
{
16641697
case YR_MINIMUM:
16651698
rp->r_loyear = ZIC_MIN;
@@ -1684,7 +1717,7 @@ rulesub(struct rule * rp, const char *loyearp, const char *hiyearp,
16841717
lp = byword(cp, end_years);
16851718
rp->r_hiwasnum = lp == NULL;
16861719
if (!rp->r_hiwasnum)
1687-
switch ((int) lp->l_value)
1720+
switch (lp->l_value)
16881721
{
16891722
case YR_MINIMUM:
16901723
rp->r_hiyear = ZIC_MIN;
@@ -1834,19 +1867,19 @@ static void
18341867
writezone(const char *const name, const char *const string, char version)
18351868
{
18361869
FILE *fp;
1837-
int i,
1870+
ptrdiff_t i,
18381871
j;
18391872
int leapcnt32,
18401873
leapi32;
1841-
int timecnt32,
1874+
ptrdiff_t timecnt32,
18421875
timei32;
18431876
int pass;
18441877
static const struct tzhead tzh0;
18451878
static struct tzhead tzh;
18461879
bool dir_checked = false;
18471880
zic_t one = 1;
18481881
zic_t y2038_boundary = one << 31;
1849-
int nats = timecnt + WORK_AROUND_QTBUG_53071;
1882+
ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071;
18501883
zic_t *ats = emalloc(size_product(nats, sizeof *ats + 1));
18511884
void *typesptr = ats + nats;
18521885
unsigned char *types = typesptr;
@@ -1861,8 +1894,8 @@ writezone(const char *const name, const char *const string, char version)
18611894
* Optimize.
18621895
*/
18631896
{
1864-
int fromi;
1865-
int toi;
1897+
ptrdiff_t fromi,
1898+
toi;
18661899

18671900
toi = 0;
18681901
fromi = 0;
@@ -1886,9 +1919,17 @@ writezone(const char *const name, const char *const string, char version)
18861919
}
18871920
timecnt = toi;
18881921
}
1922+
18891923
if (noise && timecnt > 1200)
1890-
warning(_("pre-2014 clients may mishandle"
1891-
" more than 1200 transition times"));
1924+
{
1925+
if (timecnt > TZ_MAX_TIMES)
1926+
warning(_("reference clients mishandle"
1927+
" more than %d transition times"),
1928+
TZ_MAX_TIMES);
1929+
else
1930+
warning(_("pre-2014 clients may mishandle"
1931+
" more than 1200 transition times"));
1932+
}
18921933

18931934
/*
18941935
* Transfer.
@@ -1991,33 +2032,38 @@ writezone(const char *const name, const char *const string, char version)
19912032
}
19922033
for (pass = 1; pass <= 2; ++pass)
19932034
{
1994-
int thistimei,
1995-
thistimecnt;
2035+
ptrdiff_t thistimei,
2036+
thistimecnt,
2037+
thistimelim;
19962038
int thisleapi,
1997-
thisleapcnt;
1998-
int thistimelim,
2039+
thisleapcnt,
19992040
thisleaplim;
20002041
int writetype[TZ_MAX_TYPES];
20012042
int typemap[TZ_MAX_TYPES];
20022043
int thistypecnt;
20032044
char thischars[TZ_MAX_CHARS];
2004-
char thischarcnt;
2045+
int thischarcnt;
2046+
bool toomanytimes;
20052047
int indmap[TZ_MAX_CHARS];
20062048

20072049
if (pass == 1)
20082050
{
20092051
thistimei = timei32;
20102052
thistimecnt = timecnt32;
2053+
toomanytimes = thistimecnt >> 31 >> 1 != 0;
20112054
thisleapi = leapi32;
20122055
thisleapcnt = leapcnt32;
20132056
}
20142057
else
20152058
{
20162059
thistimei = 0;
20172060
thistimecnt = timecnt;
2061+
toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
20182062
thisleapi = 0;
20192063
thisleapcnt = leapcnt;
20202064
}
2065+
if (toomanytimes)
2066+
error(_("too many transition times"));
20212067
thistimelim = thistimei + thistimecnt;
20222068
thisleaplim = thisleapi + thisleapcnt;
20232069
for (i = 0; i < typecnt; ++i)
@@ -2118,8 +2164,7 @@ writezone(const char *const name, const char *const string, char version)
21182164
break;
21192165
if (j == thischarcnt)
21202166
{
2121-
strcpy(&thischars[(int) thischarcnt],
2122-
thisabbr);
2167+
strcpy(&thischars[thischarcnt], thisabbr);
21232168
thischarcnt += strlen(thisabbr) + 1;
21242169
}
21252170
indmap[abbrinds[i]] = j;
@@ -2466,13 +2511,13 @@ enum
24662511
YEAR_BY_YEAR_ZONE = 1};
24672512

24682513
static int
2469-
stringzone(char *result, const struct zone * const zpfirst, const int zonecount)
2514+
stringzone(char *result, struct zone const * zpfirst, ptrdiff_t zonecount)
24702515
{
24712516
const struct zone *zp;
24722517
struct rule *rp;
24732518
struct rule *stdrp;
24742519
struct rule *dstrp;
2475-
int i;
2520+
ptrdiff_t i;
24762521
const char *abbrvar;
24772522
int compat = 0;
24782523
int c;
@@ -2601,11 +2646,11 @@ stringzone(char *result, const struct zone * const zpfirst, const int zonecount)
26012646
}
26022647

26032648
static void
2604-
outzone(const struct zone * zpfirst, int zonecount)
2649+
outzone(const struct zone * zpfirst, ptrdiff_t zonecount)
26052650
{
26062651
const struct zone *zp;
26072652
struct rule *rp;
2608-
int i,
2653+
ptrdiff_t i,
26092654
j;
26102655
bool usestart,
26112656
useuntil;
@@ -2627,7 +2672,7 @@ outzone(const struct zone * zpfirst, int zonecount)
26272672
int compat;
26282673
bool do_extend;
26292674
char version;
2630-
int lastatmax = -1;
2675+
ptrdiff_t lastatmax = -1;
26312676

26322677
max_abbr_len = 2 + max_format_len + max_abbrvar_len;
26332678
max_envvar_len = 2 * max_abbr_len + 5 * 9;
@@ -2796,7 +2841,7 @@ outzone(const struct zone * zpfirst, int zonecount)
27962841
}
27972842
for (;;)
27982843
{
2799-
int k;
2844+
ptrdiff_t k;
28002845
zic_t jtime,
28012846
ktime = 0;
28022847
zic_t offset;
@@ -3091,30 +3136,52 @@ adjleap(void)
30913136
}
30923137
}
30933138

3139+
static char *
3140+
shellquote(char *b, char const * s)
3141+
{
3142+
*b++ = '\'';
3143+
while (*s)
3144+
{
3145+
if (*s == '\'')
3146+
*b++ = '\'', *b++ = '\\', *b++ = '\'';
3147+
*b++ = *s++;
3148+
}
3149+
*b++ = '\'';
3150+
return b;
3151+
}
3152+
30943153
static bool
3095-
yearistype(int year, const char *type)
3154+
yearistype(zic_t year, const char *type)
30963155
{
3097-
static char *buf;
3156+
char *buf;
3157+
char *b;
30983158
int result;
30993159

31003160
if (type == NULL || *type == '\0')
31013161
return true;
3102-
buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type));
3103-
sprintf(buf, "%s %d %s", yitcommand, year, type);
3162+
buf = emalloc(1 + 4 * strlen(yitcommand) + 2
3163+
+ INT_STRLEN_MAXIMUM(zic_t) +2 + 4 * strlen(type) + 2);
3164+
b = shellquote(buf, yitcommand);
3165+
*b++ = ' ';
3166+
b += sprintf(b, INT64_FORMAT, year);
3167+
*b++ = ' ';
3168+
b = shellquote(b, type);
3169+
*b = '\0';
31043170
result = system(buf);
31053171
if (WIFEXITED(result))
3106-
switch (WEXITSTATUS(result))
3172+
{
3173+
int status = WEXITSTATUS(result);
3174+
3175+
if (status <= 1)
31073176
{
3108-
case 0:
3109-
return true;
3110-
case 1:
3111-
return false;
3177+
free(buf);
3178+
return status == 0;
31123179
}
3180+
}
31133181
error(_("Wild result from command execution"));
31143182
fprintf(stderr, _("%s: command was '%s', result was %d\n"),
31153183
progname, buf, result);
3116-
for (;;)
3117-
exit(EXIT_FAILURE);
3184+
exit(EXIT_FAILURE);
31183185
}
31193186

31203187
/* Is A a space character in the C locale? */
@@ -3348,7 +3415,7 @@ getfields(char *cp)
33483415
else
33493416
{
33503417
error(_("Odd number of quotation marks"));
3351-
exit(1);
3418+
exit(EXIT_FAILURE);
33523419
}
33533420
} while (*cp && *cp != '#' && !is_space(*cp));
33543421
if (is_space(*cp))
@@ -3537,7 +3604,8 @@ newabbr(const char *string)
35373604

35383605
/* Ensure that the directories of ARGNAME exist, by making any missing
35393606
ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
3540-
do it for ARGNAME too. Exit with failure if there is trouble. */
3607+
do it for ARGNAME too. Exit with failure if there is trouble.
3608+
Do not consider an existing non-directory to be trouble. */
35413609
static void
35423610
mkdirs(char const * argname, bool ancestors)
35433611
{
@@ -3569,7 +3637,7 @@ mkdirs(char const * argname, bool ancestors)
35693637
{
35703638
int err = errno;
35713639

3572-
if (err != EEXIST && itsdir(name) < 0)
3640+
if (err != EEXIST && !itsdir(name))
35733641
{
35743642
error(_("%s: Cannot create directory %s: %s"),
35753643
progname, name, strerror(err));

0 commit comments

Comments
 (0)
Please sign in to comment.