예제 #1
0
 public static DateTime GetLastAccessTime(Stat stat)
 {
     return(NativeConvert.ToDateTime(stat.st_atime));
 }
예제 #2
0
 public static DateTime GetLastStatusChangeTime(Stat stat)
 {
     return(NativeConvert.ToDateTime(stat.st_ctime));
 }
예제 #3
0
 public static DateTime GetLastWriteTime(Stat stat)
 {
     return(NativeConvert.ToDateTime(stat.st_mtime));
 }
예제 #4
0
        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);
        }