Return true if the TZif file with descriptor FD changed, or may have changed, since the last time we were called. Return false if it did not change. If *ST is valid it is the file's current status; otherwise, update *ST to the status if possible. */
| 820 | static bool |
| 821 | tzfile_changed(int fd, struct stat *st) |
| 822 | { |
| 823 | /* If old_ctim.tv_sec, these variables hold the corresponding part |
| 824 | of the file's metadata the last time this function was called. */ |
| 825 | static struct timespec old_ctim; |
| 826 | static dev_t old_dev; |
| 827 | static ino_t old_ino; |
| 828 | |
| 829 | if (!st->st_ctime && fstat(fd, st) < 0) { |
| 830 | /* We do not know the file's state, so reset. */ |
| 831 | old_ctim.tv_sec = 0; |
| 832 | return true; |
| 833 | } else { |
| 834 | /* Use the change time, as it changes more reliably; mod time can |
| 835 | be set back with futimens etc. Use subsecond timestamp |
| 836 | resolution if available, as this can help distinguish files on |
| 837 | non-POSIX platforms where st_dev and st_ino are unreliable. */ |
| 838 | struct timespec ctim; |
| 839 | /* Copy via members, as AIX 7.3 defaults to an incompatible st_ctim. */ |
| 840 | ctim.tv_sec = st->st_ctime; |
| 841 | #if HAVE_STRUCT_STAT_ST_CTIM |
| 842 | ctim.tv_nsec = st->st_ctim.tv_nsec; |
| 843 | #else |
| 844 | ctim.tv_nsec = 0; |
| 845 | #endif |
| 846 | |
| 847 | if ((ctim.tv_sec ^ old_ctim.tv_sec) | (ctim.tv_nsec ^ old_ctim.tv_nsec) |
| 848 | | (st->st_dev ^ old_dev) | (st->st_ino ^ old_ino)) { |
| 849 | old_ctim = ctim; |
| 850 | old_dev = st->st_dev; |
| 851 | old_ino = st->st_ino; |
| 852 | return true; |
| 853 | } |
| 854 | |
| 855 | return false; |
| 856 | } |
| 857 | } |
| 858 | |
| 859 | /* Input buffer for data read from a compiled tz file. */ |
| 860 | union input_buffer { |
| 861 | /* The first part of the buffer, interpreted as a header. */ |