@ -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 )
to dirs_made = true ;
staysymlink = itssymlink ( linkname ) ;
if ( remove ( linkname ) = = 0 )
link dirs_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 ) ;
to dirs_made = true ;
link_errno = hardlinkerr ( fromfield , tofield ) ;
mkdirs ( linkname , true ) ;
link dirs_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 ( ! to dirs_made
if ( ! link dirs_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 )