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.