//go:build linux package host import ( "crypto/sha256" "encoding/hex" "fmt" "path/filepath" "strings" "github.com/carlosframework/platform/internal/hostbox" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/hostguard" "github.com/carlosframework/platform/internal/instancefs" "github.com/carlosframework/platform/internal/provision" "golang.org/x/sys/unix" ) // servingParkStateDirectory accepts only root installation and root inventory // snapshots. The root handler reads both locally under host authority; // this function is not a transport decoder and accepts no registry row. func servingParkStateDirectory(data string, o hostclaim.Observed, installation hostguard.RootInstallation, in hostbox.StopInventory, revision uint64, actor hostbox.Actor) (servingArtifactDirectory, error) { var zero servingArtifactDirectory current, err := servingWriterIdentity(o, actor.Box, actor.Region) if err != nil { return zero, err } if !filepath.IsAbs(data) || filepath.Clean(data) != data || strings.ContainsAny(current.Host, "/\\\x00") || current.Host == "." || current.Host == ".." { return zero, hostbox.ErrChanged } h := o.Claim.Holder if h.Family != "instance" || installation.Migration == 0 || installation.Empty || installation.Host != current.Host || installation.Incarnation != current.Incarnation || installation.Stamp == 0 || installation.Stamp > current.Stamp || installation.Account != h.Account || installation.App != h.App || installation.Record != h.Key || installation.Box != actor.Box || installation.Enrollment != actor.Enrollment || actor.Enrollment == "" || actor.Revision == 0 || actor.Binding == "" || revision == 0 || installation.InventoryRevision != revision { return zero, hostbox.ErrChanged } if installation.Stamp != current.Stamp { if _, err := servingPredecessor(o.Claim, current, installation.Stamp, ""); err != nil { return zero, err } } if !in.Complete || in.Host != installation.Host || in.Incarnation != installation.Incarnation || in.InstallationStamp != installation.Stamp || in.Box != actor.Box || in.Enrollment != actor.Enrollment || in.DirectoryRevision != actor.Binding { return zero, hostbox.ErrTypedInventory } relative := filepath.ToSlash(filepath.Join("instances", provision.InstanceID(current.Host))) sum := sha256.Sum256([]byte(fmt.Sprintf("%s\x00%s\x00%d\x00%s", in.Host, in.Incarnation, in.InstallationStamp, in.Box))) owner := hex.EncodeToString(sum[:]) var selected hostbox.StopInventoryEntry for _, entry := range in.Entries { if entry.Kind != "path" || entry.ManagedRoot != "data" || entry.RelativePath != relative { continue } if selected.ArtifactID != "" || entry.ArtifactID == "" || entry.Ownership != owner || entry.Materialization != "materialized" || entry.Type != unix.S_IFDIR || entry.Device == 0 || entry.Inode == 0 { return zero, hostbox.ErrTypedInventory } selected = entry } if selected.ArtifactID == "" { return zero, hostbox.ErrTypedInventory } dir, err := instancefs.OpenDirBeneath(data, relative) if err != nil { return zero, err } defer dir.Close() id, err := servingParkDirID(dir) if err != nil { return zero, err } if id.Device != selected.Device || id.Inode != selected.Inode { return zero, hostbox.ErrChanged } return id, nil }