/// <inheritdoc /> public FileTimestamps GetFileTimestamps(string path, bool followSymlink) { var statBuffer = new StatBuffer(); unsafe { if (StatFile(path, followSymlink, ref statBuffer) != 0) { throw new BuildXLException(I($"Failed to stat file '{path}' to get its timestamps - error: {Marshal.GetLastWin32Error()}")); } } var creationTime = new Timespec() { Tv_sec = statBuffer.TimeCreation, Tv_nsec = statBuffer.TimeNSecCreation }; var lastChangeTimeTime = new Timespec() { Tv_sec = statBuffer.TimeLastStatusChange, Tv_nsec = statBuffer.TimeNSecLastStatusChange }; var lastWriteTime = new Timespec() { Tv_sec = statBuffer.TimeLastModification, Tv_nsec = statBuffer.TimeNSecLastModification }; var accessTime = new Timespec() { Tv_sec = statBuffer.TimeLastAccess, Tv_nsec = statBuffer.TimeNSecLastAccess }; return(new FileTimestamps( creationTime: creationTime.ToUtcTime(), lastChangeTime: lastChangeTimeTime.ToUtcTime(), lastWriteTime: lastWriteTime.ToUtcTime(), accessTime: accessTime.ToUtcTime())); }
/// <inheritdoc /> public void SetFileTimestamps(string path, FileTimestamps timestamps, bool followSymlink) { Contract.Requires(timestamps.CreationTime >= UnixEpoch); Contract.Requires(timestamps.AccessTime >= UnixEpoch); Contract.Requires(timestamps.LastWriteTime >= UnixEpoch); Contract.Requires(timestamps.LastChangeTime >= UnixEpoch); var statBuffer = new StatBuffer(); Timespec creationTime = Timespec.CreateFromUtcDateTime(timestamps.CreationTime); Timespec lastAccessTime = Timespec.CreateFromUtcDateTime(timestamps.AccessTime); Timespec lastModificationTime = Timespec.CreateFromUtcDateTime(timestamps.LastWriteTime); Timespec lastStatusChangeTime = Timespec.CreateFromUtcDateTime(timestamps.LastChangeTime); statBuffer.TimeCreation = creationTime.Tv_sec; statBuffer.TimeNSecCreation = creationTime.Tv_nsec; statBuffer.TimeLastAccess = lastAccessTime.Tv_sec; statBuffer.TimeNSecLastAccess = lastAccessTime.Tv_nsec; statBuffer.TimeLastModification = lastModificationTime.Tv_sec; statBuffer.TimeNSecLastModification = lastModificationTime.Tv_nsec; statBuffer.TimeLastStatusChange = lastStatusChangeTime.Tv_sec; statBuffer.TimeNSecLastStatusChange = lastStatusChangeTime.Tv_nsec; int result = SetTimeStampsForFilePath(path, followSymlink, statBuffer); if (result != 0) { throw new BuildXLException("Failed to open a file to set its timestamps - error: " + Marshal.GetLastWin32Error()); } }
/// <inheritdoc/> public (FileIdAndVolumeId, Usn)? TryGetVersionedFileIdentityByHandle(SafeFileHandle fileHandle) { var statBuffer = new StatBuffer(); unsafe { if (StatFileDescriptor(fileHandle, ref statBuffer) != 0) { return(default);
/// <summary> /// Gets device and inode number. /// </summary> public int GetDeviceAndInodeNumbers(string path, bool followSymlink, out ulong device, out ulong inode) { var statBuffer = new StatBuffer(); int result = StatFile(path, followSymlink, ref statBuffer); device = unchecked ((ulong)statBuffer.DeviceID); inode = unchecked ((ulong)statBuffer.InodeNumber); return(result); }
/// <inheritdoc /> public uint GetHardLinkCount(string path) { var statBuffer = new StatBuffer(); if (StatFile(path, true, ref statBuffer) != 0) { throw new BuildXLException(I($"Failed to stat file '{path}' to get its hardlink count - error: {Marshal.GetLastWin32Error()}")); } // TODO: Change hardlink count return type to ulong. return(unchecked ((uint)statBuffer.HardLinks)); }
/// <inheritdoc/> public FileIdAndVolumeId?TryGetFileIdentityByHandle(SafeFileHandle fileHandle) { var statBuffer = new StatBuffer(); unsafe { return(StatFileDescriptor(fileHandle, ref statBuffer) != 0 ? default : new FileIdAndVolumeId( unchecked ((ulong)statBuffer.DeviceID), new FileId(UnusedFileIdPart, unchecked ((ulong)statBuffer.InodeNumber)))); } }
/// <summary> /// Sets atime and mtime to current time. /// </summary> public static int Touch(string pathname, bool followSymlink) { var timespec = Timespec.CreateFromUtcDateTime(DateTime.UtcNow); var buf = new StatBuffer { TimeLastAccess = timespec.Tv_sec, TimeNSecLastAccess = timespec.Tv_nsec, TimeLastModification = timespec.Tv_sec, TimeNSecLastModification = timespec.Tv_nsec, }; return(SetTimeStampsForFilePath(pathname, followSymlink, buf)); }
private static int StatFile(int fd, string path, bool followSymlink, ref StatBuffer statBuf) { // using 'fstatat' instead of the newer 'statx' because Ubuntu 18.04 doesn't have iit var buf = new stat_buf(); int result = StatFile(fd, path, followSymlink, ref buf); if (result != 0) { return(ERROR); } else { Translate(buf, ref statBuf); return(0); } }
/// <summary>OSX specific implementation of <see cref="IO.StatFileDescriptor"/> </summary> internal unsafe static int StatFileDescriptor(SafeFileHandle fd, ref StatBuffer statBuf) => StatFileDescriptor(fd, ref statBuf, sizeof(StatBuffer));
public static int Stat(string path, [Out] out StatBuffer buf) { return(__XStat64(STAT_VER, path, out buf)); }
/// <summary> /// Linux specific implementation of <see cref="IO.SetTimeStampsForFilePath"/> /// </summary> /// <remarks> /// Only atime and mtime are settable /// </remarks> internal static int SetTimeStampsForFilePath(string path, bool followSymlink, StatBuffer buf) { int flags = followSymlink ? 0 : AT_SYMLINK_NOFOLLOW; var atime = new Timespec { Tv_sec = buf.TimeLastAccess, Tv_nsec = buf.TimeNSecLastAccess }; var mtime = new Timespec { Tv_sec = buf.TimeLastModification, Tv_nsec = buf.TimeNSecLastModification }; return(utimensat(AT_FDCWD, path, new[] { atime, mtime }, flags)); }
/// <summary>Linux specific implementation of <see cref="IO.StatFileDescriptor"/> </summary> public static int StatFileDescriptor(SafeFileHandle fd, ref StatBuffer statBuf) { return(StatFile(ToInt(fd), string.Empty, followSymlink: false, ref statBuf)); }
public static int StatFileDescriptor(SafeFileHandle fd, ref StatBuffer statBuf) => StatFileDescriptor(fd, ref statBuf, Marshal.SizeOf(statBuf));
public static int StatFile(string path, bool followSymlink, ref StatBuffer statBuf) => StatFile(path, followSymlink, ref statBuf, Marshal.SizeOf(statBuf));
/// <summary>Linux specific implementation of <see cref="IO.StatFile"/> </summary> internal static int StatFile(string path, bool followSymlink, ref StatBuffer statBuf) { Contract.Requires(!string.IsNullOrEmpty(path)); return(StatFile(AT_FDCWD, path, followSymlink, ref statBuf)); }
public Bar(int historySize) { mAverageValues = new StatBuffer(historySize); }
public Bar() { mAverageValues = new StatBuffer(5); }
/// <inheritdoc /> public void InKernelFileCopy(string source, string destination, bool followSymlink) { SafeFileHandle sourceHandle; OpenFileResult openResult = m_fileSystem.TryCreateOrOpenFile( source, FileDesiredAccess.GenericRead, FileShare.Read | FileShare.Delete, FileMode.Open, followSymlink ? FileFlagsAndAttributes.FileFlagOpenReparsePoint : FileFlagsAndAttributes.None, out sourceHandle); if (!openResult.Succeeded) { throw new NativeWin32Exception(Marshal.GetLastWin32Error(), I($"Failed to open source file '{source}' in {nameof(InKernelFileCopy)}")); } using (sourceHandle) { // Ignore return of PosixFadvise(), the file handle was opened successfully above // and the advice hint is a less important optimization. Interop.Unix.IO.PosixFadvise(sourceHandle, 0, 0, AdviceHint.POSIX_FADV_SEQUENTIAL); SafeFileHandle destinationHandle; openResult = m_fileSystem.TryCreateOrOpenFile( destination, FileDesiredAccess.GenericRead | FileDesiredAccess.GenericWrite, FileShare.Read | FileShare.Write | FileShare.Delete, FileMode.Create, FileFlagsAndAttributes.None, out destinationHandle); if (!openResult.Succeeded) { throw new NativeWin32Exception(Marshal.GetLastWin32Error(), I($"Failed to open destination file '{destination}' in {nameof(InKernelFileCopy)}")); } using (destinationHandle) { var statBuffer = new StatBuffer(); if (StatFileDescriptor(sourceHandle, ref statBuffer) != 0) { throw new NativeWin32Exception(Marshal.GetLastWin32Error(), I($"Failed to stat source file '{source}' for size query in {nameof(InKernelFileCopy)}")); } var length = statBuffer.Size; long bytesCopied = 0; int lastError = 0; do { bytesCopied = Interop.Unix.IO.CopyFileRange(sourceHandle, IntPtr.Zero, destinationHandle, IntPtr.Zero, s_copyBufferSizeMax); if (bytesCopied == -1) { lastError = Marshal.GetLastWin32Error(); break; } length -= bytesCopied; } while (length > 0 && bytesCopied > 0); // copy_file_range() is available in kernel versions > 4.5, let's try sendfile() if copy_file_range() is not implemented if (lastError == (int)Errno.ENOSYS) { length = statBuffer.Size; bytesCopied = 0; lastError = 0; do { bytesCopied = Interop.Unix.IO.SendFile(sourceHandle, destinationHandle, IntPtr.Zero, s_copyBufferSizeMax); if (bytesCopied == -1) { lastError = Marshal.GetLastWin32Error(); break; } length -= bytesCopied; } while (length > 0 && bytesCopied > 0); } if (lastError != 0) { throw new NativeWin32Exception(lastError, I($"{nameof(InKernelFileCopy)} failed copying '{source}' to '{destination}' with error code: {lastError}")); } } } }
/// <summary>OSX specific implementation of <see cref="IO.StatFile"/> </summary> internal unsafe static int StatFile(string path, bool followSymlink, ref StatBuffer statBuf) => StatFile(path, followSymlink, ref statBuf, sizeof(StatBuffer));
private static extern int StatFile(string path, bool followSymlink, ref StatBuffer statBuf, long statBufferSize);
public static int LStat(string pathname, [Out] out StatBuffer buf) { return(__LXStat64(STAT_VER, pathname, out buf)); }
private static extern int StatFileDescriptor(SafeFileHandle fd, ref StatBuffer statBuf, long statBufferSize);
private static extern int __LXStat64(int vers, string pathname, [Out] out StatBuffer buf);
public static extern int SetTimeStampsForFilePath(string path, bool followSymlink, StatBuffer buffer);
/// <summary> /// Implements the standard unix 'stat' command. /// </summary> /// <returns> /// Upon successful completion a value of 0 is returned and the result is stored in <paramref name="statBuf"/>; /// otherwise, a value of -1 is returned and <see cref="Marshal.GetLastWin32Error"/> is set to indicate the error. /// </returns> public static int StatFile(string path, bool followSymlink, ref StatBuffer statBuf) => IsMacOS ? Impl_Mac.StatFile(path, followSymlink, ref statBuf) : Impl_Linux.StatFile(path, followSymlink, ref statBuf);
/// <summary> /// Same as <see cref="StatFile" /> except that the target file is given as a file descriptor (<paramref name="fd" />). /// </summary> public static int StatFileDescriptor(SafeFileHandle fd, ref StatBuffer statBuf) => IsMacOS ? Impl_Mac.StatFileDescriptor(fd, ref statBuf) : Impl_Linux.StatFileDescriptor(fd, ref statBuf);
/// <summary> /// Sets the creation, modification, change and access time of a file specified at path /// </summary> /// <returns>Returns zero in case of success, otherwise error</returns> public static int SetTimeStampsForFilePath(string path, bool followSymlink, StatBuffer buffer) => IsMacOS ? Impl_Mac.SetTimeStampsForFilePath(path, followSymlink, buffer) : Impl_Linux.SetTimeStampsForFilePath(path, followSymlink, buffer);
public static extern int Stat(string path, [Out] out StatBuffer statBuffer);
/// <inheritdoc /> public Possible <Unit> InKernelFileCopy(string source, string destination, bool followSymlink) { SafeFileHandle sourceHandle; OpenFileResult openResult = m_fileSystem.TryCreateOrOpenFile( source, FileDesiredAccess.GenericRead, FileShare.Read | FileShare.Delete, FileMode.Open, followSymlink ? FileFlagsAndAttributes.FileFlagOpenReparsePoint : FileFlagsAndAttributes.None, out sourceHandle); if (!openResult.Succeeded) { return(new NativeFailure(Marshal.GetLastWin32Error(), I($"Failed to open source file '{source}' in {nameof(InKernelFileCopy)}"))); } using (sourceHandle) { // Ignore return of PosixFadvise(), the file handle was opened successfully above // and the advice hint is a less important optimization. Interop.Unix.IO.PosixFadvise(sourceHandle, 0, 0, AdviceHint.POSIX_FADV_SEQUENTIAL); SafeFileHandle destinationHandle; openResult = m_fileSystem.TryCreateOrOpenFile( destination, FileDesiredAccess.GenericRead | FileDesiredAccess.GenericWrite, FileShare.Read | FileShare.Write | FileShare.Delete, FileMode.Create, FileFlagsAndAttributes.None, out destinationHandle); if (!openResult.Succeeded) { return(new NativeFailure(Marshal.GetLastWin32Error(), I($"Failed to open destination file '{destination}' in {nameof(InKernelFileCopy)}"))); } using (destinationHandle) { var statBuffer = new StatBuffer(); if (StatFileDescriptor(sourceHandle, ref statBuffer) != 0) { return(new NativeFailure(Marshal.GetLastWin32Error(), I($"Failed to stat source file '{source}' for size query in {nameof(InKernelFileCopy)}"))); } var length = statBuffer.Size; long bytesCopied = 0; int lastError = 0; do { bytesCopied = CopyBytes(sourceHandle, destinationHandle); if (bytesCopied == -1) { return(new NativeFailure(Marshal.GetLastWin32Error(), I($"{nameof(InKernelFileCopy)} failed copying '{source}' to '{destination}' with error code: {lastError}"))); } length -= bytesCopied; } while (length > 0 && bytesCopied > 0); return(Unit.Void); } } }