#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- # Time/Date Configuration handling # # Copyright (C) 2000-2001 Ximian, Inc. # # Authors: Hans Petter Jansson # Carlos Garnacho # Grzegorz Golawski (PLD Support) # James Ogley (SuSE 9.0 support) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Library General Public License as published # by the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. package Time::TimeDate; use File::Copy; sub get_utc_time { my (%h, $trash); ($h{"second"}, $h{"minute"}, $h{"hour"}, $h{"monthday"}, $h{"month"}, $h{"year"}, $trash, $trash, $trash) = gmtime (time); $h{"year"} += 1900; return \%h; } # This function will force date format when setting time sub change_timedate { my ($time) = @_; my (@command); my $system_table = { "Linux" => "date -u %02d%02d%02d%02d%04d.%02d", "FreeBSD" => "date -u -f %%m%%d%%H%%M%%Y.%%S %02d%02d%02d%02d%04d.%02d", "SunOS" => "date -u %02d%02d%02d%02d%04d.%02d", }; @command = split (/ /, sprintf ($$system_table {$Utils::Backend::tool{"system"}}, $$time{"month"} + 1, $$time{"monthday"}, $$time{"hour"}, $$time{"minute"}, $$time{"year"}, $$time{"second"})); &Utils::Report::do_report ("time_localtime_set", @command); return &Utils::File::run (@command); } sub set_utc_time { my ($time) = @_; my ($res); $res = &change_timedate ($time); return -1 if $res; return 0; } sub time_sync_hw_from_sys { &Utils::File::run ("hwclock", "--systohc") if ($$tool{"system"} eq "Linux"); return 0; } sub get_timezone { my ($local_time_file, $zoneinfo_dir) = @_; local *TZLIST; my $zone; my $size_search; my $size_test; # First check whether it's a link, if it is, it's pretty straighforward $zone = readlink ($local_time_file); if ($zone && $zone =~ /^$zoneinfo_dir/) { $zone =~ s/^$zoneinfo_dir\/+//; return $zone; } *TZLIST = &Utils::File::open_read_from_names($zoneinfo_dir . "/zone.tab"); if (not *TZLIST) { return; } &Utils::Report::do_report ("time_timezone_scan"); # Get the filesize for /etc/localtime so that we don't have to execute # a diff for every file, only for file with the correct size. This speeds # up loading $size_search = (stat ($local_time_file))[7]; while () { if (/^\#/) { next; } # Skip comments. ($d, $d, $zone) = split /[\t ]+/, $_; # Get 3rd column. chomp $zone; # Remove linefeeds. # See if this zone file matches the installed one. &Utils::Report::do_report ("time_timezone_cmp", $zone); $size_test = (stat("$zoneinfo_dir/$zone"))[7]; if ($size_test eq $size_search) { if (!&Utils::File::run ("diff", "$zoneinfo_dir/$zone", $local_time_file)) { # Found a match. last; } } $zone = ""; } close (TZLIST); return $zone; } sub set_timezone { my ($localtime, $zonebase, $timezone) = @_; &Utils::Report::enter (); &Utils::Report::do_report ("time_timezone_set", $timezone); $tz = "$zonebase/$timezone"; if (stat($tz) ne "") { unlink $localtime; # Important, since it might be a symlink. &Utils::Report::enter (); $res = copy ($tz, $localtime); &Utils::Report::leave (); return -1 unless $res; return 0; } &Utils::Report::leave (); return -1; } sub get_dist { my %dist_map = ( "debian" => "debian", "redhat-6.2" => "redhat-6.2", "redhat-7.0" => "redhat-6.2", "redhat-7.1" => "redhat-6.2", "redhat-7.2" => "redhat-6.2", "redhat-7.3" => "redhat-6.2", "redhat-8.0" => "redhat-6.2", "mandrake-9.0" => "redhat-6.2", "suse-9.0" => "redhat-6.2", "slackware-9.1.0" => "redhat-6.2", "gentoo" => "redhat-6.2", "archlinux" => "archlinux", "pld-1.0" => "redhat-6.2", "vine-3.0" => "redhat-6.2", "freebsd-5" => "redhat-6.2", "solaris-2.11" => "solaris-2.11", ); return $dist_map{$Utils::Backend::tool{"platform"}}; } sub conf_get_parse_table { my %dist_tables = ( "redhat-6.2" => { fn => { ZONEINFO => "/usr/share/zoneinfo", LOCAL_TIME => "/etc/localtime" }, table => [ [ "local_time", \&get_utc_time ], [ "timezone", \&get_timezone, [LOCAL_TIME, ZONEINFO] ], ] }, "debian" => { fn => { TIMEZONE => "/etc/timezone" }, table => [ [ "local_time", \&get_utc_time ], [ "timezone", \&Utils::Parse::get_first_line, TIMEZONE ], ] }, "archlinux" => { fn => { RC_CONF => "/etc/rc.conf", ZONEINFO => "/usr/share/zoneinfo", LOCAL_TIME => "/etc/localtime" }, table => [ [ "local_time", \&get_utc_time ], [ "timezone", \&Utils::Parse::get_sh, RC_CONF, TIMEZONE ], ] }, "solaris-2.11" => { fn => { NTP_CONF => "/etc/inet/ntp.conf", INIT_FILE => "/etc/default/init" }, table => [ [ "local_time", \&get_utc_time ], [ "timezone", \&Utils::Parse::get_sh, INIT_FILE, TZ ], ] }, ); my $dist = &get_dist(); return %{$dist_tables{$dist}} if $dist; &Utils::Report::do_report ("platform_no_table", $Utils::backend::tool{"platform"}); return undef; } sub conf_get_replace_table { my %dist_tables = ( "redhat-6.2" => { fn => { ZONEINFO => "/usr/share/zoneinfo", LOCAL_TIME => "/etc/localtime" }, table => [ [ "timezone", \&set_timezone, [LOCAL_TIME, ZONEINFO] ], [ "local_time", \&set_utc_time ], ] }, "debian" => { fn => { ZONEINFO => "/usr/share/zoneinfo", LOCAL_TIME => "/etc/localtime", TIMEZONE => "/etc/timezone" }, table => [ [ "timezone", \&set_timezone, [LOCAL_TIME, ZONEINFO] ], [ "timezone", \&Utils::Replace::set_first_line, TIMEZONE ], [ "local_time", \&set_utc_time ], ] }, "archlinux" => { fn => { RC_LOCAL => "/etc/rc.local", ZONEINFO => "/usr/share/zoneinfo", LOCAL_TIME => "/etc/localtime", }, table => [ [ "timezone", \&Utils::Replace::set_sh, RC_LOCAL, TIMEZONE ], [ "timezone", \&set_timezone, [LOCAL_TIME, ZONEINFO] ], [ "local_time", \&set_utc_time ], ] }, "solaris-2.11" => { fn => { ZONEINFO => "/usr/share/lib/zoneinfo", LOCAL_TIME => "/etc/localtime", INIT_FILE => "/etc/default/init" }, table => [ [ "timezone", \&Utils::Replace::set_sh, INIT_FILE, TZ ], [ "timezone", \&set_timezone, [LOCAL_TIME, ZONEINFO] ], [ "local_time", \&set_utc_time ], ] }, ); my $dist = &get_dist (); return %{$dist_tables{$dist}} if $dist; &Utils::Report::do_report ("platform_no_table", $Utils::Backend::tool{"platform"}); return undef; } sub get { my %dist_attrib; my $hash; %dist_attrib = &conf_get_parse_table (); $hash = &Utils::Parse::get_from_table ($dist_attrib{"fn"}, $dist_attrib{"table"}); $h = $$hash {"local_time"}; return ($$h {"year"}, $$h {"month"}, $$h {"monthday"}, $$h {"hour"}, $$h {"minute"}, $$h {"second"}, $$hash{"timezone"}); } sub set { my (@config) = @_; my ($hash, %localtime); %localtime = ( "year" => $config[0], "month" => $config[1], "monthday" => $config[2], "hour" => $config[3], "minute" => $config[4], "second" => $config[5] ); $$hash{"local_time"} = \%localtime; $$hash{"timezone"} = $config[6]; %dist_attrib = &conf_get_replace_table (); $res = &Utils::Replace::set_from_table ($dist_attrib{"fn"}, $dist_attrib{"table"}, $hash); &time_sync_hw_from_sys (); return $res; } sub get_files { my (%dist_attrib, $fn, $f, $files); %dist_attrib = &conf_get_replace_table (); $fn = $dist_attrib {"fn"}; foreach $f (values %$fn) { push @$files, $f; } return $files; } 1;