Port envd from e2b with internalized shared packages and Connect RPC
- Copy envd source from e2b-dev/infra, internalize shared dependencies
into envd/internal/shared/ (keys, filesystem, id, smap, utils)
- Switch from gRPC to Connect RPC for all envd services
- Update module paths to git.omukk.dev/wrenn/{sandbox,sandbox/envd}
- Add proto specs (process, filesystem) with buf-based code generation
- Implement full envd: process exec, filesystem ops, port forwarding,
cgroup management, MMDS integration, and HTTP API
- Update main module dependencies (firecracker SDK, pgx, goose, etc.)
- Remove placeholder .gitkeep files replaced by real implementations
This commit is contained in:
108
envd/internal/shared/filesystem/entry.go
Normal file
108
envd/internal/shared/filesystem/entry.go
Normal file
@ -0,0 +1,108 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetEntryFromPath(path string) (EntryInfo, error) {
|
||||
fileInfo, err := os.Lstat(path)
|
||||
if err != nil {
|
||||
return EntryInfo{}, err
|
||||
}
|
||||
|
||||
return GetEntryInfo(path, fileInfo), nil
|
||||
}
|
||||
|
||||
func GetEntryInfo(path string, fileInfo os.FileInfo) EntryInfo {
|
||||
fileMode := fileInfo.Mode()
|
||||
|
||||
var symlinkTarget *string
|
||||
if fileMode&os.ModeSymlink != 0 {
|
||||
// If we can't resolve the symlink target, we won't set the target
|
||||
target := followSymlink(path)
|
||||
symlinkTarget = &target
|
||||
}
|
||||
|
||||
var entryType FileType
|
||||
var mode os.FileMode
|
||||
|
||||
if symlinkTarget == nil {
|
||||
entryType = getEntryType(fileMode)
|
||||
mode = fileMode.Perm()
|
||||
} else {
|
||||
// If it's a symlink, we need to determine the type of the target
|
||||
targetInfo, err := os.Stat(*symlinkTarget)
|
||||
if err != nil {
|
||||
entryType = UnknownFileType
|
||||
} else {
|
||||
entryType = getEntryType(targetInfo.Mode())
|
||||
mode = targetInfo.Mode().Perm()
|
||||
}
|
||||
}
|
||||
|
||||
entry := EntryInfo{
|
||||
Name: fileInfo.Name(),
|
||||
Path: path,
|
||||
Type: entryType,
|
||||
Size: fileInfo.Size(),
|
||||
Mode: mode,
|
||||
Permissions: fileMode.String(),
|
||||
ModifiedTime: fileInfo.ModTime(),
|
||||
SymlinkTarget: symlinkTarget,
|
||||
}
|
||||
|
||||
if base := getBase(fileInfo.Sys()); base != nil {
|
||||
entry.AccessedTime = toTimestamp(base.Atim)
|
||||
entry.CreatedTime = toTimestamp(base.Ctim)
|
||||
entry.ModifiedTime = toTimestamp(base.Mtim)
|
||||
entry.UID = base.Uid
|
||||
entry.GID = base.Gid
|
||||
} else if !fileInfo.ModTime().IsZero() {
|
||||
entry.ModifiedTime = fileInfo.ModTime()
|
||||
}
|
||||
|
||||
return entry
|
||||
}
|
||||
|
||||
// getEntryType determines the type of file entry based on its mode and path.
|
||||
// If the file is a symlink, it follows the symlink to determine the actual type.
|
||||
func getEntryType(mode os.FileMode) FileType {
|
||||
switch {
|
||||
case mode.IsRegular():
|
||||
return FileFileType
|
||||
case mode.IsDir():
|
||||
return DirectoryFileType
|
||||
case mode&os.ModeSymlink == os.ModeSymlink:
|
||||
return SymlinkFileType
|
||||
default:
|
||||
return UnknownFileType
|
||||
}
|
||||
}
|
||||
|
||||
// followSymlink resolves a symbolic link to its target path.
|
||||
func followSymlink(path string) string {
|
||||
// Resolve symlinks
|
||||
resolvedPath, err := filepath.EvalSymlinks(path)
|
||||
if err != nil {
|
||||
return path
|
||||
}
|
||||
|
||||
return resolvedPath
|
||||
}
|
||||
|
||||
func toTimestamp(spec syscall.Timespec) time.Time {
|
||||
if spec.Sec == 0 && spec.Nsec == 0 {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
return time.Unix(spec.Sec, spec.Nsec)
|
||||
}
|
||||
|
||||
func getBase(sys any) *syscall.Stat_t {
|
||||
st, _ := sys.(*syscall.Stat_t)
|
||||
|
||||
return st
|
||||
}
|
||||
Reference in New Issue
Block a user