Exemple #1
0
        /// <summary>
        /// Reads the specification file that specifies the contents of the package.
        /// </summary>
        /// <param name="fileName">The name of the package specification file.</param>
        public void ReadSpecification(string fileName)
        {
            srcBasePath = Path.GetDirectoryName(fileName);

            controlParams = new DebControlParams();

            using (var sr = new StreamReader(fileName))
            {
                int  lineNumber    = 0;
                bool inDescription = false;
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
                    lineNumber++;
                    Match m;

                    if (line.TrimStart() == "")
                    {
                        inDescription = false;
                        continue;                           // Skip empty lines
                    }
                    if (line.TrimStart().StartsWith("#"))
                    {
                        inDescription = false;
                        continue;                           // Skip comments
                    }

                    m = Regex.Match(line, @"^basepath\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        srcBasePath = ResolveVariables(m.Groups[1].Value.Trim());
                        if (!Path.IsPathRooted(srcBasePath))
                        {
                            // Interpret non-rooted paths relative to the spec file
                            srcBasePath = Path.Combine(Path.GetDirectoryName(fileName), srcBasePath);
                        }
                        if (!Directory.Exists(srcBasePath))
                        {
                            throw new ArgumentException("Specified base path directory does not exist: " + srcBasePath);
                        }
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^outdir\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        OutDir = ResolveVariables(m.Groups[1].Value.Trim());
                        if (!Path.IsPathRooted(OutDir))
                        {
                            // Interpret non-rooted paths relative to the spec file
                            OutDir = Path.Combine(Path.GetDirectoryName(fileName), OutDir);
                        }
                        inDescription = false;
                        continue;
                    }

                    m = Regex.Match(line, @"^package\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.Package = ResolveVariables(m.Groups[1].Value.Trim());
                        // Source: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Source
                        if (!Regex.IsMatch(controlParams.Package, "^[a-z0-9+.-]+$"))
                        {
                            throw new FormatException("Invalid format of the Package name.");
                        }
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^version\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.Version = ResolveVariables(m.Groups[1].Value.Trim());
                        // Source: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
                        if (!Regex.IsMatch(controlParams.Version, "^[A-Za-z0-9.+~-]+$"))
                        {
                            throw new FormatException("Invalid format of the Version number.");
                        }
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^convert-semver\s*$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.ConvertFromSemVer = true;
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^section\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.Section = ResolveVariables(m.Groups[1].Value.Trim());
                        inDescription         = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^prio(?:rity)?\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.Priority = ResolveVariables(m.Groups[1].Value.Trim());
                        inDescription          = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^arch(?:itecture)?\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.Architecture = ResolveVariables(m.Groups[1].Value.Trim());
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^depends\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        string depends = ResolveVariables(m.Groups[1].Value.Trim());
                        inDescription = false;
                        if (string.IsNullOrWhiteSpace(controlParams.Depends))
                        {
                            controlParams.Depends = depends;
                        }
                        else
                        {
                            controlParams.Depends += ", " + depends;
                        }
                        continue;
                    }
                    m = Regex.Match(line, @"^pre-depends\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        string preDepends = ResolveVariables(m.Groups[1].Value.Trim());
                        inDescription = false;
                        if (string.IsNullOrWhiteSpace(controlParams.PreDepends))
                        {
                            controlParams.PreDepends = preDepends;
                        }
                        else
                        {
                            controlParams.PreDepends += ", " + preDepends;
                        }
                        continue;
                    }
                    m = Regex.Match(line, @"^conflicts\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.Conflicts = ResolveVariables(m.Groups[1].Value.Trim());
                        inDescription           = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^maintainer\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.Maintainer = ResolveVariables(m.Groups[1].Value.Trim());
                        inDescription            = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^homepage\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.Homepage = ResolveVariables(m.Groups[1].Value.Trim());
                        inDescription          = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^desc(?:ription)?\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        controlParams.Description = ResolveVariables(m.Groups[1].Value.Trim());
                        inDescription             = true;
                        continue;
                    }

                    m = Regex.Match(line, @"^preinst\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        preInstFileName = ResolveVariables(m.Groups[1].Value.Trim());
                        if (!Path.IsPathRooted(preInstFileName))
                        {
                            // Interpret non-rooted paths relative to the base path
                            preInstFileName = Path.Combine(srcBasePath, preInstFileName);
                        }
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^postinst\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        postInstFileName = ResolveVariables(m.Groups[1].Value.Trim());
                        if (!Path.IsPathRooted(postInstFileName))
                        {
                            // Interpret non-rooted paths relative to the base path
                            postInstFileName = Path.Combine(srcBasePath, postInstFileName);
                        }
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^prerm\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        preRmFileName = ResolveVariables(m.Groups[1].Value.Trim());
                        if (!Path.IsPathRooted(preRmFileName))
                        {
                            // Interpret non-rooted paths relative to the base path
                            preRmFileName = Path.Combine(srcBasePath, preRmFileName);
                        }
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^postrm\s*:\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        postRmFileName = ResolveVariables(m.Groups[1].Value.Trim());
                        if (!Path.IsPathRooted(postRmFileName))
                        {
                            // Interpret non-rooted paths relative to the base path
                            postRmFileName = Path.Combine(srcBasePath, postRmFileName);
                        }
                        inDescription = false;
                        continue;
                    }

                    m = Regex.Match(line, @"^file\s*:\s*(\S+)\s+(\S+)(?:\s+([0-9]+)(?:\s+([0-9]+)\s+([0-9]+))?)?\s*$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        // Add data file
                        var fileItem = new DebFileItem
                        {
                            SourcePath = ResolveVariables(m.Groups[1].Value.Trim())
                        };
                        if (!Path.IsPathRooted(fileItem.SourcePath))
                        {
                            // Interpret non-rooted paths relative to the base path
                            fileItem.SourcePath = Path.Combine(srcBasePath, fileItem.SourcePath);
                        }
                        fileItem.DestPath = ResolveVariables(m.Groups[2].Value.Trim());
                        if (m.Groups[3].Length > 0)
                        {
                            fileItem.Mode = Convert.ToInt32(ResolveVariables(m.Groups[3].Value), 8);
                        }
                        if (m.Groups[4].Length > 0)
                        {
                            fileItem.UserId = Convert.ToInt32(ResolveVariables(m.Groups[4].Value));
                        }
                        if (m.Groups[5].Length > 0)
                        {
                            fileItem.GroupId = Convert.ToInt32(ResolveVariables(m.Groups[5].Value));
                        }
                        foreach (var fi in ResolveFileItems(fileItem))
                        {
                            var existingItem = fileItems.FirstOrDefault(x => x.SourcePath == fi.SourcePath);
                            if (existingItem != null)
                            {
                                fileItems.Remove(existingItem);
                            }
                            fileItems.Add(fi);
                        }
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^conffile\s*:\s*(\S+)\s+(\S+)(?:\s+([0-9]+)(?:\s+([0-9]+)\s+([0-9]+))?)?\s*$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        // Add data file as conffile
                        var fileItem = new DebFileItem
                        {
                            SourcePath = ResolveVariables(m.Groups[1].Value.Trim())
                        };
                        if (!Path.IsPathRooted(fileItem.SourcePath))
                        {
                            // Interpret non-rooted paths relative to the base path
                            fileItem.SourcePath = Path.Combine(srcBasePath, fileItem.SourcePath);
                        }
                        fileItem.DestPath = ResolveVariables(m.Groups[2].Value.Trim());
                        if (m.Groups[3].Length > 0)
                        {
                            fileItem.Mode = Convert.ToInt32(ResolveVariables(m.Groups[3].Value), 8);
                        }
                        if (m.Groups[4].Length > 0)
                        {
                            fileItem.UserId = Convert.ToInt32(ResolveVariables(m.Groups[4].Value));
                        }
                        if (m.Groups[5].Length > 0)
                        {
                            fileItem.GroupId = Convert.ToInt32(ResolveVariables(m.Groups[5].Value));
                        }
                        fileItem.IsConfig = true;
                        foreach (var fi in ResolveFileItems(fileItem))
                        {
                            fileItems.Add(fi);
                        }
                        inDescription = false;
                        continue;
                    }
                    m = Regex.Match(line, @"^dir(?:ectory)?\s*:\s*(\S+)(?:\s+([0-9]+)(?:\s+([0-9]+)\s+([0-9]+))?)?\s*$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        // Add empty directory
                        var fileItem = new DebFileItem
                        {
                            DestPath = ResolveVariables(m.Groups[1].Value.Trim()).TrimEnd('/')
                        };
                        if (m.Groups[2].Length > 0)
                        {
                            fileItem.Mode = Convert.ToInt32(ResolveVariables(m.Groups[2].Value), 8);
                        }
                        else
                        {
                            fileItem.Mode = 493 /* 0755 */;
                        }
                        if (m.Groups[3].Length > 0)
                        {
                            fileItem.UserId = Convert.ToInt32(ResolveVariables(m.Groups[3].Value));
                        }
                        if (m.Groups[4].Length > 0)
                        {
                            fileItem.GroupId = Convert.ToInt32(ResolveVariables(m.Groups[4].Value));
                        }
                        fileItem.IsDirectory = true;
                        fileItems.Add(fileItem);
                        inDescription = false;
                        continue;
                    }

                    m = Regex.Match(line, @"^(\S+)\s*=\s*(.+)$", RegexOptions.IgnoreCase);
                    if (m.Success)
                    {
                        variables[m.Groups[1].Value.Trim()] = ResolveVariables(m.Groups[2].Value.Trim());
                        inDescription = false;
                        continue;
                    }

                    if (inDescription)
                    {
                        m = Regex.Match(line, @"^\s+", RegexOptions.IgnoreCase);
                        if (m.Success)
                        {
                            // Continuation line for the Description field, follows the original control file syntax
                            controlParams.Description += "\n" + ResolveVariables(line.TrimEnd());
                            continue;
                        }
                    }

                    throw new Exception("Unrecognised directive in line " + lineNumber + ".");
                }
            }

            if (string.IsNullOrWhiteSpace(controlParams.Package))
            {
                throw new ArgumentException("Package field missing.");
            }
            if (string.IsNullOrWhiteSpace(controlParams.Version))
            {
                throw new ArgumentException("Version field missing.");
            }
            if (string.IsNullOrWhiteSpace(controlParams.Architecture))
            {
                throw new ArgumentException("Architecture field missing.");
            }
            if (string.IsNullOrWhiteSpace(controlParams.Maintainer))
            {
                throw new ArgumentException("Maintainer field missing.");
            }
            if (string.IsNullOrWhiteSpace(controlParams.Description))
            {
                throw new ArgumentException("Description field missing.");
            }

            // Calculate InstalledSize in KiB
            // Source: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Installed-Size
            long byteCount = 0;

            foreach (var fileItem in fileItems)
            {
                if (fileItem.SourcePath != null)
                {
                    var fi = new FileInfo(fileItem.SourcePath);
                    byteCount += fi.Length;
                }
            }
            controlParams.InstalledSize = (long)Math.Ceiling((decimal)byteCount / 1024);
        }
