changeset 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 e246c8a4d28e
files file/file.go multipass-add.go
diffstat 2 files changed, 64 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/file/file.go	Sun Oct 25 10:45:32 2015 -0400
+++ b/file/file.go	Sun Oct 25 11:47:20 2015 -0400
@@ -11,9 +11,9 @@
 	"errors"
 	"os"
 	"os/user"
+	"path"
 	"syscall"
-
-	"path"
+	"time"
 
 	"golang.org/x/sys/unix"
 	"pfish.zone/go/multipass/auth"
@@ -122,6 +122,45 @@
 	return handle.finalize()
 }
 
+func (f *ShadowFile) AllEntries() ([]*auth.Entry, error) {
+	file, scanner, err := f.open()
+	if err != nil {
+		return nil, err
+	}
+	defer file.Close()
+
+	var entries []*auth.Entry
+
+	for scanner.Scan() {
+		entry, err := auth.EntryFromShadow(scanner.Text())
+		// Skip invalid lines.
+		if err != nil {
+			continue
+		}
+		entries = append(entries, entry)
+	}
+	return entries, nil
+}
+
+func (f *ShadowFile) Remove(id uint64) error {
+	handle, err := f.openWrite()
+	if err != nil {
+		return err
+	}
+	for handle.next() {
+		if entry, err := handle.entry(); err == nil {
+			// If we get an invalid entry, just skip it.
+			if entry.ID() != id {
+				if err := handle.write(entry); err != nil {
+					handle.bail()
+					return err
+				}
+			}
+		}
+	}
+	return handle.finalize()
+}
+
 func (f *ShadowFile) openWrite() (*writeHandle, error) {
 	return openWriteHandle(f.newFilename(), f.name)
 }
@@ -143,14 +182,28 @@
 	h := new(writeHandle)
 	h.tempName = tempName
 	h.fileName = fileName
-	// Open the output file, readable by everybody, but only if it doesn't exist.
+	// Open the output file, but only if it doesn't exist.
 	// This prevents race conditions.
 	oldUmask := unix.Umask(077)
-	tempFile, err := os.OpenFile(tempName, os.O_CREATE | os.O_EXCL | os.O_WRONLY | os.O_SYNC, 0600)
+	var tempFile *os.File
+	delay := time.Nanosecond
+	for tempFile == nil {
+		tempTempFile, err := os.OpenFile(tempName, os.O_CREATE|os.O_EXCL|os.O_WRONLY|os.O_SYNC, 0600)
+		tempFile = tempTempFile
+		if err != nil {
+			perr := err.(*os.PathError)
+			errno, ok := perr.Err.(syscall.Errno)
+			if !ok {
+				return nil, err
+			}
+			if errno != syscall.EEXIST || delay > time.Minute {
+				return nil, err
+			}
+			time.Sleep(delay)
+			delay *= 2
+		}
+	}
 	unix.Umask(oldUmask)
-	if err != nil {
-		return nil, err
-	}
 	h.tempFile = tempFile
 	// Open the input file.
 	inFile, err := os.Open(fileName)
--- a/multipass-add.go	Sun Oct 25 10:45:32 2015 -0400
+++ b/multipass-add.go	Sun Oct 25 11:47:20 2015 -0400
@@ -13,6 +13,10 @@
 
 func main() {
 	passfile, err := file.ForMe()
+	if err != nil {
+		fmt.Println(err.Error())
+		os.Exit(1)
+	}
 	reader := bufio.NewReader(os.Stdin)
 	fmt.Print("Describe password: ")
 	text, err := reader.ReadString('\n')