github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/lib/file/atomic.go (about)

     1  package file
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	"github.com/hashicorp/go-uuid"
     9  )
    10  
    11  // WriteAtomicWithPerms creates a temp file with specific permissions and then renames and
    12  // moves it to the path.
    13  func WriteAtomicWithPerms(path string, contents []byte, dirPerms, filePerms os.FileMode) error {
    14  
    15  	uuid, err := uuid.GenerateUUID()
    16  	if err != nil {
    17  		return err
    18  	}
    19  	tempPath := fmt.Sprintf("%s-%s.tmp", path, uuid)
    20  
    21  	// Make a directory within the current one.
    22  	if err := os.MkdirAll(filepath.Dir(path), dirPerms); err != nil {
    23  		return err
    24  	}
    25  
    26  	// File opened with write only permissions. Will be created if it does not exist
    27  	// file is given specific permissions
    28  	fh, err := os.OpenFile(tempPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, filePerms)
    29  	if err != nil {
    30  		return err
    31  	}
    32  
    33  	defer os.RemoveAll(tempPath) // clean up
    34  
    35  	if _, err := fh.Write(contents); err != nil {
    36  		fh.Close()
    37  		return err
    38  	}
    39  	// Commits the current state of the file to disk
    40  	if err := fh.Sync(); err != nil {
    41  		fh.Close()
    42  		return err
    43  	}
    44  	if err := fh.Close(); err != nil {
    45  		return err
    46  	}
    47  	if err := os.Rename(tempPath, path); err != nil {
    48  		return err
    49  	}
    50  	return nil
    51  }