Exemple #2
0
        public void ReadSpecificationDeb(string path)
        {
            srcBasePath = Path.GetDirectoryName(path);

            controlParams = new DebControlParams();


            var confDir = Path.Combine(path, "DEBIAN");

            #region get control file check
            var controlFile = File.ReadAllText(Path.Combine(confDir, "control"));

            var m = Regex.Match(controlFile, @"package\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.Package = ResolveVariables(m.Groups[1].Value.Trim());
            }

            m = Regex.Match(controlFile, @"version\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.Version = ResolveVariables(m.Groups[1].Value.Trim());
            }

            m = Regex.Match(controlFile, @"convert-semver\s*", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.ConvertFromSemVer = true;
            }

            m = Regex.Match(controlFile, @"section\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.Section = ResolveVariables(m.Groups[1].Value.Trim());
            }

            m = Regex.Match(controlFile, @"prio(?:rity)?\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.Priority = ResolveVariables(m.Groups[1].Value.Trim());
            }

            m = Regex.Match(controlFile, @"arch(?:itecture)?\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.Architecture = ResolveVariables(m.Groups[1].Value.Trim());
            }

            m = Regex.Match(controlFile, @"depends\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                string depends = ResolveVariables(m.Groups[1].Value.Trim());
                if (string.IsNullOrWhiteSpace(controlParams.Depends))
                {
                    controlParams.Depends = depends;
                }
                else
                {
                    controlParams.Depends += ", " + depends;
                }
            }

            m = Regex.Match(controlFile, @"pre-depends\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                string preDepends = ResolveVariables(m.Groups[1].Value.Trim());
                if (string.IsNullOrWhiteSpace(controlParams.PreDepends))
                {
                    controlParams.PreDepends = preDepends;
                }
                else
                {
                    controlParams.PreDepends += ", " + preDepends;
                }
            }

            m = Regex.Match(controlFile, @"conflicts\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.Conflicts = ResolveVariables(m.Groups[1].Value.Trim());
            }

            m = Regex.Match(controlFile, @"maintainer\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.Maintainer = ResolveVariables(m.Groups[1].Value.Trim());
            }

            m = Regex.Match(controlFile, @"homepage\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.Homepage = ResolveVariables(m.Groups[1].Value.Trim());
            }

            m = Regex.Match(controlFile, @"desc(?:ription)?\s*:\s*(.+)", RegexOptions.IgnoreCase);
            if (m.Success)
            {
                controlParams.Description = ResolveVariables(m.Groups[1].Value.Trim());
            }
            #endregion


            // preinst
            if (File.Exists(Path.Combine(confDir, "preinst")))
            {
                preInstFileName = Path.Combine(confDir, "preinst");
            }

            // postinst
            if (File.Exists(Path.Combine(confDir, "postinst")))
            {
                postInstFileName = Path.Combine(confDir, "postinst");
            }

            // prerm
            if (File.Exists(Path.Combine(confDir, "prerm")))
            {
                preRmFileName = Path.Combine(confDir, "prerm");
            }

            // postrm
            if (File.Exists(Path.Combine(confDir, "postrm")))
            {
                postRmFileName = Path.Combine(confDir, "postrm");
            }


            #region add files
            // Add data file
            foreach (var file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
            {
                var destPath = file.Replace(path, "").TrimStart('\\');

                if (destPath.StartsWith("DEBIAN"))
                {
                    continue;
                }

                var fileItem = new DebFileItem
                {
                    SourcePath = file
                };

                fileItem.DestPath = destPath.Replace(@"\", "/");
                //fileItem.Mode    = Convert.ToInt32(ResolveVariables(m.Groups[3].Value), 8);
                //fileItem.UserId  = Convert.ToInt32(ResolveVariables(m.Groups[4].Value));
                //fileItem.GroupId = Convert.ToInt32(ResolveVariables(m.Groups[5].Value));
                foreach (var fi in ResolveFileItems(fileItem))
                {
                    var existingItem = fileItems.FirstOrDefault(x => x.SourcePath == fi.SourcePath);
                    if (existingItem != null)
                    {
                        fileItems.Remove(existingItem);
                    }
                    fileItems.Add(fi);
                }
            }
            #endregion

            #region add empty dir
            foreach (var dir in Directory.GetDirectories(path, "*", SearchOption.AllDirectories))
            {
                var destPath = dir.Replace(path, "").TrimStart('\\');

                if (destPath.StartsWith("DEBIAN"))
                {
                    continue;
                }

                var fileItem = new DebFileItem
                {
                    DestPath = destPath.Replace(@"\", "/")
                };
                fileItem.Mode = 493 /* 0755 */;
                //fileItem.UserId = Convert.ToInt32(ResolveVariables(m.Groups[3].Value));
                //fileItem.GroupId = Convert.ToInt32(ResolveVariables(m.Groups[4].Value));
                fileItem.IsDirectory = true;
                fileItems.Add(fileItem);
            }
            #endregion


            if (string.IsNullOrWhiteSpace(controlParams.Package))
            {
                throw new ArgumentException("Package field missing.");
            }
            if (string.IsNullOrWhiteSpace(controlParams.Version))
            {
                throw new ArgumentException("Version field missing.");
            }
            if (string.IsNullOrWhiteSpace(controlParams.Architecture))
            {
                throw new ArgumentException("Architecture field missing.");
            }
            if (string.IsNullOrWhiteSpace(controlParams.Maintainer))
            {
                throw new ArgumentException("Maintainer field missing.");
            }
            if (string.IsNullOrWhiteSpace(controlParams.Description))
            {
                throw new ArgumentException("Description field missing.");
            }

            // Calculate InstalledSize in KiB
            // Source: https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Installed-Size
            long byteCount = 0;
            foreach (var fileItem in fileItems)
            {
                if (fileItem.SourcePath != null)
                {
                    var fi = new FileInfo(fileItem.SourcePath);
                    byteCount += fi.Length;
                }
            }
            controlParams.InstalledSize = (long)Math.Ceiling((decimal)byteCount / 1024);
        }