safefile

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2024 License: BSD-2-Clause Imports: 7 Imported by: 0

README

safefile

Build Status Windows Build status

Go package safefile implements safe "atomic" saving of files.

Instead of truncating and overwriting the destination file, it creates a temporary file in the same directory, writes to it, and then renames the temporary file to the original name when calling Commit.

Installation
$ go get github.com/dchest/safefile
Documentation

https://godoc.org/github.com/dchest/safefile

Example
f, err := safefile.Create("/home/ken/report.txt", 0644)
if err != nil {
	// ...
}
// Created temporary file /home/ken/sf-ppcyksu5hyw2mfec.tmp

defer f.Close()

_, err = io.WriteString(f, "Hello world")
if err != nil {
	// ...
}
// Wrote "Hello world" to /home/ken/sf-ppcyksu5hyw2mfec.tmp

err = f.Commit()
if err != nil {
    // ...
}
// Renamed /home/ken/sf-ppcyksu5hyw2mfec.tmp to /home/ken/report.txt

Documentation

Overview

Package safefile implements safe "atomic" saving of files.

Instead of truncating and overwriting the destination file, it creates a temporary file in the same directory, writes to it, and then renames the temporary file to the original name when calling Commit.

Example:

f, err := safefile.Create("/home/ken/report.txt", 0644)
if err != nil {
	// ...
}
// Created temporary file /home/ken/sf-ppcyksu5hyw2mfec.tmp

defer f.Close()

_, err = io.WriteString(f, "Hello world")
if err != nil {
	// ...
}
// Wrote "Hello world" to /home/ken/sf-ppcyksu5hyw2mfec.tmp

err = f.Commit()
if err != nil {
    // ...
}
// Renamed /home/ken/sf-ppcyksu5hyw2mfec.tmp to /home/ken/report.txt

Index

Constants

This section is empty.

Variables

View Source
var ErrAlreadyCommitted = errors.New("file already committed")

ErrAlreadyCommitted error is returned when calling Commit on a file that has been already successfully committed.

Functions

func WriteFile

func WriteFile(filename string, data []byte, perm os.FileMode) error

WriteFile is a safe analog of ioutil.WriteFile.

Types

type File

type File struct {
	*os.File
	// contains filtered or unexported fields
}

func Create

func Create(filename string, perm os.FileMode) (*File, error)

Create creates a temporary file in the same directory as filename, which will be renamed to the given filename when calling Commit.

func (*File) Close

func (f *File) Close() error

Close closes temporary file and removes it. If the file has been committed, Close is no-op.

func (*File) Commit

func (f *File) Commit() error

Commit safely commits data into the original file by syncing temporary file to disk, closing it and renaming to the original file name.

In case of success, the temporary file is closed and no longer exists on disk. It is safe to call Close after Commit: the operation will do nothing.

In case of error, the temporary file is still opened and exists on disk; it must be closed by callers by calling Close or by trying to commit again.

Note that when trying to Commit again after a failed Commit when the file has been closed, but not renamed to its original name (the new commit will try again to rename it), safefile cannot guarantee that the temporary file has not been changed, or that it is the same temporary file we were dealing with. However, since the temporary name is unpredictable, it is unlikely that this happened accidentally. If complete atomicity is needed, do not Commit again after error, write the file again.

func (*File) CommitIfNotExists

func (f *File) CommitIfNotExists() error

CommitIfNotExists safely commits data into the original file by syncing temporary file to disk, closing it, and linking it to the original file name. Linking fails with EEXIST if there already exists a file with the target name. That means that if two processes race to create a new file with CommitIfNotExists, one will succeed, and the other one fail and leave target file untouched.

In case of success, the temporary file is closed and removed. If the removal fails for any reason, this method still returns nil; removal will be retried by Close. It is safe to call Close after Commit: the operation will retry removing the temporary file, if needed (and return any resulting error), but otherwise do nothing.

In case of error, the temporary file is still opened and exists on disk; it must be closed by callers by calling Close or by trying to commit again.

func (*File) OrigName

func (f *File) OrigName() string

OrigName returns the original filename given to Create.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL