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:
107
envd/internal/services/filesystem/utils.go
Normal file
107
envd/internal/services/filesystem/utils.go
Normal file
@ -0,0 +1,107 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/user"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
rpc "git.omukk.dev/wrenn/sandbox/envd/internal/services/spec/filesystem"
|
||||
"git.omukk.dev/wrenn/sandbox/envd/internal/shared/filesystem"
|
||||
)
|
||||
|
||||
// Filesystem magic numbers from Linux kernel (include/uapi/linux/magic.h)
|
||||
const (
|
||||
nfsSuperMagic = 0x6969
|
||||
cifsMagic = 0xFF534D42
|
||||
smbSuperMagic = 0x517B
|
||||
smb2MagicNumber = 0xFE534D42
|
||||
fuseSuperMagic = 0x65735546
|
||||
)
|
||||
|
||||
// IsPathOnNetworkMount checks if the given path is on a network filesystem mount.
|
||||
// Returns true if the path is on NFS, CIFS, SMB, or FUSE filesystem.
|
||||
func IsPathOnNetworkMount(path string) (bool, error) {
|
||||
var statfs syscall.Statfs_t
|
||||
if err := syscall.Statfs(path, &statfs); err != nil {
|
||||
return false, fmt.Errorf("failed to statfs %s: %w", path, err)
|
||||
}
|
||||
|
||||
switch statfs.Type {
|
||||
case nfsSuperMagic, cifsMagic, smbSuperMagic, smb2MagicNumber, fuseSuperMagic:
|
||||
return true, nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
func entryInfo(path string) (*rpc.EntryInfo, error) {
|
||||
info, err := filesystem.GetEntryFromPath(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("file not found: %w", err))
|
||||
}
|
||||
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("error getting file info: %w", err))
|
||||
}
|
||||
|
||||
owner, group := getFileOwnership(info)
|
||||
|
||||
return &rpc.EntryInfo{
|
||||
Name: info.Name,
|
||||
Type: getEntryType(info.Type),
|
||||
Path: info.Path,
|
||||
Size: info.Size,
|
||||
Mode: uint32(info.Mode),
|
||||
Permissions: info.Permissions,
|
||||
Owner: owner,
|
||||
Group: group,
|
||||
ModifiedTime: toTimestamp(info.ModifiedTime),
|
||||
SymlinkTarget: info.SymlinkTarget,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func toTimestamp(time time.Time) *timestamppb.Timestamp {
|
||||
if time.IsZero() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return timestamppb.New(time)
|
||||
}
|
||||
|
||||
// getFileOwnership returns the owner and group names for a file.
|
||||
// If the lookup fails, it returns the numeric UID and GID as strings.
|
||||
func getFileOwnership(fileInfo filesystem.EntryInfo) (owner, group string) {
|
||||
// Look up username
|
||||
owner = fmt.Sprintf("%d", fileInfo.UID)
|
||||
if u, err := user.LookupId(owner); err == nil {
|
||||
owner = u.Username
|
||||
}
|
||||
|
||||
// Look up group name
|
||||
group = fmt.Sprintf("%d", fileInfo.GID)
|
||||
if g, err := user.LookupGroupId(group); err == nil {
|
||||
group = g.Name
|
||||
}
|
||||
|
||||
return owner, group
|
||||
}
|
||||
|
||||
// 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(fileType filesystem.FileType) rpc.FileType {
|
||||
switch fileType {
|
||||
case filesystem.FileFileType:
|
||||
return rpc.FileType_FILE_TYPE_FILE
|
||||
case filesystem.DirectoryFileType:
|
||||
return rpc.FileType_FILE_TYPE_DIRECTORY
|
||||
case filesystem.SymlinkFileType:
|
||||
return rpc.FileType_FILE_TYPE_SYMLINK
|
||||
default:
|
||||
return rpc.FileType_FILE_TYPE_UNSPECIFIED
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user