61 lines
1.9 KiB
Go
61 lines
1.9 KiB
Go
package fileops
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// WorkspaceDirectoryMode is the POSIX mode for ordinary, shareable workspace
|
|
// directories. The set-group-ID bit preserves the configured workspace group
|
|
// for nested files and directories.
|
|
const WorkspaceDirectoryMode os.FileMode = os.ModeSetgid | 0o775
|
|
|
|
// WorkspaceFileMode is the POSIX mode for ordinary, shareable workspace files.
|
|
const WorkspaceFileMode os.FileMode = 0o664
|
|
|
|
// EnsureWorkspaceDirectory creates directory and makes every directory created
|
|
// for it conform to the ordinary workspace sharing contract. Existing
|
|
// directories retain their owner and group; only their mode is updated.
|
|
func EnsureWorkspaceDirectory(directory string) error {
|
|
if strings.TrimSpace(directory) == "" {
|
|
return fmt.Errorf("workspace directory is required")
|
|
}
|
|
|
|
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
|
|
}
|