diff options
Diffstat (limited to 'src/timezone/zic.c')
-rw-r--r-- | src/timezone/zic.c | 205 |
1 files changed, 67 insertions, 138 deletions
diff --git a/src/timezone/zic.c b/src/timezone/zic.c index 10c5b4bfb5b..a1c64051f78 100644 --- a/src/timezone/zic.c +++ b/src/timezone/zic.c @@ -37,10 +37,6 @@ typedef int64 zic_t; #define MKDIR_UMASK 0755 #endif #endif -#ifndef AT_SYMLINK_FOLLOW -#define linkat(fromdir, from, todir, to, flag) \ - (itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to)) -#endif /* Port to native MS-Windows and to ancient UNIX. */ #if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) @@ -66,7 +62,6 @@ struct rule zic_t r_loyear; /* for example, 1986 */ zic_t r_hiyear; /* for example, 1986 */ - const char *r_yrtype; bool r_lowasnum; bool r_hiwasnum; @@ -116,7 +111,11 @@ struct zone zic_t z_untiltime; }; -extern int link(const char *fromname, const char *toname); +extern int link(const char *target, const char *linkname); +#ifndef AT_SYMLINK_FOLLOW +#define linkat(targetdir, target, linknamedir, linkname, flag) \ + (itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname)) +#endif static void memory_exhausted(const char *msg) pg_attribute_noreturn(); static void verror(const char *string, va_list args) pg_attribute_printf(1, 0); @@ -154,7 +153,6 @@ static void rulesub(struct rule *rp, 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(zic_t year, const char *type); /* Bound on length of what %z can expand to. */ enum @@ -253,8 +251,8 @@ static int typecnt; * Which fields are which on a Link line. */ -#define LF_FROM 1 -#define LF_TO 2 +#define LF_TARGET 1 +#define LF_LINKNAME 2 #define LINK_FIELDS 3 /* @@ -292,8 +290,8 @@ struct link { const char *l_filename; lineno_t l_linenum; - const char *l_from; - const char *l_to; + const char *l_target; + const char *l_linkname; }; static struct link *links; @@ -634,11 +632,9 @@ static const char *lcltime; static const char *directory; static const char *leapsec; static const char *tzdefault; -static const char *yitcommand; /* -1 if the TZif output file should be slim, 0 if default, 1 if the - output should be fat for backward compatibility. Currently the - default is fat, although this may change. */ + output should be fat for backward compatibility. The default is slim. */ static int bloat; static bool @@ -648,7 +644,7 @@ want_bloat(void) } #ifndef ZIC_BLOAT_DEFAULT -#define ZIC_BLOAT_DEFAULT "fat" +#define ZIC_BLOAT_DEFAULT "slim" #endif int @@ -747,18 +743,7 @@ main(int argc, char **argv) tzdefault = optarg; break; case 'y': - if (yitcommand == NULL) - { - warning(_("-y is obsolescent")); - yitcommand = strdup(optarg); - } - else - { - fprintf(stderr, - _("%s: More than one -y option specified\n"), - progname); - return EXIT_FAILURE; - } + warning(_("-y ignored")); break; case 'L': if (leapsec == NULL) @@ -807,8 +792,6 @@ main(int argc, char **argv) directory = "data"; if (tzdefault == NULL) tzdefault = TZDEFAULT; - if (yitcommand == NULL) - yitcommand = "yearistype"; if (optind < argc && leapsec != NULL) { @@ -838,11 +821,11 @@ main(int argc, char **argv) for (i = 0; i < nlinks; ++i) { eat(links[i].l_filename, links[i].l_linenum); - dolink(links[i].l_from, links[i].l_to, false); + dolink(links[i].l_target, links[i].l_linkname, false); if (noise) for (j = 0; j < nlinks; ++j) - if (strcmp(links[i].l_to, - links[j].l_from) == 0) + if (strcmp(links[i].l_linkname, + links[j].l_target) == 0) warning(_("link to link")); } if (lcltime != NULL) @@ -953,7 +936,7 @@ namecheck(const char *name) */ #ifdef HAVE_SYMLINK static char * -relname(char const *from, char const *to) +relname(char const *target, char const *linkname) { size_t i, taillen, @@ -961,26 +944,26 @@ relname(char const *from, char const *to) size_t dir_len = 0, dotdots = 0, linksize = SIZE_MAX; - char const *f = from; + char const *f = target; char *result = NULL; - if (*to == '/') + if (*linkname == '/') { /* Make F absolute too. */ size_t len = strlen(directory); bool needslash = len && directory[len - 1] != '/'; - linksize = len + needslash + strlen(from) + 1; + linksize = len + needslash + strlen(target) + 1; f = result = emalloc(linksize); strcpy(result, directory); result[len] = '/'; - strcpy(result + len + needslash, from); + strcpy(result + len + needslash, target); } - for (i = 0; f[i] && f[i] == to[i]; i++) + for (i = 0; f[i] && f[i] == linkname[i]; i++) if (f[i] == '/') dir_len = i + 1; - for (; to[i]; i++) - dotdots += to[i] == '/' && to[i - 1] != '/'; + for (; linkname[i]; i++) + dotdots += linkname[i] == '/' && linkname[i - 1] != '/'; taillen = strlen(f + dir_len); dotdotetcsize = 3 * dotdots + taillen + 1; if (dotdotetcsize <= linksize) @@ -998,62 +981,65 @@ relname(char const *from, char const *to) /* 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) +hardlinkerr(char const *target, char const *linkname) { - int r = linkat(AT_FDCWD, from, AT_FDCWD, to, AT_SYMLINK_FOLLOW); + int r = linkat(AT_FDCWD, target, AT_FDCWD, linkname, AT_SYMLINK_FOLLOW); return r == 0 ? 0 : errno; } static void -dolink(char const *fromfield, char const *tofield, bool staysymlink) +dolink(char const *target, char const *linkname, bool staysymlink) { - bool todirs_made = false; + bool remove_only = strcmp(target, "-") == 0; + bool linkdirs_made = false; int link_errno; /* * We get to be careful here since there's a fair chance of root running * us. */ - if (itsdir(fromfield)) + if (!remove_only && itsdir(target)) { - fprintf(stderr, _("%s: link from %s/%s failed: %s\n"), - progname, directory, fromfield, strerror(EPERM)); + fprintf(stderr, _("%s: linking target %s/%s failed: %s\n"), + progname, directory, target, strerror(EPERM)); exit(EXIT_FAILURE); } if (staysymlink) - staysymlink = itssymlink(tofield); - if (remove(tofield) == 0) - todirs_made = true; + staysymlink = itssymlink(linkname); + if (remove(linkname) == 0) + linkdirs_made = true; else if (errno != ENOENT) { char const *e = strerror(errno); fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"), - progname, directory, tofield, e); + progname, directory, linkname, e); exit(EXIT_FAILURE); } - link_errno = staysymlink ? ENOTSUP : hardlinkerr(fromfield, tofield); - if (link_errno == ENOENT && !todirs_made) + if (remove_only) + return; + link_errno = staysymlink ? ENOTSUP : hardlinkerr(target, linkname); + if (link_errno == ENOENT && !linkdirs_made) { - mkdirs(tofield, true); - todirs_made = true; - link_errno = hardlinkerr(fromfield, tofield); + mkdirs(linkname, true); + linkdirs_made = true; + link_errno = hardlinkerr(target, linkname); } if (link_errno != 0) { #ifdef HAVE_SYMLINK - bool absolute = *fromfield == '/'; - char *linkalloc = absolute ? NULL : relname(fromfield, tofield); - char const *contents = absolute ? fromfield : linkalloc; - int symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno; + bool absolute = *target == '/'; + char *linkalloc = absolute ? NULL : relname(target, linkname); + char const *contents = absolute ? target : linkalloc; + int symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno; - if (!todirs_made + if (!linkdirs_made && (symlink_errno == ENOENT || symlink_errno == ENOTSUP)) { - mkdirs(tofield, true); + mkdirs(linkname, true); if (symlink_errno == ENOENT) - symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno; + symlink_errno = symlink(contents, linkname) == 0 ? 0 : errno; } free(linkalloc); if (symlink_errno == 0) @@ -1069,28 +1055,28 @@ dolink(char const *fromfield, char const *tofield, bool staysymlink) *tp; int c; - fp = fopen(fromfield, "rb"); + fp = fopen(target, "rb"); if (!fp) { char const *e = strerror(errno); fprintf(stderr, _("%s: Can't read %s/%s: %s\n"), - progname, directory, fromfield, e); + progname, directory, target, e); exit(EXIT_FAILURE); } - tp = fopen(tofield, "wb"); + tp = fopen(linkname, "wb"); if (!tp) { char const *e = strerror(errno); fprintf(stderr, _("%s: Can't create %s/%s: %s\n"), - progname, directory, tofield, e); + progname, directory, linkname, e); exit(EXIT_FAILURE); } while ((c = getc(fp)) != EOF) putc(c, tp); - close_file(fp, directory, fromfield); - close_file(tp, directory, tofield); + close_file(fp, directory, target); + close_file(tp, directory, linkname); if (link_errno != ENOTSUP) warning(_("copy used because hard link failed: %s"), strerror(link_errno)); @@ -1806,17 +1792,17 @@ inlink(char **fields, int nfields) error(_("wrong number of fields on Link line")); return; } - if (*fields[LF_FROM] == '\0') + if (*fields[LF_TARGET] == '\0') { - error(_("blank FROM field on Link line")); + error(_("blank TARGET field on Link line")); return; } - if (!namecheck(fields[LF_TO])) + if (!namecheck(fields[LF_LINKNAME])) return; l.l_filename = filename; l.l_linenum = linenum; - l.l_from = ecpyalloc(fields[LF_FROM]); - l.l_to = ecpyalloc(fields[LF_TO]); + l.l_target = ecpyalloc(fields[LF_TARGET]); + l.l_linkname = ecpyalloc(fields[LF_LINKNAME]); links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc); links[nlinks++] = l; } @@ -1932,18 +1918,11 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, error(_("starting year greater than ending year")); return; } - if (*typep == '\0') - rp->r_yrtype = NULL; - else + if (*typep != '\0') { - if (rp->r_loyear == rp->r_hiyear) - { - error(_("typed single year")); - return; - } - warning(_("year type \"%s\" is obsolete; use \"-\" instead"), - typep); - rp->r_yrtype = ecpyalloc(typep); + error(_("year type \"%s\" is unsupported; use \"-\" instead"), + typep); + return; } /* @@ -2848,8 +2827,6 @@ stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount) rp = &zp->z_rules[i]; if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX) continue; - if (rp->r_yrtype != NULL) - continue; if (!rp->r_isdst) { if (stdrp == NULL) @@ -3145,7 +3122,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount) /* * Mark which rules to do in the current year. For those to - * do, calculate rpytime(rp, year); + * do, calculate rpytime(rp, year); The former TYPE field was + * also considered here. */ for (j = 0; j < zp->z_nrules; ++j) { @@ -3153,8 +3131,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount) eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); rp->r_todo = year >= rp->r_loyear && - year <= rp->r_hiyear && - yearistype(year, rp->r_yrtype); + year <= rp->r_hiyear; if (rp->r_todo) { rp->r_temp = rpytime(rp, year); @@ -3474,54 +3451,6 @@ 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(zic_t year, const char *type) -{ - char *buf; - char *b; - int result; - - if (type == NULL || *type == '\0') - return true; - 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)) - { - int status = WEXITSTATUS(result); - - if (status <= 1) - { - free(buf); - return status == 0; - } - } - error(_("Wild result from command execution")); - fprintf(stderr, _("%s: command was '%s', result was %d\n"), - progname, buf, result); - exit(EXIT_FAILURE); -} - /* Is A a space character in the C locale? */ static bool is_space(char a) |