Simplify atomic file replacement and bounded reads
This commit is contained in:
@@ -3,6 +3,7 @@ package fileops
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -22,8 +23,38 @@ func EnsureWorkspaceDirectory(directory string) error {
|
||||
return fmt.Errorf("workspace directory is required")
|
||||
}
|
||||
|
||||
if err := ensureConfinedDirectory(directory, WorkspaceDirectoryMode); err != nil {
|
||||
return fmt.Errorf("set workspace directory permissions %q: %w", directory, err)
|
||||
clean := filepath.Clean(directory)
|
||||
ancestor := clean
|
||||
var missing []string
|
||||
for {
|
||||
info, err := os.Stat(ancestor)
|
||||
if err == nil {
|
||||
if !info.IsDir() {
|
||||
return fmt.Errorf("workspace directory %q is not a directory", ancestor)
|
||||
}
|
||||
break
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("inspect workspace directory %q: %w", ancestor, err)
|
||||
}
|
||||
parent := filepath.Dir(ancestor)
|
||||
if parent == ancestor {
|
||||
return fmt.Errorf("find workspace directory ancestor for %q", clean)
|
||||
}
|
||||
missing = append(missing, ancestor)
|
||||
ancestor = parent
|
||||
}
|
||||
for index := len(missing) - 1; index >= 0; index-- {
|
||||
created := missing[index]
|
||||
if err := os.Mkdir(created, WorkspaceDirectoryMode); err != nil && !os.IsExist(err) {
|
||||
return fmt.Errorf("create workspace directory %q: %w", created, err)
|
||||
}
|
||||
if err := os.Chmod(created, WorkspaceDirectoryMode); err != nil {
|
||||
return fmt.Errorf("set workspace directory permissions %q: %w", created, err)
|
||||
}
|
||||
}
|
||||
if err := os.Chmod(clean, WorkspaceDirectoryMode); err != nil {
|
||||
return fmt.Errorf("set workspace directory permissions %q: %w", clean, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user