static const char* get_zoneinfo_timezone( void ) { if (!android_timezone_init) { const char* tz = getenv("TZ"); char buff[PATH_MAX+1]; android_timezone_init = 1; if (tz == NULL) { int len = readlink(LOCALTIME_FILE, buff, sizeof(buff)); if (len < 0) { dprint( "### WARNING: Could not read %s, something is very wrong on your system", LOCALTIME_FILE); return NULL; } buff[len] = 0; D("%s: %s points to %s\n", __FUNCTION__, LOCALTIME_FILE, buff); if ( memcmp(buff, ZONEINFO_DIR, sizeof(ZONEINFO_DIR)-1) ) { dprint( "### WARNING: %s does not point to %s, can't determine zoneinfo timezone name", LOCALTIME_FILE, ZONEINFO_DIR ); return NULL; } tz = buff + sizeof(ZONEINFO_DIR)-1; if ( !check_timezone_is_zoneinfo(tz) ) { dprint( "### WARNING: %s does not point to zoneinfo-compatible timezone name\n", LOCALTIME_FILE ); return NULL; } } snprintf(android_timezone0, sizeof(android_timezone0), "%s", tz ); android_timezone = android_timezone0; } D( "found timezone %s", android_timezone ); return android_timezone; }
static const char* scan_timezone_dir( ScanDataRec* scan, char* top, int depth ) { DIR* d = opendir( scan->path ); const char* result = NULL; D( "%s: entering '%s\n", __FUNCTION__, scan->path ); if (d != NULL) { struct dirent* ent; while ((ent = readdir(d)) != NULL) { struct stat ent_st; char* p = top; if (ent->d_name[0] == '.') /* avoid hidden and special files */ continue; p = bufprint( p, scan->path_end, "/%s", ent->d_name ); if (p >= scan->path_end) continue; //D( "%s: scanning '%s'\n", __FUNCTION__, scan->path ); if ( stat( scan->path, &ent_st ) < 0 ) continue; if ( S_ISDIR(ent_st.st_mode) && depth < 2 ) { //D( "%s: directory '%s'\n", __FUNCTION__, scan->path ); result = scan_timezone_dir( scan, p, depth + 1 ); if (result != NULL) break; } else if ( S_ISREG(ent_st.st_mode) && (depth >= 1 && depth <= 2) ) { char* name = scan->path_root + 1; if ( check_timezone_is_zoneinfo( name ) ) { if (compare_timezone_to_localtime( scan, scan->path )) { result = strdup( name ); D( "%s: found '%s'\n", __FUNCTION__, result ); break; } } else { //D( "%s: ignoring '%s'\n", __FUNCTION__, scan->path ); } } } closedir(d); } return result; }
char* bufprint_zoneinfo_timezone( char* p, char* end ) { const char* tz = get_zoneinfo_timezone(); if (tz == NULL || !check_timezone_is_zoneinfo(tz)) return bufprint(p, end, "Unknown/Unknown"); else return bufprint(p, end, "%s", tz); }
int timezone_set( const char* tzname ) { int len; if ( !check_timezone_is_zoneinfo(tzname) ) return -1; len = strlen(tzname); if (len > (int)sizeof(android_timezone0)-1) return -1; strcpy( android_timezone0, tzname ); android_timezone = android_timezone0; android_timezone_init = 1; return 0; }
static const char* get_zoneinfo_timezone( void ) { if (!android_timezone_init) { const char* tz = getenv( "TZ" ); android_timezone_init = 1; if ( tz != NULL && !check_timezone_is_zoneinfo(tz) ) { D( "%s: ignoring non zoneinfo formatted TZ environment variable: '%s'\n", __FUNCTION__, tz ); tz = NULL; } if (tz == NULL) { char* tzdir = NULL; int tzdirlen = 0; char* localtime = NULL; int len; char temp[ PATH_MAX ]; /* determine the correct timezone directory */ { const char* env = getenv("TZDIR"); const char* zoneinfo_dir = ZONEINFO_DIR; if (env == NULL) env = zoneinfo_dir; if ( access( env, R_OK ) != 0 ) { if ( env == zoneinfo_dir ) { fprintf( stderr, "### WARNING: could not find %s directory. unable to determine host timezone\n", env ); } else { D( "%s: TZDIR does not point to valid directory, using %s instead\n", __FUNCTION__, zoneinfo_dir ); env = zoneinfo_dir; } return NULL; } tzdir = strdup(env); } /* remove trailing slash, if any */ len = strlen(tzdir); if (len > 0 && tzdir[len-1] == '/') { tzdir[len-1] = 0; len -= 1; } tzdirlen = len; D( "%s: found timezone dir as %s\n", __FUNCTION__, tzdir ); /* try to find the localtime file */ localtime = LOCALTIME_FILE1; if ( access( localtime, R_OK ) != 0 ) { char *p = temp, *end = p + sizeof(temp); p = bufprint( p, end, "%s/%s", tzdir, "localtime" ); if (p >= end || access( temp, R_OK ) != 0 ) { fprintf( stderr, "### WARNING: could not find %s or %s. unable to determine host timezone\n", LOCALTIME_FILE1, temp ); goto Exit; } localtime = temp; } localtime = strdup(localtime); D( "%s: found localtime file as %s\n", __FUNCTION__, localtime ); #if 1 /* if the localtime file is a link, make a quick check */ len = readlink( localtime, temp, sizeof(temp)-1 ); if (len >= 0 && len > tzdirlen + 2) { temp[len] = 0; /* verify that the link points to tzdir/<something> where <something> is a valid zoneinfo name */ if ( !memcmp( temp, tzdir, tzdirlen ) && temp[tzdirlen] == '/' ) { if ( check_timezone_is_zoneinfo( temp + tzdirlen + 1 ) ) { /* we have it ! */ tz = temp + tzdirlen + 1; D( "%s: found zoneinfo timezone %s from %s symlink\n", __FUNCTION__, tz, localtime ); goto Exit; } D( "%s: %s link points to non-zoneinfo filename %s, comparing contents\n", __FUNCTION__, localtime, temp ); } } #endif /* otherwise, parse all files under tzdir and see if we have something that looks like it */ { ScanDataRec scan[1]; if ( stat( localtime, &scan->localtime_st ) < 0 ) { fprintf( stderr, "### WARNING: can't access '%s', unable to determine host timezone\n", localtime ); goto Exit; } scan->localtime = localtime; scan->path_end = scan->path + sizeof(scan->path); scan->path_root = bufprint( scan->path, scan->path_end, "%s", tzdir ); tz = scan_timezone_dir( scan, scan->path_root, 0 ); } Exit: if (tzdir) free(tzdir); if (localtime) free(localtime); if (tz == NULL) return NULL; snprintf(android_timezone0, sizeof(android_timezone0), "%s", tz); android_timezone = android_timezone0; } D( "found timezone %s\n", android_timezone ); } return android_timezone; }
static const char* scan_timezone_dir( ScanDataRec* scan, char* top, int depth ) { DIR* d = opendir( scan->path ); const char* result = NULL; D( "%s: entering '%s\n", __FUNCTION__, scan->path ); if (d != NULL) { struct dirent* ent; while ((ent = readdir(d)) != NULL) { struct stat ent_st; char* p = top; if (ent->d_name[0] == '.') /* avoid hidden and special files */ continue; p = bufprint( p, scan->path_end, "/%s", ent->d_name ); if (p >= scan->path_end) continue; //D( "%s: scanning '%s'\n", __FUNCTION__, scan->path ); // Important: use lstat() instead of stat() because recent // Ubuntu distributions creates directories full of links, e.g. // /usr/share/info/posix/Australia/Sydney -> ../../Australia/Sydney // and we want to ignore them. if ( lstat( scan->path, &ent_st ) < 0 ) continue; if ( S_ISDIR(ent_st.st_mode) && depth < 2 ) { //D( "%s: directory '%s'\n", __FUNCTION__, scan->path ); result = scan_timezone_dir( scan, p, depth + 1 ); if (result != NULL) break; } else if ( S_ISREG(ent_st.st_mode) && (depth >= 1 && depth <= 2) ) { char* name = scan->path_root + 1; if ( check_timezone_is_zoneinfo( name ) ) { if (compare_timezone_to_localtime( scan, scan->path )) { result = strdup( name ); D( "%s: found '%s'\n", __FUNCTION__, result ); break; } } else { //D( "%s: ignoring '%s'\n", __FUNCTION__, scan->path ); } } } closedir(d); } return result; }