blob: 1e7b6215e10d5444e93acaf78483a4dcf414a22a [file] [log] [blame]
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sysapi
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"syscall"
)
// AtomicWriteFile atomically writes a file.
func AtomicWriteFile(name string, content []byte, perm os.FileMode) error {
// Write to a temporary file in the same directory first. This is to
// guarantee the the temporary file and the intended file are on the
// same filesystem.
dir := filepath.Dir(name)
tmpFile, err := ioutil.TempFile(dir, "atom_write")
if err != nil {
return err
}
// Write the file. os.Write() is guaranteed to return a non-nil error
// when the number of bytes written != len(content).
_, err = tmpFile.Write(content)
if err1 := tmpFile.Close(); err == nil {
err = err1
}
if err != nil {
os.Remove(tmpFile.Name())
return err
}
// Rename the temporary file to the desired name. This is an atomic
// operation on POSIX compliant file systems.
return syscall.Rename(tmpFile.Name(), name)
}
// RunCommand returns the stdout and stderr produced by running the named
// program with the given arguments.
func RunCommand(name string, args ...string) ([]byte, []byte, error) {
cmd := exec.Command(name, args...)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return nil, nil, err
}
return stdout.Bytes(), stderr.Bytes(), nil
}
// FileExists checks if the named file exists.
func FileExists(path string) bool {
if _, err := os.Stat(path); os.IsNotExist(err) {
return false
}
return true
}