Load tz data from the file named NAME into *SP. Respect TZLOADFLAGS. Use **LSPP for temporary storage. Return 0 on success, an errno value on failure. */
| 904 | Use **LSPP for temporary storage. Return 0 on |
| 905 | success, an errno value on failure. */ |
| 906 | static int |
| 907 | tzloadbody(char const *name, struct state *sp, char tzloadflags, |
| 908 | union local_storage **lspp) |
| 909 | { |
| 910 | register int i; |
| 911 | register int fid; |
| 912 | register int stored; |
| 913 | register ssize_t nread; |
| 914 | char const *relname; |
| 915 | union local_storage *lsp = *lspp; |
| 916 | union input_buffer *up; |
| 917 | register int tzheadsize = sizeof(struct tzhead); |
| 918 | int dd = AT_FDCWD; |
| 919 | int oflags = (O_RDONLY | O_BINARY | O_CLOEXEC | O_CLOFORK |
| 920 | | O_IGNORE_CTTY | O_NOCTTY | O_REGULAR); |
| 921 | bool might_escape = false; |
| 922 | int err; |
| 923 | struct stat st; |
| 924 | st.st_ctime = 0; |
| 925 | |
| 926 | sp->goback = sp->goahead = false; |
| 927 | |
| 928 | if (! name) { |
| 929 | name = TZDEFAULT; |
| 930 | if (! name) |
| 931 | return EINVAL; |
| 932 | } |
| 933 | |
| 934 | if (name[0] == ':') |
| 935 | ++name; |
| 936 | |
| 937 | relname = name; |
| 938 | |
| 939 | /* If the program is privileged, NAME is TZDEFAULT or |
| 940 | subsidiary to TZDIR. Also, NAME is not a device. */ |
| 941 | if (name[0] == '/' && strcmp(name, TZDEFAULT) != 0) { |
| 942 | if (!SUPPRESS_TZDIR |
| 943 | && strncmp(relname, tzdirslash, tzdirslashlen) == 0) |
| 944 | for (relname += tzdirslashlen; *relname == '/'; relname++) |
| 945 | continue; |
| 946 | else if (issetugid()) |
| 947 | return ENOTCAPABLE; |
| 948 | else |
| 949 | might_escape = true; |
| 950 | } |
| 951 | |
| 952 | if (relname[0] != '/') { |
| 953 | if (!OPENAT_TZDIR || !O_RESOLVE_BENEATH) { |
| 954 | /* Fail if a relative name contains a non-terminal ".." component, |
| 955 | as such a name could read a non-directory outside TZDIR |
| 956 | when AT_FDCWD and O_RESOLVE_BENEATH are not available. */ |
| 957 | char const *component; |
| 958 | for (component = relname; component[0]; component++) |
| 959 | if (component[0] == '.' && component[1] == '.' |
| 960 | && component[2] == '/' |
| 961 | && (component == relname || component[-1] == '/')) { |
| 962 | if (issetugid()) |
| 963 | return ENOTCAPABLE; |
no test coverage detected