Nanos_In_56_Years : constant := (14 * 366 + 42 * 365) * Nanos_In_Day;
- -- Base C types. There is no point dragging in Interfaces.C just for
- -- these four types.
-
- type char_Pointer is access Character;
- subtype int is Integer;
subtype long is Long_Integer;
type long_Pointer is access all long;
- -- The Ada equivalent of struct tm and type time_t
-
- type tm is record
- tm_sec : int; -- seconds after the minute (0 .. 60)
- tm_min : int; -- minutes after the hour (0 .. 59)
- tm_hour : int; -- hours since midnight (0 .. 24)
- tm_mday : int; -- day of the month (1 .. 31)
- tm_mon : int; -- months since January (0 .. 11)
- tm_year : int; -- years since 1900
- tm_wday : int; -- days since Sunday (0 .. 6)
- tm_yday : int; -- days since January 1 (0 .. 365)
- tm_isdst : int; -- Daylight Savings Time flag (-1 .. 1)
- tm_gmtoff : long; -- offset from UTC in seconds
- tm_zone : char_Pointer; -- timezone abbreviation
- end record;
-
- type tm_Pointer is access all tm;
-
subtype time_t is long;
type time_t_Pointer is access all time_t;
procedure localtime_tzoff
- (C : time_t_Pointer;
- res : tm_Pointer;
- off : long_Pointer);
+ (timer : time_t_Pointer;
+ off : long_Pointer);
pragma Import (C, localtime_tzoff, "__gnat_localtime_tzoff");
-- This is a lightweight wrapper around the system library function
-- localtime_r. Parameter 'off' captures the UTC offset which is either
Date_N : Time_Rep;
Offset : aliased long;
Secs_T : aliased time_t;
- Secs_TM : aliased tm;
begin
Date_N := Time_Rep (Date);
localtime_tzoff
(Secs_T'Unchecked_Access,
- Secs_TM'Unchecked_Access,
Offset'Unchecked_Access);
return Offset;
end case;
end if;
+ -- Special case: EAGAIN may be the same value as EWOULDBLOCK, so we
+ -- can't include it in the case statement below.
+
+ pragma Warnings (Off);
+ -- Condition "EAGAIN /= EWOULDBLOCK" is known at compile time
+
+ if EAGAIN /= EWOULDBLOCK and then Error_Value = EAGAIN then
+ return Resource_Temporarily_Unavailable;
+ end if;
+ pragma Warnings (On);
+
case Error_Value is
when ENOERROR => return Success;
when EACCES => return Permission_Denied;
when ENOTSOCK => return Socket_Operation_On_Non_Socket;
when EOPNOTSUPP => return Operation_Not_Supported;
when EPFNOSUPPORT => return Protocol_Family_Not_Supported;
+ when EPIPE => return Broken_Pipe;
when EPROTONOSUPPORT => return Protocol_Not_Supported;
when EPROTOTYPE => return Protocol_Wrong_Type_For_Socket;
when ESHUTDOWN => return
when ETIMEDOUT => return Connection_Timed_Out;
when ETOOMANYREFS => return Too_Many_References;
when EWOULDBLOCK => return Resource_Temporarily_Unavailable;
- when others => null;
- end case;
- return Cannot_Resolve_Error;
+ when others => return Cannot_Resolve_Error;
+ end case;
end Resolve_Error;
-----------------------
/* Reentrant localtime for Windows and OS/2. */
-extern struct tm *
-__gnat_localtime_tzoff (const time_t *, struct tm *, long *);
+extern void
+__gnat_localtime_tzoff (const time_t *, long *);
-struct tm *
-__gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
+static const unsigned long long w32_epoch_offset = 11644473600ULL;
+void
+__gnat_localtime_tzoff (const time_t *timer, long *off)
{
- DWORD dwRet;
- struct tm *tmp;
+ union
+ {
+ FILETIME ft_time;
+ unsigned long long ull_time;
+ } utc_time, local_time;
+
+ SYSTEMTIME utc_sys_time, local_sys_time;
TIME_ZONE_INFORMATION tzi;
+ BOOL status = 1;
+ DWORD tzi_status;
+
(*Lock_Task) ();
- tmp = localtime (timer);
- memcpy (tp, tmp, sizeof (struct tm));
- dwRet = GetTimeZoneInformation (&tzi);
- *off = tzi.Bias;
- if (tp->tm_isdst > 0)
- *off = *off + tzi.DaylightBias;
- *off = *off * -60;
+
+ /* First convert unix time_t structure to windows FILETIME format. */
+ utc_time.ull_time = ((unsigned long long) *timer + w32_epoch_offset)
+ * 10000000ULL;
+
+ tzi_status = GetTimeZoneInformation (&tzi);
+
+ /* If GetTimeZoneInformation does not return a value between 0 and 2 then
+ it means that we were not able to retrieve timezone informations.
+ Note that we cannot use here FileTimeToLocalFileTime as Windows will use
+ in always in this case the current timezone setting. As suggested on
+ MSDN we use the following three system calls to get the right information.
+ Note also that starting with Windows Vista new functions are provided to
+ get timezone settings that depend on the year. We cannot use them as we
+ still support Windows XP and Windows 2003. */
+ status = (tzi_status >= 0 && tzi_status <= 2)
+ && FileTimeToSystemTime (&utc_time.ft_time, &utc_sys_time)
+ && SystemTimeToTzSpecificLocalTime (&tzi, &utc_sys_time, &local_sys_time)
+ && SystemTimeToFileTime (&local_sys_time, &local_time.ft_time);
+
+ if (!status)
+ /* An error occurs so return invalid_tzoff. */
+ *off = __gnat_invalid_tzoff;
+ else
+ *off = (long) ((local_time.ull_time - utc_time.ull_time) / 10000000ULL);
+
(*Unlock_Task) ();
- return tp;
}
#else
spec is required. Only use when ___THREADS_POSIX4ad4__ is defined,
the Lynx convention when building against the legacy API. */
-extern struct tm *
-__gnat_localtime_tzoff (const time_t *, struct tm *, long *);
+extern void
+__gnat_localtime_tzoff (const time_t *, long *);
-struct tm *
-__gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
+void
+__gnat_localtime_tzoff (const time_t *timer, long *off)
{
/* Treat all time values in GMT */
- localtime_r (tp, timer);
*off = 0;
- return NULL;
}
#else
/* All other targets provide a standard localtime_r */
-extern struct tm *
-__gnat_localtime_tzoff (const time_t *, struct tm *, long *);
+extern void
+__gnat_localtime_tzoff (const time_t *, long *);
-struct tm *
-__gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
+void
+__gnat_localtime_tzoff (const time_t *timer, long *off)
{
- localtime_r (timer, tp);
+ struct tm tp;
+ localtime_r (timer, &tp);
/* AIX, HPUX, SGI Irix, Sun Solaris */
#if defined (_AIX) || defined (__hpux__) || defined (sgi) || defined (sun)
- /* The contents of external variable "timezone" may not always be
- initialized. Instead of returning an incorrect offset, treat the local
- time zone as 0 (UTC). The value of 28 hours is the maximum valid offset
- allowed by Ada.Calendar.Time_Zones. */
- if ((timezone < -28 * 3600) || (timezone > 28 * 3600))
- *off = 0;
- else
- {
- *off = (long) -timezone;
- if (tp->tm_isdst > 0)
- *off = *off + 3600;
- }
+ *off = (long) -timezone;
+ if (tp.tm_isdst > 0)
+ *off = *off + 3600;
+
/* Lynx - Treat all time values in GMT */
#elif defined (__Lynx__)
*off = 0;
}
}
-/* Darwin, Free BSD, Linux, Tru64, where there exists a component tm_gmtoff
- in struct tm */
+/* Darwin, Free BSD, Linux, Tru64, where component tm_gmtoff is present in
+ struct tm */
#elif defined (__APPLE__) || defined (__FreeBSD__) || defined (linux) ||\
(defined (__alpha__) && defined (__osf__)) || defined (__GLIBC__)
- *off = tp->tm_gmtoff;
+ *off = tp.tm_gmtoff;
/* All other platforms: Treat all time values in GMT */
#else
*off = 0;
#endif
- return NULL;
}
#endif