public static DateTime GetLastAccessTime(Stat stat) { return(NativeConvert.ToDateTime(stat.st_atime)); }
public static DateTime GetLastStatusChangeTime(Stat stat) { return(NativeConvert.ToDateTime(stat.st_ctime)); }
public static DateTime GetLastWriteTime(Stat stat) { return(NativeConvert.ToDateTime(stat.st_mtime)); }
bool CopyFile(string source_absolute_path, string target_path) { bool ret = false; bool target_exists = false; // Stat target Stat tstat; lock (this) ProcessedFiles++; while (Syscall.stat(target_path, out tstat) == 0) { if (tstat.st_mode.HasFlag(FilePermissions.S_IFDIR)) { if (ShouldRetryOperation("Target file is a directory", "Source file \"{0}\"", Path.GetFileName(source_absolute_path))) { continue; } return(false); } else { target_exists = true; } break; } // Open Source int source_fd; while (true) { source_fd = Syscall.open(source_absolute_path, OpenFlags.O_RDONLY, (FilePermissions)0); if (source_fd != -1) { break; } if (ShouldRetryOperation("While opening \"{0}\"", target_path)) { continue; } return(false); } Stat stat; while (true) { if (Syscall.fstat(source_fd, out stat) != -1) { break; } if (ShouldRetryOperation("While probing for state of \"{0}\"", target_path)) { continue; } goto close_source; } // Make sure we are not overwriting the same file if (stat.st_dev == tstat.st_dev && stat.st_ino == tstat.st_ino) { Interaction.Error("Can not copy a file into itself"); skip = true; goto close_source; } lock (this) { CurrentFileProgress = 0; CurrentFileSize = tstat.st_size; } if (target_exists) { if (target_exists_action < TargetExistsAction.AlwaysOverwrite) { target_exists_action = Interaction.TargetExists( target_path, NativeConvert.ToDateTime(stat.st_mtime), stat.st_size, NativeConvert.ToDateTime(tstat.st_mtime), tstat.st_size, Interaction.Count > 1); } if (target_exists_action == TargetExistsAction.Cancel) { goto close_source; } if (target_exists_action == TargetExistsAction.Skip) { goto close_source; } } // Open target int target_fd; switch (target_exists_action) { case TargetExistsAction.AlwaysUpdate: if (stat.st_mtime > tstat.st_mtime) { goto case TargetExistsAction.Overwrite; } skip = true; goto close_source; case TargetExistsAction.AlwaysUpdateOnSizeMismatch: if (stat.st_size != tstat.st_size) { goto case TargetExistsAction.Overwrite; } skip = true; goto close_source; // Real cancels are taken care of immediately after the dialog // this means: never used, target does not exist. case TargetExistsAction.Cancel: case TargetExistsAction.AlwaysOverwrite: case TargetExistsAction.Overwrite: target_fd = Syscall.open(target_path, OpenFlags.O_CREAT | OpenFlags.O_WRONLY, FilePermissions.S_IWUSR); break; case TargetExistsAction.Append: target_fd = Syscall.open(target_path, OpenFlags.O_APPEND, FilePermissions.S_IWUSR); break; default: throw new Exception(String.Format("Internal error: unhandled TargetExistsAction value {0}", target_exists_action)); } while (true) { if (target_fd != -1) { break; } if (ShouldRetryOperation("While creating \"{0}\"", target_path)) { continue; } goto close_source; } AllocateBuffer(); long n; do { while (true) { n = Syscall.read(source_fd, io_buffer, COPY_BUFFER_SIZE); if (n != -1) { break; } if (ShouldRetryOperation("While reading \"{0}\"", Path.GetFileName(source_absolute_path))) { continue; } goto close_both; } while (true) { long count = Syscall.write(target_fd, io_buffer, (ulong)n); if (count != -1) { break; } if (ShouldRetryOperation("While writing \"{0}\"", target_path)) { continue; } goto close_both; } lock (this) { ProcessedBytes += n; CurrentFileSize += n; } } while (n != 0); // File mode while (true) { n = Syscall.fchmod(target_fd, stat.st_mode); if (n == 0) { break; } if (ShouldRetryOperation("Setting permissions on \"{0}\"", target_path)) { continue; } goto close_both; } // The following are not considered errors if we can not set them ret = true; // preserve owner and group if running as root if (Syscall.geteuid() == 0) { Syscall.fchown(target_fd, stat.st_uid, stat.st_gid); } // Set file time Timeval[] dates = new Timeval [2] { new Timeval() { tv_sec = stat.st_atime }, new Timeval() { tv_sec = stat.st_mtime } }; Syscall.futimes(target_fd, dates); close_both: Syscall.close(target_fd); close_source: Syscall.close(source_fd); return(ret); }