-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathembed.go
More file actions
144 lines (128 loc) · 4.16 KB
/
Copy pathembed.go
File metadata and controls
144 lines (128 loc) · 4.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package macwifi
import (
"crypto/sha256"
"embed"
"encoding/hex"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
)
// embeddedVersion is a human-readable cache namespace. The actual cache key
// also includes a digest of the embedded bundle, so updated helper files are
// extracted without requiring a manual version bump. Release Please keeps
// this in sync with the module version on each release.
const embeddedVersion = "1.0.0" // x-release-please-version
// scannerBundle is the signed + notarized WifiScanner.app. Every file
// under embedded/WifiScanner.app/ is baked into the Go binary — consumers
// `go get` the module and get the helper automatically.
//
// The `all:` prefix is required because the bundle contains a
// `_CodeSignature` directory; embed otherwise skips names starting
// with `_` or `.`.
//
//go:embed all:embedded/WifiScanner.app
var scannerBundle embed.FS
// scannerSourcePrefix is the root path inside scannerBundle we copy out.
const scannerSourcePrefix = "embedded/WifiScanner.app"
// extractScannerApp materializes the embedded bundle to the user's cache
// dir and returns the absolute path to the extracted .app. Idempotent:
// re-extracts only when embeddedVersion changes or the marker is missing.
func extractScannerApp() (string, error) {
cacheBase, err := os.UserCacheDir()
if err != nil {
return "", fmt.Errorf("macwifi: locate cache dir: %w", err)
}
cacheKey, err := scannerCacheKey()
if err != nil {
return "", fmt.Errorf("macwifi: hash embedded bundle: %w", err)
}
versionDir := filepath.Join(cacheBase, "macwifi", cacheKey)
appPath := filepath.Join(versionDir, "WifiScanner.app")
marker := filepath.Join(versionDir, ".extracted")
// Fast path: already extracted at this version.
if b, err := os.ReadFile(marker); err == nil && string(b) == cacheKey {
return appPath, nil
}
// Clean any prior (partial) extraction at this version.
if err := os.RemoveAll(versionDir); err != nil {
return "", fmt.Errorf("macwifi: clean cache dir: %w", err)
}
if err := os.MkdirAll(versionDir, 0o755); err != nil {
return "", fmt.Errorf("macwifi: create cache dir: %w", err)
}
if err := copyEmbedTree(scannerBundle, scannerSourcePrefix, appPath); err != nil {
_ = os.RemoveAll(versionDir)
return "", fmt.Errorf("macwifi: extract bundle: %w", err)
}
if err := os.WriteFile(marker, []byte(cacheKey), 0o644); err != nil {
return "", err
}
return appPath, nil
}
func scannerCacheKey() (string, error) {
sum, err := fsTreeDigest(scannerBundle, scannerSourcePrefix)
if err != nil {
return "", err
}
return embeddedVersion + "-" + sum[:12], nil
}
func fsTreeDigest(src fs.FS, srcPrefix string) (string, error) {
h := sha256.New()
if err := fs.WalkDir(src, srcPrefix, func(path string, d fs.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
rel := strings.TrimPrefix(path, srcPrefix)
rel = strings.TrimPrefix(rel, "/")
if rel == "" {
return nil
}
_, _ = h.Write([]byte(rel))
_, _ = h.Write([]byte{0})
if d.IsDir() {
_, _ = h.Write([]byte{1})
return nil
}
data, err := fs.ReadFile(src, path)
if err != nil {
return err
}
_, _ = h.Write(data)
_, _ = h.Write([]byte{0})
return nil
}); err != nil {
return "", err
}
return hex.EncodeToString(h.Sum(nil)), nil
}
// copyEmbedTree walks srcPrefix inside src and mirrors the tree under dst,
// preserving executability for the inner binary.
func copyEmbedTree(src fs.FS, srcPrefix, dst string) error {
return fs.WalkDir(src, srcPrefix, func(path string, d fs.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
rel := strings.TrimPrefix(path, srcPrefix)
rel = strings.TrimPrefix(rel, "/")
target := filepath.Join(dst, rel)
if d.IsDir() {
return os.MkdirAll(target, 0o755)
}
data, err := fs.ReadFile(src, path)
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
return err
}
mode := os.FileMode(0o644)
// The inner Mach-O binary must be executable. Everything else is
// plain data (Info.plist, code signature blobs, notarization ticket).
if rel == "Contents/MacOS/wifi-scanner" {
mode = 0o755
}
return os.WriteFile(target, data, mode)
})
}