Exemplo n.º 1
0
        private unsafe void SetAccessOrWriteTime(string path, DateTimeOffset time, bool isAccessTime)
        {
            // force a refresh so that we have an up-to-date times for values not being overwritten
            _fileStatusInitialized = -1;
            EnsureStatInitialized(path);

            // we use utimes()/utimensat() to set the accessTime and writeTime
            Interop.Sys.TimeSpec *buf = stackalloc Interop.Sys.TimeSpec[2];

            long seconds = time.ToUnixTimeSeconds();

            const long TicksPerMillisecond = 10000;
            const long TicksPerSecond      = TicksPerMillisecond * 1000;
            long       nanoseconds         = (time.UtcDateTime.Ticks - DateTimeOffset.UnixEpoch.Ticks - seconds * TicksPerSecond) * NanosecondsPerTick;

            if (isAccessTime)
            {
                buf[0].TvSec  = seconds;
                buf[0].TvNsec = nanoseconds;
                buf[1].TvSec  = _fileStatus.MTime;
                buf[1].TvNsec = _fileStatus.MTimeNsec;
            }
            else
            {
                buf[0].TvSec  = _fileStatus.ATime;
                buf[0].TvNsec = _fileStatus.ATimeNsec;
                buf[1].TvSec  = seconds;
                buf[1].TvNsec = nanoseconds;
            }

            Interop.CheckIo(Interop.Sys.UTimensat(path, buf), path, InitiallyDirectory);

            _fileStatusInitialized = -1;
        }
Exemplo n.º 2
0
        private unsafe void SetAccessOrWriteTimeCore(string path, DateTimeOffset time, bool isAccessTime, bool checkCreationTime)
        {
            // This api is used to set creation time on non OSX platforms, and as a fallback for OSX platforms.
            // The reason why we use it to set 'creation time' is the below comment:
            // Unix provides APIs to update the last access time (atime) and last modification time (mtime).
            // There is no API to update the CreationTime.
            // Some platforms (e.g. Linux) don't store a creation time. On those platforms, the creation time
            // is synthesized as the oldest of last status change time (ctime) and last modification time (mtime).
            // We update the LastWriteTime (mtime).
            // This triggers a metadata change for FileSystemWatcher NotifyFilters.CreationTime.
            // Updating the mtime, causes the ctime to be set to 'now'. So, on platforms that don't store a
            // CreationTime, GetCreationTime will return the value that was previously set (when that value
            // wasn't in the future).

            // force a refresh so that we have an up-to-date times for values not being overwritten
            InvalidateCaches();
            EnsureCachesInitialized(path);

            // we use utimes()/utimensat() to set the accessTime and writeTime
            Interop.Sys.TimeSpec *buf = stackalloc Interop.Sys.TimeSpec[2];

            long seconds     = time.ToUnixTimeSeconds();
            long nanoseconds = UnixTimeSecondsToNanoseconds(time, seconds);

#if TARGET_BROWSER
            buf[0].TvSec  = seconds;
            buf[0].TvNsec = nanoseconds;
            buf[1].TvSec  = seconds;
            buf[1].TvNsec = nanoseconds;
#else
            if (isAccessTime)
            {
                buf[0].TvSec  = seconds;
                buf[0].TvNsec = nanoseconds;
                buf[1].TvSec  = _fileCache.MTime;
                buf[1].TvNsec = _fileCache.MTimeNsec;
            }
            else
            {
                buf[0].TvSec  = _fileCache.ATime;
                buf[0].TvNsec = _fileCache.ATimeNsec;
                buf[1].TvSec  = seconds;
                buf[1].TvNsec = nanoseconds;
            }
#endif
            Interop.CheckIo(Interop.Sys.UTimensat(path, buf), path, InitiallyDirectory);

            // On OSX-like platforms, when the modification time is less than the creation time (including
            // when the modification time is already less than but access time is being set), the creation
            // time is set to the modification time due to the api we're currently using; this is not
            // desirable behaviour since it is inconsistent with windows behaviour and is not logical to
            // the programmer (ie. we'd have to document it), so these api calls revert the creation time
            // when it shouldn't be set (since we're setting modification time and access time here).
            // checkCreationTime is only true on OSX-like platforms.
            // allowFallbackToLastWriteTime is ignored on non OSX-like platforms.
            bool updateCreationTime = checkCreationTime && (_fileCache.Flags & Interop.Sys.FileStatusFlags.HasBirthTime) != 0 &&
                                      (buf[1].TvSec < _fileCache.BirthTime || (buf[1].TvSec == _fileCache.BirthTime && buf[1].TvNsec < _fileCache.BirthTimeNsec));

            InvalidateCaches();

            if (updateCreationTime)
            {
                Interop.Error error = SetCreationTimeCore(path, _fileCache.BirthTime, _fileCache.BirthTimeNsec);
                if (error != Interop.Error.SUCCESS && error != Interop.Error.ENOTSUP)
                {
                    Interop.CheckIo(error, path, InitiallyDirectory);
                }
            }
        }