@@ -2,9 +2,13 @@ package osutil
2
2
3
3
import (
4
4
"fmt"
5
+ "os/exec"
5
6
"os/user"
7
+ "path/filepath"
6
8
"regexp"
9
+ "runtime"
7
10
"strconv"
11
+ "strings"
8
12
"sync"
9
13
10
14
"github.com/sirupsen/logrus"
@@ -15,6 +19,7 @@ type User struct {
15
19
Uid uint32
16
20
Group string
17
21
Gid uint32
22
+ Home string
18
23
}
19
24
20
25
type Group struct {
@@ -46,7 +51,7 @@ func LookupUser(name string) (User, error) {
46
51
if err != nil {
47
52
return User {}, err
48
53
}
49
- users [name ] = User {User : u .Username , Uid : uint32 (uid ), Group : g .Name , Gid : uint32 (gid )}
54
+ users [name ] = User {User : u .Username , Uid : uint32 (uid ), Group : g .Name , Gid : uint32 (gid ), Home : u . HomeDir }
50
55
}
51
56
return users [name ], nil
52
57
}
@@ -71,31 +76,94 @@ func LookupGroup(name string) (Group, error) {
71
76
72
77
const (
73
78
fallbackUser = "lima"
79
+ fallbackUid = 1000
80
+ fallbackGid = 1000
74
81
)
75
82
76
83
var cache struct {
77
84
sync.Once
78
- u * user.User
79
- err error
80
- warning string
85
+ u * user.User
86
+ err error
87
+ warnings []string
88
+ }
89
+
90
+ func call (args []string ) (string , error ) {
91
+ cmd := exec .Command (args [0 ], args [1 :]... )
92
+ out , err := cmd .Output ()
93
+ if err != nil {
94
+ return "" , err
95
+ }
96
+ return strings .TrimSpace (string (out )), nil
81
97
}
82
98
83
99
func LimaUser (warn bool ) (* user.User , error ) {
100
+ cache .warnings = []string {}
84
101
cache .Do (func () {
85
102
cache .u , cache .err = user .Current ()
86
103
if cache .err == nil {
87
104
// `useradd` only allows user and group names matching the following pattern:
88
105
// (it allows a trailing '$', but it feels prudent to map those to the fallback user as well)
89
106
validName := "^[a-z_][a-z0-9_-]*$"
90
107
if ! regexp .MustCompile (validName ).Match ([]byte (cache .u .Username )) {
91
- cache . warning = fmt .Sprintf ("local user %q is not a valid Linux username (must match %q); using %q username instead" ,
108
+ warning : = fmt .Sprintf ("local user %q is not a valid Linux username (must match %q); using %q username instead" ,
92
109
cache .u .Username , validName , fallbackUser )
110
+ cache .warnings = append (cache .warnings , warning )
93
111
cache .u .Username = fallbackUser
94
112
}
113
+ if runtime .GOOS == "windows" {
114
+ idu , err := call ([]string {"id" , "-u" })
115
+ if err != nil {
116
+ logrus .Debug (err )
117
+ }
118
+ uid , err := strconv .ParseUint (idu , 10 , 32 )
119
+ if err != nil {
120
+ uid = fallbackUid
121
+ }
122
+ if ! regexp .MustCompile ("^[0-9]+$" ).Match ([]byte (cache .u .Uid )) {
123
+ warning := fmt .Sprintf ("local uid %q is not a valid Linux uid (must be integer); using %d uid instead" ,
124
+ cache .u .Uid , uid )
125
+ cache .warnings = append (cache .warnings , warning )
126
+ cache .u .Uid = fmt .Sprintf ("%d" , uid )
127
+ }
128
+ idg , err := call ([]string {"id" , "-g" })
129
+ if err != nil {
130
+ logrus .Debug (err )
131
+ }
132
+ gid , err := strconv .ParseUint (idg , 10 , 32 )
133
+ if err != nil {
134
+ gid = fallbackGid
135
+ }
136
+ if ! regexp .MustCompile ("^[0-9]+$" ).Match ([]byte (cache .u .Gid )) {
137
+ warning := fmt .Sprintf ("local gid %q is not a valid Linux gid (must be integer); using %d gid instead" ,
138
+ cache .u .Gid , gid )
139
+ cache .warnings = append (cache .warnings , warning )
140
+ cache .u .Gid = fmt .Sprintf ("%d" , gid )
141
+ }
142
+ home , err := call ([]string {"cygpath" , cache .u .HomeDir })
143
+ if err != nil {
144
+ logrus .Debug (err )
145
+ }
146
+ if home == "" {
147
+ drive := filepath .VolumeName (cache .u .HomeDir )
148
+ home = filepath .ToSlash (cache .u .HomeDir )
149
+ // replace C: with /c
150
+ prefix := strings .ToLower (fmt .Sprintf ("/%c" , drive [0 ]))
151
+ home = strings .Replace (home , drive , prefix , 1 )
152
+ }
153
+ validPath := "^[/a-zA-Z0-9_-]+$"
154
+ if ! regexp .MustCompile (validPath ).Match ([]byte (cache .u .HomeDir )) {
155
+ warning := fmt .Sprintf ("local home %q is not a valid Linux path (must match %q); using %q home instead" ,
156
+ cache .u .HomeDir , validPath , home )
157
+ cache .warnings = append (cache .warnings , warning )
158
+ cache .u .HomeDir = home
159
+ }
160
+ }
95
161
}
96
162
})
97
- if warn && cache .warning != "" {
98
- logrus .Warn (cache .warning )
163
+ if warn && len (cache .warnings ) > 0 {
164
+ for _ , warning := range cache .warnings {
165
+ logrus .Warn (warning )
166
+ }
99
167
}
100
168
return cache .u , cache .err
101
169
}
0 commit comments