/* We want to use the POSIX variants of include files. */
#define POSIX
#include "vxWorks.h"
+#include <sys/time.h>
#if defined (__mips_vxworks)
#include "cacheLib.h"
return __gnat_file_time_fd_attr (fd, &attr);
}
+extern long long __gnat_file_time(char* name)
+{
+ long long result;
+
+ if (name == NULL) {
+ return LLONG_MIN;
+ }
+ /* Number of seconds between <Jan 1st 1970> and <Jan 1st 2150>. */
+ static const long long ada_epoch_offset = (136 * 365 + 44 * 366) * 86400LL;
+#if defined(_WIN32)
+
+ /* Number of 100 nanoseconds between <Jan 1st 1601> and <Jan 1st 2150>. */
+ static const long long w32_epoch_offset =
+ (11644473600LL + ada_epoch_offset) * 1E7;
+
+ WIN32_FILE_ATTRIBUTE_DATA fad;
+ union
+ {
+ FILETIME ft_time;
+ long long ll_time;
+ } t_write;
+
+ if (!GetFileAttributesExA(name, GetFileExInfoStandard, &fad)) {
+ return LLONG_MIN;
+ }
+
+ t_write.ft_time = fad.ftLastWriteTime;
+
+ /* Next code similar to (t_write.ll_time - w32_epoch_offset) * 100
+ but on overflow returns LLONG_MIN value. */
+
+ if (__builtin_ssubll_overflow(t_write.ll_time, w32_epoch_offset, &result)) {
+ return LLONG_MIN;
+ }
+
+ if (__builtin_smulll_overflow(result, 100, &result)) {
+ return LLONG_MIN;
+ }
+
+#else
+
+ struct stat sb;
+ if (stat(name, &sb) != 0) {
+ return LLONG_MIN;
+ }
+
+ /* Next code similar to
+ (sb.st_mtime - ada_epoch_offset) * 1E9 + sb.st_mtim.tv_nsec
+ but on overflow returns LLONG_MIN value. */
+
+ if (__builtin_ssubll_overflow(sb.st_mtime, ada_epoch_offset, &result)) {
+ return LLONG_MIN;
+ }
+
+ if (__builtin_smulll_overflow(result, 1E9, &result)) {
+ return LLONG_MIN;
+ }
+
+#if defined(st_mtime)
+ if (__builtin_saddll_overflow(result, sb.st_mtim.tv_nsec, &result)) {
+ return LLONG_MIN;
+ }
+#endif
+
+#endif
+ return result;
+}
+
/* Set the file time stamp. */
void
#else
GNAT_STRUCT_STAT fbuf;
- struct utimbuf tbuf;
if (GNAT_STAT (from, &fbuf) == -1) {
return -1;
}
- /* Do we need to copy timestamp ? */
+#if _POSIX_C_SOURCE >= 200809L
+ struct timespec tbuf[2];
+
if (mode != 2) {
- tbuf.actime = fbuf.st_atime;
- tbuf.modtime = fbuf.st_mtime;
+ tbuf[0] = fbuf.st_atim;
+ tbuf[1] = fbuf.st_mtim;
- if (utime (to, &tbuf) == -1) {
+ if (utimensat (AT_FDCWD, to, tbuf, 0) == -1) {
return -1;
}
}
+#else
+ struct timeval tbuf[2];
+ /* Do we need to copy timestamp ? */
+
+ if (mode != 2) {
+ tbuf[0].tv_sec = fbuf.st_atime;
+ tbuf[1].tv_sec = fbuf.st_mtime;
+
+ #if defined(st_mtime)
+ tbuf[0].tv_usec = fbuf.st_atim.tv_nsec / 1000;
+ tbuf[1].tv_usec = fbuf.st_mtim.tv_nsec / 1000;
+ #else
+ tbuf[0].tv_usec = 0;
+ tbuf[1].tv_usec = 0;
+ #endif
+
+ if (utimes (to, tbuf) == -1) {
+ return -1;
+ }
+ }
+#endif
+
/* Do we need to copy file permissions ? */
if (mode != 0 && (chmod (to, fbuf.st_mode) == -1)) {
return -1;
------------------------------------------------------------------------------
with Ada.Calendar; use Ada.Calendar;
-with Ada.Calendar.Formatting; use Ada.Calendar.Formatting;
with Ada.Characters.Handling; use Ada.Characters.Handling;
with Ada.Directories.Validity; use Ada.Directories.Validity;
with Ada.Directories.Hierarchical_File_Names;
pragma Import (C, Max_Path, "__gnat_max_path_len");
-- The maximum length of a path
+ function C_Modification_Time (N : System.Address) return Ada.Calendar.Time;
+ pragma Import (C, C_Modification_Time, "__gnat_file_time");
+ -- Get modification time for file with name referenced by N
+
+ Invalid_Time : constant Ada.Calendar.Time :=
+ C_Modification_Time (System.Null_Address);
+ -- Result returned from C_Modification_Time call when routine unable to get
+ -- file modification time.
+
type Search_Data is record
Is_Valid : Boolean := False;
Name : Unbounded_String;
-----------------------
function Modification_Time (Name : String) return Time is
- Date : OS_Time;
- Year : Year_Type;
- Month : Month_Type;
- Day : Day_Type;
- Hour : Hour_Type;
- Minute : Minute_Type;
- Second : Second_Type;
+ Date : Time;
+ C_Name : aliased String (1 .. Name'Length + 1);
begin
-- First, the invalid cases
raise Name_Error with '"' & Name & """ not a file or directory";
else
- Date := File_Time_Stamp (Name);
-
- -- Break down the time stamp into its constituents relative to GMT.
- -- This version of Split does not recognize leap seconds or buffer
- -- space for time zone processing.
+ C_Name := Name & ASCII.NUL;
+ Date := C_Modification_Time (C_Name'Address);
- GM_Split (Date, Year, Month, Day, Hour, Minute, Second);
-
- -- The result must be in GMT. Ada.Calendar.
- -- Formatting.Time_Of with default time zone of zero (0) is the
- -- routine of choice.
+ if Date = Invalid_Time then
+ raise Use_Error with
+ "Unable to get modification time of the file """ & Name & '"';
+ end if;
- return Time_Of (Year, Month, Day, Hour, Minute, Second, 0.0);
+ return Date;
end if;
end Modification_Time;