Skip to content

Commit

Permalink
Refactor copy driver files
Browse files Browse the repository at this point in the history
Signed-off-by: JUN JIE NAN <[email protected]>
  • Loading branch information
nanjj committed May 13, 2024
1 parent 1713fa9 commit 7b0baee
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 97 deletions.
194 changes: 102 additions & 92 deletions distrobuilder/main_repack-windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -469,132 +469,71 @@ func (c *cmdRepackWindows) injectDrivers(dirs map[string]string) error {
driversRegistry := "Windows Registry Editor Version 5.00"
systemRegistry := "Windows Registry Editor Version 5.00"
softwareRegistry := "Windows Registry Editor Version 5.00"

for driver, info := range windows.Drivers {
logger.WithField("driver", driver).Debug("Injecting driver")

ctx := pongo2.Context{
"infFile": fmt.Sprintf("oem%d.inf", i),
"packageName": info.PackageName,
"driverName": driver,
infDir := dirs["inf"]
driversDir := dirs["drivers"]
filerepositoryDir := dirs["filerepository"]
for driverName, driverInfo := range windows.Drivers {
logger.WithField("driver", driverName).Debug("Injecting driver")
infFilename := fmt.Sprintf("oem%d.inf", i)
sourceDir := filepath.Join(driverPath, driverName, c.flagWindowsVersion, c.flagWindowsArchitecture)
targetBaseDir := filepath.Join(filerepositoryDir, driverInfo.PackageName)
err := c.copyDriverFiles(driverName, sourceDir, targetBaseDir, infDir, infFilename, driversDir)
if err != nil {
return fmt.Errorf("Failed to copy driver files: %w", err)
}

sourceDir := filepath.Join(driverPath, driver, c.flagWindowsVersion, c.flagWindowsArchitecture)
targetBasePath := filepath.Join(dirs["filerepository"], info.PackageName)

if !incus.PathExists(targetBasePath) {
err := os.MkdirAll(targetBasePath, 0755)
if err != nil {
return fmt.Errorf("Failed to create directory %q: %w", targetBasePath, err)
}
classGuid, err := parseDriverClassGuid(driverName, filepath.Join(infDir, infFilename))
if err != nil {
return err
}

err := filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
ext := filepath.Ext(path)
targetPath := filepath.Join(targetBasePath, filepath.Base(path))

// Copy driver files
if slices.Contains([]string{".cat", ".dll", ".inf", ".sys"}, ext) {
logger.WithFields(logrus.Fields{"src": path, "dest": targetPath}).Debug("Copying file")

err := shared.Copy(path, targetPath)
if err != nil {
return fmt.Errorf("Failed to copy %q to %q: %w", filepath.Base(path), targetPath, err)
}
}

// Copy .inf file
if ext == ".inf" {
target := filepath.Join(dirs["inf"], ctx["infFile"].(string))
logger.WithFields(logrus.Fields{"src": path, "dest": target}).Debug("Copying file")

err := shared.Copy(path, target)
if err != nil {
return fmt.Errorf("Failed to copy %q to %q: %w", filepath.Base(path), target, err)
}

// Retrieve the ClassGuid which is needed for the Windows registry entries.
file, err := os.Open(path)
if err != nil {
return fmt.Errorf("Failed to open %s: %w", path, err)
}

re := regexp.MustCompile(`(?i)^ClassGuid[ ]*=[ ]*(.+)$`)
scanner := bufio.NewScanner(file)

for scanner.Scan() {
matches := re.FindStringSubmatch(scanner.Text())

if len(matches) > 0 {
ctx["classGuid"] = strings.TrimSpace(matches[1])
}
}

file.Close()

_, ok := ctx["classGuid"]
if !ok {
return fmt.Errorf("Failed to determine classGUID for driver %q", driver)
}
}

// Copy .sys and .dll files
if ext == ".dll" || ext == ".sys" {
target := filepath.Join(dirs["drivers"], filepath.Base(path))
logger.WithFields(logrus.Fields{"src": path, "dest": target}).Debug("Copying file")

err := shared.Copy(path, target)
if err != nil {
return fmt.Errorf("Failed to copy %q to %q: %w", filepath.Base(path), target, err)
}
}

return nil
})
if err != nil {
return fmt.Errorf("Failed to copy driver files: %w", err)
ctx := pongo2.Context{
"infFile": infFilename,
"packageName": driverInfo.PackageName,
"driverName": driverName,
"classGuid": classGuid,
}

// Update Windows DRIVERS registry
if info.DriversRegistry != "" {
tpl, err := pongo2.FromString(info.DriversRegistry)
if driverInfo.DriversRegistry != "" {
tpl, err := pongo2.FromString(driverInfo.DriversRegistry)
if err != nil {
return fmt.Errorf("Failed to parse template for driver %q: %w", driver, err)
return fmt.Errorf("Failed to parse template for driver %q: %w", driverName, err)
}

out, err := tpl.Execute(ctx)
if err != nil {
return fmt.Errorf("Failed to render template for driver %q: %w", driver, err)
return fmt.Errorf("Failed to render template for driver %q: %w", driverName, err)
}

driversRegistry = fmt.Sprintf("%s\n\n%s", driversRegistry, out)
}

// Update Windows SYSTEM registry
if info.SystemRegistry != "" {
tpl, err := pongo2.FromString(info.SystemRegistry)
if driverInfo.SystemRegistry != "" {
tpl, err := pongo2.FromString(driverInfo.SystemRegistry)
if err != nil {
return fmt.Errorf("Failed to parse template for driver %q: %w", driver, err)
return fmt.Errorf("Failed to parse template for driver %q: %w", driverName, err)
}

out, err := tpl.Execute(ctx)
if err != nil {
return fmt.Errorf("Failed to render template for driver %q: %w", driver, err)
return fmt.Errorf("Failed to render template for driver %q: %w", driverName, err)
}

systemRegistry = fmt.Sprintf("%s\n\n%s", systemRegistry, out)
}

// Update Windows SOFTWARE registry
if info.SoftwareRegistry != "" {
tpl, err := pongo2.FromString(info.SoftwareRegistry)
if driverInfo.SoftwareRegistry != "" {
tpl, err := pongo2.FromString(driverInfo.SoftwareRegistry)
if err != nil {
return fmt.Errorf("Failed to parse template for driver %q: %w", driver, err)
return fmt.Errorf("Failed to parse template for driver %q: %w", driverName, err)
}

out, err := tpl.Execute(ctx)
if err != nil {
return fmt.Errorf("Failed to render template for driver %q: %w", driver, err)
return fmt.Errorf("Failed to render template for driver %q: %w", driverName, err)
}

softwareRegistry = fmt.Sprintf("%s\n\n%s", softwareRegistry, out)
Expand Down Expand Up @@ -627,6 +566,77 @@ func (c *cmdRepackWindows) injectDrivers(dirs map[string]string) error {
return nil
}

func (c *cmdRepackWindows) copyDriverFiles(driverName, sourceDir, targetBaseDir, infDir, infFilename, driversDir string) (err error) {
logger := c.global.logger
if !incus.PathExists(targetBaseDir) {
err = os.MkdirAll(targetBaseDir, 0755)
if err != nil {
err = fmt.Errorf("Failed to create directory %q: %w", targetBaseDir, err)
return
}
}

targetCopy := func(sourcePath, targetDir, targetName string) {
if targetDir == "" {
return
}

targetPath := filepath.Join(targetDir, targetName)
logger.WithFields(logrus.Fields{"src": sourcePath, "dest": targetPath}).Debug("Copying file")
err := shared.Copy(sourcePath, targetPath)
if err != nil {
logger.Infof("failed to copy from %q to %q %q", sourcePath, targetDir, targetName)
}
}

driverPath := ""
for name, dir := range map[string]string{
"inf": infDir,
"cat": "",
"dll": driversDir,
"sys": driversDir} {
driverPath, err = shared.FindFirstMatch(sourceDir, fmt.Sprintf("*.%s", name))
if err != nil {
logger.Debugf("failed to find first match %q %q", driverName, name)
continue
}
targetCopy(driverPath, targetBaseDir, filepath.Base(driverPath))
targetName := infFilename
if name != "inf" {
targetName = filepath.Base(driverPath)
}
targetCopy(driverPath, dir, targetName)
}
return nil
}

func parseDriverClassGuid(driverName, infPath string) (classGuid string, err error) {
// Retrieve the ClassGuid which is needed for the Windows registry entries.
file, err := os.Open(infPath)
if err != nil {
err = fmt.Errorf("Failed to open driver %s inf %s: %w", driverName, infPath, err)
return
}

defer func() {
file.Close()
if classGuid == "" {
err = fmt.Errorf("Failed to parse driver %s classGuid %s", driverName, infPath)
}
}()
re := regexp.MustCompile(`(?i)^ClassGuid[ ]*=[ ]*(.+)$`)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
matches := re.FindStringSubmatch(scanner.Text())
if len(matches) > 1 {
classGuid = strings.TrimSpace(matches[1])
return
}
}

return
}

// toHex is a pongo2 filter which converts the provided value to a hex value understood by the Windows registry.
func toHex(in *pongo2.Value, param *pongo2.Value) (out *pongo2.Value, err *pongo2.Error) {
dst := make([]byte, hex.EncodedLen(len(in.String())))
Expand Down
11 changes: 6 additions & 5 deletions shared/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ func CaseInsensitive(s string) (pattern string) {
b := s2[i : i+1]
if a != b {
pattern += "[" + a + b + "]"
} else if a != "/" {
pattern += "\\" + a
} else if strings.Contains("?*[]/", a) {
pattern += a
} else {
pattern += "/"
pattern += "\\" + a
}
}
return
Expand All @@ -70,13 +70,14 @@ func FindFirstMatch(dir string, elem ...string) (found string, err error) {
names = append(names, CaseInsensitive(name))
}

matches, err := filepath.Glob(filepath.Join(names...))
pattern := filepath.Join(names...)
matches, err := filepath.Glob(pattern)
if err != nil {
return
}

if len(matches) == 0 {
err = fmt.Errorf("No match found")
err = fmt.Errorf("No match found %s", pattern)
return
}

Expand Down

0 comments on commit 7b0baee

Please sign in to comment.