Mercurial > go > multipass
comparison file/file.go @ 10:1246b4b9028b
Add tool to remove passwords.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 25 Oct 2015 11:47:20 -0400 |
parents | e58bfc7fc207 |
children | da6c493cf08a |
comparison
equal
deleted
inserted
replaced
9:e58bfc7fc207 | 10:1246b4b9028b |
---|---|
9 import ( | 9 import ( |
10 "bufio" | 10 "bufio" |
11 "errors" | 11 "errors" |
12 "os" | 12 "os" |
13 "os/user" | 13 "os/user" |
14 "path" | |
14 "syscall" | 15 "syscall" |
15 | 16 "time" |
16 "path" | |
17 | 17 |
18 "golang.org/x/sys/unix" | 18 "golang.org/x/sys/unix" |
19 "pfish.zone/go/multipass/auth" | 19 "pfish.zone/go/multipass/auth" |
20 ) | 20 ) |
21 | 21 |
120 } | 120 } |
121 } | 121 } |
122 return handle.finalize() | 122 return handle.finalize() |
123 } | 123 } |
124 | 124 |
125 func (f *ShadowFile) AllEntries() ([]*auth.Entry, error) { | |
126 file, scanner, err := f.open() | |
127 if err != nil { | |
128 return nil, err | |
129 } | |
130 defer file.Close() | |
131 | |
132 var entries []*auth.Entry | |
133 | |
134 for scanner.Scan() { | |
135 entry, err := auth.EntryFromShadow(scanner.Text()) | |
136 // Skip invalid lines. | |
137 if err != nil { | |
138 continue | |
139 } | |
140 entries = append(entries, entry) | |
141 } | |
142 return entries, nil | |
143 } | |
144 | |
145 func (f *ShadowFile) Remove(id uint64) error { | |
146 handle, err := f.openWrite() | |
147 if err != nil { | |
148 return err | |
149 } | |
150 for handle.next() { | |
151 if entry, err := handle.entry(); err == nil { | |
152 // If we get an invalid entry, just skip it. | |
153 if entry.ID() != id { | |
154 if err := handle.write(entry); err != nil { | |
155 handle.bail() | |
156 return err | |
157 } | |
158 } | |
159 } | |
160 } | |
161 return handle.finalize() | |
162 } | |
163 | |
125 func (f *ShadowFile) openWrite() (*writeHandle, error) { | 164 func (f *ShadowFile) openWrite() (*writeHandle, error) { |
126 return openWriteHandle(f.newFilename(), f.name) | 165 return openWriteHandle(f.newFilename(), f.name) |
127 } | 166 } |
128 | 167 |
129 type writeHandle struct { | 168 type writeHandle struct { |
141 | 180 |
142 func openWriteHandle(tempName, fileName string) (*writeHandle, error) { | 181 func openWriteHandle(tempName, fileName string) (*writeHandle, error) { |
143 h := new(writeHandle) | 182 h := new(writeHandle) |
144 h.tempName = tempName | 183 h.tempName = tempName |
145 h.fileName = fileName | 184 h.fileName = fileName |
146 // Open the output file, readable by everybody, but only if it doesn't exist. | 185 // Open the output file, but only if it doesn't exist. |
147 // This prevents race conditions. | 186 // This prevents race conditions. |
148 oldUmask := unix.Umask(077) | 187 oldUmask := unix.Umask(077) |
149 tempFile, err := os.OpenFile(tempName, os.O_CREATE | os.O_EXCL | os.O_WRONLY | os.O_SYNC, 0600) | 188 var tempFile *os.File |
189 delay := time.Nanosecond | |
190 for tempFile == nil { | |
191 tempTempFile, err := os.OpenFile(tempName, os.O_CREATE|os.O_EXCL|os.O_WRONLY|os.O_SYNC, 0600) | |
192 tempFile = tempTempFile | |
193 if err != nil { | |
194 perr := err.(*os.PathError) | |
195 errno, ok := perr.Err.(syscall.Errno) | |
196 if !ok { | |
197 return nil, err | |
198 } | |
199 if errno != syscall.EEXIST || delay > time.Minute { | |
200 return nil, err | |
201 } | |
202 time.Sleep(delay) | |
203 delay *= 2 | |
204 } | |
205 } | |
150 unix.Umask(oldUmask) | 206 unix.Umask(oldUmask) |
151 if err != nil { | |
152 return nil, err | |
153 } | |
154 h.tempFile = tempFile | 207 h.tempFile = tempFile |
155 // Open the input file. | 208 // Open the input file. |
156 inFile, err := os.Open(fileName) | 209 inFile, err := os.Open(fileName) |
157 if err == nil { | 210 if err == nil { |
158 // Prepare to read in the input file, if it exists. | 211 // Prepare to read in the input file, if it exists. |