示例#1
0
        public static TaskFunc FindGamesTask(Dictionary <String, FoundGame> foundGames)
        {
            return((Tasker tasker, Object taskObject) =>
            {
                tasker.SetStatus(Resources.Scanning);
                if (hakchi.Shell.IsOnline)
                {
                    var mountpoint = hakchi.Shell is ClovershellConnection ? "" : hakchi.Shell.ExecuteSimple("hakchi get mountpoint", throwOnNonZero: true);
                    var rootfs = hakchi.Shell is ClovershellConnection ? "/var/lib/hakchi/rootfs" : hakchi.Shell.ExecuteSimple("hakchi get rootfs", throwOnNonZero: true);
                    var searchPaths = new string[]
                    {
                        $"{rootfs}/usr/share/games",
                        $"{mountpoint}/var/lib/hakchi/games",
                        $"{mountpoint}/media/hakchi/games"
                    };
                    using (var desktopTarStream = new MemoryStream())
                        using (var sizeStream = new MemoryStream())
                        {
                            var paths = "";
                            foreach (var path in searchPaths)
                            {
                                paths = $"{paths} {Shared.EscapeShellArgument(path)}";
                            }

                            hakchi.Shell.Execute($"find {paths} -name \"CLV-*.desktop\" | sort | tar -cf - -T -", null, desktopTarStream);
                            desktopTarStream.Seek(0, SeekOrigin.Begin);

                            var sizeRegex = new Regex(@"^(\d+)\s*(/.*)$", RegexOptions.Multiline);
                            if (desktopTarStream.Length > 0)
                            {
                                hakchi.Shell.Execute($"du {paths}", null, sizeStream);
                                sizeStream.Seek(0, SeekOrigin.Begin);

                                using (var extractor = ArchiveFactory.Open(desktopTarStream))
                                    using (var reader = extractor.ExtractAllEntries())
                                    {
                                        while (reader.MoveToNextEntry())
                                        {
                                            var entry = reader.Entry;
                                            Trace.WriteLine(entry.Key);
                                            using (var entryStream = reader.OpenEntryStream())
                                            {
                                                var key = Path.GetDirectoryName($"/{entry.Key}").Replace('\\', '/');
                                                var desktop = new DesktopFile(entryStream);

                                                if (desktop.IconPath.EndsWith("/.storage"))
                                                {
                                                    // This is a linked game
                                                    key = $"{mountpoint}{desktop.IconPath}/{desktop.Code}";
                                                }

                                                desktop.Exec = desktop.Exec.Replace(desktop.IconPath, "/var/games");
                                                desktop.IconPath = "/var/games";
                                                desktop.ProfilePath = "/var/saves";

                                                if (!NesApplication.AllDefaultGames.ContainsKey(desktop.Code) && desktop.Bin != "/bin/chmenu")
                                                {
                                                    foundGames.Add(key, new FoundGame()
                                                    {
                                                        RemotePath = key,
                                                        Desktop = desktop,
                                                        Size = 0
                                                    });
                                                }
                                            }
                                        }
                                    }

                                using (var sr = new StreamReader(sizeStream))
                                {
                                    var matches = sizeRegex.Matches(sr.ReadToEnd());
                                    foreach (Match match in matches)
                                    {
                                        var size = long.Parse(match.Groups[1].Value) * 1024;
                                        var path = match.Groups[2].Value;
                                        if (foundGames.ContainsKey(path))
                                        {
                                            foundGames[path].Size = size;
                                        }
                                    }
                                }
                            }
                        }
                    return Conclusion.Success;
                }
                return Conclusion.Error;
            });
        }
示例#2
0
        public static TaskFunc GameCopyTask(FoundGame game)
        {
            return((Tasker tasker, Object sync) =>
            {
                if (game.Desktop.Code.StartsWith("CLV-"))
                {
                    long dataTransferred = 0;
                    var destinationPath = Path.Combine(NesApplication.GamesDirectory, game.Desktop.Code);
                    tasker?.SetStatus($"{game.Desktop.Name}");

                    if (Directory.Exists(destinationPath))
                    {
                        Directory.Delete(destinationPath, true);
                    }

                    Directory.CreateDirectory(destinationPath);

                    foreach (var folder in hakchi.Shell.ExecuteSimple($"cd {Shared.EscapeShellArgument(game.RemotePath)}; find -type d").Split('\n'))
                    {
                        Directory.CreateDirectory(Path.Combine(destinationPath, folder));
                    }

                    FtpClient ftp = null;

                    if (hakchi.Shell is INetworkShell)
                    {
                        ftp = new FtpClient(new Uri($"ftp://{(hakchi.Shell as INetworkShell).IPAddress}"), new NetworkCredential("root", "root"));
                    }

                    foreach (Match match in new Regex(@"^(\d+)\s*\./(.*)$", RegexOptions.Multiline).Matches(hakchi.Shell.ExecuteSimple($"cd {Shared.EscapeShellArgument(game.RemotePath)}; find -type f -exec du {"{}"} \\;")))
                    {
                        var size = long.Parse(match.Groups[1].Value) * 1024;
                        var filename = match.Groups[2].Value;

                        using (var file = File.Create(Path.Combine(destinationPath, filename)))
                            using (var tracker = new TrackableStream(file))
                            {
                                tracker.OnProgress += (long transferred, long length) =>
                                {
                                    var totalTransferred = Math.Min(dataTransferred + transferred, game.Size);
                                    tasker?.SetProgress(totalTransferred, game.Size);
                                    tasker?.SetStatus($"{game.Desktop.Name} ({Shared.SizeSuffix(totalTransferred, 2)} / {Shared.SizeSuffix(game.Size, 2)})");
                                };

                                if (hakchi.Shell is INetworkShell)
                                {
                                    using (var ftpStream = ftp.Retr($"{game.RemotePath}/{filename}"))
                                    {
                                        ftpStream.CopyTo(tracker);
                                    }
                                }
                                else
                                {
                                    hakchi.Shell.Execute($"cat {Shared.EscapeShellArgument($"{game.RemotePath}/{filename}")}", null, tracker, throwOnNonZero: true);
                                }

                                dataTransferred += size;
                            }
                    }

                    ftp?.Dispose();
                    ftp = null;

                    game.Desktop.Save(Path.Combine(destinationPath, $"{game.Desktop.Code}.desktop"));

                    if (!ConfigIni.Instance.SelectedGames.Contains(game.Desktop.Code))
                    {
                        ConfigIni.Instance.SelectedGames.Add(game.Desktop.Code);
                    }

                    return Conclusion.Success;
                }

                return Conclusion.Error;
            });
        }