Documentation ¶
Overview ¶
Package atomicfile implements all-or-nothing file replacement by staging output to a temporary file adjacent to the target, and renaming over the target when the temporary is closed.
If (and only if) the implementation of rename is atomic the replacement is also atomic. Since IEEE Std 1003.1 requires rename to be atomic, this is ordinarily true on POSIX-compatible filesystems.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Tx ¶ added in v0.3.0
Tx calls f with a file constructed by New. If f reports an error or panics, the file is automatically cancelled and Tx returns the error from f. Otherwise, Tx returns the error from calling Close on the file.
func WriteAll ¶
WriteAll copies all the data from r to the specified target path via a File. It reports the total number of bytes copied.
Example ¶
package main import ( "fmt" "io" "log" "os" "path/filepath" "strings" "github.com/creachadair/atomicfile" ) var tempDir string func cat(path string) { f, err := os.Open(path) if err != nil { log.Fatalf("Open: %v", err) } defer f.Close() io.Copy(os.Stdout, f) } func main() { path := filepath.Join(tempDir, "writeall.txt") nw, err := atomicfile.WriteAll(path, strings.NewReader("I knew you were trouble"), 0640) if err != nil { log.Fatalf("WriteAll: %v", err) } fmt.Println(nw) cat(path) }
Output: 23 I knew you were trouble
func WriteData ¶
WriteData copies data to the specified target path via a File.
Example ¶
package main import ( "io" "log" "os" "path/filepath" "github.com/creachadair/atomicfile" ) var tempDir string func cat(path string) { f, err := os.Open(path) if err != nil { log.Fatalf("Open: %v", err) } defer f.Close() io.Copy(os.Stdout, f) } func main() { path := filepath.Join(tempDir, "writedata.txt") if err := atomicfile.WriteData(path, []byte("99 Luftballons"), 0600); err != nil { log.Fatalf("WriteData: %v", err) } cat(path) }
Output: 99 Luftballons
Types ¶
type File ¶
type File struct {
// contains filtered or unexported fields
}
A File is a writable temporary file that will be renamed to a target path when successfully closed.
func New ¶
New constructs a new writable File with the given mode that will be renamed to target when successfully closed. New reports an error if target already exists and is not a plain (regular) file.
Example ¶
package main import ( "fmt" "io" "log" "os" "path/filepath" "github.com/creachadair/atomicfile" ) var tempDir string func cat(path string) { f, err := os.Open(path) if err != nil { log.Fatalf("Open: %v", err) } defer f.Close() io.Copy(os.Stdout, f) } func main() { path := filepath.Join(tempDir, "new.txt") f, err := atomicfile.New(path, 0600) if err != nil { log.Fatalf("New: %v", err) } defer f.Cancel() fmt.Fprintln(f, "Hello, world!") if err := f.Close(); err != nil { log.Fatalf("Close: %v", err) } cat(path) }
Output: Hello, world!
func (*File) Cancel ¶
func (f *File) Cancel()
Cancel closes the temporary associated with f and discards it. It is safe to call Cancel even if f.Close has already succeeded; in that case the cancellation has no effect.
Example ¶
package main import ( "fmt" "io" "log" "os" "path/filepath" "github.com/creachadair/atomicfile" ) var tempDir string func cat(path string) { f, err := os.Open(path) if err != nil { log.Fatalf("Open: %v", err) } defer f.Close() io.Copy(os.Stdout, f) } func main() { path := filepath.Join(tempDir, "cancel.txt") if err := os.WriteFile(path, []byte("left right\n"), 0600); err != nil { log.Fatalf("WriteFile: %v", err) } cat(path) f, err := atomicfile.New(path, 0640) if err != nil { log.Fatalf("New: %v", err) } fmt.Fprintln(f, "Hello, world!") f.Cancel() // After cancellation, Close reports an error. if err := f.Close(); err == nil { log.Fatal("Close should have reported an error") } // The target path should not have been modified. cat(path) }
Output: left right left right
func (*File) Close ¶
Close closes the temporary associated with f and renames it to the designated target file. If closing the temporary fails, or if the rename fails, the temporary file is unlinked before Close returns.