-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extractor for Windows patch level. Uses the `dism /get-packages /onli…
…ne` command under the hood. PiperOrigin-RevId: 630352135
- Loading branch information
1 parent
6a999b0
commit 0f9acb4
Showing
9 changed files
with
747 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
extractor/standalone/windows/dismpatch/dismparser/dism_parser.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// Package dismparser has methods that can be used to parse DISM output | ||
package dismparser | ||
|
||
import ( | ||
"errors" | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
// DismPkg reports information about a package as reported by the DISM tool. | ||
type DismPkg struct { | ||
PackageIdentity string | ||
PackageVersion string | ||
State string | ||
ReleaseType string | ||
InstallTime string | ||
} | ||
|
||
// Parse parses dism output into an array of dismPkgs. | ||
func Parse(input string) ([]DismPkg, string, error) { | ||
pkgs := strings.Split(input, "Package Id") | ||
|
||
pkgExp, err := regexp.Compile("entity :(.*)\n*State :(.*)\n*Release Type :(.*)\n*Install Time :(.*)\n*") | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
|
||
imgExp, err := regexp.Compile("Image Version: (.*)") | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
|
||
imgVersion := "" | ||
dismPkgs := []DismPkg{} | ||
|
||
for _, pkg := range pkgs { | ||
matches := pkgExp.FindStringSubmatch(pkg) | ||
if len(matches) > 4 { | ||
dismPkg := DismPkg{ | ||
PackageIdentity: strings.TrimSpace(matches[1]), | ||
State: strings.TrimSpace(matches[2]), | ||
ReleaseType: strings.TrimSpace(matches[3]), | ||
InstallTime: strings.TrimSpace(matches[4]), | ||
} | ||
dismPkg.PackageVersion = findVersion(dismPkg.PackageIdentity) | ||
dismPkgs = append(dismPkgs, dismPkg) | ||
} else { | ||
// this is the first entry that has the image version | ||
matches = imgExp.FindStringSubmatch(pkg) | ||
if len(matches) > 1 { | ||
imgVersion = matches[1] | ||
} | ||
} | ||
} | ||
|
||
if len(dismPkgs) == 0 { | ||
return nil, "", errors.New("Could not parse DISM output successfully") | ||
} | ||
|
||
return dismPkgs, imgVersion, nil | ||
} | ||
|
||
func findVersion(identity string) string { | ||
pkgVer := strings.Split(identity, "~~") | ||
if len(pkgVer) > 1 { | ||
return pkgVer[1] | ||
} | ||
return "" | ||
} |
115 changes: 115 additions & 0 deletions
115
extractor/standalone/windows/dismpatch/dismparser/dism_parser_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package dismparser | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
) | ||
|
||
func TestParse(t *testing.T) { | ||
content, err := os.ReadFile("testdata/dism_testdata.txt") | ||
if err != nil { | ||
t.Fatalf("Failed to read testdata: %v", err) | ||
} | ||
|
||
pkgs, imgVersion, err := Parse(string(content)) | ||
if err != nil { | ||
t.Errorf("Error while parsing the output: %v", err) | ||
} | ||
|
||
if imgVersion != "10.0.17763.3406" { | ||
t.Errorf("Parse, ImageVersion: Got: %v, Want: %v", imgVersion, "10.0.17763.3406") | ||
} | ||
|
||
want := []DismPkg{ | ||
DismPkg{ | ||
PackageIdentity: "Microsoft-Windows-FodMetadata-Package~31bf3856ad364e35~amd64~~10.0.17763.1", | ||
PackageVersion: "10.0.17763.1", | ||
State: "Installed", | ||
ReleaseType: "Feature Pack", | ||
InstallTime: "9/15/2018 9:08 AM", | ||
}, | ||
DismPkg{ | ||
PackageIdentity: "Package_for_KB4470788~31bf3856ad364e35~amd64~~17763.164.1.1", | ||
PackageVersion: "17763.164.1.1", | ||
State: "Installed", | ||
ReleaseType: "Security Update", | ||
InstallTime: "3/12/2019 6:27 AM", | ||
}, | ||
DismPkg{ | ||
PackageIdentity: "Package_for_RollupFix~31bf3856ad364e35~amd64~~17763.3406.1.5", | ||
PackageVersion: "17763.3406.1.5", | ||
State: "Installed", | ||
ReleaseType: "Security Update", | ||
InstallTime: "9/13/2022 11:06 PM", | ||
}, | ||
DismPkg{ | ||
PackageIdentity: "Package_for_RollupFix~31bf3856ad364e35~amd64~~17763.379.1.11", | ||
PackageVersion: "17763.379.1.11", | ||
State: "Superseded", | ||
ReleaseType: "Security Update", | ||
InstallTime: "3/12/2019 6:31 AM", | ||
}, | ||
DismPkg{ | ||
PackageIdentity: "Package_for_ServicingStack_3232~31bf3856ad364e35~amd64~~17763.3232.1.1", | ||
PackageVersion: "17763.3232.1.1", | ||
State: "Installed", | ||
ReleaseType: "Update", | ||
InstallTime: "9/13/2022 10:46 PM", | ||
}, | ||
} | ||
|
||
if diff := cmp.Diff(want, pkgs); diff != "" { | ||
t.Errorf("Parse: Diff = %v", diff) | ||
} | ||
} | ||
|
||
func TestFindVersion(t *testing.T) { | ||
type test struct { | ||
input string | ||
want string | ||
} | ||
|
||
tests := []test{ | ||
{ | ||
input: "Microsoft-Windows-FodMetadata-Package~31bf3856ad364e35~amd64~~10.0.17763.1", | ||
want: "10.0.17763.1", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.input, func(t *testing.T) { | ||
got := findVersion(tt.input) | ||
if got != tt.want { | ||
t.Errorf("findVersion: Got: %v, Want: %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestParseError(t *testing.T) { | ||
content, err := os.ReadFile("testdata/err_testdata.txt") | ||
if err != nil { | ||
t.Fatalf("Failed to read testdata: %v", err) | ||
} | ||
|
||
_, _, err = Parse(string(content)) | ||
if err == nil || err.Error() != "Could not parse DISM output successfully" { | ||
t.Errorf("Parse: Want: %v, Got: %v", "Could not parse DISM output successfully", err) | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
extractor/standalone/windows/dismpatch/dismparser/testdata/dism_testdata.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
Deployment Image Servicing and Management tool | ||
Version: 10.0.20348.681 | ||
|
||
Image Version: 10.0.17763.3406 | ||
|
||
Package Identity : Microsoft-Windows-FodMetadata-Package~31bf3856ad364e35~amd64~~10.0.17763.1 | ||
State : Installed | ||
Release Type : Feature Pack | ||
Install Time : 9/15/2018 9:08 AM | ||
|
||
Package Identity : Package_for_KB4470788~31bf3856ad364e35~amd64~~17763.164.1.1 | ||
State : Installed | ||
Release Type : Security Update | ||
Install Time : 3/12/2019 6:27 AM | ||
|
||
Package Identity : Package_for_RollupFix~31bf3856ad364e35~amd64~~17763.3406.1.5 | ||
State : Installed | ||
Release Type : Security Update | ||
Install Time : 9/13/2022 11:06 PM | ||
|
||
Package Identity : Package_for_RollupFix~31bf3856ad364e35~amd64~~17763.379.1.11 | ||
State : Superseded | ||
Release Type : Security Update | ||
Install Time : 3/12/2019 6:31 AM | ||
|
||
Package Identity : Package_for_ServicingStack_3232~31bf3856ad364e35~amd64~~17763.3232.1.1 | ||
State : Installed | ||
Release Type : Update | ||
Install Time : 9/13/2022 10:46 PM | ||
|
||
The operation completed successfully. |
Oops, something went wrong.