zic.c 101 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961
  1. /* Compile .zi time zone data into TZif binary files. */
  2. /*
  3. ** This file is in the public domain, so clarified as of
  4. ** 2006-07-17 by Arthur David Olson.
  5. */
  6. /* Use the system 'time' function, instead of any private replacement.
  7. This avoids creating an unnecessary dependency on localtime.c. */
  8. #undef EPOCH_LOCAL
  9. #undef EPOCH_OFFSET
  10. #undef RESERVE_STD_EXT_IDS
  11. #undef time_tz
  12. #include "version.h"
  13. #include "private.h"
  14. #include "tzdir.h"
  15. #include "tzfile.h"
  16. #include <fcntl.h>
  17. #include <locale.h>
  18. #include <signal.h>
  19. #include <stdarg.h>
  20. #include <stdio.h>
  21. typedef int_fast64_t zic_t;
  22. static zic_t const
  23. ZIC_MIN = INT_FAST64_MIN,
  24. ZIC_MAX = INT_FAST64_MAX,
  25. ZIC32_MIN = -1 - (zic_t) 0x7fffffff,
  26. ZIC32_MAX = 0x7fffffff;
  27. #define SCNdZIC SCNdFAST64
  28. #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
  29. # define ZIC_MAX_ABBR_LEN_WO_WARN 6
  30. #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
  31. /* Minimum and maximum years, assuming signed 32-bit time_t. */
  32. enum { YEAR_32BIT_MIN = 1901, YEAR_32BIT_MAX = 2038 };
  33. /* An upper bound on how much a format might grow due to concatenation. */
  34. enum { FORMAT_LEN_GROWTH_BOUND = 5 };
  35. #ifdef HAVE_DIRECT_H
  36. # include <direct.h>
  37. # include <io.h>
  38. # undef mkdir
  39. # define mkdir(name, mode) _mkdir(name)
  40. #endif
  41. #ifndef HAVE_GETRANDOM
  42. # ifdef __has_include
  43. # if __has_include(<sys/random.h>)
  44. # include <sys/random.h>
  45. # endif
  46. # elif 2 < __GLIBC__ + (25 <= __GLIBC_MINOR__)
  47. # include <sys/random.h>
  48. # endif
  49. # define HAVE_GETRANDOM GRND_RANDOM
  50. #elif HAVE_GETRANDOM
  51. # include <sys/random.h>
  52. #endif
  53. #if HAVE_SYS_STAT_H
  54. # include <sys/stat.h>
  55. #endif
  56. #ifdef S_IRUSR
  57. # define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
  58. #else
  59. # define MKDIR_UMASK 0755
  60. #endif
  61. /* The minimum alignment of a type, for pre-C23 platforms.
  62. The __SUNPRO_C test is because Oracle Developer Studio 12.6 lacks
  63. <stdalign.h> even though __STDC_VERSION__ == 201112. */
  64. #if __STDC_VERSION__ < 201112 || defined __SUNPRO_C
  65. # define alignof(type) offsetof(struct { char a; type b; }, b)
  66. #elif __STDC_VERSION__ < 202311
  67. # include <stdalign.h>
  68. #endif
  69. /* The maximum length of a text line, including the trailing newline. */
  70. #ifndef _POSIX2_LINE_MAX
  71. # define _POSIX2_LINE_MAX 2048
  72. #endif
  73. /* The type for line numbers. Use PRIdMAX to format them; formerly
  74. there was also "#define PRIdLINENO PRIdMAX" and formats used
  75. PRIdLINENO, but xgettext cannot grok that. */
  76. typedef intmax_t lineno;
  77. struct rule {
  78. int r_filenum;
  79. lineno r_linenum;
  80. const char * r_name;
  81. zic_t r_loyear; /* for example, 1986 */
  82. zic_t r_hiyear; /* for example, 1986 */
  83. bool r_hiwasnum;
  84. int r_month; /* 0..11 */
  85. int r_dycode; /* see below */
  86. int r_dayofmonth;
  87. int r_wday;
  88. zic_t r_tod; /* time from midnight */
  89. bool r_todisstd; /* is r_tod standard time? */
  90. bool r_todisut; /* is r_tod UT? */
  91. bool r_isdst; /* is this daylight saving time? */
  92. zic_t r_save; /* offset from standard time */
  93. const char * r_abbrvar; /* variable part of abbreviation */
  94. bool r_todo; /* a rule to do (used in outzone) */
  95. zic_t r_temp; /* used in outzone */
  96. };
  97. /*
  98. ** r_dycode r_dayofmonth r_wday
  99. */
  100. enum {
  101. DC_DOM, /* 1..31 */ /* unused */
  102. DC_DOWGEQ, /* 1..31 */ /* 0..6 (Sun..Sat) */
  103. DC_DOWLEQ /* 1..31 */ /* 0..6 (Sun..Sat) */
  104. };
  105. struct zone {
  106. int z_filenum;
  107. lineno z_linenum;
  108. const char * z_name;
  109. zic_t z_stdoff;
  110. char * z_rule;
  111. const char * z_format;
  112. char z_format_specifier;
  113. bool z_isdst;
  114. zic_t z_save;
  115. struct rule * z_rules;
  116. ptrdiff_t z_nrules;
  117. struct rule z_untilrule;
  118. zic_t z_untiltime;
  119. };
  120. #if !HAVE_POSIX_DECLS
  121. extern int getopt(int argc, char * const argv[],
  122. const char * options);
  123. extern int link(const char * target, const char * linkname);
  124. extern char * optarg;
  125. extern int optind;
  126. #endif
  127. #if ! HAVE_SYMLINK
  128. static ssize_t
  129. readlink(char const *restrict file, char *restrict buf, size_t size)
  130. {
  131. errno = ENOTSUP;
  132. return -1;
  133. }
  134. static int
  135. symlink(char const *target, char const *linkname)
  136. {
  137. errno = ENOTSUP;
  138. return -1;
  139. }
  140. #endif
  141. #ifndef AT_SYMLINK_FOLLOW
  142. # define linkat(targetdir, target, linknamedir, linkname, flag) \
  143. (errno = ENOTSUP, -1)
  144. #endif
  145. static void addtt(zic_t starttime, int type);
  146. static int addtype(zic_t, char const *, bool, bool, bool);
  147. static void leapadd(zic_t, int, int);
  148. static void adjleap(void);
  149. static void associate(void);
  150. static void dolink(const char *, const char *, bool);
  151. static int getfields(char *, char **, int);
  152. static zic_t gethms(const char * string, const char * errstring);
  153. static zic_t getsave(char *, bool *);
  154. static void inexpires(char **, int);
  155. static void infile(int, char const *);
  156. static void inleap(char ** fields, int nfields);
  157. static void inlink(char ** fields, int nfields);
  158. static void inrule(char ** fields, int nfields);
  159. static bool inzcont(char ** fields, int nfields);
  160. static bool inzone(char ** fields, int nfields);
  161. static bool inzsub(char **, int, bool);
  162. static int itssymlink(char const *, int *);
  163. static bool is_alpha(char a);
  164. static char lowerit(char);
  165. static void mkdirs(char const *, bool);
  166. static void newabbr(const char * abbr);
  167. static zic_t oadd(zic_t t1, zic_t t2);
  168. static void outzone(const struct zone * zp, ptrdiff_t ntzones);
  169. static zic_t rpytime(const struct rule * rp, zic_t wantedy);
  170. static bool rulesub(struct rule * rp,
  171. const char * loyearp, const char * hiyearp,
  172. const char * typep, const char * monthp,
  173. const char * dayp, const char * timep);
  174. static zic_t tadd(zic_t t1, zic_t t2);
  175. /* Bound on length of what %z can expand to. */
  176. enum { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1 };
  177. static int charcnt;
  178. static bool errors;
  179. static bool warnings;
  180. static int filenum;
  181. static int leapcnt;
  182. static bool leapseen;
  183. static zic_t leapminyear;
  184. static zic_t leapmaxyear;
  185. static lineno linenum;
  186. static int max_abbrvar_len = PERCENT_Z_LEN_BOUND;
  187. static int max_format_len;
  188. static zic_t max_year;
  189. static zic_t min_year;
  190. static bool noise;
  191. static int rfilenum;
  192. static lineno rlinenum;
  193. static const char * progname;
  194. static char const * leapsec;
  195. static char *const * main_argv;
  196. static ptrdiff_t timecnt;
  197. static ptrdiff_t timecnt_alloc;
  198. static int typecnt;
  199. static int unspecifiedtype;
  200. /*
  201. ** Line codes.
  202. */
  203. enum {
  204. LC_RULE,
  205. LC_ZONE,
  206. LC_LINK,
  207. LC_LEAP,
  208. LC_EXPIRES
  209. };
  210. /*
  211. ** Which fields are which on a Zone line.
  212. */
  213. enum {
  214. ZF_NAME = 1,
  215. ZF_STDOFF,
  216. ZF_RULE,
  217. ZF_FORMAT,
  218. ZF_TILYEAR,
  219. ZF_TILMONTH,
  220. ZF_TILDAY,
  221. ZF_TILTIME,
  222. ZONE_MAXFIELDS,
  223. ZONE_MINFIELDS = ZF_TILYEAR
  224. };
  225. /*
  226. ** Which fields are which on a Zone continuation line.
  227. */
  228. enum {
  229. ZFC_STDOFF,
  230. ZFC_RULE,
  231. ZFC_FORMAT,
  232. ZFC_TILYEAR,
  233. ZFC_TILMONTH,
  234. ZFC_TILDAY,
  235. ZFC_TILTIME,
  236. ZONEC_MAXFIELDS,
  237. ZONEC_MINFIELDS = ZFC_TILYEAR
  238. };
  239. /*
  240. ** Which files are which on a Rule line.
  241. */
  242. enum {
  243. RF_NAME = 1,
  244. RF_LOYEAR,
  245. RF_HIYEAR,
  246. RF_COMMAND,
  247. RF_MONTH,
  248. RF_DAY,
  249. RF_TOD,
  250. RF_SAVE,
  251. RF_ABBRVAR,
  252. RULE_FIELDS
  253. };
  254. /*
  255. ** Which fields are which on a Link line.
  256. */
  257. enum {
  258. LF_TARGET = 1,
  259. LF_LINKNAME,
  260. LINK_FIELDS
  261. };
  262. /*
  263. ** Which fields are which on a Leap line.
  264. */
  265. enum {
  266. LP_YEAR = 1,
  267. LP_MONTH,
  268. LP_DAY,
  269. LP_TIME,
  270. LP_CORR,
  271. LP_ROLL,
  272. LEAP_FIELDS,
  273. /* Expires lines are like Leap lines, except without CORR and ROLL fields. */
  274. EXPIRES_FIELDS = LP_TIME + 1
  275. };
  276. /* The maximum number of fields on any of the above lines.
  277. (The "+"s pacify gcc -Wenum-compare.) */
  278. enum {
  279. MAX_FIELDS = max(max(+RULE_FIELDS, +LINK_FIELDS),
  280. max(+LEAP_FIELDS, +EXPIRES_FIELDS))
  281. };
  282. /*
  283. ** Year synonyms.
  284. */
  285. enum {
  286. YR_MINIMUM, /* "minimum" is for backward compatibility only */
  287. YR_MAXIMUM,
  288. YR_ONLY
  289. };
  290. static struct rule * rules;
  291. static ptrdiff_t nrules; /* number of rules */
  292. static ptrdiff_t nrules_alloc;
  293. static struct zone * zones;
  294. static ptrdiff_t nzones; /* number of zones */
  295. static ptrdiff_t nzones_alloc;
  296. struct link {
  297. int l_filenum;
  298. lineno l_linenum;
  299. const char * l_target;
  300. const char * l_linkname;
  301. };
  302. static struct link * links;
  303. static ptrdiff_t nlinks;
  304. static ptrdiff_t nlinks_alloc;
  305. struct lookup {
  306. const char * l_word;
  307. const int l_value;
  308. };
  309. static struct lookup const * byword(const char * string,
  310. const struct lookup * lp);
  311. static struct lookup const zi_line_codes[] = {
  312. { "Rule", LC_RULE },
  313. { "Zone", LC_ZONE },
  314. { "Link", LC_LINK },
  315. { NULL, 0 }
  316. };
  317. static struct lookup const leap_line_codes[] = {
  318. { "Leap", LC_LEAP },
  319. { "Expires", LC_EXPIRES },
  320. { NULL, 0}
  321. };
  322. static struct lookup const mon_names[] = {
  323. { "January", TM_JANUARY },
  324. { "February", TM_FEBRUARY },
  325. { "March", TM_MARCH },
  326. { "April", TM_APRIL },
  327. { "May", TM_MAY },
  328. { "June", TM_JUNE },
  329. { "July", TM_JULY },
  330. { "August", TM_AUGUST },
  331. { "September", TM_SEPTEMBER },
  332. { "October", TM_OCTOBER },
  333. { "November", TM_NOVEMBER },
  334. { "December", TM_DECEMBER },
  335. { NULL, 0 }
  336. };
  337. static struct lookup const wday_names[] = {
  338. { "Sunday", TM_SUNDAY },
  339. { "Monday", TM_MONDAY },
  340. { "Tuesday", TM_TUESDAY },
  341. { "Wednesday", TM_WEDNESDAY },
  342. { "Thursday", TM_THURSDAY },
  343. { "Friday", TM_FRIDAY },
  344. { "Saturday", TM_SATURDAY },
  345. { NULL, 0 }
  346. };
  347. static struct lookup const lasts[] = {
  348. { "last-Sunday", TM_SUNDAY },
  349. { "last-Monday", TM_MONDAY },
  350. { "last-Tuesday", TM_TUESDAY },
  351. { "last-Wednesday", TM_WEDNESDAY },
  352. { "last-Thursday", TM_THURSDAY },
  353. { "last-Friday", TM_FRIDAY },
  354. { "last-Saturday", TM_SATURDAY },
  355. { NULL, 0 }
  356. };
  357. static struct lookup const begin_years[] = {
  358. { "minimum", YR_MINIMUM },
  359. { NULL, 0 }
  360. };
  361. static struct lookup const end_years[] = {
  362. { "maximum", YR_MAXIMUM },
  363. { "only", YR_ONLY },
  364. { NULL, 0 }
  365. };
  366. static struct lookup const leap_types[] = {
  367. { "Rolling", true },
  368. { "Stationary", false },
  369. { NULL, 0 }
  370. };
  371. static const int len_months[2][MONSPERYEAR] = {
  372. { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  373. { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  374. };
  375. static const int len_years[2] = {
  376. DAYSPERNYEAR, DAYSPERLYEAR
  377. };
  378. static struct attype {
  379. zic_t at;
  380. bool dontmerge;
  381. unsigned char type;
  382. } * attypes;
  383. static zic_t utoffs[TZ_MAX_TYPES];
  384. static char isdsts[TZ_MAX_TYPES];
  385. static unsigned char desigidx[TZ_MAX_TYPES];
  386. static bool ttisstds[TZ_MAX_TYPES];
  387. static bool ttisuts[TZ_MAX_TYPES];
  388. static char chars[TZ_MAX_CHARS];
  389. static zic_t trans[TZ_MAX_LEAPS];
  390. static zic_t corr[TZ_MAX_LEAPS];
  391. static char roll[TZ_MAX_LEAPS];
  392. /*
  393. ** Memory allocation.
  394. */
  395. ATTRIBUTE_NORETURN static void
  396. memory_exhausted(const char *msg)
  397. {
  398. fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
  399. exit(EXIT_FAILURE);
  400. }
  401. ATTRIBUTE_NORETURN static void
  402. size_overflow(void)
  403. {
  404. memory_exhausted(_("size overflow"));
  405. }
  406. ATTRIBUTE_PURE_114833 static ptrdiff_t
  407. size_sum(size_t a, size_t b)
  408. {
  409. #ifdef ckd_add
  410. ptrdiff_t sum;
  411. if (!ckd_add(&sum, a, b) && sum <= INDEX_MAX)
  412. return sum;
  413. #else
  414. if (a <= INDEX_MAX && b <= INDEX_MAX - a)
  415. return a + b;
  416. #endif
  417. size_overflow();
  418. }
  419. ATTRIBUTE_PURE_114833 static ptrdiff_t
  420. size_product(ptrdiff_t nitems, ptrdiff_t itemsize)
  421. {
  422. #ifdef ckd_mul
  423. ptrdiff_t product;
  424. if (!ckd_mul(&product, nitems, itemsize) && product <= INDEX_MAX)
  425. return product;
  426. #else
  427. ptrdiff_t nitems_max = INDEX_MAX / itemsize;
  428. if (nitems <= nitems_max)
  429. return nitems * itemsize;
  430. #endif
  431. size_overflow();
  432. }
  433. ATTRIBUTE_PURE_114833 static ptrdiff_t
  434. align_to(ptrdiff_t size, ptrdiff_t alignment)
  435. {
  436. ptrdiff_t lo_bits = alignment - 1, sum = size_sum(size, lo_bits);
  437. return sum & ~lo_bits;
  438. }
  439. #if !HAVE_STRDUP
  440. static char *
  441. strdup(char const *str)
  442. {
  443. char *result = malloc(strlen(str) + 1);
  444. return result ? strcpy(result, str) : result;
  445. }
  446. #endif
  447. static void *
  448. memcheck(void *ptr)
  449. {
  450. if (ptr == NULL)
  451. memory_exhausted(strerror(HAVE_MALLOC_ERRNO ? errno : ENOMEM));
  452. return ptr;
  453. }
  454. static void *
  455. emalloc(size_t size)
  456. {
  457. return memcheck(malloc(size));
  458. }
  459. static void *
  460. erealloc(void *ptr, size_t size)
  461. {
  462. return memcheck(realloc(ptr, size));
  463. }
  464. static char *
  465. estrdup(char const *str)
  466. {
  467. return memcheck(strdup(str));
  468. }
  469. static ptrdiff_t
  470. grow_nitems_alloc(ptrdiff_t *nitems_alloc, ptrdiff_t itemsize)
  471. {
  472. ptrdiff_t addend = (*nitems_alloc >> 1) + 1;
  473. #if defined ckd_add && defined ckd_mul
  474. ptrdiff_t product;
  475. if (!ckd_add(nitems_alloc, *nitems_alloc, addend)
  476. && !ckd_mul(&product, *nitems_alloc, itemsize) && product <= INDEX_MAX)
  477. return product;
  478. #else
  479. if (*nitems_alloc <= ((INDEX_MAX - 1) / 3 * 2) / itemsize) {
  480. *nitems_alloc += addend;
  481. return *nitems_alloc * itemsize;
  482. }
  483. #endif
  484. memory_exhausted(_("integer overflow"));
  485. }
  486. static void *
  487. growalloc(void *ptr, ptrdiff_t itemsize, ptrdiff_t nitems,
  488. ptrdiff_t *nitems_alloc)
  489. {
  490. return (nitems < *nitems_alloc
  491. ? ptr
  492. : erealloc(ptr, grow_nitems_alloc(nitems_alloc, itemsize)));
  493. }
  494. /*
  495. ** Error handling.
  496. */
  497. /* In most of the code, an input file name is represented by its index
  498. into the main argument vector, except that LEAPSEC_FILENUM stands
  499. for leapsec and COMMAND_LINE_FILENUM stands for the command line. */
  500. enum { LEAPSEC_FILENUM = -2, COMMAND_LINE_FILENUM = -1 };
  501. /* Return the name of the Ith input file, for diagnostics. */
  502. static char const *
  503. filename(int i)
  504. {
  505. if (i == COMMAND_LINE_FILENUM)
  506. return _("command line");
  507. else {
  508. char const *fname = i == LEAPSEC_FILENUM ? leapsec : main_argv[i];
  509. return strcmp(fname, "-") == 0 ? _("standard input") : fname;
  510. }
  511. }
  512. static void
  513. eats(int fnum, lineno num, int rfnum, lineno rnum)
  514. {
  515. filenum = fnum;
  516. linenum = num;
  517. rfilenum = rfnum;
  518. rlinenum = rnum;
  519. }
  520. static void
  521. eat(int fnum, lineno num)
  522. {
  523. eats(fnum, num, 0, -1);
  524. }
  525. ATTRIBUTE_FORMAT((printf, 1, 0)) static void
  526. verror(const char *const string, va_list args)
  527. {
  528. /*
  529. ** Match the format of "cc" to allow sh users to
  530. ** zic ... 2>&1 | error -t "*" -v
  531. ** on BSD systems.
  532. */
  533. if (filenum)
  534. fprintf(stderr, _("\"%s\", line %"PRIdMAX": "),
  535. filename(filenum), linenum);
  536. vfprintf(stderr, string, args);
  537. if (rfilenum)
  538. fprintf(stderr, _(" (rule from \"%s\", line %"PRIdMAX")"),
  539. filename(rfilenum), rlinenum);
  540. fprintf(stderr, "\n");
  541. }
  542. ATTRIBUTE_FORMAT((printf, 1, 2)) static void
  543. error(const char *const string, ...)
  544. {
  545. va_list args;
  546. va_start(args, string);
  547. verror(string, args);
  548. va_end(args);
  549. errors = true;
  550. }
  551. ATTRIBUTE_FORMAT((printf, 1, 2)) static void
  552. warning(const char *const string, ...)
  553. {
  554. va_list args;
  555. fprintf(stderr, _("warning: "));
  556. va_start(args, string);
  557. verror(string, args);
  558. va_end(args);
  559. warnings = true;
  560. }
  561. /* Close STREAM. If it had an I/O error, report it against DIR/NAME,
  562. remove TEMPNAME if nonnull, and then exit. */
  563. static void
  564. close_file(FILE *stream, char const *dir, char const *name,
  565. char const *tempname)
  566. {
  567. char const *e = (ferror(stream) ? _("I/O error")
  568. : fclose(stream) != 0 ? strerror(errno) : NULL);
  569. if (e) {
  570. fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
  571. dir ? dir : "", dir ? "/" : "",
  572. name ? name : "", name ? ": " : "",
  573. e);
  574. if (tempname)
  575. remove(tempname);
  576. exit(EXIT_FAILURE);
  577. }
  578. }
  579. ATTRIBUTE_NORETURN static void
  580. usage(FILE *stream, int status)
  581. {
  582. fprintf(stream,
  583. _("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n"
  584. "\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ]"
  585. " [ -L leapseconds ] \\\n"
  586. "\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -R '@hi' ] \\\n"
  587. "\t[ -t localtime-link ] \\\n"
  588. "\t[ filename ... ]\n\n"
  589. "Report bugs to %s.\n"),
  590. progname, progname, REPORT_BUGS_TO);
  591. if (status == EXIT_SUCCESS)
  592. close_file(stream, NULL, NULL, NULL);
  593. exit(status);
  594. }
  595. /* Change the working directory to DIR, possibly creating DIR and its
  596. ancestors. After this is done, all files are accessed with names
  597. relative to DIR. */
  598. static void
  599. change_directory(char const *dir)
  600. {
  601. if (chdir(dir) != 0) {
  602. int chdir_errno = errno;
  603. if (chdir_errno == ENOENT) {
  604. mkdirs(dir, false);
  605. chdir_errno = chdir(dir) == 0 ? 0 : errno;
  606. }
  607. if (chdir_errno != 0) {
  608. fprintf(stderr, _("%s: Can't chdir to %s: %s\n"),
  609. progname, dir, strerror(chdir_errno));
  610. exit(EXIT_FAILURE);
  611. }
  612. }
  613. }
  614. /* Compare the two links A and B, for a stable sort by link name. */
  615. static int
  616. qsort_linkcmp(void const *a, void const *b)
  617. {
  618. struct link const *l = a;
  619. struct link const *m = b;
  620. int cmp = strcmp(l->l_linkname, m->l_linkname);
  621. if (cmp)
  622. return cmp;
  623. /* The link names are the same. Make the sort stable by comparing
  624. file numbers (where subtraction cannot overflow) and possibly
  625. line numbers (where it can). */
  626. cmp = l->l_filenum - m->l_filenum;
  627. if (cmp)
  628. return cmp;
  629. return (l->l_linenum > m->l_linenum) - (l->l_linenum < m->l_linenum);
  630. }
  631. /* Compare the string KEY to the link B, for bsearch. */
  632. static int
  633. bsearch_linkcmp(void const *key, void const *b)
  634. {
  635. struct link const *m = b;
  636. return strcmp(key, m->l_linkname);
  637. }
  638. /* Make the links specified by the Link lines. */
  639. static void
  640. make_links(void)
  641. {
  642. ptrdiff_t i, j, nalinks, pass_size;
  643. if (1 < nlinks)
  644. qsort(links, nlinks, sizeof *links, qsort_linkcmp);
  645. /* Ignore each link superseded by a later link with the same name. */
  646. j = 0;
  647. for (i = 0; i < nlinks; i++) {
  648. while (i + 1 < nlinks
  649. && strcmp(links[i].l_linkname, links[i + 1].l_linkname) == 0)
  650. i++;
  651. links[j++] = links[i];
  652. }
  653. nlinks = pass_size = j;
  654. /* Walk through the link array making links. However,
  655. if a link's target has not been made yet, append a copy to the
  656. end of the array. The end of the array will gradually fill
  657. up with a small sorted subsequence of not-yet-made links.
  658. nalinks counts all the links in the array, including copies.
  659. When we reach the copied subsequence, it may still contain
  660. a link to a not-yet-made link, so the process repeats.
  661. At any given point in time, the link array consists of the
  662. following subregions, where 0 <= i <= j <= nalinks and
  663. 0 <= nlinks <= nalinks:
  664. 0 .. (i - 1):
  665. links that either have been made, or have been copied to a
  666. later point point in the array (this later point can be in
  667. any of the three subregions)
  668. i .. (j - 1):
  669. not-yet-made links for this pass
  670. j .. (nalinks - 1):
  671. not-yet-made links that this pass has skipped because
  672. they were links to not-yet-made links
  673. The first subregion might not be sorted if nlinks < i;
  674. the other two subregions are sorted. This algorithm does
  675. not alter entries 0 .. (nlinks - 1), which remain sorted.
  676. If there are L links, this algorithm is O(C*L*log(L)) where
  677. C is the length of the longest link chain. Usually C is
  678. short (e.g., 3) though its worst-case value is L. */
  679. j = nalinks = nlinks;
  680. for (i = 0; i < nalinks; i++) {
  681. struct link *l;
  682. eat(links[i].l_filenum, links[i].l_linenum);
  683. /* If this pass examined all its links, start the next pass. */
  684. if (i == j) {
  685. if (nalinks - i == pass_size) {
  686. error(_("\"Link %s %s\" is part of a link cycle"),
  687. links[i].l_target, links[i].l_linkname);
  688. break;
  689. }
  690. j = nalinks;
  691. pass_size = nalinks - i;
  692. }
  693. /* Diagnose self links, which the cycle detection algorithm would not
  694. otherwise catch. */
  695. if (strcmp(links[i].l_target, links[i].l_linkname) == 0) {
  696. error(_("link %s targets itself"), links[i].l_target);
  697. continue;
  698. }
  699. /* Make this link unless its target has not been made yet. */
  700. l = bsearch(links[i].l_target, &links[i + 1], j - (i + 1),
  701. sizeof *links, bsearch_linkcmp);
  702. if (!l)
  703. l = bsearch(links[i].l_target, &links[j], nalinks - j,
  704. sizeof *links, bsearch_linkcmp);
  705. if (!l)
  706. dolink(links[i].l_target, links[i].l_linkname, false);
  707. else {
  708. /* The link target has not been made yet; copy the link to the end. */
  709. links = growalloc(links, sizeof *links, nalinks, &nlinks_alloc);
  710. links[nalinks++] = links[i];
  711. }
  712. if (noise && i < nlinks) {
  713. if (l)
  714. warning(_("link %s targeting link %s mishandled by pre-2023 zic"),
  715. links[i].l_linkname, links[i].l_target);
  716. else if (bsearch(links[i].l_target, links, nlinks, sizeof *links,
  717. bsearch_linkcmp))
  718. warning(_("link %s targeting link %s"),
  719. links[i].l_linkname, links[i].l_target);
  720. }
  721. }
  722. }
  723. /* Simple signal handling: just set a flag that is checked
  724. periodically outside critical sections. To set up the handler,
  725. prefer sigaction if available to close a signal race. */
  726. static sig_atomic_t got_signal;
  727. static void
  728. signal_handler(int sig)
  729. {
  730. #ifndef SA_SIGINFO
  731. signal(sig, signal_handler);
  732. #endif
  733. got_signal = sig;
  734. }
  735. /* Arrange for SIGINT etc. to be caught by the handler. */
  736. static void
  737. catch_signals(void)
  738. {
  739. static int const signals[] = {
  740. #ifdef SIGHUP
  741. SIGHUP,
  742. #endif
  743. SIGINT,
  744. #ifdef SIGPIPE
  745. SIGPIPE,
  746. #endif
  747. SIGTERM
  748. };
  749. int i;
  750. for (i = 0; i < sizeof signals / sizeof signals[0]; i++) {
  751. #ifdef SA_SIGINFO
  752. struct sigaction act0, act;
  753. act.sa_handler = signal_handler;
  754. sigemptyset(&act.sa_mask);
  755. act.sa_flags = 0;
  756. if (sigaction(signals[i], &act, &act0) == 0
  757. && ! (act0.sa_flags & SA_SIGINFO) && act0.sa_handler == SIG_IGN) {
  758. sigaction(signals[i], &act0, NULL);
  759. got_signal = 0;
  760. }
  761. #else
  762. if (signal(signals[i], signal_handler) == SIG_IGN) {
  763. signal(signals[i], SIG_IGN);
  764. got_signal = 0;
  765. }
  766. #endif
  767. }
  768. }
  769. /* If a signal has arrived, terminate zic with appropriate status. */
  770. static void
  771. check_for_signal(void)
  772. {
  773. int sig = got_signal;
  774. if (sig) {
  775. signal(sig, SIG_DFL);
  776. raise(sig);
  777. abort(); /* A bug in 'raise'. */
  778. }
  779. }
  780. enum { TIME_T_BITS_IN_FILE = 64 };
  781. /* The minimum and maximum values representable in a TZif file. */
  782. static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
  783. static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
  784. /* The minimum, and one less than the maximum, values specified by
  785. the -r option. These default to MIN_TIME and MAX_TIME. */
  786. static zic_t lo_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
  787. static zic_t hi_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
  788. /* The time specified by the -R option, defaulting to MIN_TIME;
  789. or lo_time, whichever is greater. */
  790. static zic_t redundant_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
  791. /* The time specified by an Expires line, or negative if no such line. */
  792. static zic_t leapexpires = -1;
  793. /* Set the time range of the output to TIMERANGE.
  794. Return true if successful. */
  795. static bool
  796. timerange_option(char *timerange)
  797. {
  798. intmax_t lo = min_time, hi = max_time;
  799. char *lo_end = timerange, *hi_end;
  800. if (*timerange == '@') {
  801. errno = 0;
  802. lo = strtoimax(timerange + 1, &lo_end, 10);
  803. if (lo_end == timerange + 1 || (lo == INTMAX_MAX && errno == ERANGE))
  804. return false;
  805. }
  806. hi_end = lo_end;
  807. if (lo_end[0] == '/' && lo_end[1] == '@') {
  808. errno = 0;
  809. hi = strtoimax(lo_end + 2, &hi_end, 10);
  810. if (hi_end == lo_end + 2 || hi == INTMAX_MIN)
  811. return false;
  812. hi -= ! (hi == INTMAX_MAX && errno == ERANGE);
  813. }
  814. if (*hi_end || hi < lo || max_time < lo || hi < min_time)
  815. return false;
  816. lo_time = max(lo, min_time);
  817. hi_time = min(hi, max_time);
  818. return true;
  819. }
  820. /* Generate redundant time stamps up to OPT. Return true if successful. */
  821. static bool
  822. redundant_time_option(char *opt)
  823. {
  824. if (*opt == '@') {
  825. intmax_t redundant;
  826. char *opt_end;
  827. redundant = strtoimax(opt + 1, &opt_end, 10);
  828. if (opt_end != opt + 1 && !*opt_end) {
  829. redundant_time = max(redundant_time, redundant);
  830. return true;
  831. }
  832. }
  833. return false;
  834. }
  835. static const char * psxrules;
  836. static const char * lcltime;
  837. static const char * directory;
  838. static const char * tzdefault;
  839. /* -1 if the TZif output file should be slim, 0 if default, 1 if the
  840. output should be fat for backward compatibility. ZIC_BLOAT_DEFAULT
  841. determines the default. */
  842. static int bloat;
  843. static bool
  844. want_bloat(void)
  845. {
  846. return 0 <= bloat;
  847. }
  848. #ifndef ZIC_BLOAT_DEFAULT
  849. # define ZIC_BLOAT_DEFAULT "slim"
  850. #endif
  851. int
  852. main(int argc, char **argv)
  853. {
  854. register int c, k;
  855. register ptrdiff_t i, j;
  856. bool timerange_given = false;
  857. #ifdef S_IWGRP
  858. umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
  859. #endif
  860. #if HAVE_GETTEXT
  861. setlocale(LC_ALL, "");
  862. # ifdef TZ_DOMAINDIR
  863. bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
  864. # endif /* defined TEXTDOMAINDIR */
  865. textdomain(TZ_DOMAIN);
  866. #endif /* HAVE_GETTEXT */
  867. main_argv = argv;
  868. progname = argv[0] ? argv[0] : "zic";
  869. if (TYPE_BIT(zic_t) < 64) {
  870. fprintf(stderr, "%s: %s\n", progname,
  871. _("wild compilation-time specification of zic_t"));
  872. return EXIT_FAILURE;
  873. }
  874. for (k = 1; k < argc; k++)
  875. if (strcmp(argv[k], "--version") == 0) {
  876. printf("zic %s%s\n", PKGVERSION, TZVERSION);
  877. close_file(stdout, NULL, NULL, NULL);
  878. return EXIT_SUCCESS;
  879. } else if (strcmp(argv[k], "--help") == 0) {
  880. usage(stdout, EXIT_SUCCESS);
  881. }
  882. while ((c = getopt(argc, argv, "b:d:l:L:p:r:R:st:vy:")) != EOF
  883. && c != -1)
  884. switch (c) {
  885. default:
  886. usage(stderr, EXIT_FAILURE);
  887. case 'b':
  888. if (strcmp(optarg, "slim") == 0) {
  889. if (0 < bloat)
  890. error(_("incompatible -b options"));
  891. bloat = -1;
  892. } else if (strcmp(optarg, "fat") == 0) {
  893. if (bloat < 0)
  894. error(_("incompatible -b options"));
  895. bloat = 1;
  896. } else
  897. error(_("invalid option: -b '%s'"), optarg);
  898. break;
  899. case 'd':
  900. if (directory == NULL)
  901. directory = optarg;
  902. else {
  903. fprintf(stderr,
  904. _("%s: More than one -d option"
  905. " specified\n"),
  906. progname);
  907. return EXIT_FAILURE;
  908. }
  909. break;
  910. case 'l':
  911. if (lcltime == NULL)
  912. lcltime = optarg;
  913. else {
  914. fprintf(stderr,
  915. _("%s: More than one -l option"
  916. " specified\n"),
  917. progname);
  918. return EXIT_FAILURE;
  919. }
  920. break;
  921. case 'p':
  922. if (psxrules == NULL)
  923. psxrules = optarg;
  924. else {
  925. fprintf(stderr,
  926. _("%s: More than one -p option"
  927. " specified\n"),
  928. progname);
  929. return EXIT_FAILURE;
  930. }
  931. break;
  932. case 't':
  933. if (tzdefault != NULL) {
  934. fprintf(stderr,
  935. _("%s: More than one -t option"
  936. " specified\n"),
  937. progname);
  938. return EXIT_FAILURE;
  939. }
  940. tzdefault = optarg;
  941. break;
  942. case 'y':
  943. warning(_("-y ignored"));
  944. break;
  945. case 'L':
  946. if (leapsec == NULL)
  947. leapsec = optarg;
  948. else {
  949. fprintf(stderr,
  950. _("%s: More than one -L option"
  951. " specified\n"),
  952. progname);
  953. return EXIT_FAILURE;
  954. }
  955. break;
  956. case 'v':
  957. noise = true;
  958. break;
  959. case 'r':
  960. if (timerange_given) {
  961. fprintf(stderr,
  962. _("%s: More than one -r option"
  963. " specified\n"),
  964. progname);
  965. return EXIT_FAILURE;
  966. }
  967. if (! timerange_option(optarg)) {
  968. fprintf(stderr,
  969. _("%s: invalid time range: %s\n"),
  970. progname, optarg);
  971. return EXIT_FAILURE;
  972. }
  973. timerange_given = true;
  974. break;
  975. case 'R':
  976. if (! redundant_time_option(optarg)) {
  977. fprintf(stderr, _("%s: invalid time: %s\n"),
  978. progname, optarg);
  979. return EXIT_FAILURE;
  980. }
  981. break;
  982. case 's':
  983. warning(_("-s ignored"));
  984. break;
  985. }
  986. if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
  987. usage(stderr, EXIT_FAILURE); /* usage message by request */
  988. if (hi_time + (hi_time < ZIC_MAX) < redundant_time) {
  989. fprintf(stderr, _("%s: -R time exceeds -r cutoff\n"), progname);
  990. return EXIT_FAILURE;
  991. }
  992. if (redundant_time < lo_time)
  993. redundant_time = lo_time;
  994. if (bloat == 0) {
  995. static char const bloat_default[] = ZIC_BLOAT_DEFAULT;
  996. if (strcmp(bloat_default, "slim") == 0)
  997. bloat = -1;
  998. else if (strcmp(bloat_default, "fat") == 0)
  999. bloat = 1;
  1000. else
  1001. abort(); /* Configuration error. */
  1002. }
  1003. if (directory == NULL)
  1004. directory = TZDIR;
  1005. if (tzdefault == NULL)
  1006. tzdefault = TZDEFAULT;
  1007. if (optind < argc && leapsec != NULL) {
  1008. infile(LEAPSEC_FILENUM, leapsec);
  1009. adjleap();
  1010. }
  1011. for (k = optind; k < argc; k++)
  1012. infile(k, argv[k]);
  1013. if (errors)
  1014. return EXIT_FAILURE;
  1015. associate();
  1016. change_directory(directory);
  1017. catch_signals();
  1018. for (i = 0; i < nzones; i = j) {
  1019. /*
  1020. ** Find the next non-continuation zone entry.
  1021. */
  1022. for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
  1023. continue;
  1024. outzone(&zones[i], j - i);
  1025. }
  1026. make_links();
  1027. if (lcltime != NULL) {
  1028. eat(COMMAND_LINE_FILENUM, 1);
  1029. dolink(lcltime, tzdefault, true);
  1030. }
  1031. if (psxrules != NULL) {
  1032. eat(COMMAND_LINE_FILENUM, 1);
  1033. dolink(psxrules, TZDEFRULES, true);
  1034. }
  1035. if (warnings && (ferror(stderr) || fclose(stderr) != 0))
  1036. return EXIT_FAILURE;
  1037. return errors ? EXIT_FAILURE : EXIT_SUCCESS;
  1038. }
  1039. static bool
  1040. componentcheck(char const *name, char const *component,
  1041. char const *component_end)
  1042. {
  1043. enum { component_len_max = 14 };
  1044. ptrdiff_t component_len = component_end - component;
  1045. if (component_len == 0) {
  1046. if (!*name)
  1047. error(_("empty file name"));
  1048. else
  1049. error(_(component == name
  1050. ? "file name '%s' begins with '/'"
  1051. : *component_end
  1052. ? "file name '%s' contains '//'"
  1053. : "file name '%s' ends with '/'"),
  1054. name);
  1055. return false;
  1056. }
  1057. if (0 < component_len && component_len <= 2
  1058. && component[0] == '.' && component_end[-1] == '.') {
  1059. int len = component_len;
  1060. error(_("file name '%s' contains '%.*s' component"),
  1061. name, len, component);
  1062. return false;
  1063. }
  1064. if (noise) {
  1065. if (0 < component_len && component[0] == '-')
  1066. warning(_("file name '%s' component contains leading '-'"),
  1067. name);
  1068. if (component_len_max < component_len)
  1069. warning(_("file name '%s' contains overlength component"
  1070. " '%.*s...'"),
  1071. name, component_len_max, component);
  1072. }
  1073. return true;
  1074. }
  1075. static bool
  1076. namecheck(const char *name)
  1077. {
  1078. register char const *cp;
  1079. /* Benign characters in a portable file name. */
  1080. static char const benign[] =
  1081. "-/_"
  1082. "abcdefghijklmnopqrstuvwxyz"
  1083. "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  1084. /* Non-control chars in the POSIX portable character set,
  1085. excluding the benign characters. */
  1086. static char const printable_and_not_benign[] =
  1087. " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
  1088. register char const *component = name;
  1089. for (cp = name; *cp; cp++) {
  1090. unsigned char c = *cp;
  1091. if (noise && !strchr(benign, c)) {
  1092. warning((strchr(printable_and_not_benign, c)
  1093. ? _("file name '%s' contains byte '%c'")
  1094. : _("file name '%s' contains byte '\\%o'")),
  1095. name, c);
  1096. }
  1097. if (c == '/') {
  1098. if (!componentcheck(name, component, cp))
  1099. return false;
  1100. component = cp + 1;
  1101. }
  1102. }
  1103. return componentcheck(name, component, cp);
  1104. }
  1105. /* Return a random uint_fast64_t. */
  1106. static uint_fast64_t
  1107. get_rand_u64(void)
  1108. {
  1109. #if HAVE_GETRANDOM
  1110. static uint_fast64_t entropy_buffer[max(1, 256 / sizeof(uint_fast64_t))];
  1111. static int nwords;
  1112. if (!nwords) {
  1113. ssize_t s;
  1114. do
  1115. s = getrandom(entropy_buffer, sizeof entropy_buffer, 0);
  1116. while (s < 0 && errno == EINTR);
  1117. nwords = s < 0 ? -1 : s / sizeof *entropy_buffer;
  1118. }
  1119. if (0 < nwords)
  1120. return entropy_buffer[--nwords];
  1121. #endif
  1122. /* getrandom didn't work, so fall back on portable code that is
  1123. not the best because the seed isn't cryptographically random and
  1124. 'rand' might not be cryptographically secure. */
  1125. {
  1126. static bool initialized;
  1127. if (!initialized) {
  1128. srand(time(NULL));
  1129. initialized = true;
  1130. }
  1131. }
  1132. /* Return a random number if rand() yields a random number and in
  1133. the typical case where RAND_MAX is one less than a power of two.
  1134. In other cases this code yields a sort-of-random number. */
  1135. {
  1136. uint_fast64_t rand_max = RAND_MAX,
  1137. nrand = rand_max < UINT_FAST64_MAX ? rand_max + 1 : 0,
  1138. rmod = INT_MAX < UINT_FAST64_MAX ? 0 : UINT_FAST64_MAX / nrand + 1,
  1139. r = 0, rmax = 0;
  1140. do {
  1141. uint_fast64_t rmax1 = rmax;
  1142. if (rmod) {
  1143. /* Avoid signed integer overflow on theoretical platforms
  1144. where uint_fast64_t promotes to int. */
  1145. rmax1 %= rmod;
  1146. r %= rmod;
  1147. }
  1148. rmax1 = nrand * rmax1 + rand_max;
  1149. r = nrand * r + rand();
  1150. rmax = rmax < rmax1 ? rmax1 : UINT_FAST64_MAX;
  1151. } while (rmax < UINT_FAST64_MAX);
  1152. return r;
  1153. }
  1154. }
  1155. /* Generate a randomish name in the same directory as *NAME. If
  1156. *NAMEALLOC, put the name into *NAMEALLOC which is assumed to be
  1157. that returned by a previous call and is thus already almost set up
  1158. and equal to *NAME; otherwise, allocate a new name and put its
  1159. address into both *NAMEALLOC and *NAME. */
  1160. static void
  1161. random_dirent(char const **name, char **namealloc)
  1162. {
  1163. char const *src = *name;
  1164. char *dst = *namealloc;
  1165. static char const prefix[] = ".zic";
  1166. static char const alphabet[] =
  1167. "abcdefghijklmnopqrstuvwxyz"
  1168. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  1169. "0123456789";
  1170. enum { prefixlen = sizeof prefix - 1, alphabetlen = sizeof alphabet - 1 };
  1171. int suffixlen = 6;
  1172. char const *lastslash = strrchr(src, '/');
  1173. ptrdiff_t dirlen = lastslash ? lastslash + 1 - src : 0;
  1174. int i;
  1175. uint_fast64_t r;
  1176. uint_fast64_t base = alphabetlen;
  1177. /* BASE**6 */
  1178. uint_fast64_t base__6 = base * base * base * base * base * base;
  1179. /* The largest uintmax_t that is a multiple of BASE**6. Any random
  1180. uintmax_t value that is this value or greater, yields a biased
  1181. remainder when divided by BASE**6. UNFAIR_MIN equals the
  1182. mathematical value of ((UINTMAX_MAX + 1) - (UINTMAX_MAX + 1) % BASE**6)
  1183. computed without overflow. */
  1184. uint_fast64_t unfair_min = - ((UINTMAX_MAX % base__6 + 1) % base__6);
  1185. if (!dst) {
  1186. dst = emalloc(size_sum(dirlen, prefixlen + suffixlen + 1));
  1187. memcpy(dst, src, dirlen);
  1188. memcpy(dst + dirlen, prefix, prefixlen);
  1189. dst[dirlen + prefixlen + suffixlen] = '\0';
  1190. *name = *namealloc = dst;
  1191. }
  1192. do
  1193. r = get_rand_u64();
  1194. while (unfair_min <= r);
  1195. for (i = 0; i < suffixlen; i++) {
  1196. dst[dirlen + prefixlen + i] = alphabet[r % alphabetlen];
  1197. r /= alphabetlen;
  1198. }
  1199. }
  1200. /* Prepare to write to the file *OUTNAME, using *TEMPNAME to store the
  1201. name of the temporary file that will eventually be renamed to
  1202. *OUTNAME. Assign the temporary file's name to both *OUTNAME and
  1203. *TEMPNAME. If *TEMPNAME is null, allocate the name of any such
  1204. temporary file; otherwise, reuse *TEMPNAME's storage, which is
  1205. already set up and only needs its trailing suffix updated. */
  1206. static FILE *
  1207. open_outfile(char const **outname, char **tempname)
  1208. {
  1209. #if __STDC_VERSION__ < 201112
  1210. static char const fopen_mode[] = "wb";
  1211. #else
  1212. static char const fopen_mode[] = "wbx";
  1213. #endif
  1214. FILE *fp;
  1215. bool dirs_made = false;
  1216. if (!*tempname)
  1217. random_dirent(outname, tempname);
  1218. while (! (fp = fopen(*outname, fopen_mode))) {
  1219. int fopen_errno = errno;
  1220. if (fopen_errno == ENOENT && !dirs_made) {
  1221. mkdirs(*outname, true);
  1222. dirs_made = true;
  1223. } else if (fopen_errno == EEXIST)
  1224. random_dirent(outname, tempname);
  1225. else {
  1226. fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
  1227. progname, directory, *outname, strerror(fopen_errno));
  1228. exit(EXIT_FAILURE);
  1229. }
  1230. }
  1231. return fp;
  1232. }
  1233. /* If TEMPNAME, the result is in the temporary file TEMPNAME even
  1234. though the user wanted it in NAME, so rename TEMPNAME to NAME.
  1235. Report an error and exit if there is trouble. Also, free TEMPNAME. */
  1236. static void
  1237. rename_dest(char *tempname, char const *name)
  1238. {
  1239. if (tempname) {
  1240. if (rename(tempname, name) != 0) {
  1241. int rename_errno = errno;
  1242. remove(tempname);
  1243. fprintf(stderr, _("%s: rename to %s/%s: %s\n"),
  1244. progname, directory, name, strerror(rename_errno));
  1245. exit(EXIT_FAILURE);
  1246. }
  1247. free(tempname);
  1248. }
  1249. }
  1250. /* Create symlink contents suitable for symlinking TARGET to LINKNAME, as a
  1251. freshly allocated string. TARGET should be a relative file name, and
  1252. is relative to the global variable DIRECTORY. LINKNAME can be either
  1253. relative or absolute. */
  1254. static char *
  1255. relname(char const *target, char const *linkname)
  1256. {
  1257. size_t i, taillen, dir_len = 0, dotdots = 0;
  1258. ptrdiff_t dotdotetcsize, linksize = INDEX_MAX;
  1259. char const *f = target;
  1260. char *result = NULL;
  1261. if (*linkname == '/') {
  1262. /* Make F absolute too. */
  1263. size_t len = strlen(directory);
  1264. size_t lenslash = len + (len && directory[len - 1] != '/');
  1265. size_t targetsize = strlen(target) + 1;
  1266. linksize = size_sum(lenslash, targetsize);
  1267. f = result = emalloc(linksize);
  1268. memcpy(result, directory, len);
  1269. result[len] = '/';
  1270. memcpy(result + lenslash, target, targetsize);
  1271. }
  1272. for (i = 0; f[i] && f[i] == linkname[i]; i++)
  1273. if (f[i] == '/')
  1274. dir_len = i + 1;
  1275. for (; linkname[i]; i++)
  1276. dotdots += linkname[i] == '/' && linkname[i - 1] != '/';
  1277. taillen = strlen(f + dir_len);
  1278. dotdotetcsize = size_sum(size_product(dotdots, 3), taillen + 1);
  1279. if (dotdotetcsize <= linksize) {
  1280. if (!result)
  1281. result = emalloc(dotdotetcsize);
  1282. for (i = 0; i < dotdots; i++)
  1283. memcpy(result + 3 * i, "../", 3);
  1284. memmove(result + 3 * dotdots, f + dir_len, taillen + 1);
  1285. }
  1286. return result;
  1287. }
  1288. /* Return true if A and B must have the same parent dir if A and B exist.
  1289. Return false if this is not necessarily true (though it might be true).
  1290. Keep it simple, and do not inspect the file system. */
  1291. ATTRIBUTE_PURE_114833 static bool
  1292. same_parent_dirs(char const *a, char const *b)
  1293. {
  1294. for (; *a == *b; a++, b++)
  1295. if (!*a)
  1296. return true;
  1297. return ! (strchr(a, '/') || strchr(b, '/'));
  1298. }
  1299. static void
  1300. dolink(char const *target, char const *linkname, bool staysymlink)
  1301. {
  1302. bool linkdirs_made = false;
  1303. int link_errno;
  1304. char *tempname = NULL;
  1305. char const *outname = linkname;
  1306. int targetissym = -2, linknameissym = -2;
  1307. check_for_signal();
  1308. if (strcmp(target, "-") == 0) {
  1309. if (remove(linkname) == 0 || errno == ENOENT || errno == ENOTDIR)
  1310. return;
  1311. else {
  1312. char const *e = strerror(errno);
  1313. fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
  1314. progname, directory, linkname, e);
  1315. exit(EXIT_FAILURE);
  1316. }
  1317. }
  1318. while (true) {
  1319. if (linkat(AT_FDCWD, target, AT_FDCWD, outname, AT_SYMLINK_FOLLOW)
  1320. == 0) {
  1321. link_errno = 0;
  1322. break;
  1323. }
  1324. link_errno = errno;
  1325. /* Linux 2.6.16 and 2.6.17 mishandle AT_SYMLINK_FOLLOW. */
  1326. if (link_errno == EINVAL)
  1327. link_errno = ENOTSUP;
  1328. #if HAVE_LINK
  1329. /* If linkat is not supported, fall back on link(A, B).
  1330. However, skip this if A is a relative symlink
  1331. and A and B might not have the same parent directory.
  1332. On some platforms link(A, B) does not follow a symlink A,
  1333. and if A is relative it might misbehave elsewhere. */
  1334. if (link_errno == ENOTSUP
  1335. && (same_parent_dirs(target, outname)
  1336. || 0 <= itssymlink(target, &targetissym))) {
  1337. if (link(target, outname) == 0) {
  1338. link_errno = 0;
  1339. break;
  1340. }
  1341. link_errno = errno;
  1342. }
  1343. #endif
  1344. if (link_errno == EXDEV || link_errno == ENOTSUP)
  1345. break;
  1346. if (link_errno == EEXIST) {
  1347. staysymlink &= !tempname;
  1348. random_dirent(&outname, &tempname);
  1349. if (staysymlink && itssymlink(linkname, &linknameissym))
  1350. break;
  1351. } else if (link_errno == ENOENT && !linkdirs_made) {
  1352. mkdirs(linkname, true);
  1353. linkdirs_made = true;
  1354. } else {
  1355. fprintf(stderr, _("%s: Can't link %s/%s to %s/%s: %s\n"),
  1356. progname, directory, target, directory, outname,
  1357. strerror(link_errno));
  1358. exit(EXIT_FAILURE);
  1359. }
  1360. }
  1361. if (link_errno != 0) {
  1362. bool absolute = *target == '/';
  1363. char *linkalloc = absolute ? NULL : relname(target, linkname);
  1364. char const *contents = absolute ? target : linkalloc;
  1365. int symlink_errno;
  1366. while (true) {
  1367. if (symlink(contents, outname) == 0) {
  1368. symlink_errno = 0;
  1369. break;
  1370. }
  1371. symlink_errno = errno;
  1372. if (symlink_errno == EEXIST)
  1373. random_dirent(&outname, &tempname);
  1374. else if (symlink_errno == ENOENT && !linkdirs_made) {
  1375. mkdirs(linkname, true);
  1376. linkdirs_made = true;
  1377. } else
  1378. break;
  1379. }
  1380. free(linkalloc);
  1381. if (symlink_errno == 0) {
  1382. if (link_errno != ENOTSUP && link_errno != EEXIST)
  1383. warning(_("symbolic link used because hard link failed: %s"),
  1384. strerror(link_errno));
  1385. } else {
  1386. FILE *fp, *tp;
  1387. int c;
  1388. fp = fopen(target, "rb");
  1389. if (!fp) {
  1390. char const *e = strerror(errno);
  1391. fprintf(stderr, _("%s: Can't read %s/%s: %s\n"),
  1392. progname, directory, target, e);
  1393. exit(EXIT_FAILURE);
  1394. }
  1395. tp = open_outfile(&outname, &tempname);
  1396. while ((c = getc(fp)) != EOF)
  1397. putc(c, tp);
  1398. close_file(tp, directory, linkname, tempname);
  1399. close_file(fp, directory, target, NULL);
  1400. if (link_errno != ENOTSUP)
  1401. warning(_("copy used because hard link failed: %s"),
  1402. strerror(link_errno));
  1403. else if (symlink_errno != ENOTSUP)
  1404. warning(_("copy used because symbolic link failed: %s"),
  1405. strerror(symlink_errno));
  1406. }
  1407. }
  1408. rename_dest(tempname, linkname);
  1409. }
  1410. /* Return 1 if NAME is an absolute symbolic link, -1 if it is relative,
  1411. 0 if it is not a symbolic link. If *CACHE is not -2, it is the
  1412. cached result of a previous call to this function with the same NAME. */
  1413. static int
  1414. itssymlink(char const *name, int *cache)
  1415. {
  1416. if (*cache == -2) {
  1417. char c = '\0';
  1418. *cache = readlink(name, &c, 1) < 0 ? 0 : c == '/' ? 1 : -1;
  1419. }
  1420. return *cache;
  1421. }
  1422. /*
  1423. ** Associate sets of rules with zones.
  1424. */
  1425. /*
  1426. ** Sort by rule name.
  1427. */
  1428. static int
  1429. rcomp(const void *cp1, const void *cp2)
  1430. {
  1431. struct rule const *r1 = cp1, *r2 = cp2;
  1432. return strcmp(r1->r_name, r2->r_name);
  1433. }
  1434. static void
  1435. associate(void)
  1436. {
  1437. register struct zone * zp;
  1438. register struct rule * rp;
  1439. register ptrdiff_t i, j, base, out;
  1440. if (1 < nrules) {
  1441. qsort(rules, nrules, sizeof *rules, rcomp);
  1442. for (i = 0; i < nrules - 1; ++i) {
  1443. if (strcmp(rules[i].r_name,
  1444. rules[i + 1].r_name) != 0)
  1445. continue;
  1446. if (rules[i].r_filenum == rules[i + 1].r_filenum)
  1447. continue;
  1448. eat(rules[i].r_filenum, rules[i].r_linenum);
  1449. warning(_("same rule name in multiple files"));
  1450. eat(rules[i + 1].r_filenum, rules[i + 1].r_linenum);
  1451. warning(_("same rule name in multiple files"));
  1452. for (j = i + 2; j < nrules; ++j) {
  1453. if (strcmp(rules[i].r_name,
  1454. rules[j].r_name) != 0)
  1455. break;
  1456. if (rules[i].r_filenum == rules[j].r_filenum)
  1457. continue;
  1458. if (rules[i + 1].r_filenum
  1459. == rules[j].r_filenum)
  1460. continue;
  1461. break;
  1462. }
  1463. i = j - 1;
  1464. }
  1465. }
  1466. for (i = 0; i < nzones; ++i) {
  1467. zp = &zones[i];
  1468. zp->z_rules = NULL;
  1469. zp->z_nrules = 0;
  1470. }
  1471. for (base = 0; base < nrules; base = out) {
  1472. rp = &rules[base];
  1473. for (out = base + 1; out < nrules; ++out)
  1474. if (strcmp(rp->r_name, rules[out].r_name) != 0)
  1475. break;
  1476. for (i = 0; i < nzones; ++i) {
  1477. zp = &zones[i];
  1478. if (strcmp(zp->z_rule, rp->r_name) != 0)
  1479. continue;
  1480. zp->z_rules = rp;
  1481. zp->z_nrules = out - base;
  1482. }
  1483. }
  1484. for (i = 0; i < nzones; ++i) {
  1485. zp = &zones[i];
  1486. if (zp->z_nrules == 0) {
  1487. /*
  1488. ** Maybe we have a local standard time offset.
  1489. */
  1490. eat(zp->z_filenum, zp->z_linenum);
  1491. zp->z_save = getsave(zp->z_rule, &zp->z_isdst);
  1492. /*
  1493. ** Note, though, that if there's no rule,
  1494. ** a '%s' in the format is a bad thing.
  1495. */
  1496. if (zp->z_format_specifier == 's')
  1497. error("%s", _("%s in ruleless zone"));
  1498. }
  1499. }
  1500. if (errors)
  1501. exit(EXIT_FAILURE);
  1502. }
  1503. /* Read a text line from FP into BUF, which is of size BUFSIZE.
  1504. Terminate it with a NUL byte instead of a newline.
  1505. Return true if successful, false if EOF.
  1506. On error, report the error and exit. */
  1507. static bool
  1508. inputline(FILE *fp, char *buf, ptrdiff_t bufsize)
  1509. {
  1510. ptrdiff_t linelen = 0, ch;
  1511. while ((ch = getc(fp)) != '\n') {
  1512. if (ch < 0) {
  1513. if (ferror(fp)) {
  1514. error(_("input error"));
  1515. exit(EXIT_FAILURE);
  1516. }
  1517. if (linelen == 0)
  1518. return false;
  1519. error(_("unterminated line"));
  1520. exit(EXIT_FAILURE);
  1521. }
  1522. if (!ch) {
  1523. error(_("NUL input byte"));
  1524. exit(EXIT_FAILURE);
  1525. }
  1526. buf[linelen++] = ch;
  1527. if (linelen == bufsize) {
  1528. error(_("line too long"));
  1529. exit(EXIT_FAILURE);
  1530. }
  1531. }
  1532. buf[linelen] = '\0';
  1533. return true;
  1534. }
  1535. static void
  1536. infile(int fnum, char const *name)
  1537. {
  1538. register FILE * fp;
  1539. register const struct lookup * lp;
  1540. register bool wantcont;
  1541. register lineno num;
  1542. if (strcmp(name, "-") == 0) {
  1543. fp = stdin;
  1544. } else if ((fp = fopen(name, "r")) == NULL) {
  1545. const char *e = strerror(errno);
  1546. fprintf(stderr, _("%s: Can't open %s: %s\n"),
  1547. progname, name, e);
  1548. exit(EXIT_FAILURE);
  1549. }
  1550. wantcont = false;
  1551. for (num = 1; ; ++num) {
  1552. enum { bufsize_bound
  1553. = (min(INT_MAX, INDEX_MAX) / FORMAT_LEN_GROWTH_BOUND) };
  1554. char buf[min(_POSIX2_LINE_MAX, bufsize_bound)];
  1555. int nfields;
  1556. char *fields[MAX_FIELDS];
  1557. eat(fnum, num);
  1558. if (!inputline(fp, buf, sizeof buf))
  1559. break;
  1560. nfields = getfields(buf, fields,
  1561. sizeof fields / sizeof *fields);
  1562. if (nfields == 0) {
  1563. /* nothing to do */
  1564. } else if (wantcont) {
  1565. wantcont = inzcont(fields, nfields);
  1566. } else {
  1567. struct lookup const *line_codes
  1568. = fnum < 0 ? leap_line_codes : zi_line_codes;
  1569. lp = byword(fields[0], line_codes);
  1570. if (lp == NULL)
  1571. error(_("input line of unknown type"));
  1572. else switch (lp->l_value) {
  1573. case LC_RULE:
  1574. inrule(fields, nfields);
  1575. wantcont = false;
  1576. break;
  1577. case LC_ZONE:
  1578. wantcont = inzone(fields, nfields);
  1579. break;
  1580. case LC_LINK:
  1581. inlink(fields, nfields);
  1582. wantcont = false;
  1583. break;
  1584. case LC_LEAP:
  1585. inleap(fields, nfields);
  1586. wantcont = false;
  1587. break;
  1588. case LC_EXPIRES:
  1589. inexpires(fields, nfields);
  1590. wantcont = false;
  1591. break;
  1592. default: unreachable();
  1593. }
  1594. }
  1595. }
  1596. close_file(fp, NULL, filename(fnum), NULL);
  1597. if (wantcont)
  1598. error(_("expected continuation line not found"));
  1599. }
  1600. /*
  1601. ** Convert a string of one of the forms
  1602. ** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss
  1603. ** into a number of seconds.
  1604. ** A null string maps to zero.
  1605. ** Call error with errstring and return zero on errors.
  1606. */
  1607. static zic_t
  1608. gethms(char const *string, char const *errstring)
  1609. {
  1610. zic_t hh;
  1611. int sign, mm = 0, ss = 0;
  1612. char hhx, mmx, ssx, xr = '0', xs;
  1613. int tenths = 0;
  1614. bool ok = true;
  1615. if (string == NULL || *string == '\0')
  1616. return 0;
  1617. if (*string == '-') {
  1618. sign = -1;
  1619. ++string;
  1620. } else sign = 1;
  1621. switch (sscanf(string,
  1622. "%"SCNdZIC"%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
  1623. &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs)) {
  1624. default: ok = false; break;
  1625. case 8:
  1626. ok = '0' <= xr && xr <= '9';
  1627. ATTRIBUTE_FALLTHROUGH;
  1628. case 7:
  1629. ok &= ssx == '.';
  1630. if (ok && noise)
  1631. warning(_("fractional seconds rejected by"
  1632. " pre-2018 versions of zic"));
  1633. ATTRIBUTE_FALLTHROUGH;
  1634. case 5: ok &= mmx == ':'; ATTRIBUTE_FALLTHROUGH;
  1635. case 3: ok &= hhx == ':'; ATTRIBUTE_FALLTHROUGH;
  1636. case 1: break;
  1637. }
  1638. if (!ok) {
  1639. error("%s", errstring);
  1640. return 0;
  1641. }
  1642. if (hh < 0 ||
  1643. mm < 0 || mm >= MINSPERHOUR ||
  1644. ss < 0 || ss > SECSPERMIN) {
  1645. error("%s", errstring);
  1646. return 0;
  1647. }
  1648. if (ZIC_MAX / SECSPERHOUR < hh) {
  1649. error(_("time overflow"));
  1650. return 0;
  1651. }
  1652. ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even. */
  1653. if (noise && (hh > HOURSPERDAY ||
  1654. (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
  1655. warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
  1656. return oadd(sign * hh * SECSPERHOUR,
  1657. sign * (mm * SECSPERMIN + ss));
  1658. }
  1659. static zic_t
  1660. getsave(char *field, bool *isdst)
  1661. {
  1662. int dst = -1;
  1663. zic_t save;
  1664. ptrdiff_t fieldlen = strlen(field);
  1665. if (fieldlen != 0) {
  1666. char *ep = field + fieldlen - 1;
  1667. switch (*ep) {
  1668. case 'd': dst = 1; *ep = '\0'; break;
  1669. case 's': dst = 0; *ep = '\0'; break;
  1670. }
  1671. }
  1672. save = gethms(field, _("invalid saved time"));
  1673. *isdst = dst < 0 ? save != 0 : dst;
  1674. return save;
  1675. }
  1676. static void
  1677. inrule(char **fields, int nfields)
  1678. {
  1679. struct rule r;
  1680. if (nfields != RULE_FIELDS) {
  1681. error(_("wrong number of fields on Rule line"));
  1682. return;
  1683. }
  1684. switch (*fields[RF_NAME]) {
  1685. case '\0':
  1686. case ' ': case '\f': case '\n': case '\r': case '\t': case '\v':
  1687. case '+': case '-':
  1688. case '0': case '1': case '2': case '3': case '4':
  1689. case '5': case '6': case '7': case '8': case '9':
  1690. error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
  1691. return;
  1692. }
  1693. r.r_filenum = filenum;
  1694. r.r_linenum = linenum;
  1695. r.r_save = getsave(fields[RF_SAVE], &r.r_isdst);
  1696. if (!rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR],
  1697. fields[RF_COMMAND], fields[RF_MONTH], fields[RF_DAY],
  1698. fields[RF_TOD]))
  1699. return;
  1700. r.r_name = estrdup(fields[RF_NAME]);
  1701. r.r_abbrvar = estrdup(fields[RF_ABBRVAR]);
  1702. if (max_abbrvar_len < strlen(r.r_abbrvar))
  1703. max_abbrvar_len = strlen(r.r_abbrvar);
  1704. rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
  1705. rules[nrules++] = r;
  1706. }
  1707. static bool
  1708. inzone(char **fields, int nfields)
  1709. {
  1710. register ptrdiff_t i;
  1711. if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
  1712. error(_("wrong number of fields on Zone line"));
  1713. return false;
  1714. }
  1715. if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0) {
  1716. error(_("\"Zone %s\" line and -l option are mutually exclusive"),
  1717. tzdefault);
  1718. return false;
  1719. }
  1720. if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
  1721. error(_("\"Zone %s\" line and -p option are mutually exclusive"),
  1722. TZDEFRULES);
  1723. return false;
  1724. }
  1725. for (i = 0; i < nzones; ++i)
  1726. if (zones[i].z_name != NULL &&
  1727. strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
  1728. error(_("duplicate zone name %s"
  1729. " (file \"%s\", line %"PRIdMAX")"),
  1730. fields[ZF_NAME],
  1731. filename(zones[i].z_filenum),
  1732. zones[i].z_linenum);
  1733. return false;
  1734. }
  1735. return inzsub(fields, nfields, false);
  1736. }
  1737. static bool
  1738. inzcont(char **fields, int nfields)
  1739. {
  1740. if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
  1741. error(_("wrong number of fields on Zone continuation line"));
  1742. return false;
  1743. }
  1744. return inzsub(fields, nfields, true);
  1745. }
  1746. static bool
  1747. inzsub(char **fields, int nfields, bool iscont)
  1748. {
  1749. register char * cp;
  1750. char * cp1;
  1751. struct zone z;
  1752. int format_len;
  1753. register int i_stdoff, i_rule, i_format;
  1754. register int i_untilyear, i_untilmonth;
  1755. register int i_untilday, i_untiltime;
  1756. register bool hasuntil;
  1757. if (iscont) {
  1758. i_stdoff = ZFC_STDOFF;
  1759. i_rule = ZFC_RULE;
  1760. i_format = ZFC_FORMAT;
  1761. i_untilyear = ZFC_TILYEAR;
  1762. i_untilmonth = ZFC_TILMONTH;
  1763. i_untilday = ZFC_TILDAY;
  1764. i_untiltime = ZFC_TILTIME;
  1765. } else if (!namecheck(fields[ZF_NAME]))
  1766. return false;
  1767. else {
  1768. i_stdoff = ZF_STDOFF;
  1769. i_rule = ZF_RULE;
  1770. i_format = ZF_FORMAT;
  1771. i_untilyear = ZF_TILYEAR;
  1772. i_untilmonth = ZF_TILMONTH;
  1773. i_untilday = ZF_TILDAY;
  1774. i_untiltime = ZF_TILTIME;
  1775. }
  1776. z.z_filenum = filenum;
  1777. z.z_linenum = linenum;
  1778. z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
  1779. if ((cp = strchr(fields[i_format], '%')) != NULL) {
  1780. if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
  1781. || strchr(fields[i_format], '/')) {
  1782. error(_("invalid abbreviation format"));
  1783. return false;
  1784. }
  1785. }
  1786. z.z_format_specifier = cp ? *cp : '\0';
  1787. format_len = strlen(fields[i_format]);
  1788. if (max_format_len < format_len)
  1789. max_format_len = format_len;
  1790. hasuntil = nfields > i_untilyear;
  1791. if (hasuntil) {
  1792. z.z_untilrule.r_filenum = filenum;
  1793. z.z_untilrule.r_linenum = linenum;
  1794. if (!rulesub(
  1795. &z.z_untilrule,
  1796. fields[i_untilyear],
  1797. "only",
  1798. "",
  1799. (nfields > i_untilmonth) ?
  1800. fields[i_untilmonth] : "Jan",
  1801. (nfields > i_untilday) ? fields[i_untilday] : "1",
  1802. (nfields > i_untiltime) ? fields[i_untiltime] : "0"))
  1803. return false;
  1804. z.z_untiltime = rpytime(&z.z_untilrule,
  1805. z.z_untilrule.r_loyear);
  1806. if (iscont && nzones > 0 &&
  1807. z.z_untiltime > min_time &&
  1808. z.z_untiltime < max_time &&
  1809. zones[nzones - 1].z_untiltime > min_time &&
  1810. zones[nzones - 1].z_untiltime < max_time &&
  1811. zones[nzones - 1].z_untiltime >= z.z_untiltime) {
  1812. error(_("Zone continuation line end time is"
  1813. " not after end time of previous line"));
  1814. return false;
  1815. }
  1816. }
  1817. z.z_name = iscont ? NULL : estrdup(fields[ZF_NAME]);
  1818. z.z_rule = estrdup(fields[i_rule]);
  1819. z.z_format = cp1 = estrdup(fields[i_format]);
  1820. if (z.z_format_specifier == 'z') {
  1821. cp1[cp - fields[i_format]] = 's';
  1822. if (noise)
  1823. warning(_("format '%s' not handled by pre-2015 versions of zic"),
  1824. fields[i_format]);
  1825. }
  1826. zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
  1827. zones[nzones++] = z;
  1828. /*
  1829. ** If there was an UNTIL field on this line,
  1830. ** there's more information about the zone on the next line.
  1831. */
  1832. return hasuntil;
  1833. }
  1834. static zic_t
  1835. getleapdatetime(char **fields, bool expire_line)
  1836. {
  1837. register const char * cp;
  1838. register const struct lookup * lp;
  1839. register zic_t i, j;
  1840. zic_t year;
  1841. int month, day;
  1842. zic_t dayoff, tod;
  1843. zic_t t;
  1844. char xs;
  1845. dayoff = 0;
  1846. cp = fields[LP_YEAR];
  1847. if (sscanf(cp, "%"SCNdZIC"%c", &year, &xs) != 1) {
  1848. /*
  1849. ** Leapin' Lizards!
  1850. */
  1851. error(_("invalid leaping year"));
  1852. return -1;
  1853. }
  1854. if (!expire_line) {
  1855. if (!leapseen || leapmaxyear < year)
  1856. leapmaxyear = year;
  1857. if (!leapseen || leapminyear > year)
  1858. leapminyear = year;
  1859. leapseen = true;
  1860. }
  1861. j = EPOCH_YEAR;
  1862. while (j != year) {
  1863. if (year > j) {
  1864. i = len_years[isleap(j)];
  1865. ++j;
  1866. } else {
  1867. --j;
  1868. i = -len_years[isleap(j)];
  1869. }
  1870. dayoff = oadd(dayoff, i);
  1871. }
  1872. if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
  1873. error(_("invalid month name"));
  1874. return -1;
  1875. }
  1876. month = lp->l_value;
  1877. j = TM_JANUARY;
  1878. while (j != month) {
  1879. i = len_months[isleap(year)][j];
  1880. dayoff = oadd(dayoff, i);
  1881. ++j;
  1882. }
  1883. cp = fields[LP_DAY];
  1884. if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
  1885. day <= 0 || day > len_months[isleap(year)][month]) {
  1886. error(_("invalid day of month"));
  1887. return -1;
  1888. }
  1889. dayoff = oadd(dayoff, day - 1);
  1890. if (dayoff < min_time / SECSPERDAY) {
  1891. error(_("time too small"));
  1892. return -1;
  1893. }
  1894. if (dayoff > max_time / SECSPERDAY) {
  1895. error(_("time too large"));
  1896. return -1;
  1897. }
  1898. t = dayoff * SECSPERDAY;
  1899. tod = gethms(fields[LP_TIME], _("invalid time of day"));
  1900. t = tadd(t, tod);
  1901. if (t < 0)
  1902. error(_("leap second precedes Epoch"));
  1903. return t;
  1904. }
  1905. static void
  1906. inleap(char **fields, int nfields)
  1907. {
  1908. if (nfields != LEAP_FIELDS)
  1909. error(_("wrong number of fields on Leap line"));
  1910. else {
  1911. zic_t t = getleapdatetime(fields, false);
  1912. if (0 <= t) {
  1913. struct lookup const *lp = byword(fields[LP_ROLL], leap_types);
  1914. if (!lp)
  1915. error(_("invalid Rolling/Stationary field on Leap line"));
  1916. else {
  1917. int correction = 0;
  1918. if (!fields[LP_CORR][0]) /* infile() turns "-" into "". */
  1919. correction = -1;
  1920. else if (strcmp(fields[LP_CORR], "+") == 0)
  1921. correction = 1;
  1922. else
  1923. error(_("invalid CORRECTION field on Leap line"));
  1924. if (correction)
  1925. leapadd(t, correction, lp->l_value);
  1926. }
  1927. }
  1928. }
  1929. }
  1930. static void
  1931. inexpires(char **fields, int nfields)
  1932. {
  1933. if (nfields != EXPIRES_FIELDS)
  1934. error(_("wrong number of fields on Expires line"));
  1935. else if (0 <= leapexpires)
  1936. error(_("multiple Expires lines"));
  1937. else
  1938. leapexpires = getleapdatetime(fields, true);
  1939. }
  1940. static void
  1941. inlink(char **fields, int nfields)
  1942. {
  1943. struct link l;
  1944. if (nfields != LINK_FIELDS) {
  1945. error(_("wrong number of fields on Link line"));
  1946. return;
  1947. }
  1948. if (*fields[LF_TARGET] == '\0') {
  1949. error(_("blank TARGET field on Link line"));
  1950. return;
  1951. }
  1952. if (! namecheck(fields[LF_LINKNAME]))
  1953. return;
  1954. l.l_filenum = filenum;
  1955. l.l_linenum = linenum;
  1956. l.l_target = estrdup(fields[LF_TARGET]);
  1957. l.l_linkname = estrdup(fields[LF_LINKNAME]);
  1958. links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
  1959. links[nlinks++] = l;
  1960. }
  1961. static bool
  1962. rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
  1963. const char *typep, const char *monthp, const char *dayp,
  1964. const char *timep)
  1965. {
  1966. register const struct lookup * lp;
  1967. register const char * cp;
  1968. register char * dp;
  1969. register char * ep;
  1970. char xs;
  1971. if ((lp = byword(monthp, mon_names)) == NULL) {
  1972. error(_("invalid month name"));
  1973. return false;
  1974. }
  1975. rp->r_month = lp->l_value;
  1976. rp->r_todisstd = false;
  1977. rp->r_todisut = false;
  1978. dp = estrdup(timep);
  1979. if (*dp != '\0') {
  1980. ep = dp + strlen(dp) - 1;
  1981. switch (lowerit(*ep)) {
  1982. case 's': /* Standard */
  1983. rp->r_todisstd = true;
  1984. rp->r_todisut = false;
  1985. *ep = '\0';
  1986. break;
  1987. case 'w': /* Wall */
  1988. rp->r_todisstd = false;
  1989. rp->r_todisut = false;
  1990. *ep = '\0';
  1991. break;
  1992. case 'g': /* Greenwich */
  1993. case 'u': /* Universal */
  1994. case 'z': /* Zulu */
  1995. rp->r_todisstd = true;
  1996. rp->r_todisut = true;
  1997. *ep = '\0';
  1998. break;
  1999. }
  2000. }
  2001. rp->r_tod = gethms(dp, _("invalid time of day"));
  2002. free(dp);
  2003. /*
  2004. ** Year work.
  2005. */
  2006. cp = loyearp;
  2007. lp = byword(cp, begin_years);
  2008. if (lp) switch (lp->l_value) {
  2009. case YR_MINIMUM:
  2010. warning(_("FROM year \"%s\" is obsolete;"
  2011. " treated as %d"),
  2012. cp, YEAR_32BIT_MIN - 1);
  2013. rp->r_loyear = YEAR_32BIT_MIN - 1;
  2014. break;
  2015. default: unreachable();
  2016. } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_loyear, &xs) != 1) {
  2017. error(_("invalid starting year"));
  2018. return false;
  2019. }
  2020. cp = hiyearp;
  2021. lp = byword(cp, end_years);
  2022. rp->r_hiwasnum = lp == NULL;
  2023. if (!rp->r_hiwasnum) switch (lp->l_value) {
  2024. case YR_MAXIMUM:
  2025. rp->r_hiyear = ZIC_MAX;
  2026. break;
  2027. case YR_ONLY:
  2028. rp->r_hiyear = rp->r_loyear;
  2029. break;
  2030. default: unreachable();
  2031. } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_hiyear, &xs) != 1) {
  2032. error(_("invalid ending year"));
  2033. return false;
  2034. }
  2035. if (rp->r_loyear > rp->r_hiyear) {
  2036. error(_("starting year greater than ending year"));
  2037. return false;
  2038. }
  2039. if (*typep != '\0') {
  2040. error(_("year type \"%s\" is unsupported; use \"-\" instead"),
  2041. typep);
  2042. return false;
  2043. }
  2044. /*
  2045. ** Day work.
  2046. ** Accept things such as:
  2047. ** 1
  2048. ** lastSunday
  2049. ** last-Sunday (undocumented; warn about this)
  2050. ** Sun<=20
  2051. ** Sun>=7
  2052. */
  2053. dp = estrdup(dayp);
  2054. if ((lp = byword(dp, lasts)) != NULL) {
  2055. rp->r_dycode = DC_DOWLEQ;
  2056. rp->r_wday = lp->l_value;
  2057. rp->r_dayofmonth = len_months[1][rp->r_month];
  2058. } else {
  2059. if ((ep = strchr(dp, '<')) != NULL)
  2060. rp->r_dycode = DC_DOWLEQ;
  2061. else if ((ep = strchr(dp, '>')) != NULL)
  2062. rp->r_dycode = DC_DOWGEQ;
  2063. else {
  2064. ep = dp;
  2065. rp->r_dycode = DC_DOM;
  2066. }
  2067. if (rp->r_dycode != DC_DOM) {
  2068. *ep++ = 0;
  2069. if (*ep++ != '=') {
  2070. error(_("invalid day of month"));
  2071. free(dp);
  2072. return false;
  2073. }
  2074. if ((lp = byword(dp, wday_names)) == NULL) {
  2075. error(_("invalid weekday name"));
  2076. free(dp);
  2077. return false;
  2078. }
  2079. rp->r_wday = lp->l_value;
  2080. }
  2081. if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 ||
  2082. rp->r_dayofmonth <= 0 ||
  2083. (rp->r_dayofmonth > len_months[1][rp->r_month])) {
  2084. error(_("invalid day of month"));
  2085. free(dp);
  2086. return false;
  2087. }
  2088. }
  2089. free(dp);
  2090. return true;
  2091. }
  2092. static void
  2093. convert(uint_fast32_t val, char *buf)
  2094. {
  2095. register int i;
  2096. register int shift;
  2097. unsigned char *const b = (unsigned char *) buf;
  2098. for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
  2099. b[i] = (val >> shift) & 0xff;
  2100. }
  2101. static void
  2102. convert64(uint_fast64_t val, char *buf)
  2103. {
  2104. register int i;
  2105. register int shift;
  2106. unsigned char *const b = (unsigned char *) buf;
  2107. for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
  2108. b[i] = (val >> shift) & 0xff;
  2109. }
  2110. static void
  2111. puttzcode(zic_t val, FILE *fp)
  2112. {
  2113. char buf[4];
  2114. convert(val, buf);
  2115. fwrite(buf, sizeof buf, 1, fp);
  2116. }
  2117. static void
  2118. puttzcodepass(zic_t val, FILE *fp, int pass)
  2119. {
  2120. if (pass == 1)
  2121. puttzcode(val, fp);
  2122. else {
  2123. char buf[8];
  2124. convert64(val, buf);
  2125. fwrite(buf, sizeof buf, 1, fp);
  2126. }
  2127. }
  2128. static int
  2129. atcomp(const void *avp, const void *bvp)
  2130. {
  2131. struct attype const *ap = avp, *bp = bvp;
  2132. zic_t a = ap->at, b = bp->at;
  2133. return a < b ? -1 : a > b;
  2134. }
  2135. struct timerange {
  2136. int defaulttype;
  2137. ptrdiff_t base, count;
  2138. int leapbase, leapcount;
  2139. bool leapexpiry;
  2140. };
  2141. static struct timerange
  2142. limitrange(struct timerange r, zic_t lo, zic_t hi,
  2143. zic_t const *ats, unsigned char const *types)
  2144. {
  2145. /* Omit ordinary transitions < LO. */
  2146. while (0 < r.count && ats[r.base] < lo) {
  2147. r.defaulttype = types[r.base];
  2148. r.count--;
  2149. r.base++;
  2150. }
  2151. /* Omit as many initial leap seconds as possible, such that the
  2152. first leap second in the truncated list is <= LO, and is a
  2153. positive leap second if and only if it has a positive correction.
  2154. This supports common TZif readers that assume that the first leap
  2155. second is positive if and only if its correction is positive. */
  2156. while (1 < r.leapcount && trans[r.leapbase + 1] <= lo) {
  2157. r.leapcount--;
  2158. r.leapbase++;
  2159. }
  2160. while (0 < r.leapbase
  2161. && ((corr[r.leapbase - 1] < corr[r.leapbase])
  2162. != (0 < corr[r.leapbase]))) {
  2163. r.leapcount++;
  2164. r.leapbase--;
  2165. }
  2166. /* Omit ordinary and leap second transitions greater than HI + 1. */
  2167. if (hi < max_time) {
  2168. while (0 < r.count && hi + 1 < ats[r.base + r.count - 1])
  2169. r.count--;
  2170. while (0 < r.leapcount && hi + 1 < trans[r.leapbase + r.leapcount - 1])
  2171. r.leapcount--;
  2172. }
  2173. /* Determine whether to append an expiration to the leap second table. */
  2174. r.leapexpiry = 0 <= leapexpires && leapexpires - 1 <= hi;
  2175. return r;
  2176. }
  2177. static void
  2178. writezone(const char *const name, const char *const string, char version,
  2179. int defaulttype)
  2180. {
  2181. register FILE * fp;
  2182. register ptrdiff_t i, j;
  2183. register int pass;
  2184. char *tempname = NULL;
  2185. char const *outname = name;
  2186. /* Allocate the ATS and TYPES arrays via a single malloc,
  2187. as this is a bit faster. Do not malloc(0) if !timecnt,
  2188. as that might return NULL even on success. */
  2189. zic_t *ats = emalloc(align_to(size_product(timecnt + !timecnt,
  2190. sizeof *ats + 1),
  2191. alignof(zic_t)));
  2192. void *typesptr = ats + timecnt;
  2193. unsigned char *types = typesptr;
  2194. struct timerange rangeall = {0}, range32, range64;
  2195. /*
  2196. ** Sort.
  2197. */
  2198. if (timecnt > 1)
  2199. qsort(attypes, timecnt, sizeof *attypes, atcomp);
  2200. /*
  2201. ** Optimize.
  2202. */
  2203. {
  2204. ptrdiff_t fromi, toi;
  2205. toi = 0;
  2206. fromi = 0;
  2207. for ( ; fromi < timecnt; ++fromi) {
  2208. if (toi != 0
  2209. && ((attypes[fromi].at
  2210. + utoffs[attypes[toi - 1].type])
  2211. <= (attypes[toi - 1].at
  2212. + utoffs[toi == 1 ? 0
  2213. : attypes[toi - 2].type]))) {
  2214. attypes[toi - 1].type =
  2215. attypes[fromi].type;
  2216. continue;
  2217. }
  2218. if (toi == 0
  2219. || attypes[fromi].dontmerge
  2220. || (utoffs[attypes[toi - 1].type]
  2221. != utoffs[attypes[fromi].type])
  2222. || (isdsts[attypes[toi - 1].type]
  2223. != isdsts[attypes[fromi].type])
  2224. || (desigidx[attypes[toi - 1].type]
  2225. != desigidx[attypes[fromi].type]))
  2226. attypes[toi++] = attypes[fromi];
  2227. }
  2228. timecnt = toi;
  2229. }
  2230. if (noise && timecnt > 1200) {
  2231. if (timecnt > TZ_MAX_TIMES)
  2232. warning(_("reference clients mishandle"
  2233. " more than %d transition times"),
  2234. TZ_MAX_TIMES);
  2235. else
  2236. warning(_("pre-2014 clients may mishandle"
  2237. " more than 1200 transition times"));
  2238. }
  2239. /*
  2240. ** Transfer.
  2241. */
  2242. for (i = 0; i < timecnt; ++i) {
  2243. ats[i] = attypes[i].at;
  2244. types[i] = attypes[i].type;
  2245. }
  2246. /*
  2247. ** Correct for leap seconds.
  2248. */
  2249. for (i = 0; i < timecnt; ++i) {
  2250. j = leapcnt;
  2251. while (--j >= 0)
  2252. if (ats[i] > trans[j] - corr[j]) {
  2253. ats[i] = tadd(ats[i], corr[j]);
  2254. break;
  2255. }
  2256. }
  2257. rangeall.defaulttype = defaulttype;
  2258. rangeall.count = timecnt;
  2259. rangeall.leapcount = leapcnt;
  2260. range64 = limitrange(rangeall, lo_time,
  2261. max(hi_time,
  2262. redundant_time - (ZIC_MIN < redundant_time)),
  2263. ats, types);
  2264. range32 = limitrange(range64, ZIC32_MIN, ZIC32_MAX, ats, types);
  2265. /* TZif version 4 is needed if a no-op transition is appended to
  2266. indicate the expiration of the leap second table, or if the first
  2267. leap second transition is not to a +1 or -1 correction. */
  2268. for (pass = 1; pass <= 2; pass++) {
  2269. struct timerange const *r = pass == 1 ? &range32 : &range64;
  2270. if (pass == 1 && !want_bloat())
  2271. continue;
  2272. if (r->leapexpiry) {
  2273. if (noise)
  2274. warning(_("%s: pre-2021b clients may mishandle"
  2275. " leap second expiry"),
  2276. name);
  2277. version = '4';
  2278. }
  2279. if (0 < r->leapcount
  2280. && corr[r->leapbase] != 1 && corr[r->leapbase] != -1) {
  2281. if (noise)
  2282. warning(_("%s: pre-2021b clients may mishandle"
  2283. " leap second table truncation"),
  2284. name);
  2285. version = '4';
  2286. }
  2287. if (version == '4')
  2288. break;
  2289. }
  2290. fp = open_outfile(&outname, &tempname);
  2291. for (pass = 1; pass <= 2; ++pass) {
  2292. register ptrdiff_t thistimei, thistimecnt, thistimelim;
  2293. register int thisleapi, thisleapcnt, thisleaplim;
  2294. struct tzhead tzh;
  2295. int pretranstype = -1, thisdefaulttype;
  2296. bool locut, hicut, thisleapexpiry;
  2297. zic_t lo, thismin, thismax;
  2298. int old0;
  2299. char omittype[TZ_MAX_TYPES];
  2300. int typemap[TZ_MAX_TYPES];
  2301. int thistypecnt, stdcnt, utcnt;
  2302. char thischars[TZ_MAX_CHARS];
  2303. int thischarcnt;
  2304. bool toomanytimes;
  2305. int indmap[TZ_MAX_CHARS];
  2306. if (pass == 1) {
  2307. thisdefaulttype = range32.defaulttype;
  2308. thistimei = range32.base;
  2309. thistimecnt = range32.count;
  2310. toomanytimes = thistimecnt >> 31 >> 1 != 0;
  2311. thisleapi = range32.leapbase;
  2312. thisleapcnt = range32.leapcount;
  2313. thisleapexpiry = range32.leapexpiry;
  2314. thismin = ZIC32_MIN;
  2315. thismax = ZIC32_MAX;
  2316. } else {
  2317. thisdefaulttype = range64.defaulttype;
  2318. thistimei = range64.base;
  2319. thistimecnt = range64.count;
  2320. toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
  2321. thisleapi = range64.leapbase;
  2322. thisleapcnt = range64.leapcount;
  2323. thisleapexpiry = range64.leapexpiry;
  2324. thismin = min_time;
  2325. thismax = max_time;
  2326. }
  2327. if (toomanytimes)
  2328. error(_("too many transition times"));
  2329. locut = thismin < lo_time && lo_time <= thismax;
  2330. hicut = thismin <= hi_time && hi_time < thismax;
  2331. thistimelim = thistimei + thistimecnt;
  2332. memset(omittype, true, typecnt);
  2333. /* Determine whether to output a transition before the first
  2334. transition in range. This is needed when the output is
  2335. truncated at the start, and is also useful when catering to
  2336. buggy 32-bit clients that do not use time type 0 for
  2337. timestamps before the first transition. */
  2338. if ((locut || (pass == 1 && thistimei))
  2339. && ! (thistimecnt && ats[thistimei] == lo_time)) {
  2340. pretranstype = thisdefaulttype;
  2341. omittype[pretranstype] = false;
  2342. }
  2343. /* Arguably the default time type in the 32-bit data
  2344. should be range32.defaulttype, which is suited for
  2345. timestamps just before ZIC32_MIN. However, zic
  2346. traditionally used the time type of the indefinite
  2347. past instead. Internet RFC 8532 says readers should
  2348. ignore 32-bit data, so this discrepancy matters only
  2349. to obsolete readers where the traditional type might
  2350. be more appropriate even if it's "wrong". So, use
  2351. the historical zic value, unless -r specifies a low
  2352. cutoff that excludes some 32-bit timestamps. */
  2353. if (pass == 1 && lo_time <= thismin)
  2354. thisdefaulttype = range64.defaulttype;
  2355. if (locut)
  2356. thisdefaulttype = unspecifiedtype;
  2357. omittype[thisdefaulttype] = false;
  2358. for (i = thistimei; i < thistimelim; i++)
  2359. omittype[types[i]] = false;
  2360. if (hicut)
  2361. omittype[unspecifiedtype] = false;
  2362. /* Reorder types to make THISDEFAULTTYPE type 0.
  2363. Use TYPEMAP to swap OLD0 and THISDEFAULTTYPE so that
  2364. THISDEFAULTTYPE appears as type 0 in the output instead
  2365. of OLD0. TYPEMAP also omits unused types. */
  2366. old0 = strlen(omittype);
  2367. #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
  2368. /*
  2369. ** For some pre-2011 systems: if the last-to-be-written
  2370. ** standard (or daylight) type has an offset different from the
  2371. ** most recently used offset,
  2372. ** append an (unused) copy of the most recently used type
  2373. ** (to help get global "altzone" and "timezone" variables
  2374. ** set correctly).
  2375. */
  2376. if (want_bloat()) {
  2377. register int mrudst, mrustd, hidst, histd, type;
  2378. hidst = histd = mrudst = mrustd = -1;
  2379. if (0 <= pretranstype) {
  2380. if (isdsts[pretranstype])
  2381. mrudst = pretranstype;
  2382. else
  2383. mrustd = pretranstype;
  2384. }
  2385. for (i = thistimei; i < thistimelim; i++)
  2386. if (isdsts[types[i]])
  2387. mrudst = types[i];
  2388. else mrustd = types[i];
  2389. for (i = old0; i < typecnt; i++) {
  2390. int h = (i == old0 ? thisdefaulttype
  2391. : i == thisdefaulttype ? old0 : i);
  2392. if (!omittype[h]) {
  2393. if (isdsts[h])
  2394. hidst = i;
  2395. else
  2396. histd = i;
  2397. }
  2398. }
  2399. if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
  2400. utoffs[hidst] != utoffs[mrudst]) {
  2401. isdsts[mrudst] = -1;
  2402. type = addtype(utoffs[mrudst],
  2403. &chars[desigidx[mrudst]],
  2404. true,
  2405. ttisstds[mrudst],
  2406. ttisuts[mrudst]);
  2407. isdsts[mrudst] = 1;
  2408. omittype[type] = false;
  2409. }
  2410. if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
  2411. utoffs[histd] != utoffs[mrustd]) {
  2412. isdsts[mrustd] = -1;
  2413. type = addtype(utoffs[mrustd],
  2414. &chars[desigidx[mrustd]],
  2415. false,
  2416. ttisstds[mrustd],
  2417. ttisuts[mrustd]);
  2418. isdsts[mrustd] = 0;
  2419. omittype[type] = false;
  2420. }
  2421. }
  2422. #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
  2423. thistypecnt = 0;
  2424. for (i = old0; i < typecnt; i++)
  2425. if (!omittype[i])
  2426. typemap[i == old0 ? thisdefaulttype
  2427. : i == thisdefaulttype ? old0 : i]
  2428. = thistypecnt++;
  2429. for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
  2430. indmap[i] = -1;
  2431. thischarcnt = stdcnt = utcnt = 0;
  2432. for (i = old0; i < typecnt; i++) {
  2433. register char * thisabbr;
  2434. if (omittype[i])
  2435. continue;
  2436. if (ttisstds[i])
  2437. stdcnt = thistypecnt;
  2438. if (ttisuts[i])
  2439. utcnt = thistypecnt;
  2440. if (indmap[desigidx[i]] >= 0)
  2441. continue;
  2442. thisabbr = &chars[desigidx[i]];
  2443. for (j = 0; j < thischarcnt; ++j)
  2444. if (strcmp(&thischars[j], thisabbr) == 0)
  2445. break;
  2446. if (j == thischarcnt) {
  2447. strcpy(&thischars[thischarcnt], thisabbr);
  2448. thischarcnt += strlen(thisabbr) + 1;
  2449. }
  2450. indmap[desigidx[i]] = j;
  2451. }
  2452. if (pass == 1 && !want_bloat()) {
  2453. hicut = thisleapexpiry = false;
  2454. pretranstype = -1;
  2455. thistimecnt = thisleapcnt = 0;
  2456. thistypecnt = thischarcnt = 1;
  2457. }
  2458. #define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
  2459. memset(&tzh, 0, sizeof tzh);
  2460. memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
  2461. tzh.tzh_version[0] = version;
  2462. convert(utcnt, tzh.tzh_ttisutcnt);
  2463. convert(stdcnt, tzh.tzh_ttisstdcnt);
  2464. convert(thisleapcnt + thisleapexpiry, tzh.tzh_leapcnt);
  2465. convert((0 <= pretranstype) + thistimecnt + hicut,
  2466. tzh.tzh_timecnt);
  2467. convert(thistypecnt, tzh.tzh_typecnt);
  2468. convert(thischarcnt, tzh.tzh_charcnt);
  2469. DO(tzh_magic);
  2470. DO(tzh_version);
  2471. DO(tzh_reserved);
  2472. DO(tzh_ttisutcnt);
  2473. DO(tzh_ttisstdcnt);
  2474. DO(tzh_leapcnt);
  2475. DO(tzh_timecnt);
  2476. DO(tzh_typecnt);
  2477. DO(tzh_charcnt);
  2478. #undef DO
  2479. if (pass == 1 && !want_bloat()) {
  2480. /* Output a minimal data block with just one time type. */
  2481. puttzcode(0, fp); /* utoff */
  2482. putc(0, fp); /* dst */
  2483. putc(0, fp); /* index of abbreviation */
  2484. putc(0, fp); /* empty-string abbreviation */
  2485. continue;
  2486. }
  2487. /* Output a LO_TIME transition if needed; see limitrange.
  2488. But do not go below the minimum representable value
  2489. for this pass. */
  2490. lo = pass == 1 && lo_time < ZIC32_MIN ? ZIC32_MIN : lo_time;
  2491. if (0 <= pretranstype)
  2492. puttzcodepass(lo, fp, pass);
  2493. for (i = thistimei; i < thistimelim; ++i) {
  2494. puttzcodepass(ats[i], fp, pass);
  2495. }
  2496. if (hicut)
  2497. puttzcodepass(hi_time + 1, fp, pass);
  2498. if (0 <= pretranstype)
  2499. putc(typemap[pretranstype], fp);
  2500. for (i = thistimei; i < thistimelim; i++)
  2501. putc(typemap[types[i]], fp);
  2502. if (hicut)
  2503. putc(typemap[unspecifiedtype], fp);
  2504. for (i = old0; i < typecnt; i++) {
  2505. int h = (i == old0 ? thisdefaulttype
  2506. : i == thisdefaulttype ? old0 : i);
  2507. if (!omittype[h]) {
  2508. puttzcode(utoffs[h], fp);
  2509. putc(isdsts[h], fp);
  2510. putc(indmap[desigidx[h]], fp);
  2511. }
  2512. }
  2513. if (thischarcnt != 0)
  2514. fwrite(thischars, sizeof thischars[0],
  2515. thischarcnt, fp);
  2516. thisleaplim = thisleapi + thisleapcnt;
  2517. for (i = thisleapi; i < thisleaplim; ++i) {
  2518. register zic_t todo;
  2519. if (roll[i]) {
  2520. if (timecnt == 0 || trans[i] < ats[0]) {
  2521. j = 0;
  2522. while (isdsts[j])
  2523. if (++j >= typecnt) {
  2524. j = 0;
  2525. break;
  2526. }
  2527. } else {
  2528. j = 1;
  2529. while (j < timecnt &&
  2530. trans[i] >= ats[j])
  2531. ++j;
  2532. j = types[j - 1];
  2533. }
  2534. todo = tadd(trans[i], -utoffs[j]);
  2535. } else todo = trans[i];
  2536. puttzcodepass(todo, fp, pass);
  2537. puttzcode(corr[i], fp);
  2538. }
  2539. if (thisleapexpiry) {
  2540. /* Append a no-op leap correction indicating when the leap
  2541. second table expires. Although this does not conform to
  2542. Internet RFC 8536, most clients seem to accept this and
  2543. the plan is to amend the RFC to allow this in version 4
  2544. TZif files. */
  2545. puttzcodepass(leapexpires, fp, pass);
  2546. puttzcode(thisleaplim ? corr[thisleaplim - 1] : 0, fp);
  2547. }
  2548. if (stdcnt != 0)
  2549. for (i = old0; i < typecnt; i++)
  2550. if (!omittype[i])
  2551. putc(ttisstds[i], fp);
  2552. if (utcnt != 0)
  2553. for (i = old0; i < typecnt; i++)
  2554. if (!omittype[i])
  2555. putc(ttisuts[i], fp);
  2556. }
  2557. fprintf(fp, "\n%s\n", string);
  2558. close_file(fp, directory, name, tempname);
  2559. rename_dest(tempname, name);
  2560. free(ats);
  2561. }
  2562. static char const *
  2563. abbroffset(char *buf, zic_t offset)
  2564. {
  2565. char sign = '+';
  2566. int seconds, minutes;
  2567. if (offset < 0) {
  2568. offset = -offset;
  2569. sign = '-';
  2570. }
  2571. seconds = offset % SECSPERMIN;
  2572. offset /= SECSPERMIN;
  2573. minutes = offset % MINSPERHOUR;
  2574. offset /= MINSPERHOUR;
  2575. if (100 <= offset) {
  2576. error(_("%%z UT offset magnitude exceeds 99:59:59"));
  2577. return "%z";
  2578. } else {
  2579. char *p = buf;
  2580. *p++ = sign;
  2581. *p++ = '0' + offset / 10;
  2582. *p++ = '0' + offset % 10;
  2583. if (minutes | seconds) {
  2584. *p++ = '0' + minutes / 10;
  2585. *p++ = '0' + minutes % 10;
  2586. if (seconds) {
  2587. *p++ = '0' + seconds / 10;
  2588. *p++ = '0' + seconds % 10;
  2589. }
  2590. }
  2591. *p = '\0';
  2592. return buf;
  2593. }
  2594. }
  2595. static char const disable_percent_s[] = "";
  2596. static ptrdiff_t
  2597. doabbr(char *abbr, struct zone const *zp, char const *letters,
  2598. bool isdst, zic_t save, bool doquotes)
  2599. {
  2600. register char * cp;
  2601. register char * slashp;
  2602. ptrdiff_t len;
  2603. char const *format = zp->z_format;
  2604. slashp = strchr(format, '/');
  2605. if (slashp == NULL) {
  2606. char letterbuf[PERCENT_Z_LEN_BOUND + 1];
  2607. if (zp->z_format_specifier == 'z')
  2608. letters = abbroffset(letterbuf, zp->z_stdoff + save);
  2609. else if (!letters)
  2610. letters = "%s";
  2611. else if (letters == disable_percent_s)
  2612. return 0;
  2613. sprintf(abbr, format, letters);
  2614. } else if (isdst) {
  2615. strcpy(abbr, slashp + 1);
  2616. } else {
  2617. memcpy(abbr, format, slashp - format);
  2618. abbr[slashp - format] = '\0';
  2619. }
  2620. len = strlen(abbr);
  2621. if (!doquotes)
  2622. return len;
  2623. for (cp = abbr; is_alpha(*cp); cp++)
  2624. continue;
  2625. if (len > 0 && *cp == '\0')
  2626. return len;
  2627. abbr[len + 2] = '\0';
  2628. abbr[len + 1] = '>';
  2629. memmove(abbr + 1, abbr, len);
  2630. abbr[0] = '<';
  2631. return len + 2;
  2632. }
  2633. static void
  2634. updateminmax(const zic_t x)
  2635. {
  2636. if (min_year > x)
  2637. min_year = x;
  2638. if (max_year < x)
  2639. max_year = x;
  2640. }
  2641. static int
  2642. stringoffset(char *result, zic_t offset)
  2643. {
  2644. register int hours;
  2645. register int minutes;
  2646. register int seconds;
  2647. bool negative = offset < 0;
  2648. int len = negative;
  2649. if (negative) {
  2650. offset = -offset;
  2651. result[0] = '-';
  2652. }
  2653. seconds = offset % SECSPERMIN;
  2654. offset /= SECSPERMIN;
  2655. minutes = offset % MINSPERHOUR;
  2656. offset /= MINSPERHOUR;
  2657. hours = offset;
  2658. if (hours >= HOURSPERDAY * DAYSPERWEEK) {
  2659. result[0] = '\0';
  2660. return 0;
  2661. }
  2662. len += sprintf(result + len, "%d", hours);
  2663. if (minutes != 0 || seconds != 0) {
  2664. len += sprintf(result + len, ":%02d", minutes);
  2665. if (seconds != 0)
  2666. len += sprintf(result + len, ":%02d", seconds);
  2667. }
  2668. return len;
  2669. }
  2670. static int
  2671. stringrule(char *result, struct rule *const rp, zic_t save, zic_t stdoff)
  2672. {
  2673. register zic_t tod = rp->r_tod;
  2674. register int compat = 0;
  2675. if (rp->r_dycode == DC_DOM) {
  2676. register int month, total;
  2677. if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
  2678. return -1;
  2679. total = 0;
  2680. for (month = 0; month < rp->r_month; ++month)
  2681. total += len_months[0][month];
  2682. /* Omit the "J" in Jan and Feb, as that's shorter. */
  2683. if (rp->r_month <= 1)
  2684. result += sprintf(result, "%d", total + rp->r_dayofmonth - 1);
  2685. else
  2686. result += sprintf(result, "J%d", total + rp->r_dayofmonth);
  2687. } else {
  2688. register int week;
  2689. register int wday = rp->r_wday;
  2690. register int wdayoff;
  2691. if (rp->r_dycode == DC_DOWGEQ) {
  2692. wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK;
  2693. if (wdayoff)
  2694. compat = 2013;
  2695. wday -= wdayoff;
  2696. tod += wdayoff * SECSPERDAY;
  2697. week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK;
  2698. } else if (rp->r_dycode == DC_DOWLEQ) {
  2699. if (rp->r_dayofmonth == len_months[1][rp->r_month])
  2700. week = 5;
  2701. else {
  2702. wdayoff = rp->r_dayofmonth % DAYSPERWEEK;
  2703. if (wdayoff)
  2704. compat = 2013;
  2705. wday -= wdayoff;
  2706. tod += wdayoff * SECSPERDAY;
  2707. week = rp->r_dayofmonth / DAYSPERWEEK;
  2708. }
  2709. } else return -1; /* "cannot happen" */
  2710. if (wday < 0)
  2711. wday += DAYSPERWEEK;
  2712. result += sprintf(result, "M%d.%d.%d",
  2713. rp->r_month + 1, week, wday);
  2714. }
  2715. if (rp->r_todisut)
  2716. tod += stdoff;
  2717. if (rp->r_todisstd && !rp->r_isdst)
  2718. tod += save;
  2719. if (tod != 2 * SECSPERMIN * MINSPERHOUR) {
  2720. *result++ = '/';
  2721. if (! stringoffset(result, tod))
  2722. return -1;
  2723. if (tod < 0) {
  2724. if (compat < 2013)
  2725. compat = 2013;
  2726. } else if (SECSPERDAY <= tod) {
  2727. if (compat < 1994)
  2728. compat = 1994;
  2729. }
  2730. }
  2731. return compat;
  2732. }
  2733. static int
  2734. rule_cmp(struct rule const *a, struct rule const *b)
  2735. {
  2736. if (!a)
  2737. return -!!b;
  2738. if (!b)
  2739. return 1;
  2740. if (a->r_hiyear != b->r_hiyear)
  2741. return a->r_hiyear < b->r_hiyear ? -1 : 1;
  2742. if (a->r_hiyear == ZIC_MAX)
  2743. return 0;
  2744. if (a->r_month - b->r_month != 0)
  2745. return a->r_month - b->r_month;
  2746. return a->r_dayofmonth - b->r_dayofmonth;
  2747. }
  2748. /* Store into RESULT a proleptic TZ string that represent the future
  2749. predictions for the zone ZPFIRST with ZONECOUNT entries. Return a
  2750. compatibility indicator (a TZDB release year) if successful, a
  2751. negative integer if no such TZ string exists. */
  2752. static int
  2753. stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
  2754. {
  2755. register const struct zone * zp;
  2756. register struct rule * rp;
  2757. register struct rule * stdrp;
  2758. register struct rule * dstrp;
  2759. register ptrdiff_t i;
  2760. register int compat = 0;
  2761. register int c;
  2762. int offsetlen;
  2763. struct rule stdr, dstr;
  2764. ptrdiff_t len;
  2765. int dstcmp;
  2766. struct rule *lastrp[2] = { NULL, NULL };
  2767. struct zone zstr[2];
  2768. struct zone const *stdzp;
  2769. struct zone const *dstzp;
  2770. result[0] = '\0';
  2771. /* Internet RFC 8536 section 5.1 says to use an empty TZ string if
  2772. future timestamps are truncated. */
  2773. if (hi_time < max_time)
  2774. return -1;
  2775. zp = zpfirst + zonecount - 1;
  2776. for (i = 0; i < zp->z_nrules; ++i) {
  2777. struct rule **last;
  2778. int cmp;
  2779. rp = &zp->z_rules[i];
  2780. last = &lastrp[rp->r_isdst];
  2781. cmp = rule_cmp(*last, rp);
  2782. if (cmp < 0)
  2783. *last = rp;
  2784. else if (cmp == 0)
  2785. return -1;
  2786. }
  2787. stdrp = lastrp[false];
  2788. dstrp = lastrp[true];
  2789. dstcmp = zp->z_nrules ? rule_cmp(dstrp, stdrp) : zp->z_isdst ? 1 : -1;
  2790. stdzp = dstzp = zp;
  2791. if (dstcmp < 0) {
  2792. /* Standard time all year. */
  2793. dstrp = NULL;
  2794. } else if (0 < dstcmp) {
  2795. /* DST all year. Use an abbreviation like
  2796. "XXX3EDT4,0/0,J365/23" for EDT (-04) all year. */
  2797. zic_t save = dstrp ? dstrp->r_save : zp->z_save;
  2798. if (0 <= save)
  2799. {
  2800. /* Positive DST, the typical case for all-year DST.
  2801. Fake a timezone with negative DST. */
  2802. stdzp = &zstr[0];
  2803. dstzp = &zstr[1];
  2804. zstr[0].z_stdoff = zp->z_stdoff + 2 * save;
  2805. zstr[0].z_format = "XXX"; /* Any 3 letters will do. */
  2806. zstr[0].z_format_specifier = 0;
  2807. zstr[1].z_stdoff = zstr[0].z_stdoff;
  2808. zstr[1].z_format = zp->z_format;
  2809. zstr[1].z_format_specifier = zp->z_format_specifier;
  2810. }
  2811. dstr.r_month = TM_JANUARY;
  2812. dstr.r_dycode = DC_DOM;
  2813. dstr.r_dayofmonth = 1;
  2814. dstr.r_tod = 0;
  2815. dstr.r_todisstd = dstr.r_todisut = false;
  2816. dstr.r_isdst = true;
  2817. dstr.r_save = save < 0 ? save : -save;
  2818. dstr.r_abbrvar = dstrp ? dstrp->r_abbrvar : NULL;
  2819. stdr.r_month = TM_DECEMBER;
  2820. stdr.r_dycode = DC_DOM;
  2821. stdr.r_dayofmonth = 31;
  2822. stdr.r_tod = SECSPERDAY + dstr.r_save;
  2823. stdr.r_todisstd = stdr.r_todisut = false;
  2824. stdr.r_isdst = false;
  2825. stdr.r_save = 0;
  2826. stdr.r_abbrvar = save < 0 && stdrp ? stdrp->r_abbrvar : NULL;
  2827. dstrp = &dstr;
  2828. stdrp = &stdr;
  2829. }
  2830. len = doabbr(result, stdzp, stdrp ? stdrp->r_abbrvar : NULL,
  2831. false, 0, true);
  2832. offsetlen = stringoffset(result + len, - stdzp->z_stdoff);
  2833. if (! offsetlen) {
  2834. result[0] = '\0';
  2835. return -1;
  2836. }
  2837. len += offsetlen;
  2838. if (dstrp == NULL)
  2839. return compat;
  2840. len += doabbr(result + len, dstzp, dstrp->r_abbrvar,
  2841. dstrp->r_isdst, dstrp->r_save, true);
  2842. if (dstrp->r_save != SECSPERMIN * MINSPERHOUR) {
  2843. offsetlen = stringoffset(result + len,
  2844. - (dstzp->z_stdoff + dstrp->r_save));
  2845. if (! offsetlen) {
  2846. result[0] = '\0';
  2847. return -1;
  2848. }
  2849. len += offsetlen;
  2850. }
  2851. result[len++] = ',';
  2852. c = stringrule(result + len, dstrp, dstrp->r_save, stdzp->z_stdoff);
  2853. if (c < 0) {
  2854. result[0] = '\0';
  2855. return -1;
  2856. }
  2857. if (compat < c)
  2858. compat = c;
  2859. len += strlen(result + len);
  2860. result[len++] = ',';
  2861. c = stringrule(result + len, stdrp, dstrp->r_save, stdzp->z_stdoff);
  2862. if (c < 0) {
  2863. result[0] = '\0';
  2864. return -1;
  2865. }
  2866. if (compat < c)
  2867. compat = c;
  2868. return compat;
  2869. }
  2870. static void
  2871. outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
  2872. {
  2873. register ptrdiff_t i, j;
  2874. register zic_t starttime, untiltime;
  2875. register bool startttisstd;
  2876. register bool startttisut;
  2877. register char * startbuf;
  2878. register char * ab;
  2879. register char * envvar;
  2880. register int max_abbr_len;
  2881. register int max_envvar_len;
  2882. register int compat;
  2883. register bool do_extend;
  2884. register char version;
  2885. zic_t nonTZlimtime = ZIC_MIN;
  2886. int nonTZlimtype = -1;
  2887. zic_t max_year0;
  2888. int defaulttype = -1;
  2889. check_for_signal();
  2890. /* This cannot overflow; see FORMAT_LEN_GROWTH_BOUND. */
  2891. max_abbr_len = 2 + max_format_len + max_abbrvar_len;
  2892. max_envvar_len = 2 * max_abbr_len + 5 * 9;
  2893. startbuf = emalloc(max_abbr_len + 1);
  2894. ab = emalloc(max_abbr_len + 1);
  2895. envvar = emalloc(max_envvar_len + 1);
  2896. INITIALIZE(untiltime);
  2897. INITIALIZE(starttime);
  2898. /*
  2899. ** Now. . .finally. . .generate some useful data!
  2900. */
  2901. timecnt = 0;
  2902. typecnt = 0;
  2903. charcnt = 0;
  2904. /*
  2905. ** Thanks to Earl Chew
  2906. ** for noting the need to unconditionally initialize startttisstd.
  2907. */
  2908. startttisstd = false;
  2909. startttisut = false;
  2910. min_year = max_year = EPOCH_YEAR;
  2911. if (leapseen) {
  2912. updateminmax(leapminyear);
  2913. updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX));
  2914. }
  2915. for (i = 0; i < zonecount; ++i) {
  2916. struct zone const *zp = &zpfirst[i];
  2917. if (i < zonecount - 1)
  2918. updateminmax(zp->z_untilrule.r_loyear);
  2919. for (j = 0; j < zp->z_nrules; ++j) {
  2920. struct rule *rp = &zp->z_rules[j];
  2921. updateminmax(rp->r_loyear);
  2922. if (rp->r_hiwasnum)
  2923. updateminmax(rp->r_hiyear);
  2924. }
  2925. }
  2926. /*
  2927. ** Generate lots of data if a rule can't cover all future times.
  2928. */
  2929. compat = stringzone(envvar, zpfirst, zonecount);
  2930. version = compat < 2013 ? '2' : '3';
  2931. do_extend = compat < 0;
  2932. if (noise) {
  2933. if (!*envvar)
  2934. warning("%s %s",
  2935. _("no proleptic TZ string for zone"),
  2936. zpfirst->z_name);
  2937. else if (compat != 0) {
  2938. /* Circa-COMPAT clients, and earlier clients, might
  2939. not work for this zone when given dates before
  2940. 1970 or after 2038. */
  2941. warning(_("%s: pre-%d clients may mishandle"
  2942. " distant timestamps"),
  2943. zpfirst->z_name, compat);
  2944. }
  2945. }
  2946. if (do_extend) {
  2947. if (min_year >= ZIC_MIN + years_of_observations)
  2948. min_year -= years_of_observations;
  2949. else min_year = ZIC_MIN;
  2950. if (max_year <= ZIC_MAX - years_of_observations)
  2951. max_year += years_of_observations;
  2952. else max_year = ZIC_MAX;
  2953. }
  2954. max_year = max(max_year, (redundant_time / (SECSPERDAY * DAYSPERNYEAR)
  2955. + EPOCH_YEAR + 1));
  2956. max_year0 = max_year;
  2957. if (want_bloat()) {
  2958. /* For the benefit of older systems,
  2959. generate data from 1900 through 2038. */
  2960. if (min_year > YEAR_32BIT_MIN - 1)
  2961. min_year = YEAR_32BIT_MIN - 1;
  2962. if (max_year < YEAR_32BIT_MAX)
  2963. max_year = YEAR_32BIT_MAX;
  2964. }
  2965. if (min_time < lo_time || hi_time < max_time)
  2966. unspecifiedtype = addtype(0, "-00", false, false, false);
  2967. for (i = 0; i < zonecount; ++i) {
  2968. /*
  2969. ** A guess that may well be corrected later.
  2970. */
  2971. zic_t save = 0;
  2972. struct zone const *zp = &zpfirst[i];
  2973. bool usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
  2974. bool useuntil = i < (zonecount - 1);
  2975. zic_t stdoff = zp->z_stdoff;
  2976. zic_t startoff = stdoff;
  2977. if (useuntil && zp->z_untiltime <= min_time)
  2978. continue;
  2979. eat(zp->z_filenum, zp->z_linenum);
  2980. *startbuf = '\0';
  2981. if (zp->z_nrules == 0) {
  2982. int type;
  2983. save = zp->z_save;
  2984. doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
  2985. type = addtype(oadd(zp->z_stdoff, save),
  2986. startbuf, zp->z_isdst, startttisstd,
  2987. startttisut);
  2988. if (usestart) {
  2989. addtt(starttime, type);
  2990. if (useuntil && nonTZlimtime < starttime) {
  2991. nonTZlimtime = starttime;
  2992. nonTZlimtype = type;
  2993. }
  2994. usestart = false;
  2995. } else
  2996. defaulttype = type;
  2997. } else {
  2998. zic_t year;
  2999. for (year = min_year; year <= max_year; ++year) {
  3000. if (useuntil && year > zp->z_untilrule.r_hiyear)
  3001. break;
  3002. /*
  3003. ** Mark which rules to do in the current year.
  3004. ** For those to do, calculate rpytime(rp, year);
  3005. ** The former TYPE field was also considered here.
  3006. */
  3007. for (j = 0; j < zp->z_nrules; ++j) {
  3008. zic_t one = 1;
  3009. zic_t y2038_boundary = one << 31;
  3010. struct rule *rp = &zp->z_rules[j];
  3011. eats(zp->z_filenum, zp->z_linenum,
  3012. rp->r_filenum, rp->r_linenum);
  3013. rp->r_todo = year >= rp->r_loyear &&
  3014. year <= rp->r_hiyear;
  3015. if (rp->r_todo) {
  3016. rp->r_temp = rpytime(rp, year);
  3017. rp->r_todo
  3018. = (rp->r_temp < y2038_boundary
  3019. || year <= max_year0);
  3020. }
  3021. }
  3022. for ( ; ; ) {
  3023. register ptrdiff_t k;
  3024. register zic_t jtime, ktime;
  3025. register zic_t offset;
  3026. struct rule *rp;
  3027. int type;
  3028. INITIALIZE(ktime);
  3029. if (useuntil) {
  3030. /*
  3031. ** Turn untiltime into UT
  3032. ** assuming the current stdoff and
  3033. ** save values.
  3034. */
  3035. untiltime = zp->z_untiltime;
  3036. if (!zp->z_untilrule.r_todisut)
  3037. untiltime = tadd(untiltime,
  3038. -stdoff);
  3039. if (!zp->z_untilrule.r_todisstd)
  3040. untiltime = tadd(untiltime,
  3041. -save);
  3042. }
  3043. /*
  3044. ** Find the rule (of those to do, if any)
  3045. ** that takes effect earliest in the year.
  3046. */
  3047. k = -1;
  3048. for (j = 0; j < zp->z_nrules; ++j) {
  3049. struct rule *r = &zp->z_rules[j];
  3050. if (!r->r_todo)
  3051. continue;
  3052. eats(zp->z_filenum, zp->z_linenum,
  3053. r->r_filenum, r->r_linenum);
  3054. offset = r->r_todisut ? 0 : stdoff;
  3055. if (!r->r_todisstd)
  3056. offset = oadd(offset, save);
  3057. jtime = r->r_temp;
  3058. if (jtime == min_time ||
  3059. jtime == max_time)
  3060. continue;
  3061. jtime = tadd(jtime, -offset);
  3062. if (k < 0 || jtime < ktime) {
  3063. k = j;
  3064. ktime = jtime;
  3065. } else if (jtime == ktime) {
  3066. char const *dup_rules_msg =
  3067. _("two rules for same instant");
  3068. eats(zp->z_filenum, zp->z_linenum,
  3069. r->r_filenum, r->r_linenum);
  3070. warning("%s", dup_rules_msg);
  3071. r = &zp->z_rules[k];
  3072. eats(zp->z_filenum, zp->z_linenum,
  3073. r->r_filenum, r->r_linenum);
  3074. error("%s", dup_rules_msg);
  3075. }
  3076. }
  3077. if (k < 0)
  3078. break; /* go on to next year */
  3079. rp = &zp->z_rules[k];
  3080. rp->r_todo = false;
  3081. if (useuntil && ktime >= untiltime) {
  3082. if (!*startbuf
  3083. && (oadd(zp->z_stdoff, rp->r_save)
  3084. == startoff))
  3085. doabbr(startbuf, zp, rp->r_abbrvar,
  3086. rp->r_isdst, rp->r_save,
  3087. false);
  3088. break;
  3089. }
  3090. save = rp->r_save;
  3091. if (usestart && ktime == starttime)
  3092. usestart = false;
  3093. if (usestart) {
  3094. if (ktime < starttime) {
  3095. startoff = oadd(zp->z_stdoff,
  3096. save);
  3097. doabbr(startbuf, zp,
  3098. rp->r_abbrvar,
  3099. rp->r_isdst,
  3100. rp->r_save,
  3101. false);
  3102. continue;
  3103. }
  3104. if (*startbuf == '\0'
  3105. && startoff == oadd(zp->z_stdoff,
  3106. save)) {
  3107. doabbr(startbuf,
  3108. zp,
  3109. rp->r_abbrvar,
  3110. rp->r_isdst,
  3111. rp->r_save,
  3112. false);
  3113. }
  3114. }
  3115. eats(zp->z_filenum, zp->z_linenum,
  3116. rp->r_filenum, rp->r_linenum);
  3117. doabbr(ab, zp, rp->r_abbrvar,
  3118. rp->r_isdst, rp->r_save, false);
  3119. offset = oadd(zp->z_stdoff, rp->r_save);
  3120. type = addtype(offset, ab, rp->r_isdst,
  3121. rp->r_todisstd, rp->r_todisut);
  3122. if (defaulttype < 0 && !rp->r_isdst)
  3123. defaulttype = type;
  3124. addtt(ktime, type);
  3125. if (nonTZlimtime < ktime
  3126. && (useuntil || rp->r_hiyear != ZIC_MAX)) {
  3127. nonTZlimtime = ktime;
  3128. nonTZlimtype = type;
  3129. }
  3130. }
  3131. }
  3132. }
  3133. if (usestart) {
  3134. bool isdst = startoff != zp->z_stdoff;
  3135. if (*startbuf == '\0' && zp->z_format)
  3136. doabbr(startbuf, zp, disable_percent_s,
  3137. isdst, save, false);
  3138. eat(zp->z_filenum, zp->z_linenum);
  3139. if (*startbuf == '\0')
  3140. error(_("can't determine time zone abbreviation"
  3141. " to use just after until time"));
  3142. else {
  3143. int type = addtype(startoff, startbuf, isdst,
  3144. startttisstd, startttisut);
  3145. if (defaulttype < 0 && !isdst)
  3146. defaulttype = type;
  3147. addtt(starttime, type);
  3148. }
  3149. }
  3150. /*
  3151. ** Now we may get to set starttime for the next zone line.
  3152. */
  3153. if (useuntil) {
  3154. startttisstd = zp->z_untilrule.r_todisstd;
  3155. startttisut = zp->z_untilrule.r_todisut;
  3156. starttime = zp->z_untiltime;
  3157. if (!startttisstd)
  3158. starttime = tadd(starttime, -save);
  3159. if (!startttisut)
  3160. starttime = tadd(starttime, -stdoff);
  3161. }
  3162. }
  3163. if (defaulttype < 0)
  3164. defaulttype = 0;
  3165. if (!do_extend && !want_bloat()) {
  3166. /* Keep trailing transitions that are no greater than this. */
  3167. zic_t keep_at_max;
  3168. /* The earliest transition into a time governed by the TZ string. */
  3169. zic_t TZstarttime = ZIC_MAX;
  3170. for (i = 0; i < timecnt; i++) {
  3171. zic_t at = attypes[i].at;
  3172. if (nonTZlimtime < at && at < TZstarttime)
  3173. TZstarttime = at;
  3174. }
  3175. if (TZstarttime == ZIC_MAX)
  3176. TZstarttime = nonTZlimtime;
  3177. /* Omit trailing transitions deducible from the TZ string,
  3178. and not needed for -r or -R. */
  3179. keep_at_max = max(TZstarttime, redundant_time);
  3180. for (i = j = 0; i < timecnt; i++)
  3181. if (attypes[i].at <= keep_at_max) {
  3182. attypes[j].at = attypes[i].at;
  3183. attypes[j].dontmerge = (attypes[i].at == TZstarttime
  3184. && (nonTZlimtype != attypes[i].type
  3185. || strchr(envvar, ',')));
  3186. attypes[j].type = attypes[i].type;
  3187. j++;
  3188. }
  3189. timecnt = j;
  3190. }
  3191. if (do_extend) {
  3192. /*
  3193. ** If we're extending the explicitly listed observations for
  3194. ** 400 years because we can't fill the proleptic TZ field,
  3195. ** check whether we actually ended up explicitly listing
  3196. ** observations through that period. If there aren't any
  3197. ** near the end of the 400-year period, add a redundant
  3198. ** one at the end of the final year, to make it clear
  3199. ** that we are claiming to have definite knowledge of
  3200. ** the lack of transitions up to that point.
  3201. */
  3202. struct rule xr;
  3203. struct attype *lastat;
  3204. xr.r_month = TM_JANUARY;
  3205. xr.r_dycode = DC_DOM;
  3206. xr.r_dayofmonth = 1;
  3207. xr.r_tod = 0;
  3208. for (lastat = attypes, i = 1; i < timecnt; i++)
  3209. if (attypes[i].at > lastat->at)
  3210. lastat = &attypes[i];
  3211. if (!lastat || lastat->at < rpytime(&xr, max_year - 1)) {
  3212. addtt(rpytime(&xr, max_year + 1),
  3213. lastat ? lastat->type : defaulttype);
  3214. attypes[timecnt - 1].dontmerge = true;
  3215. }
  3216. }
  3217. writezone(zpfirst->z_name, envvar, version, defaulttype);
  3218. free(startbuf);
  3219. free(ab);
  3220. free(envvar);
  3221. }
  3222. static void
  3223. addtt(zic_t starttime, int type)
  3224. {
  3225. attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
  3226. attypes[timecnt].at = starttime;
  3227. attypes[timecnt].dontmerge = false;
  3228. attypes[timecnt].type = type;
  3229. ++timecnt;
  3230. }
  3231. static int
  3232. addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
  3233. {
  3234. register int i, j;
  3235. if (! (-1L - 2147483647L <= utoff && utoff <= 2147483647L)) {
  3236. error(_("UT offset out of range"));
  3237. exit(EXIT_FAILURE);
  3238. }
  3239. if (!want_bloat())
  3240. ttisstd = ttisut = false;
  3241. for (j = 0; j < charcnt; ++j)
  3242. if (strcmp(&chars[j], abbr) == 0)
  3243. break;
  3244. if (j == charcnt)
  3245. newabbr(abbr);
  3246. else {
  3247. /* If there's already an entry, return its index. */
  3248. for (i = 0; i < typecnt; i++)
  3249. if (utoff == utoffs[i] && isdst == isdsts[i] && j == desigidx[i]
  3250. && ttisstd == ttisstds[i] && ttisut == ttisuts[i])
  3251. return i;
  3252. }
  3253. /*
  3254. ** There isn't one; add a new one, unless there are already too
  3255. ** many.
  3256. */
  3257. if (typecnt >= TZ_MAX_TYPES) {
  3258. error(_("too many local time types"));
  3259. exit(EXIT_FAILURE);
  3260. }
  3261. i = typecnt++;
  3262. utoffs[i] = utoff;
  3263. isdsts[i] = isdst;
  3264. ttisstds[i] = ttisstd;
  3265. ttisuts[i] = ttisut;
  3266. desigidx[i] = j;
  3267. return i;
  3268. }
  3269. static void
  3270. leapadd(zic_t t, int correction, int rolling)
  3271. {
  3272. register int i;
  3273. if (TZ_MAX_LEAPS <= leapcnt) {
  3274. error(_("too many leap seconds"));
  3275. exit(EXIT_FAILURE);
  3276. }
  3277. if (rolling && (lo_time != min_time || hi_time != max_time)) {
  3278. error(_("Rolling leap seconds not supported with -r"));
  3279. exit(EXIT_FAILURE);
  3280. }
  3281. for (i = 0; i < leapcnt; ++i)
  3282. if (t <= trans[i])
  3283. break;
  3284. memmove(&trans[i + 1], &trans[i], (leapcnt - i) * sizeof *trans);
  3285. memmove(&corr[i + 1], &corr[i], (leapcnt - i) * sizeof *corr);
  3286. memmove(&roll[i + 1], &roll[i], (leapcnt - i) * sizeof *roll);
  3287. trans[i] = t;
  3288. corr[i] = correction;
  3289. roll[i] = rolling;
  3290. ++leapcnt;
  3291. }
  3292. static void
  3293. adjleap(void)
  3294. {
  3295. register int i;
  3296. register zic_t last = 0;
  3297. register zic_t prevtrans = 0;
  3298. /*
  3299. ** propagate leap seconds forward
  3300. */
  3301. for (i = 0; i < leapcnt; ++i) {
  3302. if (trans[i] - prevtrans < 28 * SECSPERDAY) {
  3303. error(_("Leap seconds too close together"));
  3304. exit(EXIT_FAILURE);
  3305. }
  3306. prevtrans = trans[i];
  3307. trans[i] = tadd(trans[i], last);
  3308. last = corr[i] += last;
  3309. }
  3310. if (0 <= leapexpires) {
  3311. leapexpires = oadd(leapexpires, last);
  3312. if (! (leapcnt == 0 || (trans[leapcnt - 1] < leapexpires))) {
  3313. error(_("last Leap time does not precede Expires time"));
  3314. exit(EXIT_FAILURE);
  3315. }
  3316. }
  3317. }
  3318. /* Is A a space character in the C locale? */
  3319. static bool
  3320. is_space(char a)
  3321. {
  3322. switch (a) {
  3323. default:
  3324. return false;
  3325. case ' ': case '\f': case '\n': case '\r': case '\t': case '\v':
  3326. return true;
  3327. }
  3328. }
  3329. /* Is A an alphabetic character in the C locale? */
  3330. static bool
  3331. is_alpha(char a)
  3332. {
  3333. switch (a) {
  3334. default:
  3335. return false;
  3336. case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
  3337. case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
  3338. case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
  3339. case 'V': case 'W': case 'X': case 'Y': case 'Z':
  3340. case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
  3341. case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
  3342. case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
  3343. case 'v': case 'w': case 'x': case 'y': case 'z':
  3344. return true;
  3345. }
  3346. }
  3347. /* If A is an uppercase character in the C locale, return its lowercase
  3348. counterpart. Otherwise, return A. */
  3349. static char
  3350. lowerit(char a)
  3351. {
  3352. switch (a) {
  3353. default: return a;
  3354. case 'A': return 'a'; case 'B': return 'b'; case 'C': return 'c';
  3355. case 'D': return 'd'; case 'E': return 'e'; case 'F': return 'f';
  3356. case 'G': return 'g'; case 'H': return 'h'; case 'I': return 'i';
  3357. case 'J': return 'j'; case 'K': return 'k'; case 'L': return 'l';
  3358. case 'M': return 'm'; case 'N': return 'n'; case 'O': return 'o';
  3359. case 'P': return 'p'; case 'Q': return 'q'; case 'R': return 'r';
  3360. case 'S': return 's'; case 'T': return 't'; case 'U': return 'u';
  3361. case 'V': return 'v'; case 'W': return 'w'; case 'X': return 'x';
  3362. case 'Y': return 'y'; case 'Z': return 'z';
  3363. }
  3364. }
  3365. /* case-insensitive equality */
  3366. ATTRIBUTE_PURE_114833 static bool
  3367. ciequal(register const char *ap, register const char *bp)
  3368. {
  3369. while (lowerit(*ap) == lowerit(*bp++))
  3370. if (*ap++ == '\0')
  3371. return true;
  3372. return false;
  3373. }
  3374. ATTRIBUTE_PURE_114833 static bool
  3375. itsabbr(register const char *abbr, register const char *word)
  3376. {
  3377. if (lowerit(*abbr) != lowerit(*word))
  3378. return false;
  3379. ++word;
  3380. while (*++abbr != '\0')
  3381. do {
  3382. if (*word == '\0')
  3383. return false;
  3384. } while (lowerit(*word++) != lowerit(*abbr));
  3385. return true;
  3386. }
  3387. /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */
  3388. ATTRIBUTE_PURE_114833 static bool
  3389. ciprefix(char const *abbr, char const *word)
  3390. {
  3391. do
  3392. if (!*abbr)
  3393. return true;
  3394. while (lowerit(*abbr++) == lowerit(*word++));
  3395. return false;
  3396. }
  3397. static const struct lookup *
  3398. byword(const char *word, const struct lookup *table)
  3399. {
  3400. register const struct lookup * foundlp;
  3401. register const struct lookup * lp;
  3402. if (word == NULL || table == NULL)
  3403. return NULL;
  3404. /* If TABLE is LASTS and the word starts with "last" followed
  3405. by a non-'-', skip the "last" and look in WDAY_NAMES instead.
  3406. Warn about any usage of the undocumented prefix "last-". */
  3407. if (table == lasts && ciprefix("last", word) && word[4]) {
  3408. if (word[4] == '-')
  3409. warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
  3410. word, word + 5);
  3411. else {
  3412. word += 4;
  3413. table = wday_names;
  3414. }
  3415. }
  3416. /*
  3417. ** Look for exact match.
  3418. */
  3419. for (lp = table; lp->l_word != NULL; ++lp)
  3420. if (ciequal(word, lp->l_word))
  3421. return lp;
  3422. /*
  3423. ** Look for inexact match.
  3424. */
  3425. foundlp = NULL;
  3426. for (lp = table; lp->l_word != NULL; ++lp)
  3427. if (ciprefix(word, lp->l_word)) {
  3428. if (foundlp == NULL)
  3429. foundlp = lp;
  3430. else return NULL; /* multiple inexact matches */
  3431. }
  3432. if (foundlp && noise) {
  3433. /* Warn about any backward-compatibility issue with pre-2017c zic. */
  3434. bool pre_2017c_match = false;
  3435. for (lp = table; lp->l_word; lp++)
  3436. if (itsabbr(word, lp->l_word)) {
  3437. if (pre_2017c_match) {
  3438. warning(_("\"%s\" is ambiguous in pre-2017c zic"), word);
  3439. break;
  3440. }
  3441. pre_2017c_match = true;
  3442. }
  3443. }
  3444. return foundlp;
  3445. }
  3446. static int
  3447. getfields(char *cp, char **array, int arrayelts)
  3448. {
  3449. register char * dp;
  3450. register int nsubs;
  3451. nsubs = 0;
  3452. for ( ; ; ) {
  3453. char *dstart;
  3454. while (is_space(*cp))
  3455. ++cp;
  3456. if (*cp == '\0' || *cp == '#')
  3457. break;
  3458. dstart = dp = cp;
  3459. do {
  3460. if ((*dp = *cp++) != '"')
  3461. ++dp;
  3462. else while ((*dp = *cp++) != '"')
  3463. if (*dp != '\0')
  3464. ++dp;
  3465. else {
  3466. error(_("Odd number of quotation marks"));
  3467. exit(EXIT_FAILURE);
  3468. }
  3469. } while (*cp && *cp != '#' && !is_space(*cp));
  3470. if (is_space(*cp))
  3471. ++cp;
  3472. *dp = '\0';
  3473. if (nsubs == arrayelts) {
  3474. error(_("Too many input fields"));
  3475. exit(EXIT_FAILURE);
  3476. }
  3477. array[nsubs++] = dstart + (*dstart == '-' && dp == dstart + 1);
  3478. }
  3479. return nsubs;
  3480. }
  3481. ATTRIBUTE_NORETURN static void
  3482. time_overflow(void)
  3483. {
  3484. error(_("time overflow"));
  3485. exit(EXIT_FAILURE);
  3486. }
  3487. ATTRIBUTE_PURE_114833 static zic_t
  3488. oadd(zic_t t1, zic_t t2)
  3489. {
  3490. #ifdef ckd_add
  3491. zic_t sum;
  3492. if (!ckd_add(&sum, t1, t2))
  3493. return sum;
  3494. #else
  3495. if (t1 < 0 ? ZIC_MIN - t1 <= t2 : t2 <= ZIC_MAX - t1)
  3496. return t1 + t2;
  3497. #endif
  3498. time_overflow();
  3499. }
  3500. ATTRIBUTE_PURE_114833 static zic_t
  3501. tadd(zic_t t1, zic_t t2)
  3502. {
  3503. #ifdef ckd_add
  3504. zic_t sum;
  3505. if (!ckd_add(&sum, t1, t2) && min_time <= sum && sum <= max_time)
  3506. return sum;
  3507. #else
  3508. if (t1 < 0 ? min_time - t1 <= t2 : t2 <= max_time - t1)
  3509. return t1 + t2;
  3510. #endif
  3511. if (t1 == min_time || t1 == max_time)
  3512. return t1;
  3513. time_overflow();
  3514. }
  3515. /*
  3516. ** Given a rule, and a year, compute the date (in seconds since January 1,
  3517. ** 1970, 00:00 LOCAL time) in that year that the rule refers to.
  3518. */
  3519. static zic_t
  3520. rpytime(const struct rule *rp, zic_t wantedy)
  3521. {
  3522. register int m, i;
  3523. register zic_t dayoff; /* with a nod to Margaret O. */
  3524. register zic_t t, y;
  3525. int yrem;
  3526. if (wantedy == ZIC_MIN)
  3527. return min_time;
  3528. if (wantedy == ZIC_MAX)
  3529. return max_time;
  3530. m = TM_JANUARY;
  3531. y = EPOCH_YEAR;
  3532. /* dayoff = floor((wantedy - y) / YEARSPERREPEAT) * DAYSPERREPEAT,
  3533. sans overflow. */
  3534. yrem = wantedy % YEARSPERREPEAT - y % YEARSPERREPEAT;
  3535. dayoff = ((wantedy / YEARSPERREPEAT - y / YEARSPERREPEAT
  3536. + yrem / YEARSPERREPEAT - (yrem % YEARSPERREPEAT < 0))
  3537. * DAYSPERREPEAT);
  3538. /* wantedy = y + ((wantedy - y) mod YEARSPERREPEAT), sans overflow. */
  3539. wantedy = y + (yrem + 2 * YEARSPERREPEAT) % YEARSPERREPEAT;
  3540. while (wantedy != y) {
  3541. i = len_years[isleap(y)];
  3542. dayoff = oadd(dayoff, i);
  3543. y++;
  3544. }
  3545. while (m != rp->r_month) {
  3546. i = len_months[isleap(y)][m];
  3547. dayoff = oadd(dayoff, i);
  3548. ++m;
  3549. }
  3550. i = rp->r_dayofmonth;
  3551. if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
  3552. if (rp->r_dycode == DC_DOWLEQ)
  3553. --i;
  3554. else {
  3555. error(_("use of 2/29 in non leap-year"));
  3556. exit(EXIT_FAILURE);
  3557. }
  3558. }
  3559. --i;
  3560. dayoff = oadd(dayoff, i);
  3561. if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
  3562. /*
  3563. ** Don't trust mod of negative numbers.
  3564. */
  3565. zic_t wday = ((EPOCH_WDAY + dayoff % DAYSPERWEEK + DAYSPERWEEK)
  3566. % DAYSPERWEEK);
  3567. while (wday != rp->r_wday)
  3568. if (rp->r_dycode == DC_DOWGEQ) {
  3569. dayoff = oadd(dayoff, 1);
  3570. if (++wday >= DAYSPERWEEK)
  3571. wday = 0;
  3572. ++i;
  3573. } else {
  3574. dayoff = oadd(dayoff, -1);
  3575. if (--wday < 0)
  3576. wday = DAYSPERWEEK - 1;
  3577. --i;
  3578. }
  3579. if (i < 0 || i >= len_months[isleap(y)][m]) {
  3580. if (noise)
  3581. warning(_("rule goes past start/end of month; \
  3582. will not work with pre-2004 versions of zic"));
  3583. }
  3584. }
  3585. if (dayoff < min_time / SECSPERDAY)
  3586. return min_time;
  3587. if (dayoff > max_time / SECSPERDAY)
  3588. return max_time;
  3589. t = (zic_t) dayoff * SECSPERDAY;
  3590. return tadd(t, rp->r_tod);
  3591. }
  3592. static void
  3593. newabbr(const char *string)
  3594. {
  3595. register int i;
  3596. if (strcmp(string, GRANDPARENTED) != 0) {
  3597. register const char * cp;
  3598. const char * mp;
  3599. cp = string;
  3600. mp = NULL;
  3601. while (is_alpha(*cp) || ('0' <= *cp && *cp <= '9')
  3602. || *cp == '-' || *cp == '+')
  3603. ++cp;
  3604. if (noise && cp - string < 3)
  3605. mp = _("time zone abbreviation has fewer than 3 characters");
  3606. if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
  3607. mp = _("time zone abbreviation has too many characters");
  3608. if (*cp != '\0')
  3609. mp = _("time zone abbreviation differs from POSIX standard");
  3610. if (mp != NULL)
  3611. warning("%s (%s)", mp, string);
  3612. }
  3613. i = strlen(string) + 1;
  3614. if (charcnt + i > TZ_MAX_CHARS) {
  3615. error(_("too many, or too long, time zone abbreviations"));
  3616. exit(EXIT_FAILURE);
  3617. }
  3618. strcpy(&chars[charcnt], string);
  3619. charcnt += i;
  3620. }
  3621. /* Ensure that the directories of ARGNAME exist, by making any missing
  3622. ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
  3623. do it for ARGNAME too. Exit with failure if there is trouble.
  3624. Do not consider an existing file to be trouble. */
  3625. static void
  3626. mkdirs(char const *argname, bool ancestors)
  3627. {
  3628. char *name = estrdup(argname);
  3629. char *cp = name;
  3630. /* On MS-Windows systems, do not worry about drive letters or
  3631. backslashes, as this should suffice in practice. Time zone
  3632. names do not use drive letters and backslashes. If the -d
  3633. option of zic does not name an already-existing directory,
  3634. it can use slashes to separate the already-existing
  3635. ancestor prefix from the to-be-created subdirectories. */
  3636. /* Do not mkdir a root directory, as it must exist. */
  3637. while (*cp == '/')
  3638. cp++;
  3639. while (cp && ((cp = strchr(cp, '/')) || !ancestors)) {
  3640. if (cp)
  3641. *cp = '\0';
  3642. /*
  3643. ** Try to create it. It's OK if creation fails because
  3644. ** the directory already exists, perhaps because some
  3645. ** other process just created it. For simplicity do
  3646. ** not check first whether it already exists, as that
  3647. ** is checked anyway if the mkdir fails.
  3648. */
  3649. if (mkdir(name, MKDIR_UMASK) != 0) {
  3650. /* Do not report an error if err == EEXIST, because
  3651. some other process might have made the directory
  3652. in the meantime. Likewise for ENOSYS, because
  3653. Solaris 10 mkdir fails with ENOSYS if the
  3654. directory is an automounted mount point.
  3655. Likewise for EACCES, since mkdir can fail
  3656. with EACCES merely because the parent directory
  3657. is unwritable. Likewise for most other error
  3658. numbers. */
  3659. int err = errno;
  3660. if (err == ELOOP || err == ENAMETOOLONG
  3661. || err == ENOENT || err == ENOTDIR) {
  3662. error(_("%s: Can't create directory %s: %s"),
  3663. progname, name, strerror(err));
  3664. exit(EXIT_FAILURE);
  3665. }
  3666. }
  3667. if (cp)
  3668. *cp++ = '/';
  3669. }
  3670. free(name);
  3671. }