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. |
