Full Code of apple/containerization for AI

main a59ed894213c cached
324 files
2.6 MB
696.3k tokens
501 symbols
1 requests
Download .txt
Showing preview only (2,780K chars total). Download the full file or copy to clipboard to get everything.
Repository: apple/containerization
Branch: main
Commit: a59ed894213c
Files: 324
Total size: 2.6 MB

Directory structure:
gitextract_1u63lgkp/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 01-bug.yml
│   │   ├── 02-feature.yml
│   │   └── config.yml
│   └── workflows/
│       ├── build-test-images.yml
│       ├── containerization-build-template.yml
│       ├── containerization-build.yml
│       ├── docs-release.yaml
│       └── release.yml
├── .gitignore
├── .spi.yml
├── .swift-format
├── .swift-format-nolint
├── .swift-version
├── CONTRIBUTING.md
├── LICENSE
├── MAINTAINERS.txt
├── Makefile
├── Package.resolved
├── Package.swift
├── Protobuf.Makefile
├── README.md
├── SECURITY.md
├── Sources/
│   ├── CShim/
│   │   ├── capability.c
│   │   ├── exec_command.c
│   │   ├── include/
│   │   │   ├── capability.h
│   │   │   ├── exec_command.h
│   │   │   ├── openat2.h
│   │   │   ├── prctl.h
│   │   │   ├── socket_helpers.h
│   │   │   └── vsock.h
│   │   ├── openat2.c
│   │   ├── prctl.c
│   │   ├── socket_helpers.c
│   │   └── vsock.c
│   ├── Containerization/
│   │   ├── AttachedFilesystem.swift
│   │   ├── Container.swift
│   │   ├── ContainerManager.swift
│   │   ├── ContainerStatistics.swift
│   │   ├── DNSConfiguration.swift
│   │   ├── ExitStatus.swift
│   │   ├── FileMount.swift
│   │   ├── Hash.swift
│   │   ├── HostsConfiguration.swift
│   │   ├── IO/
│   │   │   ├── ReaderStream.swift
│   │   │   ├── Terminal+ReaderStream.swift
│   │   │   └── Writer.swift
│   │   ├── Image/
│   │   │   ├── Image.swift
│   │   │   ├── ImageStore/
│   │   │   │   ├── ImageStore+Export.swift
│   │   │   │   ├── ImageStore+Import.swift
│   │   │   │   ├── ImageStore+OCILayout.swift
│   │   │   │   ├── ImageStore+ReferenceManager.swift
│   │   │   │   └── ImageStore.swift
│   │   │   ├── InitImage.swift
│   │   │   ├── KernelImage.swift
│   │   │   └── Unpacker/
│   │   │       ├── EXT4Unpacker.swift
│   │   │       └── Unpacker.swift
│   │   ├── Interface.swift
│   │   ├── Kernel.swift
│   │   ├── LinuxContainer.swift
│   │   ├── LinuxPod.swift
│   │   ├── LinuxProcess.swift
│   │   ├── LinuxProcessConfiguration.swift
│   │   ├── Mount.swift
│   │   ├── NATInterface.swift
│   │   ├── NATNetworkInterface.swift
│   │   ├── Network.swift
│   │   ├── SandboxContext/
│   │   │   ├── SandboxContext.grpc.swift
│   │   │   ├── SandboxContext.pb.swift
│   │   │   └── SandboxContext.proto
│   │   ├── SystemPlatform.swift
│   │   ├── TimeSyncer.swift
│   │   ├── UnixSocketConfiguration.swift
│   │   ├── UnixSocketRelay.swift
│   │   ├── UnixSocketRelayManager.swift
│   │   ├── VMConfiguration.swift
│   │   ├── VZVirtualMachine+Helpers.swift
│   │   ├── VZVirtualMachineInstance.swift
│   │   ├── VZVirtualMachineManager.swift
│   │   ├── VirtualMachineAgent+Additions.swift
│   │   ├── VirtualMachineAgent.swift
│   │   ├── VirtualMachineInstance.swift
│   │   ├── VirtualMachineManager.swift
│   │   ├── Vminitd+Rosetta.swift
│   │   ├── Vminitd+SocketRelay.swift
│   │   ├── Vminitd.swift
│   │   ├── VmnetNetwork.swift
│   │   └── VsockListener.swift
│   ├── ContainerizationArchive/
│   │   ├── ArchiveError.swift
│   │   ├── ArchiveReader.swift
│   │   ├── ArchiveWriter.swift
│   │   ├── ArchiveWriterConfiguration.swift
│   │   ├── CArchive/
│   │   │   ├── COPYING
│   │   │   ├── archive_swift_bridge.c
│   │   │   └── include/
│   │   │       ├── archive.h
│   │   │       ├── archive_bridge.h
│   │   │       └── archive_entry.h
│   │   ├── TempDir.swift
│   │   └── WriteEntry.swift
│   ├── ContainerizationEXT4/
│   │   ├── Documentation.docc/
│   │   │   └── ext4.md
│   │   ├── EXT4+Extensions.swift
│   │   ├── EXT4+FileTree.swift
│   │   ├── EXT4+Formatter.swift
│   │   ├── EXT4+Ptr.swift
│   │   ├── EXT4+Reader.swift
│   │   ├── EXT4+Types.swift
│   │   ├── EXT4+Xattrs.swift
│   │   ├── EXT4.swift
│   │   ├── EXT4Reader+Export.swift
│   │   ├── EXT4Reader+IO.swift
│   │   ├── FilePath+Extensions.swift
│   │   ├── FileTimestamps.swift
│   │   ├── Formatter+Unpack.swift
│   │   ├── Integer+Extensions.swift
│   │   ├── README.md
│   │   └── UnsafeLittleEndianBytes.swift
│   ├── ContainerizationError/
│   │   └── ContainerizationError.swift
│   ├── ContainerizationExtras/
│   │   ├── AddressAllocator.swift
│   │   ├── AddressError.swift
│   │   ├── AsyncLock.swift
│   │   ├── AsyncMutex.swift
│   │   ├── CIDR.swift
│   │   ├── CIDRv4.swift
│   │   ├── CIDRv6.swift
│   │   ├── FileManager+Temporary.swift
│   │   ├── IPAddress.swift
│   │   ├── IPv4Address.swift
│   │   ├── IPv6Address+Parse.swift
│   │   ├── IPv6Address.swift
│   │   ├── IndexedAddressAllocator.swift
│   │   ├── MACAddress.swift
│   │   ├── NetworkAddress+Allocator.swift
│   │   ├── Prefix.swift
│   │   ├── ProgressEvent.swift
│   │   ├── ProxyUtils.swift
│   │   ├── RotatingAddressAllocator.swift
│   │   ├── TLSUtils.swift
│   │   ├── Timeout.swift
│   │   └── UInt8+DataBinding.swift
│   ├── ContainerizationIO/
│   │   └── ReadStream.swift
│   ├── ContainerizationNetlink/
│   │   ├── NetlinkSession.swift
│   │   ├── NetlinkSocket.swift
│   │   └── Types.swift
│   ├── ContainerizationOCI/
│   │   ├── AnnotationKeys.swift
│   │   ├── Bundle.swift
│   │   ├── Client/
│   │   │   ├── Authentication.swift
│   │   │   ├── KeychainHelper.swift
│   │   │   ├── LocalOCILayoutClient.swift
│   │   │   ├── RegistryClient+Catalog.swift
│   │   │   ├── RegistryClient+Error.swift
│   │   │   ├── RegistryClient+Fetch.swift
│   │   │   ├── RegistryClient+Push.swift
│   │   │   ├── RegistryClient+Referrers.swift
│   │   │   ├── RegistryClient+Token.swift
│   │   │   └── RegistryClient.swift
│   │   ├── Content/
│   │   │   ├── AsyncTypes.swift
│   │   │   ├── Content.swift
│   │   │   ├── ContentStoreProtocol.swift
│   │   │   ├── ContentWriter.swift
│   │   │   ├── LocalContent.swift
│   │   │   ├── LocalContentStore.swift
│   │   │   ├── SHA256+Extensions.swift
│   │   │   ├── String+Extension.swift
│   │   │   └── URL+Extensions.swift
│   │   ├── Descriptor.swift
│   │   ├── FileManager+Size.swift
│   │   ├── ImageConfig.swift
│   │   ├── Index.swift
│   │   ├── Manifest.swift
│   │   ├── MediaType.swift
│   │   ├── Platform.swift
│   │   ├── Reference.swift
│   │   ├── Spec.swift
│   │   ├── State.swift
│   │   └── Version.swift
│   ├── ContainerizationOS/
│   │   ├── AsyncSignalHandler.swift
│   │   ├── BinaryInteger+Extensions.swift
│   │   ├── Command.swift
│   │   ├── File.swift
│   │   ├── FileDescriptor+SecurePath.swift
│   │   ├── Keychain/
│   │   │   ├── KeychainQuery.swift
│   │   │   └── RegistryInfo.swift
│   │   ├── Linux/
│   │   │   ├── Binfmt.swift
│   │   │   ├── Capabilities.swift
│   │   │   └── Epoll.swift
│   │   ├── Mount/
│   │   │   └── Mount.swift
│   │   ├── POSIXError+Helpers.swift
│   │   ├── Path.swift
│   │   ├── Pipe+Close.swift
│   │   ├── README.md
│   │   ├── Reaper.swift
│   │   ├── Signals.swift
│   │   ├── Socket/
│   │   │   ├── BidirectionalRelay.swift
│   │   │   ├── Socket.swift
│   │   │   ├── SocketType.swift
│   │   │   ├── UnixType.swift
│   │   │   └── VsockType.swift
│   │   ├── Syscall.swift
│   │   ├── Sysctl.swift
│   │   ├── Terminal.swift
│   │   ├── URL+Extensions.swift
│   │   └── User.swift
│   ├── Integration/
│   │   ├── ContainerTests.swift
│   │   ├── PodTests.swift
│   │   └── Suite.swift
│   └── cctl/
│       ├── ImageCommand.swift
│       ├── KernelCommand.swift
│       ├── LoginCommand.swift
│       ├── RootfsCommand.swift
│       ├── RunCommand.swift
│       ├── cctl+Utils.swift
│       └── cctl.swift
├── Tests/
│   ├── ContainerizationArchiveTests/
│   │   ├── ArchiveReaderTests.swift
│   │   ├── ArchiveTests.swift
│   │   └── Resources/
│   │       └── test.tar.zst
│   ├── ContainerizationEXT4Tests/
│   │   ├── Resources/
│   │   │   └── content/
│   │   │       └── blobs/
│   │   │           └── sha256/
│   │   │               ├── 48a06049d3738991b011ca8b12473d712b7c40666a1462118dae3c403676afc2
│   │   │               ├── 4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1
│   │   │               ├── 8e2eb240a6cd7be1a0d308125afe0060b020e89275ced2e729eda7d4eeff62a2
│   │   │               ├── ad59e9f71edceca7b1ac7c642410858489b743c97233b0a26a5e2098b1443762
│   │   │               └── c6b39de5b33961661dc939b997cc1d30cda01e38005a6c6625fd9c7e748bab44
│   │   ├── TestEXT4ExtendedAttributes.swift
│   │   ├── TestEXT4Format+Create.swift
│   │   ├── TestEXT4Format.swift
│   │   ├── TestEXT4Reader+IO.swift
│   │   ├── TestEXT4Unpacker.swift
│   │   └── TestFormatterUnpack.swift
│   ├── ContainerizationExtrasTests/
│   │   ├── AsyncMutexTests.swift
│   │   ├── ProxyUtilsTests.swift
│   │   ├── TestCIDR.swift
│   │   ├── TestIPAddress.swift
│   │   ├── TestIPv4Address.swift
│   │   ├── TestIPv6Address+Parse.swift
│   │   ├── TestIPv6Address.swift
│   │   ├── TestIPv6IPv4Parsing.swift
│   │   ├── TestMACAddress.swift
│   │   ├── TestNetworkAddress+Allocator.swift
│   │   ├── TestPrefix.swift
│   │   ├── TestTimeout.swift
│   │   └── UInt8+DataBindingTest.swift
│   ├── ContainerizationNetlinkTests/
│   │   ├── MockNetlinkSocket.swift
│   │   ├── NetlinkSessionTest.swift
│   │   └── TypesTest.swift
│   ├── ContainerizationOCITests/
│   │   ├── AuthChallengeTests.swift
│   │   ├── OCIImageTests.swift
│   │   ├── OCIPlatformTests.swift
│   │   ├── OCISpecTests.swift
│   │   ├── ReferenceTests.swift
│   │   └── RegistryClientTests.swift
│   ├── ContainerizationOSTests/
│   │   ├── FileDescriptor+SecurePathTests.swift
│   │   ├── KeychainQueryTests.swift
│   │   ├── SocketTests.swift
│   │   └── UserTests.swift
│   ├── ContainerizationTests/
│   │   ├── ContainerManagerTests.swift
│   │   ├── DNSTests.swift
│   │   ├── HashTests.swift
│   │   ├── HostsTests.swift
│   │   ├── ImageTests/
│   │   │   ├── ContainsAuth.swift
│   │   │   ├── ImageStoreImagePullTests.swift
│   │   │   └── ImageStoreTests.swift
│   │   ├── ImageTests.swift
│   │   ├── KernelTests.swift
│   │   ├── LinuxContainerTests.swift
│   │   └── MountTests.swift
│   └── TestImages/
│       ├── dockermanifestimage/
│       │   └── Dockerfile
│       └── emptyimage/
│           └── Dockerfile
├── examples/
│   ├── README.md
│   └── ctr-example/
│       ├── Makefile
│       ├── Package.resolved
│       ├── Package.swift
│       ├── README.md
│       ├── Sources/
│       │   └── ctr-example/
│       │       └── main.swift
│       ├── ctr-example.entitlements
│       └── lab.md
├── kernel/
│   ├── Makefile
│   ├── README.md
│   ├── build.sh
│   ├── config-arm64
│   └── image/
│       ├── Dockerfile
│       └── sources.list
├── licenserc.toml
├── scripts/
│   ├── check-integration-test-vm-panics.sh
│   ├── cz-header-style.toml
│   ├── ensure-hawkeye-exists.sh
│   ├── install-hawkeye.sh
│   ├── license-header.txt
│   ├── make-docs.sh
│   └── pre-commit.fmt
├── signing/
│   └── vz.entitlements
└── vminitd/
    ├── .devcontainer/
    │   ├── Dockerfile
    │   └── devcontainer.json
    ├── Makefile
    ├── Package.resolved
    ├── Package.swift
    └── Sources/
        ├── Cgroup/
        │   └── Cgroup2Manager.swift
        ├── LCShim/
        │   ├── include/
        │   │   └── syscall.h
        │   └── syscall.c
        ├── vmexec/
        │   ├── Console.swift
        │   ├── ExecCommand.swift
        │   ├── Mount.swift
        │   ├── RunCommand.swift
        │   └── vmexec.swift
        └── vminitd/
            ├── AgentCommand.swift
            ├── Application.swift
            ├── CommandRunner.swift
            ├── ContainerProcess.swift
            ├── HostStdio.swift
            ├── IOCloser+Extensions.swift
            ├── IOCloser.swift
            ├── IOPair.swift
            ├── InitCommand.swift
            ├── ManagedContainer.swift
            ├── ManagedProcess.swift
            ├── MemoryMonitor.swift
            ├── OSFile+Splice.swift
            ├── OSFile.swift
            ├── PauseCommand.swift
            ├── ProcessSupervisor.swift
            ├── Runc/
            │   ├── ConsoleSocket.swift
            │   └── Runc.swift
            ├── RuncProcess.swift
            ├── Server+GRPC.swift
            ├── Server.swift
            ├── StandardIO.swift
            ├── TerminalIO.swift
            └── VsockProxy.swift

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/01-bug.yml
================================================
name: Bug report
description: File a bug report.
title: "[Bug]: "
type: "Bug"
body:
  - type: markdown
    attributes:
      value: |
        Thanks for taking the time to fill out this bug report!
  - type: checkboxes
    id: prereqs
    attributes:
      label: I have done the following
      description: Select that you have completed the following prerequisites. 
      options:
        - label: I have searched the existing issues
          required: true
        - label: If possible, I've reproduced the issue using the 'main' branch of this project
          required: false
  - type: textarea
    id: reproduce
    attributes:
      label: Steps to reproduce
      description: Explain how to reproduce the incorrect behavior. 
    validations:
      required: true
  - type: textarea
    id: what-happened
    attributes:
      label: Current behavior
      description: A concise description of what you're experiencing.
    validations:
      required: true
  - type: textarea
    id: expected
    attributes:
      label: Expected behavior
      description: A concise description of what you expected to happen.
    validations:
      required: true
  - type: textarea
    attributes:
      label: Environment 
      description: |
        Examples: 
          - **OS**: macOS 26.0 (25A354)
          - **Xcode**: Version 26.0 (17A324)
          - **Swift**: Apple Swift version 6.2 (swift-6.2-RELEASE)
      value: |
        - OS: 
        - Xcode: 
        - Swift: 
      render: markdown
    validations:
      required: true
  - type: textarea
    id: logs
    attributes:
      label: Relevant log output
      description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
      value: |
        N/A
      render: shell
  - type: checkboxes
    id: terms
    attributes:
      label: Code of Conduct
      description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/apple/.github/blob/main/CODE_OF_CONDUCT.md).
      options:
        - label: I agree to follow this project's Code of Conduct
          required: true


================================================
FILE: .github/ISSUE_TEMPLATE/02-feature.yml
================================================
name: Feature or enhancement request
description: File a request for a feature or enhancement
title: "[Request]: "
type: "Feature"
body:
  - type: markdown
    attributes:
      value: |
        Thanks for contributing to the containerization project!
  - type: textarea
    id: request
    attributes:
      label: Feature or enhancement request details
      description: Describe your proposed feature or enhancement. Code samples that show what's missing, or what new capabilities will be possible, are very helpful! Provide links to existing issues or external references/discussions, if appropriate.
    validations:
      required: true
  - type: checkboxes
    id: terms
    attributes:
      label: Code of Conduct
      description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/apple/.github/blob/main/CODE_OF_CONDUCT.md). 
      options:
        - label: I agree to follow this project's Code of Conduct
          required: true


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Containerization community support
    url: https://github.com/apple/container/discussions
    about: Please ask and answer questions here.


================================================
FILE: .github/workflows/build-test-images.yml
================================================
name: Build and publish containerization test images

permissions:
  contents: read

on: 
  workflow_dispatch: 
    inputs: 
      publish: 
        type: boolean
        description: "Publish the built image"
        default: false
      version: 
        type: string
        description: "Version of the image to create"
        default: "test"
      image:
        type: choice
        description: Test image to build
        options:
          - dockermanifestimage
          - emptyimage
        default: 'dockermanifestimage'
      useBuildx:
        type: boolean
        description: "Use docker buildx to build the image"
        default: false

jobs: 
  image: 
    name: Build test images
    timeout-minutes: 30
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write 
    steps:
      - name: Check branch
        env:
          GH_REF: ${{ github.ref }}
          PUBLISH: ${{ inputs.publish }}
        run: |
          if [[ "${GH_REF}" != "refs/heads/main" ]] && [[ "${GH_REF}" != refs/heads/release* ]] && [[ "${PUBLISH}" == "true" ]]; then
            echo "❌ Cannot publish an image if we are not on main or a release branch."
            exit 1
          fi
      - name: Check inputs
        env:
          IMAGE: ${{ inputs.image }}
          USE_BUILDX: ${{ inputs.useBuildx }}
        run: |
          if [[ "${IMAGE}" == "dockermanifestimage" ]] && [[ "${USE_BUILDX}" == "true" ]]; then
            echo "❌ dockermanifestimage cannot be built with buildx"
            exit 1
          fi

          if [[ "${IMAGE}" == "emptyimage" ]] && [[ "${USE_BUILDX}" != "true" ]]; then
            echo "❌ emptyimage should be built with buildx"
            exit 1
          fi
      - name: Checkout repository
        uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8  # v6 
      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Set up Docker Buildx
        if: ${{ inputs.useBuildx }} 
        uses: docker/setup-buildx-action@v3
      - name: Build dockerfile and push image
        uses: docker/build-push-action@v6
        with:
          push: ${{ inputs.publish }}
          context: Tests/TestImages/${{ inputs.image }}
          tags: ghcr.io/apple/containerization/${{ inputs.image }}:${{ inputs.version }}


================================================
FILE: .github/workflows/containerization-build-template.yml
================================================
name: Build containerization template

permissions:
  contents: read

on: 
  workflow_call:
    inputs:
      release:
        type: boolean
        description: "Create a release"
        default: false
      version: 
        type: string
        description: Version of containerization 
        default: test

jobs: 
  buildAndTest: 
    name: Build and Test repo
    if: github.repository == 'apple/containerization'
    timeout-minutes: 60
    runs-on: [self-hosted, macos, tahoe, ARM64]
    permissions:
      contents: read
      packages: write
    env:
      DEVELOPER_DIR: "/Applications/Xcode-latest.app/Contents/Developer"

    steps:
      - name: Checkout repository
        uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8  # v6
        with:
          fetch-depth: 0

      - name: Activate Swiftly
        run: |
          source /opt/swiftly/env.sh
          cat /opt/swiftly/env.sh

      - name: Check formatting
        run: | 
          ./scripts/install-hawkeye.sh
          make fmt
          git diff
          if ! git diff --quiet ; then echo the following files require formatting or license headers: ; git diff --name-only ; false ; fi

      - name: Check protobufs
        run: | 
          make protos
          if ! git diff --quiet ; then echo the following files require formatting or license headers: ; git diff --name-only ; false ; fi

      - name: Make containerization and docs
        run: |
          make clean containerization docs
          tar cfz _site.tgz _site
        env:
          BUILD_CONFIGURATION: ${{ inputs.release && 'release' || 'debug' }}

      - name: Make vminitd image
        run: |
          source /opt/swiftly/env.sh
          make -C vminitd swift linux-sdk
          make init
        env:
          BUILD_CONFIGURATION: ${{ inputs.release && 'release' || 'debug' }}

      - name: Test containerization
        run: | 
          make fetch-default-kernel
          make test integration
        env:
          REGISTRY_TOKEN: ${{ github.token }}
          REGISTRY_USERNAME: ${{ github.actor }}

      - name: Push vminitd image
        if: ${{ inputs.release }}
        env:
          REGISTRY_TOKEN: ${{ github.token }}
          REGISTRY_USERNAME: ${{ github.actor }}
          REGISTRY_HOST: ghcr.io
          VERSION: ${{ inputs.version }}
        run: |
          bin/cctl images tag vminit:latest "ghcr.io/apple/containerization/vminit:${VERSION}"
          bin/cctl images push "ghcr.io/apple/containerization/vminit:${VERSION}"

      - name: Create image tar 
        if: ${{ !inputs.release }}
        run: |
          bin/cctl images save vminit:latest -o vminit.tar

      - name: Save vminit artifact
        if: ${{ !inputs.release }}
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f  # v6
        with:
          name: vminit
          path: vminit.tar

      - name: Save documentation artifact
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f  # v6
        with:
          name: api-docs
          path: "./_site.tgz"
          retention-days: 14

  uploadPages:
    # Separate upload step required because upload-pages-artifact needs
    # gtar which is not on the macOS runner.
    name: Upload artifact for GitHub Pages
    needs: buildAndTest
    timeout-minutes: 5
    runs-on: ubuntu-latest

    steps:
      - name: Setup Pages
        uses: actions/configure-pages@v5

      - name: Download a single artifact
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131  # v7
        with:
          name: api-docs

      - name: Add API docs to documentation
        run: |
          tar xfz _site.tgz

      - name: Upload Artifact
        uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b  # v4
        with:
          path: "./_site"


================================================
FILE: .github/workflows/containerization-build.yml
================================================
name: Build containerization

permissions:
  contents: read

on:
  pull_request:
    types: [opened, reopened, synchronize]
  push:
    branches:
      - main
      - release/*

jobs:
  verify-signatures:
    name: Verify commit signatures
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - name: Check all commits are signed
        env:
          GH_TOKEN: ${{ github.token }}
          REPO: ${{ github.repository }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
        run: |
          commits=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/commits" --paginate)
          unsigned_commits=""

          while IFS='|' read -r sha author verified; do
            if [ "$verified" != "true" ]; then
              unsigned_commits="$unsigned_commits  - $sha by $author\n"
            fi
          done < <(echo "$commits" | jq -r '.[] | "\(.sha)|\(.commit.author.name)|\(.commit.verification.verified)"')

          if [ -n "$unsigned_commits" ]; then
            echo "::error::The following commits are not signed:"
            echo -e "$unsigned_commits"
            echo ""
            echo "Please sign your commits. See:"
            echo  "  - https://github.com/apple/containerization/blob/main/CONTRIBUTING.md#pull-requests"
            echo  "  - https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits"
            exit 1
          fi

          echo "All commits are signed!"

  containerization:
    permissions:
      contents: read
      packages: write
      pages: write
    uses: ./.github/workflows/containerization-build-template.yml
    secrets: inherit


================================================
FILE: .github/workflows/docs-release.yaml
================================================
# Manual workflow for releasing docs ad-hoc. Workflow can only be run for main or release branches. 
# Workflow does NOT publish a release of containerization.
name: Deploy application website

permissions:
  contents: read

on: 
  workflow_dispatch:

jobs: 
  checkBranch:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags') || startsWith(github.ref, 'refs/heads/release')
    steps:
      - name: Branch validation
        env:
          REF_NAME: ${{ github.ref_name }}
        run: echo "Branch ${REF_NAME} is allowed"

  buildSite:
    name: Build application website
    needs: checkBranch
    uses: ./.github/workflows/containerization-build-template.yml
    secrets: inherit
    permissions:
      contents: read
      packages: write
      pages: write

  deployDocs:
    runs-on: ubuntu-latest
    needs: [checkBranch, buildSite]
    permissions:
      contents: read
      pages: write
      id-token: write

    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}

    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4


================================================
FILE: .github/workflows/release.yml
================================================
name: Release containerization

permissions:
  contents: read

on: 
  push: 
    tags:
      - "[0-9]+\\.[0-9]+\\.[0-9]+"

jobs: 
  containerization:
    uses: ./.github/workflows/containerization-build-template.yml
    with: 
      release: true
      version: ${{ github.ref_name }}
    secrets: inherit
    permissions:
      contents: read
      packages: write
      pages: write

  deployDocs:
    if: startsWith(github.ref, 'refs/tags/')
    runs-on: ubuntu-latest
    needs: containerization
    permissions:
      contents: read
      pages: write
      id-token: write
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

  release: 
    if: startsWith(github.ref, 'refs/tags/')
    name: Publish release
    timeout-minutes: 30
    needs: containerization
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: read
    steps:
      - name: Create release
        uses: softprops/action-gh-release@v2
        with:
          token: ${{ github.token }}
          name: ${{ github.ref_name }}-prerelease
          draft: true
          make_latest: false
          prerelease: true
          fail_on_unmatched_files: true


================================================
FILE: .gitignore
================================================
.DS_Store
bin
libexec
.build
.local
xcuserdata/
DerivedData/
.swiftpm/
.netrc
.swiftpm
workdir/
installer/
.venv/
test_results/
*.pid
*.log
*.zip
*.o
*.ext4
*.pkg
*.swp
*.tar.gz
*.tar.xz
vmlinux

# API docs for local preview only.
_site/
_serve/


================================================
FILE: .spi.yml
================================================
version: 1
builder:
  configs:
    - documentation_targets: [Containerization, ContainerizationEXT4, ContainerizationOS, ContainerizationOCI, ContainerizationNetlink, ContainerizationIO, ContainerizationExtras, ContainerizationArchive, SendableProperty]
      swift_version: '6.2'


================================================
FILE: .swift-format
================================================
{
  "fileScopedDeclarationPrivacy" : {
    "accessLevel" : "private"
  },
  "indentation" : {
    "spaces" : 4
  },
  "indentConditionalCompilationBlocks" : false,
  "indentSwitchCaseLabels" : false,
  "lineBreakAroundMultilineExpressionChainComponents" : false,
  "lineBreakBeforeControlFlowKeywords" : false,
  "lineBreakBeforeEachArgument" : false,
  "lineBreakBeforeEachGenericRequirement" : false,
  "lineLength" : 180,
  "maximumBlankLines" : 1,
  "multiElementCollectionTrailingCommas" : true,
  "noAssignmentInExpressions" : {
    "allowedFunctions" : [
      "XCTAssertNoThrow"
    ]
  },
  "prioritizeKeepingFunctionOutputTogether" : false,
  "respectsExistingLineBreaks" : true,
  "rules" : {
    "AllPublicDeclarationsHaveDocumentation" : false,
    "AlwaysUseLowerCamelCase" : true,
    "AmbiguousTrailingClosureOverload" : false,
    "BeginDocumentationCommentWithOneLineSummary" : false,
    "DoNotUseSemicolons" : true,
    "DontRepeatTypeInStaticProperties" : true,
    "FileScopedDeclarationPrivacy" : true,
    "FullyIndirectEnum" : true,
    "GroupNumericLiterals" : true,
    "IdentifiersMustBeASCII" : true,
    "NeverForceUnwrap" : true,
    "NeverUseForceTry" : true,
    "NeverUseImplicitlyUnwrappedOptionals" : true,
    "NoAccessLevelOnExtensionDeclaration" : true,
    "NoAssignmentInExpressions" : true,
    "NoBlockComments" : false,
    "NoCasesWithOnlyFallthrough" : true,
    "NoEmptyTrailingClosureParentheses" : true,
    "NoLabelsInCasePatterns" : true,
    "NoLeadingUnderscores" : false,
    "NoParensAroundConditions" : true,
    "NoPlaygroundLiterals" : true,
    "NoVoidReturnOnFunctionSignature" : true,
    "OmitExplicitReturns" : true,
    "OneCasePerLine" : true,
    "OneVariableDeclarationPerLine" : true,
    "OnlyOneTrailingClosureArgument" : true,
    "OrderedImports" : true,
    "ReplaceForEachWithForLoop" : true,
    "ReturnVoidInsteadOfEmptyTuple" : true,
    "TypeNamesShouldBeCapitalized" : true,
    "UseEarlyExits" : true,
    "UseLetInEveryBoundCaseVariable" : true,
    "UseShorthandTypeNames" : true,
    "UseSingleLinePropertyGetter" : true,
    "UseSynthesizedInitializer" : true,
    "UseTripleSlashForDocumentationComments" : true,
    "UseWhereClausesInForLoops" : false,
    "ValidateDocumentationComments" : true
  },
  "spacesAroundRangeFormationOperators" : false,
  "tabWidth" : 2,
  "version" : 1
}


================================================
FILE: .swift-format-nolint
================================================
{
  "fileScopedDeclarationPrivacy" : {
    "accessLevel" : "private"
  },
  "indentation" : {
    "spaces" : 4
  },
  "indentConditionalCompilationBlocks" : false,
  "indentSwitchCaseLabels" : false,
  "lineBreakAroundMultilineExpressionChainComponents" : false,
  "lineBreakBeforeControlFlowKeywords" : false,
  "lineBreakBeforeEachArgument" : false,
  "lineBreakBeforeEachGenericRequirement" : false,
  "lineLength" : 180,
  "maximumBlankLines" : 1,
  "multiElementCollectionTrailingCommas" : true,
  "noAssignmentInExpressions" : {
    "allowedFunctions" : [
      "XCTAssertNoThrow"
    ]
  },
  "prioritizeKeepingFunctionOutputTogether" : false,
  "respectsExistingLineBreaks" : true,
  "rules" : {
    "AllPublicDeclarationsHaveDocumentation" : false,
    "AlwaysUseLowerCamelCase" : false,
    "AmbiguousTrailingClosureOverload" : false,
    "BeginDocumentationCommentWithOneLineSummary" : false,
    "DoNotUseSemicolons" : true,
    "DontRepeatTypeInStaticProperties" : false,
    "FileScopedDeclarationPrivacy" : false,
    "FullyIndirectEnum" : false,
    "GroupNumericLiterals" : false,
    "IdentifiersMustBeASCII" : false,
    "NeverForceUnwrap" : false,
    "NeverUseForceTry" : false,
    "NeverUseImplicitlyUnwrappedOptionals" : false,
    "NoAccessLevelOnExtensionDeclaration" : false,
    "NoAssignmentInExpressions" : false,
    "NoBlockComments" : false,
    "NoCasesWithOnlyFallthrough" : false,
    "NoEmptyTrailingClosureParentheses" : true,
    "NoLabelsInCasePatterns" : false,
    "NoLeadingUnderscores" : false,
    "NoParensAroundConditions" : true,
    "NoPlaygroundLiterals" : false,
    "NoVoidReturnOnFunctionSignature" : true,
    "OmitExplicitReturns" : false,
    "OneCasePerLine" : true,
    "OneVariableDeclarationPerLine" : true,
    "OnlyOneTrailingClosureArgument" : false,
    "OrderedImports" : true,
    "ReplaceForEachWithForLoop" : false,
    "ReturnVoidInsteadOfEmptyTuple" : false,
    "TypeNamesShouldBeCapitalized" : false,
    "UseEarlyExits" : false,
    "UseLetInEveryBoundCaseVariable" : false,
    "UseShorthandTypeNames" : true,
    "UseSingleLinePropertyGetter" : true,
    "UseSynthesizedInitializer" : false,
    "UseTripleSlashForDocumentationComments" : true,
    "UseWhereClausesInForLoops" : false,
    "ValidateDocumentationComments" : false
  },
  "spacesAroundRangeFormationOperators" : false,
  "tabWidth" : 2,
  "version" : 1
}


================================================
FILE: .swift-version
================================================
6.3-snapshot-2026-02-27

================================================
FILE: CONTRIBUTING.md
================================================
# 🌈 📦️ Welcome to the Containerization community! 📦️ 🌈

Contributions to Containerization are welcomed and encouraged.

## Index

- [How you can help](#how-you-can-help)
- [Submitting issues and pull requests](#submitting-issues-and-pull-requests)
- [New to open source?](#new-to-open-source)
- [AI contribution guidelines](#ai-contribution-guidelines)
- [Code of conduct](#code-of-conduct)

## How you can help

We would love your contributions in the form of:

🐛 Bug fixes\
⚡️ Performance improvements\
✨ API additions or enhancements\
📝 Documentation\
🧑‍💻 Project advocacy: blogs, conference talks, and more

Anything else that could enhance the project!

## Submitting issues and pull requests

### Issues

To file a bug or feature request, use [GitHub issues](https://github.com/apple/containerization/issues/new).

🚧 For unexpected behavior or usability limitations, detailed instructions on how to reproduce the issue are appreciated. This will greatly help the priority setting and speed at which maintainers can get to your issue.

### Pull requests

We require all commits be signed with any of GitHub's supported methods, such as GPG or SSH. Information on how to set this up can be found on [GitHub's docs](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification#about-commit-signature-verification).

To make a pull request, use [GitHub](https://github.com/apple/containerization/compare). Please give the team a few days to review but it's ok to check in on occasion. We appreciate your contribution!

> [!IMPORTANT]
> If you plan to make substantial changes or add new features, we encourage you to first discuss them with the wider containerization developer community.
> You can do this by filing a [GitHub issue](https://github.com/apple/containerization/issues/new).
> This will save time and increases the chance of your pull request being accepted.

We use a "squash and merge" strategy to keep our `main` branch history clean and easy to follow. When your pull request
is merged, all of your commits will be combined into a single commit.

With the "squash and merge" strategy, the *title* and *body* of your pull request is extremely important. It will become the commit message
for the squashed commit. Think of it as the single, definitive description of your contribution.

Before merging, we'll review the pull request title and body to ensure it:

* Clearly and concisely describes the changes.
* Uses the imperative mood (for example, "Add feature," "Fix bug").
* Provides enough context for future developers to understand the purpose of the change.

The pull request description should be concise and accurately describe the *what* and *why* of your changes.

#### .gitignore contributions

We do not currently accept contributions to add editor specific additions to the root .gitignore. We urge contributors to make a global .gitignore file with their rulesets they may want to add instead. A global .gitignore file can be set like so:

```bash
git config --global core.excludesfile ~/.gitignore
```

#### Formatting contributions

Make sure your contributions are consistent with the rest of the project's formatting. You can do this using our Makefile:

```bash
make fmt
```

#### Applying license header to new files

If you submit a contribution that adds a new file, please add the license header. You can do this using our Makefile:

```bash
make update-licenses
```

## New to open source?

### How do I pick something to work on?

Take a look at the `good first issue` label in the [containerization](https://github.com/apple/containerization/contribute) or [container](https://github.com/apple/container/contribute) project. 
Before you start working on an issue:
* Check the comments, assignees, and any references to pull requests — make sure nobody else is actively working on it, or awaiting help or review.
* If someone is assigned to the issue or volunteered to work on it, and there are no signs of progress or activity over at least the past month, don't hesitate to check in with them
* Leave a comment that you have started working on it.

### Getting help

Don't be afraid to ask for help! When asking for help, provide as much information as possible, while highlighting anything you think may be important. Refer to the [MAINTAINERS.txt](MAINTAINERS.txt) file for the appropriate people to ping.

### I didn't get a response from someone. What should I do?

It's possible that you ask someone a question in an issue/pull request and you don't get a response as quickly as you'd like. If you don't get a response within a week, it's okay to politely ping them using an `@` mention. If you don't get a response for 2-3 weeks in a row, please ping someone else.

### I can't finish the contribution I started. 

Sometimes an issue ends up bigger, harder, or more time-consuming than expected — **and that’s completely fine.** Be sure to comment on the issue saying you’re stepping away, so that someone else is able to pick it up.

## AI contribution guidelines

We welcome thoughtful use of AI tools in your contributions to this repository. We ask that you adhere to these rules in order to preserve the project's integrity, clarity, and quality, and to respect maintainer bandwidth:

* You should be able to explain and justify every line of code or documentation that was generated or assisted by AI. Your submission should reflect your own understanding and intent.
* Use AI to augment, not totally replace, your reasoning or familiarity, especially for non-trivial parts of the system. 
* Avoid dumping AI-generated walls of text that you cannot explain. Low-effort, unexplained submissions will be deprioritized to protect maintainer bandwidth.

AI tools should be used to **enhance, not replace** the human elements that make OSS special: learning, collaboration, and community growth.

## Code of conduct

To clarify of what is expected of our contributors and community members, the Containerization team has adopted the code of conduct defined by the Contributor Covenant. This document is used across many open source communities and articulates our values well. For more detail, please read the [Code of Conduct](https://github.com/apple/.github/blob/main/CODE_OF_CONDUCT.md "Code of Conduct").


================================================
FILE: LICENSE
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

================================================
FILE: MAINTAINERS.txt
================================================
This file contains a list of maintainers and past maintainers who have made meaningful changes to this repository.

### Maintainers

Aditya Ramani (adityaramani)
AJ Emory (ajemory)
Danny Canter (dcantah)
Dmitry Kovba (dkovba)
Eric Ernst (egernst)
John Logan (jglogan)
Kathryn Baldauf (katiewasnothere)
Madhu Venugopal (mavenugo)
Michael Crosby (crosbymichael)
Raj Aryan Singh (realrajaryan)
Sidhartha Mani (wlan0)
Yibo Zhuang (yibozhuang)


### Emeritus maintainers

Agam Dua (agamdua)
Evan Hazlett (ehazlett)
Gilbert Song (gilbert88)
Hugh Bussell (hughbussell)
Tanweer Noor (tanweernoor)
Ximena Perez Diaz (ximenanperez)


================================================
FILE: Makefile
================================================
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Build configuration variables
BUILD_CONFIGURATION ?= debug
WARNINGS_AS_ERRORS ?= true
SWIFT_CONFIGURATION := $(if $(filter-out false,$(WARNINGS_AS_ERRORS)),-Xswiftc -warnings-as-errors) --disable-automatic-resolution

# Commonly used locations
SWIFT := "/usr/bin/swift"
ROOT_DIR := $(shell git rev-parse --show-toplevel)
BUILD_BIN_DIR = $(shell $(SWIFT) build -c $(BUILD_CONFIGURATION) --show-bin-path)
COV_DATA_DIR = $(shell $(SWIFT) test --show-coverage-path | xargs dirname)
COV_REPORT_FILE = $(ROOT_DIR)/code-coverage-report

# Variables for libarchive integration
LIBARCHIVE_UPSTREAM_REPO := https://github.com/libarchive/libarchive
LIBARCHIVE_UPSTREAM_VERSION := v3.7.7
LIBARCHIVE_LOCAL_DIR := workdir/libarchive

KATA_BINARY_PACKAGE := https://github.com/kata-containers/kata-containers/releases/download/3.17.0/kata-static-3.17.0-arm64.tar.xz

include Protobuf.Makefile
.DEFAULT_GOAL := all

.PHONY: all
all: containerization
all: init

.PHONY: release
release: BUILD_CONFIGURATION = release
release: all

.PHONY: containerization
containerization:
	@echo Building containerization binaries...
	@$(SWIFT) --version
	@$(SWIFT) build -c $(BUILD_CONFIGURATION) $(SWIFT_CONFIGURATION)

	@echo Copying containerization binaries...
	@mkdir -p bin
	@install "$(BUILD_BIN_DIR)/cctl" ./bin/
	@install "$(BUILD_BIN_DIR)/containerization-integration" ./bin/

	@echo Signing containerization binaries...
	@codesign --force --sign - --timestamp=none --entitlements=signing/vz.entitlements bin/cctl
	@codesign --force --sign - --timestamp=none --entitlements=signing/vz.entitlements bin/containerization-integration

.PHONY: init
init: containerization vminitd
	@echo Creating init.ext4...
	@rm -f bin/init.rootfs.tar.gz bin/init.block
	@./bin/cctl rootfs create \
		--vminitd vminitd/bin/vminitd \
		--vmexec vminitd/bin/vmexec \
		--label org.opencontainers.image.source=https://github.com/apple/containerization \
		--image vminit:latest \
		bin/init.rootfs.tar.gz

.PHONY: cross-prep
cross-prep:
	@"$(MAKE)" -C vminitd cross-prep

.PHONY: vminitd
vminitd:
	@mkdir -p ./bin
	@"$(MAKE)" -C vminitd BUILD_CONFIGURATION=$(BUILD_CONFIGURATION) WARNINGS_AS_ERRORS=$(WARNINGS_AS_ERRORS)

.PHONY: update-libarchive-source
update-libarchive-source:
	@echo Updating the libarchive source files...
	@git clone $(LIBARCHIVE_UPSTREAM_REPO) --depth 1 --branch $(LIBARCHIVE_UPSTREAM_VERSION) "$(LIBARCHIVE_LOCAL_DIR)"
	@cp "$(LIBARCHIVE_LOCAL_DIR)/libarchive/archive_entry.h" Sources/ContainerizationArchive/CArchive/include
	@cp "$(LIBARCHIVE_LOCAL_DIR)/libarchive/archive.h" Sources/ContainerizationArchive/CArchive/include
	@cp "$(LIBARCHIVE_LOCAL_DIR)/COPYING" Sources/ContainerizationArchive/CArchive/COPYING
	@rm -rf "$(LIBARCHIVE_LOCAL_DIR)"

.PHONY: test
test:
	@echo Testing all test targets...
	@$(SWIFT) test --enable-code-coverage $(SWIFT_CONFIGURATION)

.PHONY: coverage
coverage: test
	@echo Generating code coverage report...
	@xcrun llvm-cov show --compilation-dir=`pwd` \
		-instr-profile=$(COV_DATA_DIR)/default.profdata \
		--ignore-filename-regex=".build/" \
		--ignore-filename-regex=".pb.swift" \
		--ignore-filename-regex=".proto" \
		--ignore-filename-regex=".grpc.swift" \
		$(BUILD_BIN_DIR)/containerizationPackageTests.xctest/Contents/MacOS/containerizationPackageTests > $(COV_REPORT_FILE)
	@echo Code coverage report generated: $(COV_REPORT_FILE)

.PHONY: integration
integration:
ifeq (,$(wildcard bin/vmlinux))
	@echo No bin/vmlinux kernel found. See fetch-default-kernel target.
	@exit 1
endif
	@echo Running the integration tests...
	@./bin/containerization-integration

.PHONY: fetch-default-kernel
fetch-default-kernel:
	@mkdir -p .local/ bin/
ifeq (,$(wildcard .local/kata.tar.gz))
	@curl -SsL -o .local/kata.tar.gz ${KATA_BINARY_PACKAGE}
endif
ifeq (,$(wildcard .local/vmlinux))
	@tar -zxf .local/kata.tar.gz -C .local/ --strip-components=1
	@cp -L .local/opt/kata/share/kata-containers/vmlinux.container .local/vmlinux
endif
ifeq (,$(wildcard bin/vmlinux))
	@cp .local/vmlinux bin/vmlinux
endif

.PHONY: check
check: swift-fmt-check check-licenses

.PHONY: fmt
fmt: swift-fmt update-licenses

.PHONY: swift-fmt
SWIFT_SRC = $(shell find . -type f -name '*.swift' -not -path "*/.*" -not -path "*.pb.swift" -not -path "*.grpc.swift" -not -path "*/checkouts/*")
swift-fmt:
	@echo Applying the standard code formatting...
	@$(SWIFT) format --recursive --configuration .swift-format -i $(SWIFT_SRC)

swift-fmt-check:
	   @echo Applying the standard code formatting...
	   @$(SWIFT) format lint --recursive --strict --configuration .swift-format-nolint $(SWIFT_SRC)

.PHONY: update-licenses
update-licenses:
	@echo Updating license headers...
	@./scripts/ensure-hawkeye-exists.sh
	@.local/bin/hawkeye format --fail-if-unknown --fail-if-updated false

.PHONY: check-licenses
check-licenses:
	@echo Checking license headers existence in source files...
	@./scripts/ensure-hawkeye-exists.sh
	@.local/bin/hawkeye check --fail-if-unknown

.PHONY: pre-commit
pre-commit:
	   cp Scripts/pre-commit.fmt .git/hooks
	   touch .git/hooks/pre-commit
	   cat .git/hooks/pre-commit | grep -v 'hooks/pre-commit\.fmt' > /tmp/pre-commit.new || true
	   echo 'PRECOMMIT_NOFMT=$${PRECOMMIT_NOFMT} $$(git rev-parse --show-toplevel)/.git/hooks/pre-commit.fmt' >> /tmp/pre-commit.new
	   mv /tmp/pre-commit.new .git/hooks/pre-commit
	   chmod +x .git/hooks/pre-commit

.PHONY: serve-docs
serve-docs:
	@echo 'to browse: open http://127.0.0.1:8000/containerization/documentation/'
	@rm -rf _serve
	@mkdir -p _serve
	@cp -a _site _serve/containerization
	@python3 -m http.server --bind 127.0.0.1 --directory ./_serve

.PHONY: docs
docs:
	@echo Updating API documentation...
	@rm -rf _site
	@scripts/make-docs.sh _site containerization

.PHONY: cleancontent
cleancontent:
	@echo Cleaning the content...
	@rm -rf ~/Library/Application\ Support/com.apple.containerization

.PHONY: clean
clean:
	@echo Cleaning build files...
	@rm -rf bin/
	@rm -rf _site/
	@rm -rf _serve/
	@rm -f $(COV_REPORT_FILE)
	@$(SWIFT) package clean
	@"$(MAKE)" -C vminitd clean


================================================
FILE: Package.resolved
================================================
{
  "originHash" : "8b51a9ec068537ab57ce9b8034b5b84a02a4697e4a6be491954e5fbda7e5783b",
  "pins" : [
    {
      "identity" : "async-http-client",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/swift-server/async-http-client.git",
      "state" : {
        "revision" : "60235983163d040f343a489f7e2e77c1918a8bd9",
        "version" : "1.26.1"
      }
    },
    {
      "identity" : "grpc-swift",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/grpc/grpc-swift.git",
      "state" : {
        "revision" : "a56a157218877ef3e9625f7e1f7b2cb7e46ead1b",
        "version" : "1.26.1"
      }
    },
    {
      "identity" : "swift-algorithms",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-algorithms.git",
      "state" : {
        "revision" : "87e50f483c54e6efd60e885f7f5aa946cee68023",
        "version" : "1.2.1"
      }
    },
    {
      "identity" : "swift-argument-parser",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-argument-parser.git",
      "state" : {
        "revision" : "011f0c765fb46d9cac61bca19be0527e99c98c8b",
        "version" : "1.5.1"
      }
    },
    {
      "identity" : "swift-asn1",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-asn1.git",
      "state" : {
        "revision" : "a54383ada6cecde007d374f58f864e29370ba5c3",
        "version" : "1.3.2"
      }
    },
    {
      "identity" : "swift-async-algorithms",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-async-algorithms.git",
      "state" : {
        "revision" : "042e1c4d9d19748c9c228f8d4ebc97bb1e339b0b",
        "version" : "1.0.4"
      }
    },
    {
      "identity" : "swift-atomics",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-atomics.git",
      "state" : {
        "revision" : "cd142fd2f64be2100422d658e7411e39489da985",
        "version" : "1.2.0"
      }
    },
    {
      "identity" : "swift-certificates",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-certificates.git",
      "state" : {
        "revision" : "999fd70c7803da89f3904d635a6815a2a7cd7585",
        "version" : "1.10.0"
      }
    },
    {
      "identity" : "swift-collections",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-collections.git",
      "state" : {
        "revision" : "c1805596154bb3a265fd91b8ac0c4433b4348fb0",
        "version" : "1.2.0"
      }
    },
    {
      "identity" : "swift-crypto",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-crypto.git",
      "state" : {
        "revision" : "e8d6eba1fef23ae5b359c46b03f7d94be2f41fed",
        "version" : "3.12.3"
      }
    },
    {
      "identity" : "swift-docc-plugin",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/swiftlang/swift-docc-plugin",
      "state" : {
        "revision" : "d1691545d53581400b1de9b0472d45eb25c19fed",
        "version" : "1.4.4"
      }
    },
    {
      "identity" : "swift-docc-symbolkit",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/swiftlang/swift-docc-symbolkit",
      "state" : {
        "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
        "version" : "1.0.0"
      }
    },
    {
      "identity" : "swift-http-structured-headers",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-http-structured-headers.git",
      "state" : {
        "revision" : "db6eea3692638a65e2124990155cd220c2915903",
        "version" : "1.3.0"
      }
    },
    {
      "identity" : "swift-http-types",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-http-types.git",
      "state" : {
        "revision" : "a0a57e949a8903563aba4615869310c0ebf14c03",
        "version" : "1.4.0"
      }
    },
    {
      "identity" : "swift-log",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-log.git",
      "state" : {
        "revision" : "3d8596ed08bd13520157f0355e35caed215ffbfa",
        "version" : "1.6.3"
      }
    },
    {
      "identity" : "swift-nio",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio.git",
      "state" : {
        "revision" : "34d486b01cd891297ac615e40d5999536a1e138d",
        "version" : "2.83.0"
      }
    },
    {
      "identity" : "swift-nio-extras",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio-extras.git",
      "state" : {
        "revision" : "145db1962f4f33a4ea07a32e751d5217602eea29",
        "version" : "1.28.0"
      }
    },
    {
      "identity" : "swift-nio-http2",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio-http2.git",
      "state" : {
        "revision" : "4281466512f63d1bd530e33f4aa6993ee7864be0",
        "version" : "1.36.0"
      }
    },
    {
      "identity" : "swift-nio-ssl",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio-ssl.git",
      "state" : {
        "revision" : "173cc69a058623525a58ae6710e2f5727c663793",
        "version" : "2.36.0"
      }
    },
    {
      "identity" : "swift-nio-transport-services",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio-transport-services.git",
      "state" : {
        "revision" : "cd1e89816d345d2523b11c55654570acd5cd4c56",
        "version" : "1.24.0"
      }
    },
    {
      "identity" : "swift-numerics",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-numerics.git",
      "state" : {
        "revision" : "e0ec0f5f3af6f3e4d5e7a19d2af26b481acb6ba8",
        "version" : "1.0.3"
      }
    },
    {
      "identity" : "swift-protobuf",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-protobuf.git",
      "state" : {
        "revision" : "102a647b573f60f73afdce5613a51d71349fe507",
        "version" : "1.30.0"
      }
    },
    {
      "identity" : "swift-service-lifecycle",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/swift-server/swift-service-lifecycle.git",
      "state" : {
        "revision" : "e7187309187695115033536e8fc9b2eb87fd956d",
        "version" : "2.8.0"
      }
    },
    {
      "identity" : "swift-system",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-system.git",
      "state" : {
        "revision" : "395a77f0aa927f0ff73941d7ac35f2b46d47c9db",
        "version" : "1.6.3"
      }
    },
    {
      "identity" : "zstd",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/facebook/zstd.git",
      "state" : {
        "revision" : "f8745da6ff1ad1e7bab384bd1f9d742439278e99",
        "version" : "1.5.7"
      }
    }
  ],
  "version" : 3
}


================================================
FILE: Package.swift
================================================
// swift-tools-version: 6.2
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

// The swift-tools-version declares the minimum version of Swift required to build this package.

import CompilerPluginSupport
import Foundation
import PackageDescription

let package = Package(
    name: "containerization",
    platforms: [.macOS("15")],
    products: [
        .library(name: "Containerization", targets: ["Containerization", "ContainerizationError"]),
        .library(name: "ContainerizationEXT4", targets: ["ContainerizationEXT4"]),
        .library(name: "ContainerizationOCI", targets: ["ContainerizationOCI"]),
        .library(name: "ContainerizationNetlink", targets: ["ContainerizationNetlink"]),
        .library(name: "ContainerizationIO", targets: ["ContainerizationIO"]),
        .library(name: "ContainerizationOS", targets: ["ContainerizationOS"]),
        .library(name: "ContainerizationExtras", targets: ["ContainerizationExtras"]),
        .library(name: "ContainerizationArchive", targets: ["ContainerizationArchive"]),
        .executable(name: "cctl", targets: ["cctl"]),
    ],
    dependencies: [
        .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
        .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.3.0"),
        .package(url: "https://github.com/apple/swift-collections.git", from: "1.1.4"),
        .package(url: "https://github.com/apple/swift-crypto.git", from: "3.0.0"),
        .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.26.0"),
        .package(url: "https://github.com/apple/swift-protobuf.git", from: "1.29.0"),
        .package(url: "https://github.com/apple/swift-nio.git", from: "2.80.0"),
        .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.20.1"),
        .package(url: "https://github.com/apple/swift-system.git", from: "1.4.0"),
        .package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.1.0"),
        .package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.36.0"),
        .package(url: "https://github.com/facebook/zstd.git", exact: "1.5.7"),
    ],
    targets: [
        .target(
            name: "ContainerizationError"
        ),
        .target(
            name: "Containerization",
            dependencies: [
                .product(name: "Logging", package: "swift-log"),
                .product(name: "GRPC", package: "grpc-swift"),
                .product(name: "SystemPackage", package: "swift-system"),
                .product(name: "_NIOFileSystem", package: "swift-nio"),
                "ContainerizationArchive",
                "ContainerizationOCI",
                "ContainerizationOS",
                "ContainerizationIO",
                "ContainerizationExtras",
                .target(name: "ContainerizationEXT4", condition: .when(platforms: [.macOS])),
            ],
            exclude: [
                "../Containerization/SandboxContext/SandboxContext.proto"
            ]
        ),
        .executableTarget(
            name: "cctl",
            dependencies: [
                .product(name: "Logging", package: "swift-log"),
                .product(name: "ArgumentParser", package: "swift-argument-parser"),
                "Containerization",
                "ContainerizationArchive",
                "ContainerizationEXT4",
                "ContainerizationExtras",
                "ContainerizationOCI",
                "ContainerizationOS",
            ]
        ),
        .executableTarget(
            name: "containerization-integration",
            dependencies: [
                .product(name: "Logging", package: "swift-log"),
                .product(name: "ArgumentParser", package: "swift-argument-parser"),
                "Containerization",
            ],
            path: "Sources/Integration"
        ),
        .testTarget(
            name: "ContainerizationUnitTests",
            dependencies: ["Containerization"],
            path: "Tests/ContainerizationTests",
            resources: [
                .copy("ImageTests/Resources/scratch.tar"),
                .copy("ImageTests/Resources/scratch_no_annotations.tar"),
            ]
        ),
        .target(
            name: "ContainerizationEXT4",
            dependencies: [
                .target(name: "ContainerizationArchive", condition: .when(platforms: [.macOS])),
                .product(name: "SystemPackage", package: "swift-system"),
                "ContainerizationOS",
            ],
            path: "Sources/ContainerizationEXT4",
            exclude: [
                "README.md"
            ]
        ),
        .testTarget(
            name: "ContainerizationEXT4Tests",
            dependencies: [
                "ContainerizationEXT4",
                "ContainerizationArchive",
            ],
            resources: [
                .copy(
                    "Resources/content/blobs/sha256/ad59e9f71edceca7b1ac7c642410858489b743c97233b0a26a5e2098b1443762"),  // index
                .copy(
                    "Resources/content/blobs/sha256/48a06049d3738991b011ca8b12473d712b7c40666a1462118dae3c403676afc2"),  // manifest
                .copy(
                    "Resources/content/blobs/sha256/8e2eb240a6cd7be1a0d308125afe0060b020e89275ced2e729eda7d4eeff62a2"),  // config
                .copy(
                    "Resources/content/blobs/sha256/c6b39de5b33961661dc939b997cc1d30cda01e38005a6c6625fd9c7e748bab44"),  // layer 1
                .copy(
                    "Resources/content/blobs/sha256/4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1"),  // layer 2
            ]
        ),
        .target(
            name: "ContainerizationArchive",
            dependencies: [
                .product(name: "SystemPackage", package: "swift-system"),
                "CArchive",
                "ContainerizationExtras",
                "ContainerizationOS",
            ],
            exclude: [
                "CArchive"
            ]
        ),
        .testTarget(
            name: "ContainerizationArchiveTests",
            dependencies: [
                "ContainerizationArchive"
            ],
            resources: [
                .copy("Resources/test.tar.zst")
            ]
        ),
        .target(
            name: "CArchive",
            dependencies: [
                .product(name: "libzstd", package: "zstd")
            ],
            path: "Sources/ContainerizationArchive/CArchive",
            sources: [
                "archive_swift_bridge.c"
            ],
            cSettings: [
                .define(
                    "PLATFORM_CONFIG_H", to: "\"config_darwin.h\"",
                    .when(platforms: [.iOS, .macOS, .macCatalyst, .watchOS, .driverKit, .tvOS])),
                .define("PLATFORM_CONFIG_H", to: "\"config_linux.h\"", .when(platforms: [.linux])),
                .unsafeFlags(["-fno-modules"]),
            ],
            linkerSettings: [
                .linkedLibrary("z"),
                .linkedLibrary("bz2"),
                .linkedLibrary("lzma"),
                .linkedLibrary("archive"),
                .linkedLibrary("iconv", .when(platforms: [.macOS])),
                .linkedLibrary("crypto", .when(platforms: [.linux])),
            ]
        ),
        .target(
            name: "ContainerizationOCI",
            dependencies: [
                .product(name: "AsyncHTTPClient", package: "async-http-client"),
                .product(name: "Crypto", package: "swift-crypto"),
                .product(name: "Logging", package: "swift-log"),
                .product(name: "_NIOFileSystem", package: "swift-nio"),
                "ContainerizationError",
                "ContainerizationOS",
                "ContainerizationExtras",
            ]
        ),
        .testTarget(
            name: "ContainerizationOCITests",
            dependencies: [
                "ContainerizationOCI",
                "Containerization",
                "ContainerizationIO",
                .product(name: "NIO", package: "swift-nio"),
                .product(name: "Crypto", package: "swift-crypto"),
            ]
        ),
        .target(
            name: "ContainerizationNetlink",
            dependencies: [
                .product(name: "Logging", package: "swift-log"),
                "ContainerizationOS",
                "ContainerizationExtras",
            ]
        ),
        .testTarget(
            name: "ContainerizationNetlinkTests",
            dependencies: [
                "ContainerizationNetlink"
            ]
        ),
        .target(
            name: "ContainerizationOS",
            dependencies: [
                .product(name: "Logging", package: "swift-log"),
                .product(name: "SystemPackage", package: "swift-system"),
                "CShim",
                "ContainerizationError",
            ],
            exclude: [
                "../ContainerizationOS/README.md"
            ]
        ),
        .testTarget(
            name: "ContainerizationOSTests",
            dependencies: [
                .product(name: "SystemPackage", package: "swift-system"),
                "ContainerizationOS",
                "ContainerizationExtras",
            ]
        ),
        .target(
            name: "ContainerizationIO",
            dependencies: [
                "ContainerizationOS",
                .product(name: "NIO", package: "swift-nio"),
                .product(name: "NIOCore", package: "swift-nio"),
                .product(name: "NIOFoundationCompat", package: "swift-nio"),
            ]
        ),
        .target(
            name: "ContainerizationExtras",
            dependencies: [
                "ContainerizationError",
                .product(name: "Collections", package: "swift-collections"),
                .product(name: "Logging", package: "swift-log"),
                .product(name: "NIOSSL", package: "swift-nio-ssl"),

            ]
        ),
        .testTarget(
            name: "ContainerizationExtrasTests",
            dependencies: [
                "ContainerizationExtras",
                "CShim",
            ]
        ),
        .target(
            name: "CShim"
        ),
    ]
)


================================================
FILE: Protobuf.Makefile
================================================
# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

LOCAL_DIR := $(ROOT_DIR)/.local
LOCAL_BIN_DIR := $(LOCAL_DIR)/bin

# Versions
PROTOC_VERSION := 26.1

# Protoc binary installation
PROTOC_ZIP := protoc-$(PROTOC_VERSION)-osx-universal_binary.zip
PROTOC := $(LOCAL_BIN_DIR)/protoc@$(PROTOC_VERSION)/protoc
$(PROTOC):
	@echo Downloading protocol buffers...
	@mkdir -p $(LOCAL_DIR)
	@curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/$(PROTOC_ZIP)
	@mkdir -p $(dir $@)
	@unzip -jo $(PROTOC_ZIP) bin/protoc -d $(dir $@)
	@unzip -o $(PROTOC_ZIP) 'include/*' -d $(dir $@)
	@rm -f $(PROTOC_ZIP)

.PHONY: protoc-gen-swift
protoc-gen-swift:
	@$(SWIFT) build --product protoc-gen-swift
	@$(SWIFT) build --product protoc-gen-grpc-swift

.PHONY: protos
protos: $(PROTOC) protoc-gen-swift
	@echo Generating protocol buffers source code...
	@$(PROTOC) Sources/Containerization/SandboxContext/SandboxContext.proto \
		--plugin=protoc-gen-grpc-swift=$(BUILD_BIN_DIR)/protoc-gen-grpc-swift \
		--plugin=protoc-gen-swift=$(BUILD_BIN_DIR)/protoc-gen-swift \
		--proto_path=Sources/Containerization/SandboxContext \
		--grpc-swift_out="Sources/Containerization/SandboxContext" \
		--grpc-swift_opt=Visibility=Public \
		--swift_out="Sources/Containerization/SandboxContext" \
		--swift_opt=Visibility=Public \
		-I.
	@"$(MAKE)" update-licenses

.PHONY: clean-proto-tools
clean-proto-tools:
	@echo Cleaning proto tools...
	@rm -rf $(LOCAL_DIR)/bin/protoc*


================================================
FILE: README.md
================================================
# Containerization

The Containerization package allows applications to use Linux containers.
Containerization is written in [Swift](https://www.swift.org) and uses [Virtualization.framework](https://developer.apple.com/documentation/virtualization) on Apple silicon.

> **Looking for command line binaries for running containers?**\
> They are available in the dedicated [apple/container](https://github.com/apple/container) repository.

Containerization provides APIs to:

- [Manage OCI images](./Sources/ContainerizationOCI/).
- [Interact with remote registries](./Sources/ContainerizationOCI/Client/).
- [Create and populate ext4 file systems](./Sources/ContainerizationEXT4/).
- [Interact with the Netlink socket family](./Sources/ContainerizationNetlink/).
- [Create an optimized Linux kernel for fast boot times](./kernel/).
- [Spawn lightweight virtual machines and manage the runtime environment](./Sources/Containerization/LinuxContainer.swift).
- [Spawn and interact with containerized processes](./Sources/Containerization/LinuxProcess.swift).
- Use Rosetta 2 for running linux/amd64 containers on Apple silicon.

Please view the [API documentation](https://apple.github.io/containerization/documentation/) for information on the Swift packages that Containerization provides.

## Design

Containerization executes each Linux container inside of its own lightweight virtual machine. Clients can create dedicated IP addresses for every container to remove the need for individual port forwarding. Containers achieve sub-second start times using an optimized [Linux kernel configuration](/kernel) and a minimal root filesystem with a lightweight init system.

[vminitd](/vminitd) is a small init system, which is a subproject within Containerization.
`vminitd` is spawned as the initial process inside of the virtual machine and provides a GRPC API over vsock.
The API allows the runtime environment to be configured and containerized processes to be launched.
`vminitd` provides I/O, signals, and events to the calling process when a process is run.

## Requirements

To build the Containerization package, you need:

- Mac with Apple silicon
- macOS 26
- Xcode 26

Older versions of macOS are not supported. 

## Example Usage

For examples of how to use some of the libraries surface, the cctl executable is a good start. This app is a useful playground for exploring the API. It contains commands that exercise some of the core functionality of the various products, such as:

1. [Manipulating OCI images](./Sources/cctl/ImageCommand.swift)
2. [Logging in to container registries](./Sources/cctl/LoginCommand.swift)
3. [Creating root filesystem blocks](./Sources/cctl/RootfsCommand.swift)
4. [Running simple Linux containers](./Sources/cctl/RunCommand.swift)

## Linux kernel

A Linux kernel is required for spawning lightweight virtual machines on macOS.
Containerization provides an optimized kernel configuration located in the [kernel](./kernel) directory.

This directory includes a containerized build environment to easily compile a kernel for use with Containerization.

The kernel configuration is a minimal set of features to support fast start times and a light weight environment.

While this configuration will work for the majority of workloads we understand that some will need extra features.
To solve this Containerization provides first class APIs to use different kernel configurations and versions on a per container basis.
This enables containers to be developed and validated across different kernel versions.

See the [README](/kernel/README.md) in the kernel directory for instructions on how to compile the optimized kernel.

### Kernel Support

Containerization allows user provided kernels but tests functionality starting with kernel version `6.14.9`.

### Pre-built Kernel

If you wish to consume a pre-built kernel, make sure it has `VIRTIO` drivers compiled into the kernel (not merely as modules).

The [Kata Containers](https://github.com/kata-containers/kata-containers) project provides a Linux kernel that is optimized for containers, with all required configuration options enabled. The [releases](https://github.com/kata-containers/kata-containers/releases/) page contains downloadable artifacts, and the image itself (`vmlinux.container`) can be found in the `/opt/kata/share/kata-containers/` directory. 

## Prepare to build package

Install the recommended version of Xcode.

Set the active developer directory to the installed Xcode (replace `<PATH_TO_XCODE>`):
```bash
sudo xcode-select -s <PATH_TO_XCODE>
``` 

Install [Swiftly](https://github.com/swiftlang/swiftly), [Swift](https://www.swift.org), and [Static Linux SDK](https://www.swift.org/documentation/articles/static-linux-getting-started.html):

```bash
make cross-prep
```

If you use a custom terminal application, you may need to move this command from `.zprofile` to `.zshrc` (replace `<USERNAME>`):

```bash
# Added by swiftly
. "/Users/<USERNAME>/.swiftly/env.sh"
```

Restart the terminal application. Ensure this command returns `/Users/<USERNAME>/.swiftly/bin/swift` (replace `<USERNAME>`):

```bash
which swift
```

If you've installed or used a Static Linux SDK previously, you may need to remove older SDK versions from the system (replace `<SDK-ID>`):

```bash
swift sdk list
swift sdk remove <SDK-ID>
```

## Build the package

Build Containerization from sources:

```bash
make all
```

## Test the package

After building, run basic and integration tests:

```bash
make test integration
```

A kernel is required to run integration tests.
If you do not have a kernel locally for use a default kernel can be fetched using the `make fetch-default-kernel` target.

Fetching the default kernel only needs to happen after an initial build or after a `make clean`.

```bash
make fetch-default-kernel
make all test integration
```

## Protobufs

Containerization depends on specific versions of `grpc-swift` and `swift-protobuf`. You can install them and re-generate RPC interfaces with:

```bash
make protos
```

## Building a kernel

If you'd like to build your own kernel please see the instructions in the [kernel directory](./kernel/README.md).

## Pre-commit hook

Run `make pre-commit` to install a pre-commit hook that ensures that your changes have correct formatting and license headers when you run `git commit`.

## Documentation

Generate the API documentation for local viewing with:

```bash
make docs
make serve-docs
```

Preview the documentation by running in another terminal:

```bash
open http://localhost:8000/containerization/documentation/
```

## Contributing

Contributions to Containerization are welcomed and encouraged. Please see [CONTRIBUTING.md](/CONTRIBUTING.md) for more information.

## Project Status

Version 0.1.0 is the first official release of Containerization. Earlier versions have no source stability guarantees.

Because the Containerization library is under active development, source stability is only guaranteed within minor versions (for example, between 0.1.1 and 0.1.2). If you don't want potentially source-breaking package updates, you can specify your package dependency using .upToNextMinorVersion(from: "0.1.0") instead.

Future minor versions of the package may introduce changes to these rules as needed.


================================================
FILE: SECURITY.md
================================================
# Security disclosure process

If you believe that you have discovered a security or privacy vulnerability in our open source software, please report it to us using the [GitHub private vulnerability feature](https://github.com/apple/containerization/security/advisories/new). Reports should include specific product and software version(s) that you believe are affected; a technical description of the behavior that you observed and the behavior that you expected; the steps required to reproduce the issue; and a proof of concept or exploit.

The project team will do their best to acknowledge receiving all security reports within 7 days of submission. This initial acknowledgment is neither acceptance nor rejection of your report. The project team may come back to you with further questions or invite you to collaborate while working through the details of your report.

Keep these additional guidelines in mind when submitting your report:

* Reports concerning known, publicly disclosed CVEs can be submitted as normal issues to this project.
* Output from automated security scans or fuzzers MUST include additional context demonstrating the vulnerability with a proof of concept or working exploit.
* Application crashes due to malformed inputs are typically not treated as security vulnerabilities, unless they are shown to also impact other processes on the system.

While we welcome reports for open source software projects, they are not eligible for Apple Security Bounties.


================================================
FILE: Sources/CShim/capability.c
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if defined(__linux__)

#include <sys/syscall.h>
#include <unistd.h>
#include "capability.h"

// Capability syscall wrappers
int CZ_capget(void *header, void *data) {
    return syscall(SYS_capget, header, data);
}

int CZ_capset(void *header, void *data) {
    return syscall(SYS_capset, header, data);
}

#endif


================================================
FILE: Sources/CShim/exec_command.c
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if defined(__linux__) || defined(__APPLE__)

#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#if defined(__linux__)
#include <sys/prctl.h>
#endif

#include "exec_command.h"

#ifndef SYS_close_range
#define SYS_close_range 436
#endif

#ifndef CLOSE_RANGE_CLOEXEC
#define CLOSE_RANGE_CLOEXEC 0x4
#endif

static int mark_cloexec(int fd) {
    int flags = fcntl(fd, F_GETFD);

    if (flags == -1) return flags;
    if (flags & FD_CLOEXEC) return 0;

    return fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
}

static int cloexec_from(int min_fd) {
#if defined(__linux__)
    // First try close_range.
    long ret = syscall(SYS_close_range, min_fd, ~0U, CLOSE_RANGE_CLOEXEC);
    if (ret == 0) {
      return 0;
    }
    const char* dirpath = "/proc/self/fd";
#elif defined(__APPLE__)
    const char* dirpath = "/dev/fd";
#endif
    DIR *dp = opendir(dirpath);
    if (!dp) return -1;

    int dp_fd = dirfd(dp);
    struct dirent *de;

    while ((de = readdir(dp))) {
      if (de->d_name[0] == '.') continue;

      char *end;
      long val = strtol(de->d_name, &end, 10);
      if (*end || val < 0 || val > INT_MAX) continue;

      int fd = (int)val;
      if (fd < min_fd || fd == dp_fd) continue;

      int ret = mark_cloexec(fd);
      if (ret != 0) {
        return ret;
      }
    }
    close(dp_fd);
    closedir(dp);
    return 0;
}

void exec_command_attrs_init(struct exec_command_attrs *attrs) {
  attrs->setpgid = 0;
  attrs->pgid = 0;
  attrs->setsid = 0;
  attrs->setctty = 0;
  attrs->ctty = 0;
  attrs->mask = 0;
  attrs->uid = -1;
  attrs->gid = -1;
  attrs->pdeathSignal = 0;
  attrs->setfgpgrp = 0;
}

static void child_handler(const int sync_pipes[2], const char *executable,
                          char *const args[], char *const environment[],
                          const int file_handles[], const int file_handle_count,
                          const char *cwd, const sigset_t old_mask,
                          const struct exec_command_attrs attrs) {
  int i = 0;
  int err = 0;
  int fd_index = 0;
  int fd_table[file_handle_count];
  struct rlimit limits = {0};
  int syncfd = sync_pipes[1];
  struct sigaction action = {0};

  // Closing our parent's side of the pipe
  if (close(sync_pipes[0]) < 0) {
    goto fail;
  }

  // Setup process group and foreground before clearing signal mask.
  if (attrs.setpgid) {
    if (setpgid(0, attrs.pgid) < 0) {
      goto fail;
    }
  }

  // Make the new process group the foreground process group so it can read from the TTY.
  if (attrs.setfgpgrp) {
    if (tcsetpgrp(STDIN_FILENO, getpgrp()) < 0) {
      if (errno != ENOTTY && errno != ENXIO) {
        goto fail;
      }
    }
  }

  // clear sighandlers
  action.sa_flags = 0;
  action.sa_handler = SIG_DFL;
  sigemptyset(&action.sa_mask);
  for (i = 0; i < NSIG; i++) {
    sigaction(i, &action, 0);
  }

  sigset_t local_mask;
  sigemptyset(&local_mask);
  if (pthread_sigmask(SIG_SETMASK, &local_mask, NULL) < 0) {
    goto fail;
  }

  // start shuffling fds.
  // look at all the file handles and find the highest one,
  // use that for our pipe,
  //
  // Then, we need to start dup2 the fds starting for the final process
  // at 0-n.
  // as an example we have this list of FDs that should be passed to the
  // process:
  //
  /*
   The index of this list is the final result that the new process expects.
   The values are open fds provided from the parent process.
   [0] == 12
   [1] == 7
   [2] == 9
   [3] == 0

   We also have a pipe to sync the child and parent so that adds an additional
   parameter to consider.

   So we start by finding the highest open fd in the list, then move our pipe to
   the next.

   i.e. fd12 is highest so move our pipe to fd13

   Now start moving all the fds above our pipe as we will need to start placing
   the fds in the child process into the right order. Make sure they are all
   marked cloexec.

   pipe == 13
   [0] == 12 dup2 14
   [1] == 7 dup2 15
   [2] == 9 dup2 16
   [3] == 0 dup2 17

   Now overwrite the fd table for the child with the current index.

   Make index == fd.

   pipe == 13
   [0] == 14 dup2 0
   [1] == 15 dup2 1
   [2] == 16 dup2 2
   [3] == 17 dup2 3

   Clear cloexec on this new fds.
   */

  // find the highest fd value in our list.
  for (i = 0; i < file_handle_count; i++) {
    if (file_handles[i] > fd_index) {
      fd_index = file_handles[i];
    }
    fd_table[i] = file_handles[i];
  }
  // now fd_index is == to the highest fd in our list of handles.
  // Increment it and set our pipe to it.
  fd_index++;

  if (syncfd != fd_index) {
    if (dup2(syncfd, fd_index) < 0) {
      goto fail;
    }
    if (close(syncfd) < 0) {
      goto fail;
    }
    syncfd = fd_index;
  }
  fd_index++;

  // make sure our syncfd retains its cloexec
  if (fcntl(syncfd, F_SETFD, FD_CLOEXEC) == -1) {
    goto fail;
  }

  // move the rest of the fds up above our index if they don't match the index.
  for (i = 0; i < file_handle_count; i++) {
    if (fd_table[i] == i) {
      continue;
    }
    if (dup2(fd_table[i], fd_index) < 0) {
      goto fail;
    }
    if (fcntl(fd_index, F_SETFD, FD_CLOEXEC) == -1) {
      goto fail;
    }
    fd_table[i] = fd_index;
    fd_index++;
  }

  // now create the child process's final fd table. where i == i
  for (i = 0; i < file_handle_count; i++) {
    if (fd_table[i] != i) {
      if (dup2(fd_table[i], i) < 0) {
        goto fail;
      }
    }
    // now fd[i] should == i
    // clear cloexec as this fd is where we want it.
    if (fcntl(i, F_SETFD, 0) == -1) {
      goto fail;
    }
  }

  if (attrs.setsid) {
    if (setsid() == -1) {
      goto fail;
    }
  }

  if (attrs.setctty) {
    if (ioctl(attrs.ctty, TIOCSCTTY, 0)) {
      goto fail;
    }
  }

#if defined(__linux__)
  // Set parent death signal if specified
  if (attrs.pdeathSignal != 0) {
    if (prctl(PR_SET_PDEATHSIG, attrs.pdeathSignal) != 0) {
      goto fail;
    }
  }
#endif

  // close exec everything outside of our child's fd_table.
  if (cloexec_from(file_handle_count) != 0) {
    goto fail;
  }

  // set gid
  if (attrs.gid != -1) {
    if (setgid(attrs.gid) != 0) {
      goto fail;
    }
  }

  // set uid
  if (attrs.uid != -1) {
    if (setreuid(attrs.uid, attrs.uid) != 0) {
      goto fail;
    }
  }

  if (cwd != NULL) {
    if (chdir(cwd)) {
      goto fail;
    }
  }

  execve(executable, args, environment);
fail:
  err = errno;
  if (err) {
    // send our error to the parent
    while (write(syncfd, &err, sizeof(err)) < 0)
      ;
  }
  exit(127);
}

int exec_command(pid_t *result, const char *executable, char *const args[],
                 char *const envp[], const int file_handles[],
                 const int file_handle_count, const char *working_directory,
                 struct exec_command_attrs *attrs) {
  pid_t pid = 0;
  int err = 0;
  int sync_pipe[2];
  sigset_t old_mask;

  sigset_t all;
  sigfillset(&all);

  if (pipe(sync_pipe)) {
    goto fail;
  }

  if (pthread_sigmask(SIG_SETMASK, &all, &old_mask) < 0) {
    goto fail;
  }

  pid = fork();
  if (pid == -1) {
    close(sync_pipe[0]);
    close(sync_pipe[1]);
    goto fail;
  }

  if (pid == 0) {
    // hand off to child
    child_handler(sync_pipe, executable, args, envp, file_handles,
                  file_handle_count, working_directory, old_mask, *attrs);
    exit(EXIT_FAILURE);
  }

  // handle parent operations
  if (close(sync_pipe[1]) < 0) {
    goto fail;
  }

  // sync with our child process
  err = 0;
  ssize_t size = read(sync_pipe[0], &err, sizeof(err));
  // -- we didn't get an errno back
  if (size != sizeof(err)) {
    // will be used as return result
    err = 0;
  } else {
    // we did get an errno back from the child process and our
    // err var is set to that errno
    // lets set our errno and then reap the process
    errno = err;
    int status = 0;
    waitpid(pid, &status, 0);
    // lets continue our journey below
  }

  if (close(sync_pipe[0]) < 0) {
    goto fail;
  }
  if (err) {
    goto fail;
  }

  (*result) = pid;
  err = 0;
fail:
  if (pthread_sigmask(SIG_SETMASK, &old_mask, 0) < 0) {
    printf("restoring signal mask: %s\n", strerror(errno));
  }
  if (err) {
    printf("exec_command execve: %s\n", strerror(err));
    return -1;
  }
  return 0;
}

#endif

================================================
FILE: Sources/CShim/include/capability.h
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __CAPABILITY_H
#define __CAPABILITY_H

#if defined(__linux__)

// Capability syscall wrappers
int CZ_capget(void *header, void *data);
int CZ_capset(void *header, void *data);

#endif

#endif


================================================
FILE: Sources/CShim/include/exec_command.h
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef exec_command_h
#define exec_command_h

#if defined(__linux__) || defined(__APPLE__)

#include <sys/types.h>
#include <unistd.h>

struct exec_command_attrs {
  int setpgid;
  /// parent group id
  pid_t pgid;
  /// set the controlling terminal
  int setctty;
  /// controlling terminal fd
  int ctty;
  /// set the process as session leader
  int setsid;
  /// set the process user id
  uid_t uid;
  /// set the process group id
  gid_t gid;
  /// signal mask for the child process
  int mask;
  /// parent death signal (Linux only, 0 to disable)
  int pdeathSignal;
  /// make the new process group the foreground process group
  int setfgpgrp;
};

void exec_command_attrs_init(struct exec_command_attrs *attrs);

/// spawn a new child process with the provided attrs
int exec_command(pid_t *result, const char *executable, char *const argv[],
                 char *const envp[], const int file_handles[],
                 const int file_handle_count, const char *working_directory,
                 struct exec_command_attrs *attrs);

#endif /* defined(__linux__) || defined(__APPLE__) */
#endif /* exec_command_h */


================================================
FILE: Sources/CShim/include/openat2.h
================================================
/*
 * Copyright © 2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __OPENAT2_H
#define __OPENAT2_H

#include <sys/types.h>

#ifndef RESOLVE_IN_ROOT
#define RESOLVE_IN_ROOT 0x10
#endif

struct cz_open_how {
  unsigned long long flags;
  unsigned long long mode;
  unsigned long long resolve;
};

/// openat2(2) wrapper. Musl does not provide openat2 so we invoke the syscall
/// directly. Requires Linux 5.6+.
int CZ_openat2(int dirfd, const char *pathname, struct cz_open_how *how,
               size_t size);

#endif


================================================
FILE: Sources/CShim/include/prctl.h
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __PRCTL_H
#define __PRCTL_H

#if defined(__linux__)

#include <sys/types.h>

// Capability management prctl wrappers
int CZ_prctl_set_keepcaps();
int CZ_prctl_clear_keepcaps();
int CZ_prctl_capbset_drop(unsigned int capability);
int CZ_prctl_cap_ambient_clear_all();
int CZ_prctl_cap_ambient_raise(unsigned int capability);

#endif

#endif


================================================
FILE: Sources/CShim/include/socket_helpers.h
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef socket_helpers_h
#define socket_helpers_h

#include <sys/socket.h>
#include <stdint.h>

// Helper functions to access CMSG macros from Swift
struct cmsghdr* CZ_CMSG_FIRSTHDR(struct msghdr *msg);
void* CZ_CMSG_DATA(struct cmsghdr *cmsg);
size_t CZ_CMSG_SPACE(size_t length);
size_t CZ_CMSG_LEN(size_t length);

#endif /* socket_helpers_h */


================================================
FILE: Sources/CShim/include/vsock.h
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//

#ifndef vsock_h
#define vsock_h

#include <sys/ioctl.h>

#ifdef __APPLE__
    #include <sys/vsock.h>
#else
    #include <sys/socket.h>
    #include <linux/vm_sockets.h>
#endif /* __APPLE__ */

extern const unsigned long VsockLocalCIDIoctl;

#endif /* vsock_h */


================================================
FILE: Sources/CShim/openat2.c
================================================
/*
 * Copyright © 2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if defined(__linux__)

#include <sys/syscall.h>
#include <unistd.h>

#include "openat2.h"

#ifndef SYS_openat2
#define SYS_openat2 437
#endif

int CZ_openat2(int dirfd, const char *pathname, struct cz_open_how *how,
               size_t size) {
  return syscall(SYS_openat2, dirfd, pathname, how, size);
}

#endif


================================================
FILE: Sources/CShim/prctl.c
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if defined(__linux__)

#include <sys/prctl.h>
#include "prctl.h"

// Set keep caps to preserve capabilities across setuid()
int CZ_prctl_set_keepcaps() {
    return prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
}

// Clear keep caps after user change
int CZ_prctl_clear_keepcaps() {
    return prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
}

// Drop capability from bounding set
int CZ_prctl_capbset_drop(unsigned int capability) {
    return prctl(PR_CAPBSET_DROP, capability, 0, 0, 0);
}

// Clear all ambient capabilities
int CZ_prctl_cap_ambient_clear_all() {
    return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
}

// Raise ambient capability
int CZ_prctl_cap_ambient_raise(unsigned int capability) {
    return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, capability, 0, 0);
}

#endif


================================================
FILE: Sources/CShim/socket_helpers.c
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "socket_helpers.h"

struct cmsghdr* CZ_CMSG_FIRSTHDR(struct msghdr *msg) {
    return CMSG_FIRSTHDR(msg);
}

void* CZ_CMSG_DATA(struct cmsghdr *cmsg) {
    return CMSG_DATA(cmsg);
}

size_t CZ_CMSG_SPACE(size_t length) {
    return CMSG_SPACE(length);
}

size_t CZ_CMSG_LEN(size_t length) {
    return CMSG_LEN(length);
}


================================================
FILE: Sources/CShim/vsock.c
================================================
/*
 * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "vsock.h"

const unsigned long VsockLocalCIDIoctl = IOCTL_VM_SOCKETS_GET_LOCAL_CID;


================================================
FILE: Sources/Containerization/AttachedFilesystem.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import ContainerizationExtras
import ContainerizationOCI

/// A filesystem that was attached and able to be mounted inside the runtime environment.
public struct AttachedFilesystem: Sendable {
    /// The type of the filesystem.
    public var type: String
    /// The path to the filesystem within a sandbox.
    public var source: String
    /// Destination when mounting the filesystem inside a sandbox.
    public var destination: String
    /// The options to use when mounting the filesystem.
    public var options: [String]

    #if os(macOS)
    public init(mount: Mount, allocator: any AddressAllocator<Character>) throws {
        switch mount.type {
        case "virtiofs":
            let name = try hashMountSource(source: mount.source)
            self.source = name
        case "ext4":
            let char = try allocator.allocate()
            self.source = "/dev/vd\(char)"
        default:
            self.source = mount.source
        }
        self.type = mount.type
        self.options = mount.options
        self.destination = mount.destination
    }
    #endif

    public init(type: String, source: String, destination: String, options: [String]) {
        self.type = type
        self.source = source
        self.destination = destination
        self.options = options
    }
}


================================================
FILE: Sources/Containerization/Container.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

/// The core protocol container implementations must implement.
public protocol Container {
    /// ID for the container.
    var id: String { get }
    /// The amount of cpus assigned to the container.
    var cpus: Int { get }
    /// The memory in bytes assigned to the container.
    var memoryInBytes: UInt64 { get }
    /// The network interfaces assigned to the container.
    var interfaces: [any Interface] { get }
}


================================================
FILE: Sources/Containerization/ContainerManager.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

#if os(macOS)

import ContainerizationError
import ContainerizationEXT4
import ContainerizationOCI
import ContainerizationOS
import Foundation
import ContainerizationExtras
import SystemPackage
import Virtualization

/// A manager for creating and running containers.
/// Supports container networking options.
public struct ContainerManager: Sendable {
    public let imageStore: ImageStore
    private let vmm: VirtualMachineManager
    private var network: Network?

    private var containerRoot: URL {
        self.imageStore.path.appendingPathComponent("containers")
    }

    /// Create a new manager with the provided kernel, initfs mount, image store
    /// and optional network implementation. This will use a Virtualization.framework
    /// backed VMM implicitly.
    public init(
        kernel: Kernel,
        initfs: Mount,
        imageStore: ImageStore,
        network: Network? = nil,
        rosetta: Bool = false,
        nestedVirtualization: Bool = false
    ) throws {
        self.imageStore = imageStore
        self.network = network
        try Self.createRootDirectory(path: self.imageStore.path)
        self.vmm = VZVirtualMachineManager(
            kernel: kernel,
            initialFilesystem: initfs,
            rosetta: rosetta,
            nestedVirtualization: nestedVirtualization
        )
    }

    /// Create a new manager with the provided kernel, initfs mount, root state
    /// directory and optional network implementation. This will use a Virtualization.framework
    /// backed VMM implicitly.
    public init(
        kernel: Kernel,
        initfs: Mount,
        root: URL? = nil,
        network: Network? = nil,
        rosetta: Bool = false,
        nestedVirtualization: Bool = false
    ) throws {
        if let root {
            self.imageStore = try ImageStore(path: root)
        } else {
            self.imageStore = ImageStore.default
        }
        self.network = network
        try Self.createRootDirectory(path: self.imageStore.path)
        self.vmm = VZVirtualMachineManager(
            kernel: kernel,
            initialFilesystem: initfs,
            rosetta: rosetta,
            nestedVirtualization: nestedVirtualization
        )
    }

    /// Create a new manager with the provided kernel, initfs reference, image store
    /// and optional network implementation. This will use a Virtualization.framework
    /// backed VMM implicitly.
    public init(
        kernel: Kernel,
        initfsReference: String,
        imageStore: ImageStore,
        network: Network? = nil,
        rosetta: Bool = false,
        nestedVirtualization: Bool = false
    ) async throws {
        self.imageStore = imageStore
        self.network = network
        try Self.createRootDirectory(path: self.imageStore.path)

        let initPath = self.imageStore.path.appendingPathComponent("initfs.ext4")
        let initImage = try await self.imageStore.getInitImage(reference: initfsReference)
        let initfs = try await {
            do {
                return try await initImage.initBlock(at: initPath, for: .linuxArm)
            } catch let err as ContainerizationError {
                guard err.code == .exists else {
                    throw err
                }
                return .block(
                    format: "ext4",
                    source: initPath.absolutePath(),
                    destination: "/",
                    options: ["ro"]
                )
            }
        }()

        self.vmm = VZVirtualMachineManager(
            kernel: kernel,
            initialFilesystem: initfs,
            rosetta: rosetta,
            nestedVirtualization: nestedVirtualization
        )
    }

    /// Create a new manager with the provided kernel and image reference for the initfs.
    /// This will use a Virtualization.framework backed VMM implicitly.
    public init(
        kernel: Kernel,
        initfsReference: String,
        root: URL? = nil,
        network: Network? = nil,
        rosetta: Bool = false,
        nestedVirtualization: Bool = false
    ) async throws {
        if let root {
            self.imageStore = try ImageStore(path: root)
        } else {
            self.imageStore = ImageStore.default
        }
        self.network = network
        try Self.createRootDirectory(path: self.imageStore.path)

        let initPath = self.imageStore.path.appendingPathComponent("initfs.ext4")
        let initImage = try await self.imageStore.getInitImage(reference: initfsReference)
        let initfs = try await {
            do {
                return try await initImage.initBlock(at: initPath, for: .linuxArm)
            } catch let err as ContainerizationError {
                guard err.code == .exists else {
                    throw err
                }
                return .block(
                    format: "ext4",
                    source: initPath.absolutePath(),
                    destination: "/",
                    options: ["ro"]
                )
            }
        }()

        self.vmm = VZVirtualMachineManager(
            kernel: kernel,
            initialFilesystem: initfs,
            rosetta: rosetta,
            nestedVirtualization: nestedVirtualization
        )
    }

    /// Create a new manager with the provided vmm and network.
    public init(
        vmm: any VirtualMachineManager,
        network: Network? = nil
    ) throws {
        self.imageStore = ImageStore.default
        try Self.createRootDirectory(path: self.imageStore.path)
        self.network = network
        self.vmm = vmm
    }

    private static func createRootDirectory(path: URL) throws {
        try FileManager.default.createDirectory(
            at: path.appendingPathComponent("containers"),
            withIntermediateDirectories: true
        )
    }

    /// Returns a new container from the provided image reference.
    /// - Parameters:
    ///   - id: The container ID.
    ///   - reference: The image reference.
    ///   - rootfsSizeInBytes: The size of the root filesystem in bytes. Defaults to 8 GiB.
    ///   - writableLayerSizeInBytes: Optional size for a separate writable layer. When provided,
    ///     the rootfs becomes read-only and an overlayfs is used with a separate writable layer of this size.
    ///   - readOnly: Whether to mount the root filesystem as read-only.
    ///   - networking: Whether to create a network interface for this container. Defaults to `true`.
    ///     When `false`, no network resources are allocated and `releaseNetwork`/`delete` remain safe to call.
    public mutating func create(
        _ id: String,
        reference: String,
        rootfsSizeInBytes: UInt64 = 8.gib(),
        writableLayerSizeInBytes: UInt64? = nil,
        readOnly: Bool = false,
        networking: Bool = true,
        configuration: (inout LinuxContainer.Configuration) throws -> Void
    ) async throws -> LinuxContainer {
        let image = try await imageStore.get(reference: reference, pull: true)
        return try await create(
            id,
            image: image,
            rootfsSizeInBytes: rootfsSizeInBytes,
            writableLayerSizeInBytes: writableLayerSizeInBytes,
            readOnly: readOnly,
            networking: networking,
            configuration: configuration
        )
    }

    /// Returns a new container from the provided image.
    /// - Parameters:
    ///   - id: The container ID.
    ///   - image: The image.
    ///   - rootfsSizeInBytes: The size of the root filesystem in bytes. Defaults to 8 GiB.
    ///   - writableLayerSizeInBytes: Optional size for a separate writable layer. When provided,
    ///     the rootfs becomes read-only and an overlayfs is used with a separate writable layer of this size.
    ///   - readOnly: Whether to mount the root filesystem as read-only.
    ///   - networking: Whether to create a network interface for this container. Defaults to `true`.
    ///     When `false`, no network resources are allocated and `releaseNetwork`/`delete` remain safe to call.
    public mutating func create(
        _ id: String,
        image: Image,
        rootfsSizeInBytes: UInt64 = 8.gib(),
        writableLayerSizeInBytes: UInt64? = nil,
        readOnly: Bool = false,
        networking: Bool = true,
        configuration: (inout LinuxContainer.Configuration) throws -> Void
    ) async throws -> LinuxContainer {
        let path = try createContainerRoot(id)

        var rootfs = try await unpack(
            image: image,
            destination: path.appendingPathComponent("rootfs.ext4"),
            size: rootfsSizeInBytes
        )
        if readOnly {
            rootfs.options.append("ro")
        }

        // Create writable layer if size is specified.
        var writableLayer: Mount? = nil
        if let writableLayerSize = writableLayerSizeInBytes {
            writableLayer = try createEmptyFilesystem(
                at: path.appendingPathComponent("writable.ext4"),
                size: writableLayerSize
            )
        }

        return try await create(
            id,
            image: image,
            rootfs: rootfs,
            writableLayer: writableLayer,
            networking: networking,
            configuration: configuration
        )
    }

    /// Returns a new container from the provided image and root filesystem mount.
    /// - Parameters:
    ///   - id: The container ID.
    ///   - image: The image.
    ///   - rootfs: The root filesystem mount pointing to an existing block file.
    ///     The `destination` field is ignored as mounting is handled internally.
    ///   - writableLayer: Optional writable layer mount. When provided, an overlayfs is used with
    ///     rootfs as the lower layer and this as the upper layer.
    ///     The `destination` field is ignored as mounting is handled internally.
    ///   - networking: Whether to create a network interface for this container. Defaults to `true`.
    ///     When `false`, no network resources are allocated and `releaseNetwork`/`delete` remain safe to call.
    public mutating func create(
        _ id: String,
        image: Image,
        rootfs: Mount,
        writableLayer: Mount? = nil,
        networking: Bool = true,
        configuration: (inout LinuxContainer.Configuration) throws -> Void
    ) async throws -> LinuxContainer {
        let imageConfig = try await image.config(for: .current).config
        return try LinuxContainer(
            id,
            rootfs: rootfs,
            writableLayer: writableLayer,
            vmm: self.vmm
        ) { config in
            if let imageConfig {
                config.process = .init(from: imageConfig)
            }
            if networking, let interface = try self.network?.createInterface(id) {
                config.interfaces = [interface]
                guard let gateway = interface.ipv4Gateway else {
                    throw ContainerizationError(
                        .invalidState,
                        message: "missing ipv4 gateway for container \(id)"
                    )
                }
                config.dns = .init(nameservers: [gateway.description])
            }
            config.bootLog = BootLog.file(path: self.containerRoot.appendingPathComponent(id).appendingPathComponent("bootlog.log"))
            try configuration(&config)
        }
    }

    /// Releases network resources for a container.
    ///
    /// - Parameter id: The container ID.
    public mutating func releaseNetwork(_ id: String) throws {
        try self.network?.releaseInterface(id)
    }

    /// Releases network resources and removes all files for a container.
    /// - Parameter id: The container ID.
    public mutating func delete(_ id: String) throws {
        try self.releaseNetwork(id)
        let path = containerRoot.appendingPathComponent(id)
        try FileManager.default.removeItem(at: path)
    }

    private func createContainerRoot(_ id: String) throws -> URL {
        let path = containerRoot.appendingPathComponent(id)
        try FileManager.default.createDirectory(at: path, withIntermediateDirectories: false)
        return path
    }

    private func unpack(image: Image, destination: URL, size: UInt64) async throws -> Mount {
        do {
            let unpacker = EXT4Unpacker(blockSizeInBytes: size)
            return try await unpacker.unpack(image, for: .current, at: destination)
        } catch let err as ContainerizationError {
            if err.code == .exists {
                return .block(
                    format: "ext4",
                    source: destination.absolutePath(),
                    destination: "/",
                    options: []
                )
            }
            throw err
        }
    }

    private func createEmptyFilesystem(at destination: URL, size: UInt64) throws -> Mount {
        let path = destination.absolutePath()
        guard !FileManager.default.fileExists(atPath: path) else {
            throw ContainerizationError(.exists, message: "filesystem already exists at \(path)")
        }
        let filesystem = try EXT4.Formatter(FilePath(path), minDiskSize: size)
        try filesystem.close()
        return .block(
            format: "ext4",
            source: path,
            destination: "/",
            options: []
        )
    }
}

extension CIDRv4 {
    /// The gateway address of the network.
    public var gateway: IPv4Address {
        IPv4Address(self.lower.value + 1)
    }
}

#endif


================================================
FILE: Sources/Containerization/ContainerStatistics.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

/// Statistics for a container.
public struct ContainerStatistics: Sendable {
    public var id: String
    public var process: ProcessStatistics?
    public var memory: MemoryStatistics?
    public var cpu: CPUStatistics?
    public var blockIO: BlockIOStatistics?
    public var networks: [NetworkStatistics]?
    public var memoryEvents: MemoryEventStatistics?

    public init(
        id: String,
        process: ProcessStatistics? = nil,
        memory: MemoryStatistics? = nil,
        cpu: CPUStatistics? = nil,
        blockIO: BlockIOStatistics? = nil,
        networks: [NetworkStatistics]? = nil,
        memoryEvents: MemoryEventStatistics? = nil
    ) {
        self.id = id
        self.process = process
        self.memory = memory
        self.cpu = cpu
        self.blockIO = blockIO
        self.networks = networks
        self.memoryEvents = memoryEvents
    }

    /// Process statistics for a container.
    public struct ProcessStatistics: Sendable {
        public var current: UInt64
        public var limit: UInt64

        public init(current: UInt64, limit: UInt64) {
            self.current = current
            self.limit = limit
        }
    }

    /// Memory statistics for a container.
    public struct MemoryStatistics: Sendable {
        public var usageBytes: UInt64
        public var limitBytes: UInt64
        public var swapUsageBytes: UInt64
        public var swapLimitBytes: UInt64
        public var cacheBytes: UInt64
        public var kernelStackBytes: UInt64
        public var slabBytes: UInt64
        public var pageFaults: UInt64
        public var majorPageFaults: UInt64
        public var inactiveFile: UInt64
        public var anon: UInt64

        public init(
            usageBytes: UInt64,
            limitBytes: UInt64,
            swapUsageBytes: UInt64,
            swapLimitBytes: UInt64,
            cacheBytes: UInt64,
            kernelStackBytes: UInt64,
            slabBytes: UInt64,
            pageFaults: UInt64,
            majorPageFaults: UInt64,
            inactiveFile: UInt64,
            anon: UInt64
        ) {
            self.usageBytes = usageBytes
            self.limitBytes = limitBytes
            self.swapUsageBytes = swapUsageBytes
            self.swapLimitBytes = swapLimitBytes
            self.cacheBytes = cacheBytes
            self.kernelStackBytes = kernelStackBytes
            self.slabBytes = slabBytes
            self.pageFaults = pageFaults
            self.majorPageFaults = majorPageFaults
            self.inactiveFile = inactiveFile
            self.anon = anon
        }
    }

    /// CPU statistics for a container.
    public struct CPUStatistics: Sendable {
        public var usageUsec: UInt64
        public var userUsec: UInt64
        public var systemUsec: UInt64
        public var throttlingPeriods: UInt64
        public var throttledPeriods: UInt64
        public var throttledTimeUsec: UInt64

        public init(
            usageUsec: UInt64,
            userUsec: UInt64,
            systemUsec: UInt64,
            throttlingPeriods: UInt64,
            throttledPeriods: UInt64,
            throttledTimeUsec: UInt64
        ) {
            self.usageUsec = usageUsec
            self.userUsec = userUsec
            self.systemUsec = systemUsec
            self.throttlingPeriods = throttlingPeriods
            self.throttledPeriods = throttledPeriods
            self.throttledTimeUsec = throttledTimeUsec
        }
    }

    /// Block I/O statistics for a container.
    public struct BlockIOStatistics: Sendable {
        public var devices: [BlockIODevice]

        public init(devices: [BlockIODevice]) {
            self.devices = devices
        }
    }

    /// Block I/O statistics for a specific device.
    public struct BlockIODevice: Sendable {
        public var major: UInt64
        public var minor: UInt64
        public var readBytes: UInt64
        public var writeBytes: UInt64
        public var readOperations: UInt64
        public var writeOperations: UInt64

        public init(
            major: UInt64,
            minor: UInt64,
            readBytes: UInt64,
            writeBytes: UInt64,
            readOperations: UInt64,
            writeOperations: UInt64
        ) {
            self.major = major
            self.minor = minor
            self.readBytes = readBytes
            self.writeBytes = writeBytes
            self.readOperations = readOperations
            self.writeOperations = writeOperations
        }
    }

    /// Statistics for a network interface.
    public struct NetworkStatistics: Sendable {
        public var interface: String
        public var receivedPackets: UInt64
        public var transmittedPackets: UInt64
        public var receivedBytes: UInt64
        public var transmittedBytes: UInt64
        public var receivedErrors: UInt64
        public var transmittedErrors: UInt64

        public init(
            interface: String,
            receivedPackets: UInt64,
            transmittedPackets: UInt64,
            receivedBytes: UInt64,
            transmittedBytes: UInt64,
            receivedErrors: UInt64,
            transmittedErrors: UInt64
        ) {
            self.interface = interface
            self.receivedPackets = receivedPackets
            self.transmittedPackets = transmittedPackets
            self.receivedBytes = receivedBytes
            self.transmittedBytes = transmittedBytes
            self.receivedErrors = receivedErrors
            self.transmittedErrors = transmittedErrors
        }
    }

    /// Memory event counters from cgroup2's memory.events file.
    public struct MemoryEventStatistics: Sendable {
        /// Number of times the cgroup was reclaimed due to low memory.
        public var low: UInt64
        /// Number of times the cgroup exceeded its high memory limit.
        public var high: UInt64
        /// Number of times the cgroup hit its max memory limit.
        public var max: UInt64
        /// Number of times the cgroup triggered OOM.
        public var oom: UInt64
        /// Number of processes killed by OOM killer.
        public var oomKill: UInt64

        public init(low: UInt64, high: UInt64, max: UInt64, oom: UInt64, oomKill: UInt64) {
            self.low = low
            self.high = high
            self.max = max
            self.oom = oom
            self.oomKill = oomKill
        }
    }
}

/// Categories of statistics that can be requested.
public struct StatCategory: OptionSet, Sendable {
    public let rawValue: Int

    public init(rawValue: Int) {
        self.rawValue = rawValue
    }

    /// Process statistics (pids.current, pids.max).
    public static let process = StatCategory(rawValue: 1 << 0)
    /// Memory usage statistics.
    public static let memory = StatCategory(rawValue: 1 << 1)
    /// CPU usage statistics.
    public static let cpu = StatCategory(rawValue: 1 << 2)
    /// Block I/O statistics.
    public static let blockIO = StatCategory(rawValue: 1 << 3)
    /// Network interface statistics.
    public static let network = StatCategory(rawValue: 1 << 4)
    /// Memory event counters (OOM kills, pressure events, etc.).
    public static let memoryEvents = StatCategory(rawValue: 1 << 5)

    /// All available statistics categories.
    public static let all: StatCategory = [.process, .memory, .cpu, .blockIO, .network, .memoryEvents]
}


================================================
FILE: Sources/Containerization/DNSConfiguration.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

/// DNS configuration for a container. The values will be used to
/// construct /etc/resolv.conf for a given container.
public struct DNS: Sendable {
    /// The set of default nameservers to use if none are provided
    /// in the constructor.
    public static let defaultNameservers = ["1.1.1.1"]

    /// The nameservers a container should use.
    public var nameservers: [String]
    /// The DNS domain to use.
    public var domain: String?
    /// The DNS search domains to use.
    public var searchDomains: [String]
    /// The DNS options to use.
    public var options: [String]

    public init(
        nameservers: [String] = defaultNameservers,
        domain: String? = nil,
        searchDomains: [String] = [],
        options: [String] = []
    ) {
        self.nameservers = nameservers
        self.domain = domain
        self.searchDomains = searchDomains
        self.options = options
    }
}

extension DNS {
    public var resolvConf: String {
        var text = ""

        if !nameservers.isEmpty {
            text += nameservers.map { "nameserver \($0)" }.joined(separator: "\n") + "\n"
        }

        if let domain {
            text += "domain \(domain)\n"
        }

        if !searchDomains.isEmpty {
            text += "search \(searchDomains.joined(separator: " "))\n"
        }

        if !options.isEmpty {
            text += "options \(options.joined(separator: " "))\n"
        }

        return text
    }
}


================================================
FILE: Sources/Containerization/ExitStatus.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import Foundation

/// ExitStatus contains the exit code for a given container process,
/// as well as the timestamp at which it exited.
public struct ExitStatus: Sendable {
    /// The exit code for the process.
    public var exitCode: Int32
    /// The timestamp when the process exited.
    public var exitedAt: Date

    public init(exitCode: Int32) {
        self.exitCode = exitCode
        self.exitedAt = .now
    }

    public init(exitCode: Int32, exitedAt: Date) {
        self.exitCode = exitCode
        self.exitedAt = exitedAt
    }
}


================================================
FILE: Sources/Containerization/FileMount.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

#if os(macOS)

import ContainerizationError
import ContainerizationOCI
import Foundation

/// Manages single-file mounts by transforming them into virtiofs directory shares
/// plus bind mounts.
///
/// Since virtiofs only supports sharing directories, mounting a single file without
/// exposing the other potential files in that directory needs a little bit of a "hack".
/// The one we've landed on is:
///
/// 1. Creating a temporary directory containing a hardlink to the file
/// 2. Sharing that directory via virtiofs to a holding location in the guest
/// 3. Bind mounting the specific file from the holding location to the final destination
///
/// This type handles all three steps transparently.
struct FileMountContext: Sendable {
    /// Metadata for a single prepared file mount.
    struct PreparedMount: Sendable {
        /// Original file path on host
        let hostFilePath: String
        /// Where the user wants the file in the container
        let containerDestination: String
        /// Just the filename
        let filename: String
        /// Temp directory containing the hardlinked file
        let tempDirectory: URL
        /// The virtiofs tag (hash of temp dir path). Used to find the AttachedFilesystem
        let tag: String
        /// Mount options from the original mount
        let options: [String]
        /// Where we mounted the share in the guest (set after mountHoldingDirectories)
        var guestHoldingPath: String?
    }

    /// Prepared file mounts for this context
    var preparedMounts: [PreparedMount]

    /// The transformed mounts to pass to the VM (files replaced with directory shares)
    private(set) var transformedMounts: [Mount]

    private init() {
        self.preparedMounts = []
        self.transformedMounts = []
    }

    /// Returns true if there are any file mounts that need handling.
    var hasFileMounts: Bool {
        !preparedMounts.isEmpty
    }

    /// Returns the set of virtiofs tags for file mount holding directories.
    /// These should be filtered out from OCI spec mounts since we mount them
    /// separately under /run.
    var holdingDirectoryTags: Set<String> {
        Set(preparedMounts.map { $0.tag })
    }
}

extension FileMountContext {
    /// Prepare mounts for a container, detecting file mounts and transforming them.
    ///
    /// This method stats each virtiofs mount source. If it's a regular file rather than
    /// a directory, it creates a temporary directory with a hardlink to the file and
    /// substitutes a directory share for the original mount.
    ///
    /// - Parameter mounts: The original mounts from the container config
    /// - Returns: A FileMountContext containing transformed mounts and tracking info
    static func prepare(mounts: [Mount]) throws -> FileMountContext {
        var context = FileMountContext()
        var transformed: [Mount] = []

        for mount in mounts {
            // Only virtiofs mounts can be files
            guard case .virtiofs(let runtimeOpts) = mount.runtimeOptions else {
                transformed.append(mount)
                continue
            }

            // Stat the source to see if it's a file
            let fm = FileManager.default
            var isDirectory: ObjCBool = false
            guard fm.fileExists(atPath: mount.source, isDirectory: &isDirectory) else {
                // Doesn't exist. Let the normal flow handle the error
                transformed.append(mount)
                continue
            }

            if isDirectory.boolValue {
                // It's a directory, pass through unchanged
                transformed.append(mount)
                continue
            }

            // It's a file, so prepare it.
            let prepared = try context.prepareFileMount(mount: mount, runtimeOptions: runtimeOpts)

            // Create a regular directory share for the temp directory.
            // The destination here is unused. We'll mount it ourselves to a location under /run.
            let directoryShare = Mount.share(
                source: prepared.tempDirectory.path,
                destination: "/.file-mount-holding",
                options: mount.options.filter { $0 != "bind" },
                runtimeOptions: runtimeOpts
            )
            transformed.append(directoryShare)
        }

        context.transformedMounts = transformed
        return context
    }

    private mutating func prepareFileMount(
        mount: Mount,
        runtimeOptions: [String]
    ) throws -> PreparedMount {
        let resolvedSource = URL(fileURLWithPath: mount.source).resolvingSymlinksInPath()
        let sourceURL = URL(fileURLWithPath: mount.source)
        let filename = sourceURL.lastPathComponent

        let tempDir = FileManager.default.temporaryDirectory
            .appendingPathComponent("containerization-file-mounts")
            .appendingPathComponent(UUID().uuidString)

        try FileManager.default.createDirectory(
            at: tempDir,
            withIntermediateDirectories: true
        )

        // Hardlink the file (falls back to copy if cross-filesystem)
        let destURL = tempDir.appendingPathComponent(filename)
        do {
            try FileManager.default.linkItem(at: resolvedSource, to: destURL)
        } catch {
            // Hardlink failed. Fall back to copy
            try FileManager.default.copyItem(at: resolvedSource, to: destURL)
        }

        let tag = try hashMountSource(source: tempDir.path)

        let prepared = PreparedMount(
            hostFilePath: mount.source,
            containerDestination: mount.destination,
            filename: filename,
            tempDirectory: tempDir,
            tag: tag,
            options: mount.options,
            guestHoldingPath: nil
        )

        preparedMounts.append(prepared)
        return prepared
    }
}

extension FileMountContext {
    /// Mount the holding directories in the guest for all file mounts.
    /// - Parameters:
    ///   - vmMounts: The AttachedFilesystem array from the VM for this container
    ///   - agent: The VM agent for RPCs
    mutating func mountHoldingDirectories(
        vmMounts: [AttachedFilesystem],
        agent: any VirtualMachineAgent
    ) async throws {
        for i in preparedMounts.indices {
            let prepared = preparedMounts[i]

            // Find the attached filesystem by matching the virtiofs tag
            guard
                let attached = vmMounts.first(where: {
                    $0.type == "virtiofs" && $0.source == prepared.tag
                })
            else {
                throw ContainerizationError(
                    .notFound,
                    message: "could not find attached filesystem for file mount \(prepared.hostFilePath)"
                )
            }

            let guestPath = "/run/file-mounts/\(prepared.tag)"
            try await agent.mkdir(path: guestPath, all: true, perms: 0o755)
            try await agent.mount(
                ContainerizationOCI.Mount(
                    type: "virtiofs",
                    source: attached.source,
                    destination: guestPath,
                    options: []
                ))

            preparedMounts[i].guestHoldingPath = guestPath
        }
    }
}

extension FileMountContext {
    /// Get the bind mounts to append to the OCI spec.
    func ociBindMounts() -> [ContainerizationOCI.Mount] {
        preparedMounts.compactMap { prepared in
            guard let guestPath = prepared.guestHoldingPath else {
                return nil
            }

            return ContainerizationOCI.Mount(
                type: "none",
                source: "\(guestPath)/\(prepared.filename)",
                destination: prepared.containerDestination,
                options: ["bind"] + prepared.options
            )
        }
    }
}

extension FileMountContext {
    /// Clean up temp directories.
    func cleanUp() {
        let fm = FileManager.default
        for prepared in preparedMounts {
            try? fm.removeItem(at: prepared.tempDirectory)
        }
    }
}

#endif


================================================
FILE: Sources/Containerization/Hash.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

#if os(macOS)

import Crypto
import ContainerizationError
import Foundation

public func hashMountSource(source: String) throws -> String {
    // Resolve symlinks so different paths to the same directory get the same hash.
    let resolvedSource = URL(fileURLWithPath: source).resolvingSymlinksInPath().path
    guard let data = resolvedSource.data(using: .utf8) else {
        throw ContainerizationError(.invalidArgument, message: "\(source) could not be converted to Data")
    }
    return String(SHA256.hash(data: data).encoded.prefix(36))
}

#endif


================================================
FILE: Sources/Containerization/HostsConfiguration.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

/// Static table lookups for a container. The values will be used to
/// construct /etc/hosts for a given container.
public struct Hosts: Sendable {
    /// Represents one entry in an /etc/hosts file.
    public struct Entry: Sendable {
        /// The IPV4 or IPV6 address in String form.
        public var ipAddress: String
        /// The hostname(s) for the entry.
        public var hostnames: [String]
        /// An optional comment to be placed to the right side of the entry.
        public var comment: String?

        public init(ipAddress: String, hostnames: [String], comment: String? = nil) {
            self.comment = comment
            self.hostnames = hostnames
            self.ipAddress = ipAddress
        }

        /// The information in the structure rendered to a String representation
        /// that matches the format /etc/hosts expects.
        public var rendered: String {
            var line = ipAddress
            if !hostnames.isEmpty {
                line += " " + hostnames.joined(separator: " ")
            }
            if let comment {
                line += " # \(comment) "
            }
            return line
        }

        public static func localHostIPV4(comment: String? = nil) -> Self {
            Self(
                ipAddress: "127.0.0.1",
                hostnames: ["localhost"],
                comment: comment
            )
        }

        public static func localHostIPV6(comment: String? = nil) -> Self {
            Self(
                ipAddress: "::1",
                hostnames: ["localhost", "ip6-localhost", "ip6-loopback"],
                comment: comment
            )
        }

        public static func ipv6LocalNet(comment: String? = nil) -> Self {
            Self(
                ipAddress: "fe00::",
                hostnames: ["ip6-localnet"],
                comment: comment
            )
        }

        public static func ipv6MulticastPrefix(comment: String? = nil) -> Self {
            Self(
                ipAddress: "ff00::",
                hostnames: ["ip6-mcastprefix"],
                comment: comment
            )
        }

        public static func ipv6AllNodes(comment: String? = nil) -> Self {
            Self(
                ipAddress: "ff02::1",
                hostnames: ["ip6-allnodes"],
                comment: comment
            )
        }

        public static func ipv6AllRouters(comment: String? = nil) -> Self {
            Self(
                ipAddress: "ff02::2",
                hostnames: ["ip6-allrouters"],
                comment: comment
            )
        }
    }

    /// The entries to be written to /etc/hosts.
    public var entries: [Entry]

    /// A comment to render at the top of the file.
    public var comment: String?

    public init(
        entries: [Entry],
        comment: String? = nil
    ) {
        self.entries = entries
        self.comment = comment
    }
}

extension Hosts {
    /// A default entry that can be used for convenience. It contains a IPV4
    /// and IPV6 localhost entry, as well as ipv6 localnet, ipv6 mcastprefix,
    /// ipv6 allnodes, and ipv6 allrouters.
    public static let `default` = Hosts(entries: [
        Entry.localHostIPV4(),
        Entry.localHostIPV6(),
        Entry.ipv6LocalNet(),
        Entry.ipv6MulticastPrefix(),
        Entry.ipv6AllNodes(),
        Entry.ipv6AllRouters(),
    ])

    /// Returns a string variant of the data that can be written to
    /// /etc/hosts directly.
    public var hostsFile: String {
        var lines: [String] = []

        if let comment {
            lines.append("# \(comment)")
        }

        for entry in entries {
            lines.append(entry.rendered)
        }

        return lines.joined(separator: "\n") + "\n"
    }
}


================================================
FILE: Sources/Containerization/IO/ReaderStream.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import Foundation

/// A type that returns a stream of Data.
public protocol ReaderStream: Sendable {
    func stream() -> AsyncStream<Data>
}


================================================
FILE: Sources/Containerization/IO/Terminal+ReaderStream.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import ContainerizationOS
import Foundation

extension Terminal: ReaderStream {
    public func stream() -> AsyncStream<Data> {
        .init { cont in
            self.handle.readabilityHandler = { handle in
                let data = handle.availableData
                if data.isEmpty {
                    self.handle.readabilityHandler = nil
                    cont.finish()
                    return
                }
                cont.yield(data)
            }
        }
    }
}

extension Terminal: Writer {}


================================================
FILE: Sources/Containerization/IO/Writer.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import Foundation

/// A type that writes the provided Data.
public protocol Writer: Sendable {
    func write(_ data: Data) throws
    func close() throws
}


================================================
FILE: Sources/Containerization/Image/Image.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import ContainerizationError
import ContainerizationOCI
import ContainerizationOS
import Foundation

/// Type representing an OCI container image.
public struct Image: Sendable {
    private let contentStore: ContentStore
    /// The description for the image that comprises of its name and a reference to its root descriptor.
    public let description: Description

    /// A description of the OCI image.
    public struct Description: Sendable {
        /// The string reference of the image.
        public let reference: String
        /// The descriptor identifying the image.
        public let descriptor: Descriptor
        /// The digest for the image.
        public var digest: String { descriptor.digest }
        /// The media type of the image.
        public var mediaType: String { descriptor.mediaType }

        public init(reference: String, descriptor: Descriptor) {
            self.reference = reference
            self.descriptor = descriptor
        }
    }

    /// The descriptor for the image.
    public var descriptor: Descriptor { description.descriptor }
    /// The digest of the image.
    public var digest: String { description.digest }
    /// The media type of the image.
    public var mediaType: String { description.mediaType }
    /// The string reference for the image.
    public var reference: String { description.reference }

    public init(description: Description, contentStore: ContentStore) {
        self.description = description
        self.contentStore = contentStore
    }

    /// Returns the underlying OCI index for the image.
    public func index() async throws -> Index {
        guard let content: Content = try await contentStore.get(digest: digest) else {
            throw ContainerizationError(.notFound, message: "content with digest \(digest)")
        }
        return try content.decode()
    }

    /// Returns the manifest for the specified platform.
    public func manifest(for platform: Platform) async throws -> Manifest {
        let index = try await self.index()
        let desc = index.manifests.first { desc in
            desc.platform == platform
        }
        guard let desc else {
            throw ContainerizationError(.unsupported, message: "platform \(platform.description)")
        }
        guard let content: Content = try await contentStore.get(digest: desc.digest) else {
            throw ContainerizationError(.notFound, message: "content with digest \(digest)")
        }
        return try content.decode()
    }

    /// Returns the descriptor for the given platform. If it does not exist
    /// will throw a ContainerizationError with the code set to .invalidArgument.
    public func descriptor(for platform: Platform) async throws -> Descriptor {
        let index = try await self.index()
        let desc = index.manifests.first { $0.platform == platform }
        guard let desc else {
            throw ContainerizationError(.invalidArgument, message: "unsupported platform \(platform)")
        }
        return desc
    }

    /// Returns the OCI config for the specified platform.
    public func config(for platform: Platform) async throws -> ContainerizationOCI.Image {
        let manifest = try await self.manifest(for: platform)
        let desc = manifest.config
        guard let content: Content = try await contentStore.get(digest: desc.digest) else {
            throw ContainerizationError(.notFound, message: "content with digest \(digest)")
        }
        return try content.decode()
    }

    /// Returns a list of digests to all the referenced OCI objects.
    public func referencedDigests() async throws -> [String] {
        var referenced: [String] = [self.digest.trimmingDigestPrefix]
        let index = try await self.index()
        for manifest in index.manifests {
            referenced.append(manifest.digest.trimmingDigestPrefix)
            guard let m: Manifest = try? await contentStore.get(digest: manifest.digest) else {
                // If the requested digest does not exist or is not a manifest. Skip.
                // Its safe to skip processing this digest as it wont have any child layers.
                continue
            }
            let descs = m.layers + [m.config]
            referenced.append(contentsOf: descs.map { $0.digest.trimmingDigestPrefix })
        }
        return referenced
    }

    /// Returns a reference to the content blob for the image. The specified digest must be referenced by the image in one of its layers.
    public func getContent(digest: String) async throws -> Content {
        guard try await self.referencedDigests().contains(digest.trimmingDigestPrefix) else {
            throw ContainerizationError(.internalError, message: "image \(self.reference) does not reference digest \(digest)")
        }
        guard let content: Content = try await contentStore.get(digest: digest) else {
            throw ContainerizationError(.notFound, message: "content with digest \(digest)")
        }
        return content
    }
}


================================================
FILE: Sources/Containerization/Image/ImageStore/ImageStore+Export.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

//

import ContainerizationError
import ContainerizationExtras
import ContainerizationIO
import ContainerizationOCI
import Crypto
import Foundation

extension ImageStore {
    public struct ExportOperation: Sendable {
        let name: String
        let tag: String
        let contentStore: ContentStore
        let client: ContentClient
        let progress: ProgressHandler?

        public init(name: String, tag: String, contentStore: ContentStore, client: ContentClient, progress: ProgressHandler? = nil) {
            self.contentStore = contentStore
            self.client = client
            self.progress = progress
            self.name = name
            self.tag = tag
        }

        @discardableResult
        public func export(index: Descriptor, platforms: (Platform) -> Bool) async throws -> Descriptor {
            var pushQueue: [[Descriptor]] = []
            var current: [Descriptor] = [index]
            while !current.isEmpty {
                let children = try await self.getChildren(descs: current)
                let matches = try filterPlatforms(matcher: platforms, children).uniqued { $0.digest }
                pushQueue.append(matches)
                current = matches
            }
            let localIndexData = try await self.createIndex(from: index, matching: platforms)

            await updatePushProgress(pushQueue: pushQueue, localIndexData: localIndexData)

            // We need to work bottom up when pushing an image.
            // First, the tar blobs / config layers, then, the manifests and so on...
            // When processing a given "level", the requests maybe made in parallel.
            // We need to ensure that the child level has been uploaded fully
            // before uploading the parent level.
            try await withThrowingTaskGroup(of: Void.self) { group in
                for layerGroup in pushQueue.reversed() {
                    for chunk in layerGroup.chunks(ofCount: 8) {
                        for desc in chunk {
                            guard let content = try await self.contentStore.get(digest: desc.digest) else {
                                throw ContainerizationError(.notFound, message: "content with digest \(desc.digest)")
                            }
                            group.addTask {
                                let readStream = try ReadStream(url: content.path)
                                try await self.pushContent(descriptor: desc, stream: readStream)
                            }
                        }
                        try await group.waitForAll()
                    }
                }
            }

            // Lastly, we need to construct and push a new index, since we may
            // have pushed content only for specific platforms.
            let digest = SHA256.hash(data: localIndexData)
            let descriptor = Descriptor(
                mediaType: MediaTypes.index,
                digest: digest.digestString,
                size: Int64(localIndexData.count))
            let stream = ReadStream(data: localIndexData)
            try await self.pushContent(descriptor: descriptor, stream: stream)
            return descriptor
        }

        private func updatePushProgress(pushQueue: [[Descriptor]], localIndexData: Data) async {
            for layerGroup in pushQueue {
                for desc in layerGroup {
                    await progress?([
                        .addTotalSize(desc.size),
                        .addTotalItems(1),
                    ])
                }
            }
            await progress?([
                .addTotalSize(Int64(localIndexData.count)),
                .addTotalItems(1),
            ])
        }

        private func createIndex(from index: Descriptor, matching: (Platform) -> Bool) async throws -> Data {
            guard let content = try await self.contentStore.get(digest: index.digest) else {
                throw ContainerizationError(.notFound, message: "content with digest \(index.digest)")
            }
            var idx: Index = try content.decode()
            let manifests = idx.manifests
            var matchedManifests: [Descriptor] = []
            var skippedPlatforms = false
            for manifest in manifests {
                guard let p = manifest.platform else {
                    continue
                }
                if matching(p) {
                    matchedManifests.append(manifest)
                } else {
                    skippedPlatforms = true
                }
            }
            if !skippedPlatforms {
                return try content.data()
            }
            idx.manifests = matchedManifests
            return try JSONEncoder().encode(idx)
        }

        private func pushContent(descriptor: Descriptor, stream: ReadStream) async throws {
            do {
                let generator = {
                    try stream.reset()
                    return stream.stream
                }
                try await client.push(name: name, ref: tag, descriptor: descriptor, streamGenerator: generator, progress: progress)
                await progress?([
                    .addSize(descriptor.size),
                    .addItems(1),
                ])
            } catch let err as ContainerizationError {
                guard err.code != .exists else {
                    // We reported the total items and size and have to account for them in existing content.
                    await progress?([
                        .addSize(descriptor.size),
                        .addItems(1),
                    ])
                    return
                }
                throw err
            }
        }

        private func getChildren(descs: [Descriptor]) async throws -> [Descriptor] {
            var out: [Descriptor] = []
            for desc in descs {
                let mediaType = desc.mediaType
                guard let content = try await self.contentStore.get(digest: desc.digest) else {
                    throw ContainerizationError(.notFound, message: "content with digest \(desc.digest)")
                }
                switch mediaType {
                case MediaTypes.index, MediaTypes.dockerManifestList:
                    let index: Index = try content.decode()
                    out.append(contentsOf: index.manifests)
                case MediaTypes.imageManifest, MediaTypes.dockerManifest:
                    let manifest: Manifest = try content.decode()
                    out.append(manifest.config)
                    out.append(contentsOf: manifest.layers)
                default:
                    continue
                }
            }
            return out
        }
    }
}


================================================
FILE: Sources/Containerization/Image/ImageStore/ImageStore+Import.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

//

import ContainerizationError
import ContainerizationExtras
import ContainerizationOCI
import Foundation

extension ImageStore {
    public struct ImportOperation: Sendable {
        static let decoder = JSONDecoder()

        let client: ContentClient
        let ingestDir: URL
        let contentStore: ContentStore
        let progress: ProgressHandler?
        let name: String
        let maxConcurrentDownloads: Int

        public init(name: String, contentStore: ContentStore, client: ContentClient, ingestDir: URL, progress: ProgressHandler? = nil, maxConcurrentDownloads: Int = 3) {
            self.client = client
            self.ingestDir = ingestDir
            self.contentStore = contentStore
            self.progress = progress
            self.name = name
            self.maxConcurrentDownloads = maxConcurrentDownloads
        }

        /// Pull the required image layers for the provided descriptor and platform(s) into the given directory using the provided client. Returns a descriptor to the Index manifest.
        public func `import`(root: Descriptor, matcher: (ContainerizationOCI.Platform) -> Bool) async throws -> Descriptor {
            var toProcess = [root]
            while !toProcess.isEmpty {
                // Count the total number of blobs and their size
                if let progress {
                    var size: Int64 = 0
                    for desc in toProcess {
                        size += desc.size
                    }
                    await progress([
                        .addTotalSize(size),
                        .addTotalItems(toProcess.count),
                    ])
                }

                try await self.fetchAll(toProcess)
                let children = try await self.walk(toProcess)
                let filtered = try filterPlatforms(matcher: matcher, children)
                toProcess = filtered.uniqued { $0.digest }
            }

            guard root.mediaType != MediaTypes.dockerManifestList && root.mediaType != MediaTypes.index else {
                return root
            }

            // Create an index for the root descriptor and write it to the content store
            let index = try await self.createIndex(for: root)
            // In cases where the root descriptor pointed to `MediaTypes.imageManifest`
            // Or `MediaTypes.dockerManifest`, it is required that we check the supported platform
            // matches the platforms we were asked to pull. This can be done only after we created
            // the Index.
            let supportedPlatforms = index.manifests.compactMap { $0.platform }
            guard supportedPlatforms.allSatisfy(matcher) else {
                throw ContainerizationError(.unsupported, message: "image \(root.digest) does not support required platforms")
            }
            let writer = try ContentWriter(for: self.ingestDir)
            let result = try writer.create(from: index)
            return Descriptor(
                mediaType: MediaTypes.index,
                digest: result.digest.digestString,
                size: Int64(result.size))
        }

        private func getManifestContent<T: Sendable & Codable>(descriptor: Descriptor) async throws -> T {
            do {
                if let content = try await self.contentStore.get(digest: descriptor.digest.trimmingDigestPrefix) {
                    return try content.decode()
                }
                if let content = try? LocalContent(path: ingestDir.appending(path: descriptor.digest.trimmingDigestPrefix)) {
                    return try content.decode()
                }
                return try await self.client.fetch(name: name, descriptor: descriptor)
            } catch {
                throw ContainerizationError(.internalError, message: "cannot fetch content with digest \(descriptor.digest)", cause: error)
            }
        }

        private func walk(_ descriptors: [Descriptor]) async throws -> [Descriptor] {
            var out: [Descriptor] = []
            for desc in descriptors {
                let mediaType = desc.mediaType
                switch mediaType {
                case MediaTypes.index, MediaTypes.dockerManifestList:
                    let index: Index = try await self.getManifestContent(descriptor: desc)
                    out.append(contentsOf: index.manifests)
                case MediaTypes.imageManifest, MediaTypes.dockerManifest:
                    let manifest: Manifest = try await self.getManifestContent(descriptor: desc)
                    out.append(manifest.config)
                    out.append(contentsOf: manifest.layers)
                default:
                    // TODO: Explicitly handle other content types
                    continue
                }
            }
            return out
        }

        private func fetchAll(_ descriptors: [Descriptor]) async throws {
            try await withThrowingTaskGroup(of: Void.self) { group in
                var iterator = descriptors.makeIterator()
                // Start initial batch of concurrent downloads based on maxConcurrentDownloads
                for _ in 0..<self.maxConcurrentDownloads {
                    if let desc = iterator.next() {
                        group.addTask {
                            try await self.fetch(desc)
                        }
                    }
                }
                // As tasks complete, add new ones to maintain concurrency
                for try await _ in group {
                    if let desc = iterator.next() {
                        group.addTask {
                            try await self.fetch(desc)
                        }
                    }
                }
            }
        }

        private func fetch(_ descriptor: Descriptor) async throws {
            if let found = try await self.contentStore.get(digest: descriptor.digest) {
                try FileManager.default.copyItem(at: found.path, to: ingestDir.appendingPathComponent(descriptor.digest.trimmingDigestPrefix))
                await progress?([
                    // Count the size of the blob
                    .addSize(descriptor.size),
                    // Count the number of blobs
                    .addItems(1),
                ])
                return
            }

            if descriptor.size > 1.mib() {
                try await self.fetchBlob(descriptor)
            } else {
                try await self.fetchData(descriptor)
            }
            // Count the number of blobs
            await progress?([
                .addItems(1)
            ])
        }

        private func fetchBlob(_ descriptor: Descriptor) async throws {
            let id = UUID().uuidString
            let fm = FileManager.default
            let tempFile = ingestDir.appendingPathComponent(id)
            let (_, digest) = try await client.fetchBlob(name: name, descriptor: descriptor, into: tempFile, progress: progress)
            guard digest.digestString == descriptor.digest else {
                throw ContainerizationError(.internalError, message: "digest mismatch expected \(descriptor.digest), got \(digest.digestString)")
            }
            do {
                try fm.moveItem(at: tempFile, to: ingestDir.appendingPathComponent(digest.encoded))
            } catch let err as NSError {
                guard err.code == NSFileWriteFileExistsError else {
                    throw err
                }
                try fm.removeItem(at: tempFile)
            }
        }

        @discardableResult
        private func fetchData(_ descriptor: Descriptor) async throws -> Data {
            let data = try await client.fetchData(name: name, descriptor: descriptor)
            let writer = try ContentWriter(for: ingestDir)
            let result = try writer.write(data)
            if let progress {
                let size = Int64(result.size)
                await progress([
                    .addSize(size)
                ])
            }
            guard result.digest.digestString == descriptor.digest else {
                throw ContainerizationError(.internalError, message: "digest mismatch expected \(descriptor.digest), got \(result.digest.digestString)")
            }
            return data
        }

        private func createIndex(for root: Descriptor) async throws -> Index {
            switch root.mediaType {
            case MediaTypes.index, MediaTypes.dockerManifestList:
                return try await self.getManifestContent(descriptor: root)
            case MediaTypes.imageManifest, MediaTypes.dockerManifest:
                let supportedPlatforms = try await getSupportedPlatforms(for: root)
                guard supportedPlatforms.count == 1 else {
                    throw ContainerizationError(
                        .internalError,
                        message:
                            "descriptor \(root.mediaType) with digest \(root.digest) does not list any supported platform or supports more than one platform, supported platforms: \(supportedPlatforms)"
                    )
                }
                let platform = supportedPlatforms.first!
                var root = root
                root.platform = platform
                let index = ContainerizationOCI.Index(
                    schemaVersion: 2, manifests: [root],
                    annotations: [
                        // indicate that this is a synthesized index which is not directly user facing
                        AnnotationKeys.containerizationIndexIndirect: "true"
                    ])
                return index
            default:
                throw ContainerizationError(.internalError, message: "failed to create index for descriptor \(root.digest), media type \(root.mediaType)")
            }
        }

        private func getSupportedPlatforms(for root: Descriptor) async throws -> [ContainerizationOCI.Platform] {
            var supportedPlatforms: [ContainerizationOCI.Platform] = []
            var toProcess = [root]
            while !toProcess.isEmpty {
                let children = try await self.walk(toProcess)
                for child in children {
                    if let p = child.platform {
                        supportedPlatforms.append(p)
                        continue
                    }
                    switch child.mediaType {
                    case MediaTypes.imageConfig, MediaTypes.dockerImageConfig:
                        let config: ContainerizationOCI.Image = try await self.getManifestContent(descriptor: child)
                        let p = ContainerizationOCI.Platform(
                            arch: config.architecture, os: config.os, osFeatures: config.osFeatures, variant: config.variant
                        )
                        supportedPlatforms.append(p)
                    default:
                        continue
                    }
                }
                toProcess = children
            }
            return supportedPlatforms
        }

    }
}


================================================
FILE: Sources/Containerization/Image/ImageStore/ImageStore+OCILayout.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import ContainerizationError
import ContainerizationExtras
import ContainerizationOCI
import Foundation

extension ImageStore {
    /// Exports the specified images and their associated layers to an OCI Image Layout directory.
    /// This function saves the images identified by the `references` array, including their
    /// manifests and layer blobs, into a directory structure compliant with the OCI Image Layout specification at the given `out` URL.
    ///
    /// - Parameters:
    ///   - references: A list image references that exists in the `ImageStore` that are to be saved in the OCI Image Layout format.
    ///   - out: A URL to a directory on disk at which the OCI Image Layout structure will be created.
    ///   - platform: An optional parameter to indicate the platform to be saved for the images.
    ///               Defaults to `nil` signifying that layers for all supported platforms by the images will be saved.
    ///
    public func save(references: [String], out: URL, platform: Platform? = nil) async throws {
        let matcher = createPlatformMatcher(for: platform)
        let fileManager = FileManager.default
        let tempDir = fileManager.uniqueTemporaryDirectory()
        defer {
            try? fileManager.removeItem(at: tempDir)
        }

        var toSave: [Image] = []
        for reference in references {
            let image = try await self.get(reference: reference)
            let allowedMediaTypes = [MediaTypes.dockerManifestList, MediaTypes.index]
            guard allowedMediaTypes.contains(image.mediaType) else {
                throw ContainerizationError(.internalError, message: "cannot save image \(image.reference) with Index media type \(image.mediaType)")
            }
            toSave.append(image)
        }
        let client = try LocalOCILayoutClient(root: out)
        var saved: [Descriptor] = []

        for image in toSave {
            let ref = try Reference.parse(image.reference)
            let name = ref.path
            guard let tag = ref.tag ?? ref.digest else {
                throw ContainerizationError(.invalidArgument, message: "invalid tag/digest for image reference \(image.reference)")
            }
            let operation = ExportOperation(name: name, tag: tag, contentStore: self.contentStore, client: client, progress: nil)
            var descriptor = try await operation.export(index: image.descriptor, platforms: matcher)
            client.setImageReferenceAnnotation(descriptor: &descriptor, reference: image.reference)
            saved.append(descriptor)
        }
        try client.createOCILayoutStructure(directory: out, manifests: saved)
    }

    /// Imports one or more images and their associated layers from an OCI Image Layout directory.
    ///
    /// - Parameters:
    ///   - directory: A URL to a directory on disk at that follows the OCI Image Layout structure.
    ///   - progress: An optional handler over which progress update events about the load operation can be received.
    /// - Returns: The list of images that were loaded into the `ImageStore`.
    ///
    public func load(from directory: URL, progress: ProgressHandler? = nil) async throws -> [Image] {
        let client = try LocalOCILayoutClient(root: directory)
        let index = try client.loadIndexFromOCILayout(directory: directory)
        let matcher = createPlatformMatcher(for: nil)

        var loaded: [Image.Description] = []
        let (id, tempDir) = try await self.contentStore.newIngestSession()
        do {
            for descriptor in index.manifests {
                let reference = client.getImageReferencefromDescriptor(descriptor: descriptor)
                let ref = try Reference.parse(reference)
                let name = ref.path
                let operation = ImportOperation(name: name, contentStore: self.contentStore, client: client, ingestDir: tempDir, progress: progress)
                let indexDesc = try await operation.import(root: descriptor, matcher: matcher)
                loaded.append(Image.Description(reference: reference, descriptor: indexDesc))
            }

            let loadedImages = loaded
            let importedImages = try await self.lock.withLock { lock in
                var images: [Image] = []
                try await self.contentStore.completeIngestSession(id)
                for description in loadedImages {
                    let img = try await self._create(description: description, lock: lock)
                    images.append(img)
                }
                return images
            }
            guard importedImages.count > 0 else {
                throw ContainerizationError(.internalError, message: "failed to import image")
            }
            return importedImages
        } catch {
            try? await self.contentStore.cancelIngestSession(id)
            throw error
        }
    }
}


================================================
FILE: Sources/Containerization/Image/ImageStore/ImageStore+ReferenceManager.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import ContainerizationError
import ContainerizationOCI
import Foundation

extension ImageStore {
    /// A ReferenceManager handles the mappings between an image's
    /// reference and the underlying descriptor inside of a content store.
    internal actor ReferenceManager {
        private let path: URL

        private typealias State = [String: Descriptor]
        private var images: State

        public init(path: URL) throws {
            try FileManager.default.createDirectory(at: path, withIntermediateDirectories: true)

            self.path = path
            self.images = [:]
        }

        private func load() throws -> State {
            let statePath = self.path.appendingPathComponent("state.json")
            guard FileManager.default.fileExists(atPath: statePath.absolutePath()) else {
                return [:]
            }
            do {
                let data = try Data(contentsOf: statePath)
                return try JSONDecoder().decode(State.self, from: data)
            } catch {
                throw ContainerizationError(.internalError, message: "failed to load image state \(error.localizedDescription)")
            }
        }

        private func save(_ state: State) throws {
            let statePath = self.path.appendingPathComponent("state.json")
            try JSONEncoder().encode(state).write(to: statePath)
        }

        public func delete(reference: String) throws {
            var state = try self.load()
            state.removeValue(forKey: reference)
            try self.save(state)
        }

        public func delete(image: Image.Description) throws {
            try self.delete(reference: image.reference)
        }

        public func create(description: Image.Description) throws {
            var state = try self.load()
            state[description.reference] = description.descriptor
            try self.save(state)
        }

        public func list() throws -> [Image.Description] {
            let state = try self.load()
            return state.map { key, val in
                let description = Image.Description(reference: key, descriptor: val)
                return description
            }
        }

        public func get(reference: String) throws -> Image.Description {
            let images = try self.list()
            let hit = images.first(where: { image in
                image.reference == reference
            })
            guard let hit else {
                throw ContainerizationError(.notFound, message: "image \(reference) not found")
            }
            return hit
        }
    }
}


================================================
FILE: Sources/Containerization/Image/ImageStore/ImageStore.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import ContainerizationError
import ContainerizationExtras
import ContainerizationOCI
import Foundation

/// An ImageStore handles the mappings between an image's
/// reference and the underlying descriptor inside of a content store.
public actor ImageStore: Sendable {
    /// The ImageStore path it was created with.
    public nonisolated let path: URL

    private let referenceManager: ReferenceManager
    internal let contentStore: ContentStore
    internal let lock: AsyncLock = AsyncLock()

    public init(path: URL, contentStore: ContentStore? = nil) throws {
        try FileManager.default.createDirectory(at: path, withIntermediateDirectories: true)

        if let contentStore {
            self.contentStore = contentStore
        } else {
            self.contentStore = try LocalContentStore(path: path.appendingPathComponent("content"))
        }

        self.path = path
        self.referenceManager = try ReferenceManager(path: path)
    }

    /// Return the default image store for the current user.
    public static let `default`: ImageStore = {
        do {
            let root = try defaultRoot()
            return try ImageStore(path: root)
        } catch {
            fatalError("unable to initialize default ImageStore \(error)")
        }
    }()

    private static func defaultRoot() throws -> URL {
        let root = FileManager.default.urls(
            for: .applicationSupportDirectory,
            in: .userDomainMask
        ).first
        guard let root else {
            throw ContainerizationError(.notFound, message: "unable to get Application Support directory for current user")
        }
        return root.appendingPathComponent("com.apple.containerization")

    }
}

extension ImageStore {
    /// Get an image from the `ImageStore`.
    ///
    /// - Parameters:
    ///   - reference: Name of the image.
    ///   - pull: Pull the image if it is not found.
    ///
    /// - Returns: A `Containerization.Image`  object whose `reference` matches the given string.
    ///   This  method throws a `ContainerizationError(code: .notFound)` if the provided reference does not exist in the `ImageStore`.
    public func get(reference: String, pull: Bool = false) async throws -> Image {
        do {
            let desc = try await self.referenceManager.get(reference: reference)
            return Image(description: desc, contentStore: self.contentStore)
        } catch let error as ContainerizationError {
            if error.code == .notFound && pull {
                return try await self.pull(reference: reference)
            }
            throw error
        }
    }

    /// Get a list of all images in the `ImageStore`.
    ///
    /// - Returns: A `[Containerization.Image]` for all the images in the `ImageStore`.
    public func list() async throws -> [Image] {
        try await self.referenceManager.list().map { desc in
            Image(description: desc, contentStore: self.contentStore)
        }
    }

    /// Create a new image in the `ImageStore`.
    ///
    /// - Parameters:
    ///   - description: The underlying `Image.Description` that contains information about the reference and index descriptor for the image to be created.
    ///
    /// - Note: It is assumed that the underlying manifests and blob layers for the image already exists in the `ContentStore` that the `ImageStore` was initialized with. This method is invoked when the `pull(...)` , `load(...)` and `tag(...)` methods are used.
    /// - Returns: A `Containerization.Image`
    @discardableResult
    public func create(description: Image.Description) async throws -> Image {
        try await self.lock.withLock { ctx in
            try await self._create(description: description, lock: ctx)
        }
    }

    @discardableResult
    internal func _create(description: Image.Description, lock: AsyncLock.Context) async throws -> Image {
        try await self.referenceManager.create(description: description)
        return Image(description: description, contentStore: self.contentStore)
    }

    /// Delete an image from the `ImageStore`.
    ///
    /// - Parameters:
    ///   - reference: Name of the image that is to be deleted.
    ///   - performCleanup: Perform a garbage collection on the `ContentStore`, removing all unreferenced image layers and manifests,
    public func delete(reference: String, performCleanup: Bool = false) async throws {
        try await self.lock.withLock { lockCtx in
            try await self.referenceManager.delete(reference: reference)
            if performCleanup {
                try await self._cleanUpOrphanedBlobs(lockCtx)
            }
        }
    }

    /// Clean up orphaned blobs that are no longer referenced by any image.
    ///
    /// - Returns: Returns a tuple of `(deleted, freed)`.
    ///   `deleted` :  A  list of the names of the content items that were deleted from the `ContentStore`,
    ///   `freed` : The total size of the items that were deleted.
    @discardableResult
    public func cleanUpOrphanedBlobs() async throws -> (deleted: [String], freed: UInt64) {
        try await self.lock.withLock { lockCtx in
            try await self._cleanUpOrphanedBlobs(lockCtx)
        }
    }

    /// Calculate the size of orphaned blobs without deleting them.
    ///
    /// - Returns: The total size in bytes of blobs that are not referenced by any image.
    public func calculateOrphanedBlobsSize() async throws -> UInt64 {
        try await self.lock.withLock { lockCtx in
            try await self._calculateOrphanedBlobsSize(lockCtx)
        }
    }

    @discardableResult
    private func _cleanUpOrphanedBlobs(_ lock: AsyncLock.Context) async throws -> (deleted: [String], freed: UInt64) {
        let images = try await self.list()
        var referenced: [String] = []
        for image in images {
            try await referenced.append(contentsOf: image.referencedDigests().uniqued())
        }
        let (deleted, size) = try await self.contentStore.delete(keeping: referenced)
        return (deleted, size)
    }

    private func _calculateOrphanedBlobsSize(_ lock: AsyncLock.Context) async throws -> UInt64 {
        let images = try await self.list()
        var referenced: [String] = []
        for image in images {
            try await referenced.append(contentsOf: image.referencedDigests().uniqued())
        }

        // Calculate size of blobs not in the referenced list
        let referencedSet = Set(referenced.map { $0.trimmingDigestPrefix })
        let blobsPath = self.path.appendingPathComponent("content/blobs/sha256")

        let fileManager = FileManager.default
        let allBlobs = try fileManager.contentsOfDirectory(
            at: blobsPath,
            includingPropertiesForKeys: [.fileSizeKey],
            options: [.skipsHiddenFiles]
        )

        var orphanedSize: UInt64 = 0
        for blobURL in allBlobs {
            let digest = blobURL.lastPathComponent
            if !referencedSet.contains(digest) {
                if let resourceValues = try? blobURL.resourceValues(forKeys: [.fileSizeKey]),
                    let size = resourceValues.fileSize
                {
                    orphanedSize += UInt64(size)
                }
            }
        }

        return orphanedSize
    }

    /// Tag an existing image such that it can be referenced by another name.
    ///
    /// - Parameters:
    ///   - existing: The reference to an image that already exists in the `ImageStore`.
    ///   - new: The new reference by which the image should also be referenced as.
    /// - Note: The new image created in the `ImageStore` will have the same `Image.Description`
    ///         as that of the image with reference `existing.`
    /// - Returns: A `Containerization.Image` object to the newly created image.
    public func tag(existing: String, new: String) async throws -> Image {
        let old = try await self.get(reference: existing)
        let descriptor = old.descriptor
        do {
            _ = try Reference.parse(new)
        } catch {
            throw ContainerizationError(.invalidArgument, message: "invalid reference \(new), error: \(error)")
        }
        let newDescription = Image.Description(reference: new, descriptor: descriptor)
        return try await self.create(description: newDescription)
    }
}

extension ImageStore {
    /// Pull an image and its associated manifest and blob layers from a remote registry.
    ///
    /// - Parameters:
    ///   - reference: A string that references an image in a remote registry of the form `<host>[:<port>]/repository:<tag>`
    ///                For example: "docker.io/library/alpine:latest".
    ///   - platform: An optional parameter to indicate the platform to be pulled for the image.
    ///               Defaults to `nil` signifying that layers for all supported platforms by the image will be pulled.
    ///   - insecure: A boolean indicating if the connection to the remote registry should be made via plain-text http or not.
    ///               Defaults to false, meaning the connection to the registry will be over https.
    ///   - auth: An object that implements the `Authentication` protocol,
    ///           used to add any credentials to the HTTP requests that are made to the registry.
    ///           Defaults to `nil` meaning no additional credentials are added to any HTTP requests made to the registry.
    ///   - progress: An optional handler over which progress update events about the pull operation can be received.
    ///
    /// - Returns: A `Containerization.Image` object to the newly pulled image.
    public func pull(
        reference: String, platform: Platform? = nil, insecure: Bool = false,
        auth: Authentication? = nil, progress: ProgressHandler? = nil, maxConcurrentDownloads: Int = 3
    ) async throws -> Image {

        let matcher = createPlatformMatcher(for: platform)
        let client = try RegistryClient(reference: reference, insecure: insecure, auth: auth, tlsConfiguration: TLSUtils.makeEnvironmentAwareTLSConfiguration())

        let ref = try Reference.parse(reference)
        let name = ref.path
        guard let tag = ref.tag ?? ref.digest else {
            throw ContainerizationError(.invalidArgument, message: "invalid tag/digest for image reference \(reference)")
        }

        let rootDescriptor = try await client.resolve(name: name, tag: tag)
        let (id, tempDir) = try await self.contentStore.newIngestSession()
        let operation = ImportOperation(
            name: name, contentStore: self.contentStore, client: client, ingestDir: tempDir, progress: progress, maxConcurrentDownloads: maxConcurrentDownloads)
        do {
            let index = try await operation.import(root: rootDescriptor, matcher: matcher)
            return try await self.lock.withLock { lock in
                try await self.contentStore.completeIngestSession(id)
                let description = Image.Description(reference: reference, descriptor: index)
                let image = try await self._create(description: description, lock: lock)
                return image
            }
        } catch {
            try? await self.contentStore.cancelIngestSession(id)
            throw error
        }
    }

    /// Push an image and its associated manifest and blob layers to a remote registry.
    ///
    /// - Parameters:
    ///   - reference: A string that references an image in the `ImageStore`.  It must be of the form `<host>[:<port>]/repository:<tag>`
    ///                For example: "ghcr.io/foo-bar-baz/image:v1".
    ///   - platform: An optional parameter to indicate the platform to be pushed for the image.
    ///               Defaults to `nil` signifying that layers for all supported platforms by the image will be pushed to the remote registry.
    ///   - insecure: A boolean indicating if the connection to the remote registry should be made via plain-text http or not.
    ///               Defaults to false, meaning the connection to the registry will be over https.
    ///   - auth: An object that implements the `Authentication` protocol,
    ///           used to add any credentials to the HTTP requests that are made to the registry.
    ///           Defaults to `nil` meaning no additional credentials are added to any HTTP requests made to the registry.
    ///   - progress: An optional handler over which progress update events about the push operation can be received.
    ///
    public func push(reference: String, platform: Platform? = nil, insecure: Bool = false, auth: Authentication? = nil, progress: ProgressHandler? = nil) async throws {
        let matcher = createPlatformMatcher(for: platform)
        let img = try await self.get(reference: reference)
        let allowedMediaTypes = [MediaTypes.dockerManifestList, MediaTypes.index]
        guard allowedMediaTypes.contains(img.mediaType) else {
            throw ContainerizationError(.internalError, message: "cannot push image \(reference) with Index media type \(img.mediaType)")
        }
        let ref = try Reference.parse(reference)
        let name = ref.path
        guard let tag = ref.tag ?? ref.digest else {
            throw ContainerizationError(.invalidArgument, message: "invalid tag/digest for image reference \(reference)")
        }
        let client = try RegistryClient(reference: reference, insecure: insecure, auth: auth, tlsConfiguration: TLSUtils.makeEnvironmentAwareTLSConfiguration())
        let operation = ExportOperation(name: name, tag: tag, contentStore: self.contentStore, client: client, progress: progress)
        try await operation.export(index: img.descriptor, platforms: matcher)
    }
}

extension ImageStore {
    /// Get the image for the init block from the image store.
    /// If the image does not exist locally, pull the image.
    public func getInitImage(reference: String, auth: Authentication? = nil, progress: ProgressHandler? = nil) async throws -> InitImage {
        do {
            let image = try await self.get(reference: reference)
            return InitImage(image: image)
        } catch let error as ContainerizationError {
            if error.code == .notFound {
                let image = try await self.pull(reference: reference, auth: auth, progress: progress)
                return InitImage(image: image)
            }
            throw error
        }
    }
}


================================================
FILE: Sources/Containerization/Image/InitImage.swift
================================================
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//===----------------------------------------------------------------------===//

import ContainerizationError
import ContainerizationOCI
import Foundation

/// Data representing the image to use as the root filesystem for a virtual machine.
/// Typically this image would contain the guest agent used to facilitate container
/// workloads, as well as any extras that may be useful to have in the guest.
public struct InitImage: Sendable {
    public var name: String { image.reference }

    let image: Image

    public init(image: Image) {
        self.image = image
    }
}

extension InitImage {
    /// Unpack the initial filesystem for the desired platform at a given path.
    public func initBlock(at: URL, for platform: SystemPlatform) async throws -> Mount {
        let unpacker = EXT4Unpacker(blockSizeInBytes: 512.mib())
Download .txt
gitextract_1u63lgkp/

├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 01-bug.yml
│   │   ├── 02-feature.yml
│   │   └── config.yml
│   └── workflows/
│       ├── build-test-images.yml
│       ├── containerization-build-template.yml
│       ├── containerization-build.yml
│       ├── docs-release.yaml
│       └── release.yml
├── .gitignore
├── .spi.yml
├── .swift-format
├── .swift-format-nolint
├── .swift-version
├── CONTRIBUTING.md
├── LICENSE
├── MAINTAINERS.txt
├── Makefile
├── Package.resolved
├── Package.swift
├── Protobuf.Makefile
├── README.md
├── SECURITY.md
├── Sources/
│   ├── CShim/
│   │   ├── capability.c
│   │   ├── exec_command.c
│   │   ├── include/
│   │   │   ├── capability.h
│   │   │   ├── exec_command.h
│   │   │   ├── openat2.h
│   │   │   ├── prctl.h
│   │   │   ├── socket_helpers.h
│   │   │   └── vsock.h
│   │   ├── openat2.c
│   │   ├── prctl.c
│   │   ├── socket_helpers.c
│   │   └── vsock.c
│   ├── Containerization/
│   │   ├── AttachedFilesystem.swift
│   │   ├── Container.swift
│   │   ├── ContainerManager.swift
│   │   ├── ContainerStatistics.swift
│   │   ├── DNSConfiguration.swift
│   │   ├── ExitStatus.swift
│   │   ├── FileMount.swift
│   │   ├── Hash.swift
│   │   ├── HostsConfiguration.swift
│   │   ├── IO/
│   │   │   ├── ReaderStream.swift
│   │   │   ├── Terminal+ReaderStream.swift
│   │   │   └── Writer.swift
│   │   ├── Image/
│   │   │   ├── Image.swift
│   │   │   ├── ImageStore/
│   │   │   │   ├── ImageStore+Export.swift
│   │   │   │   ├── ImageStore+Import.swift
│   │   │   │   ├── ImageStore+OCILayout.swift
│   │   │   │   ├── ImageStore+ReferenceManager.swift
│   │   │   │   └── ImageStore.swift
│   │   │   ├── InitImage.swift
│   │   │   ├── KernelImage.swift
│   │   │   └── Unpacker/
│   │   │       ├── EXT4Unpacker.swift
│   │   │       └── Unpacker.swift
│   │   ├── Interface.swift
│   │   ├── Kernel.swift
│   │   ├── LinuxContainer.swift
│   │   ├── LinuxPod.swift
│   │   ├── LinuxProcess.swift
│   │   ├── LinuxProcessConfiguration.swift
│   │   ├── Mount.swift
│   │   ├── NATInterface.swift
│   │   ├── NATNetworkInterface.swift
│   │   ├── Network.swift
│   │   ├── SandboxContext/
│   │   │   ├── SandboxContext.grpc.swift
│   │   │   ├── SandboxContext.pb.swift
│   │   │   └── SandboxContext.proto
│   │   ├── SystemPlatform.swift
│   │   ├── TimeSyncer.swift
│   │   ├── UnixSocketConfiguration.swift
│   │   ├── UnixSocketRelay.swift
│   │   ├── UnixSocketRelayManager.swift
│   │   ├── VMConfiguration.swift
│   │   ├── VZVirtualMachine+Helpers.swift
│   │   ├── VZVirtualMachineInstance.swift
│   │   ├── VZVirtualMachineManager.swift
│   │   ├── VirtualMachineAgent+Additions.swift
│   │   ├── VirtualMachineAgent.swift
│   │   ├── VirtualMachineInstance.swift
│   │   ├── VirtualMachineManager.swift
│   │   ├── Vminitd+Rosetta.swift
│   │   ├── Vminitd+SocketRelay.swift
│   │   ├── Vminitd.swift
│   │   ├── VmnetNetwork.swift
│   │   └── VsockListener.swift
│   ├── ContainerizationArchive/
│   │   ├── ArchiveError.swift
│   │   ├── ArchiveReader.swift
│   │   ├── ArchiveWriter.swift
│   │   ├── ArchiveWriterConfiguration.swift
│   │   ├── CArchive/
│   │   │   ├── COPYING
│   │   │   ├── archive_swift_bridge.c
│   │   │   └── include/
│   │   │       ├── archive.h
│   │   │       ├── archive_bridge.h
│   │   │       └── archive_entry.h
│   │   ├── TempDir.swift
│   │   └── WriteEntry.swift
│   ├── ContainerizationEXT4/
│   │   ├── Documentation.docc/
│   │   │   └── ext4.md
│   │   ├── EXT4+Extensions.swift
│   │   ├── EXT4+FileTree.swift
│   │   ├── EXT4+Formatter.swift
│   │   ├── EXT4+Ptr.swift
│   │   ├── EXT4+Reader.swift
│   │   ├── EXT4+Types.swift
│   │   ├── EXT4+Xattrs.swift
│   │   ├── EXT4.swift
│   │   ├── EXT4Reader+Export.swift
│   │   ├── EXT4Reader+IO.swift
│   │   ├── FilePath+Extensions.swift
│   │   ├── FileTimestamps.swift
│   │   ├── Formatter+Unpack.swift
│   │   ├── Integer+Extensions.swift
│   │   ├── README.md
│   │   └── UnsafeLittleEndianBytes.swift
│   ├── ContainerizationError/
│   │   └── ContainerizationError.swift
│   ├── ContainerizationExtras/
│   │   ├── AddressAllocator.swift
│   │   ├── AddressError.swift
│   │   ├── AsyncLock.swift
│   │   ├── AsyncMutex.swift
│   │   ├── CIDR.swift
│   │   ├── CIDRv4.swift
│   │   ├── CIDRv6.swift
│   │   ├── FileManager+Temporary.swift
│   │   ├── IPAddress.swift
│   │   ├── IPv4Address.swift
│   │   ├── IPv6Address+Parse.swift
│   │   ├── IPv6Address.swift
│   │   ├── IndexedAddressAllocator.swift
│   │   ├── MACAddress.swift
│   │   ├── NetworkAddress+Allocator.swift
│   │   ├── Prefix.swift
│   │   ├── ProgressEvent.swift
│   │   ├── ProxyUtils.swift
│   │   ├── RotatingAddressAllocator.swift
│   │   ├── TLSUtils.swift
│   │   ├── Timeout.swift
│   │   └── UInt8+DataBinding.swift
│   ├── ContainerizationIO/
│   │   └── ReadStream.swift
│   ├── ContainerizationNetlink/
│   │   ├── NetlinkSession.swift
│   │   ├── NetlinkSocket.swift
│   │   └── Types.swift
│   ├── ContainerizationOCI/
│   │   ├── AnnotationKeys.swift
│   │   ├── Bundle.swift
│   │   ├── Client/
│   │   │   ├── Authentication.swift
│   │   │   ├── KeychainHelper.swift
│   │   │   ├── LocalOCILayoutClient.swift
│   │   │   ├── RegistryClient+Catalog.swift
│   │   │   ├── RegistryClient+Error.swift
│   │   │   ├── RegistryClient+Fetch.swift
│   │   │   ├── RegistryClient+Push.swift
│   │   │   ├── RegistryClient+Referrers.swift
│   │   │   ├── RegistryClient+Token.swift
│   │   │   └── RegistryClient.swift
│   │   ├── Content/
│   │   │   ├── AsyncTypes.swift
│   │   │   ├── Content.swift
│   │   │   ├── ContentStoreProtocol.swift
│   │   │   ├── ContentWriter.swift
│   │   │   ├── LocalContent.swift
│   │   │   ├── LocalContentStore.swift
│   │   │   ├── SHA256+Extensions.swift
│   │   │   ├── String+Extension.swift
│   │   │   └── URL+Extensions.swift
│   │   ├── Descriptor.swift
│   │   ├── FileManager+Size.swift
│   │   ├── ImageConfig.swift
│   │   ├── Index.swift
│   │   ├── Manifest.swift
│   │   ├── MediaType.swift
│   │   ├── Platform.swift
│   │   ├── Reference.swift
│   │   ├── Spec.swift
│   │   ├── State.swift
│   │   └── Version.swift
│   ├── ContainerizationOS/
│   │   ├── AsyncSignalHandler.swift
│   │   ├── BinaryInteger+Extensions.swift
│   │   ├── Command.swift
│   │   ├── File.swift
│   │   ├── FileDescriptor+SecurePath.swift
│   │   ├── Keychain/
│   │   │   ├── KeychainQuery.swift
│   │   │   └── RegistryInfo.swift
│   │   ├── Linux/
│   │   │   ├── Binfmt.swift
│   │   │   ├── Capabilities.swift
│   │   │   └── Epoll.swift
│   │   ├── Mount/
│   │   │   └── Mount.swift
│   │   ├── POSIXError+Helpers.swift
│   │   ├── Path.swift
│   │   ├── Pipe+Close.swift
│   │   ├── README.md
│   │   ├── Reaper.swift
│   │   ├── Signals.swift
│   │   ├── Socket/
│   │   │   ├── BidirectionalRelay.swift
│   │   │   ├── Socket.swift
│   │   │   ├── SocketType.swift
│   │   │   ├── UnixType.swift
│   │   │   └── VsockType.swift
│   │   ├── Syscall.swift
│   │   ├── Sysctl.swift
│   │   ├── Terminal.swift
│   │   ├── URL+Extensions.swift
│   │   └── User.swift
│   ├── Integration/
│   │   ├── ContainerTests.swift
│   │   ├── PodTests.swift
│   │   └── Suite.swift
│   └── cctl/
│       ├── ImageCommand.swift
│       ├── KernelCommand.swift
│       ├── LoginCommand.swift
│       ├── RootfsCommand.swift
│       ├── RunCommand.swift
│       ├── cctl+Utils.swift
│       └── cctl.swift
├── Tests/
│   ├── ContainerizationArchiveTests/
│   │   ├── ArchiveReaderTests.swift
│   │   ├── ArchiveTests.swift
│   │   └── Resources/
│   │       └── test.tar.zst
│   ├── ContainerizationEXT4Tests/
│   │   ├── Resources/
│   │   │   └── content/
│   │   │       └── blobs/
│   │   │           └── sha256/
│   │   │               ├── 48a06049d3738991b011ca8b12473d712b7c40666a1462118dae3c403676afc2
│   │   │               ├── 4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1
│   │   │               ├── 8e2eb240a6cd7be1a0d308125afe0060b020e89275ced2e729eda7d4eeff62a2
│   │   │               ├── ad59e9f71edceca7b1ac7c642410858489b743c97233b0a26a5e2098b1443762
│   │   │               └── c6b39de5b33961661dc939b997cc1d30cda01e38005a6c6625fd9c7e748bab44
│   │   ├── TestEXT4ExtendedAttributes.swift
│   │   ├── TestEXT4Format+Create.swift
│   │   ├── TestEXT4Format.swift
│   │   ├── TestEXT4Reader+IO.swift
│   │   ├── TestEXT4Unpacker.swift
│   │   └── TestFormatterUnpack.swift
│   ├── ContainerizationExtrasTests/
│   │   ├── AsyncMutexTests.swift
│   │   ├── ProxyUtilsTests.swift
│   │   ├── TestCIDR.swift
│   │   ├── TestIPAddress.swift
│   │   ├── TestIPv4Address.swift
│   │   ├── TestIPv6Address+Parse.swift
│   │   ├── TestIPv6Address.swift
│   │   ├── TestIPv6IPv4Parsing.swift
│   │   ├── TestMACAddress.swift
│   │   ├── TestNetworkAddress+Allocator.swift
│   │   ├── TestPrefix.swift
│   │   ├── TestTimeout.swift
│   │   └── UInt8+DataBindingTest.swift
│   ├── ContainerizationNetlinkTests/
│   │   ├── MockNetlinkSocket.swift
│   │   ├── NetlinkSessionTest.swift
│   │   └── TypesTest.swift
│   ├── ContainerizationOCITests/
│   │   ├── AuthChallengeTests.swift
│   │   ├── OCIImageTests.swift
│   │   ├── OCIPlatformTests.swift
│   │   ├── OCISpecTests.swift
│   │   ├── ReferenceTests.swift
│   │   └── RegistryClientTests.swift
│   ├── ContainerizationOSTests/
│   │   ├── FileDescriptor+SecurePathTests.swift
│   │   ├── KeychainQueryTests.swift
│   │   ├── SocketTests.swift
│   │   └── UserTests.swift
│   ├── ContainerizationTests/
│   │   ├── ContainerManagerTests.swift
│   │   ├── DNSTests.swift
│   │   ├── HashTests.swift
│   │   ├── HostsTests.swift
│   │   ├── ImageTests/
│   │   │   ├── ContainsAuth.swift
│   │   │   ├── ImageStoreImagePullTests.swift
│   │   │   └── ImageStoreTests.swift
│   │   ├── ImageTests.swift
│   │   ├── KernelTests.swift
│   │   ├── LinuxContainerTests.swift
│   │   └── MountTests.swift
│   └── TestImages/
│       ├── dockermanifestimage/
│       │   └── Dockerfile
│       └── emptyimage/
│           └── Dockerfile
├── examples/
│   ├── README.md
│   └── ctr-example/
│       ├── Makefile
│       ├── Package.resolved
│       ├── Package.swift
│       ├── README.md
│       ├── Sources/
│       │   └── ctr-example/
│       │       └── main.swift
│       ├── ctr-example.entitlements
│       └── lab.md
├── kernel/
│   ├── Makefile
│   ├── README.md
│   ├── build.sh
│   ├── config-arm64
│   └── image/
│       ├── Dockerfile
│       └── sources.list
├── licenserc.toml
├── scripts/
│   ├── check-integration-test-vm-panics.sh
│   ├── cz-header-style.toml
│   ├── ensure-hawkeye-exists.sh
│   ├── install-hawkeye.sh
│   ├── license-header.txt
│   ├── make-docs.sh
│   └── pre-commit.fmt
├── signing/
│   └── vz.entitlements
└── vminitd/
    ├── .devcontainer/
    │   ├── Dockerfile
    │   └── devcontainer.json
    ├── Makefile
    ├── Package.resolved
    ├── Package.swift
    └── Sources/
        ├── Cgroup/
        │   └── Cgroup2Manager.swift
        ├── LCShim/
        │   ├── include/
        │   │   └── syscall.h
        │   └── syscall.c
        ├── vmexec/
        │   ├── Console.swift
        │   ├── ExecCommand.swift
        │   ├── Mount.swift
        │   ├── RunCommand.swift
        │   └── vmexec.swift
        └── vminitd/
            ├── AgentCommand.swift
            ├── Application.swift
            ├── CommandRunner.swift
            ├── ContainerProcess.swift
            ├── HostStdio.swift
            ├── IOCloser+Extensions.swift
            ├── IOCloser.swift
            ├── IOPair.swift
            ├── InitCommand.swift
            ├── ManagedContainer.swift
            ├── ManagedProcess.swift
            ├── MemoryMonitor.swift
            ├── OSFile+Splice.swift
            ├── OSFile.swift
            ├── PauseCommand.swift
            ├── ProcessSupervisor.swift
            ├── Runc/
            │   ├── ConsoleSocket.swift
            │   └── Runc.swift
            ├── RuncProcess.swift
            ├── Server+GRPC.swift
            ├── Server.swift
            ├── StandardIO.swift
            ├── TerminalIO.swift
            └── VsockProxy.swift
Download .txt
SYMBOL INDEX (501 symbols across 13 files)

FILE: Sources/CShim/capability.c
  function CZ_capget (line 24) | int CZ_capget(void *header, void *data) {
  function CZ_capset (line 28) | int CZ_capset(void *header, void *data) {

FILE: Sources/CShim/exec_command.c
  function mark_cloexec (line 49) | static int mark_cloexec(int fd) {
  function cloexec_from (line 58) | static int cloexec_from(int min_fd) {
  function exec_command_attrs_init (line 95) | void exec_command_attrs_init(struct exec_command_attrs *attrs) {
  function child_handler (line 108) | static void child_handler(const int sync_pipes[2], const char *executable,
  function exec_command (line 317) | int exec_command(pid_t *result, const char *executable, char *const args[],

FILE: Sources/CShim/include/exec_command.h
  type exec_command_attrs (line 25) | struct exec_command_attrs {
  type exec_command_attrs (line 47) | struct exec_command_attrs
  type exec_command_attrs (line 53) | struct exec_command_attrs

FILE: Sources/CShim/include/openat2.h
  type cz_open_how (line 26) | struct cz_open_how {
  type cz_open_how (line 34) | struct cz_open_how

FILE: Sources/CShim/include/socket_helpers.h
  type cmsghdr (line 24) | struct cmsghdr
  type msghdr (line 24) | struct msghdr
  type cmsghdr (line 25) | struct cmsghdr

FILE: Sources/CShim/openat2.c
  function CZ_openat2 (line 28) | int CZ_openat2(int dirfd, const char *pathname, struct cz_open_how *how,

FILE: Sources/CShim/prctl.c
  function CZ_prctl_set_keepcaps (line 23) | int CZ_prctl_set_keepcaps() {
  function CZ_prctl_clear_keepcaps (line 28) | int CZ_prctl_clear_keepcaps() {
  function CZ_prctl_capbset_drop (line 33) | int CZ_prctl_capbset_drop(unsigned int capability) {
  function CZ_prctl_cap_ambient_clear_all (line 38) | int CZ_prctl_cap_ambient_clear_all() {
  function CZ_prctl_cap_ambient_raise (line 43) | int CZ_prctl_cap_ambient_raise(unsigned int capability) {

FILE: Sources/CShim/socket_helpers.c
  type cmsghdr (line 19) | struct cmsghdr
  type msghdr (line 19) | struct msghdr
  type cmsghdr (line 23) | struct cmsghdr
  function CZ_CMSG_SPACE (line 27) | size_t CZ_CMSG_SPACE(size_t length) {
  function CZ_CMSG_LEN (line 31) | size_t CZ_CMSG_LEN(size_t length) {

FILE: Sources/ContainerizationArchive/CArchive/archive_swift_bridge.c
  function archive_set_error_wrapper (line 22) | void archive_set_error_wrapper(struct archive *a, int error_number, cons...
  function zstd_decompress_fd (line 26) | int zstd_decompress_fd(int src_fd, int dst_fd) {

FILE: Sources/ContainerizationArchive/CArchive/include/archive.h
  type __int64 (line 65) | typedef __int64 la_int64_t;
  type la_int64_t (line 69) | typedef long long la_int64_t;
  type la_int64_t (line 71) | typedef int64_t la_int64_t;
  type la_ssize_t (line 85) | typedef ssize_t la_ssize_t;
  type __int64 (line 87) | typedef __int64 la_ssize_t;
  type la_ssize_t (line 89) | typedef long la_ssize_t;
  type la_ssize_t (line 93) | typedef ssize_t la_ssize_t;
  type archive (line 183) | struct archive
  type archive_entry (line 184) | struct archive_entry
  type la_ssize_t (line 222) | typedef la_ssize_t	archive_read_callback(struct archive *,
  type la_int64_t (line 230) | typedef la_int64_t	archive_skip_callback(struct archive *,
  type la_int64_t (line 237) | typedef la_int64_t	archive_seek_callback(struct archive *,
  type la_ssize_t (line 241) | typedef la_ssize_t	archive_write_callback(struct archive *,
  type archive (line 245) | struct archive
  type archive (line 247) | struct archive
  type archive (line 249) | struct archive
  type archive (line 255) | struct archive
  type archive (line 262) | struct archive
  type archive (line 395) | struct archive
  type archive (line 397) | struct archive
  type archive (line 399) | struct archive
  type archive (line 401) | struct archive
  type archive (line 403) | struct archive
  type archive (line 405) | struct archive
  type archive (line 407) | struct archive
  type archive (line 409) | struct archive
  type archive (line 412) | struct archive
  type archive (line 415) | struct archive
  type archive (line 417) | struct archive
  type archive (line 419) | struct archive
  type archive (line 423) | struct archive
  type archive (line 424) | struct archive
  type archive (line 425) | struct archive
  type archive (line 426) | struct archive
  type archive (line 427) | struct archive
  type archive (line 428) | struct archive
  type archive (line 429) | struct archive
  type archive (line 430) | struct archive
  type archive (line 431) | struct archive
  type archive (line 432) | struct archive
  type archive (line 433) | struct archive
  type archive (line 434) | struct archive
  type archive (line 435) | struct archive
  type archive (line 438) | struct archive
  type archive (line 440) | struct archive
  type archive (line 441) | struct archive
  type archive (line 442) | struct archive
  type archive (line 443) | struct archive
  type archive (line 445) | struct archive
  type archive (line 446) | struct archive
  type archive (line 447) | struct archive
  type archive (line 448) | struct archive
  type archive (line 449) | struct archive
  type archive (line 450) | struct archive
  type archive (line 451) | struct archive
  type archive (line 452) | struct archive
  type archive (line 453) | struct archive
  type archive (line 454) | struct archive
  type archive (line 455) | struct archive
  type archive (line 456) | struct archive
  type archive (line 457) | struct archive
  type archive (line 458) | struct archive
  type archive (line 459) | struct archive
  type archive (line 460) | struct archive
  type archive (line 461) | struct archive
  type archive (line 464) | struct archive
  type archive (line 468) | struct archive
  type archive (line 470) | struct archive
  type archive (line 476) | struct archive
  type archive (line 477) | struct archive
  type archive (line 478) | struct archive
  type archive (line 481) | struct archive
  type archive (line 484) | struct archive
  type archive (line 486) | struct archive
  type archive (line 488) | struct archive
  type archive (line 490) | struct archive
  type archive (line 492) | struct archive
  type archive (line 495) | struct archive
  type archive (line 499) | struct archive
  type archive (line 501) | struct archive
  type archive (line 504) | struct archive
  type archive (line 507) | struct archive
  type archive (line 509) | struct archive
  type archive (line 512) | struct archive
  type archive (line 515) | struct archive
  type archive (line 518) | struct archive
  type archive (line 528) | struct archive
  type archive (line 532) | struct archive
  type archive (line 534) | struct archive
  type archive (line 537) | struct archive
  type archive (line 541) | struct archive
  type archive (line 544) | struct archive
  type archive (line 547) | struct archive
  type archive (line 550) | struct archive
  type archive (line 554) | struct archive
  type archive (line 557) | struct archive
  type archive_entry (line 558) | struct archive_entry
  type archive (line 561) | struct archive
  type archive_entry (line 562) | struct archive_entry
  type archive (line 568) | struct archive
  type archive (line 588) | struct archive
  type archive (line 594) | struct archive
  type archive (line 597) | struct archive
  type archive (line 601) | struct archive
  type archive (line 609) | struct archive
  type archive (line 618) | struct archive
  type archive (line 619) | struct archive
  type archive (line 625) | struct archive
  type archive (line 629) | struct archive
  type archive (line 633) | struct archive
  type archive (line 637) | struct archive
  type archive (line 643) | struct archive
  type archive (line 644) | struct archive
  type archive (line 707) | struct archive
  type archive_entry (line 707) | struct archive_entry
  type archive (line 709) | struct archive
  type archive_entry (line 709) | struct archive_entry
  type archive (line 710) | struct archive
  type archive (line 711) | struct archive
  type archive (line 716) | struct archive
  type archive (line 720) | struct archive
  type archive (line 723) | struct archive
  type archive (line 726) | struct archive
  type archive (line 745) | struct archive
  type archive (line 747) | struct archive
  type archive (line 749) | struct archive
  type archive (line 751) | struct archive
  type archive (line 755) | struct archive
  type archive (line 759) | struct archive
  type archive (line 761) | struct archive
  type archive (line 763) | struct archive
  type archive (line 765) | struct archive
  type archive (line 767) | struct archive
  type archive (line 769) | struct archive
  type archive (line 771) | struct archive
  type archive (line 773) | struct archive
  type archive (line 778) | struct archive
  type archive (line 779) | struct archive
  type archive (line 781) | struct archive
  type archive (line 782) | struct archive
  type archive (line 783) | struct archive
  type archive (line 784) | struct archive
  type archive (line 785) | struct archive
  type archive (line 786) | struct archive
  type archive (line 787) | struct archive
  type archive (line 788) | struct archive
  type archive (line 789) | struct archive
  type archive (line 790) | struct archive
  type archive (line 791) | struct archive
  type archive (line 792) | struct archive
  type archive (line 794) | struct archive
  type archive (line 795) | struct archive
  type archive (line 796) | struct archive
  type archive (line 800) | struct archive
  type archive (line 801) | struct archive
  type archive (line 804) | struct archive
  type archive (line 805) | struct archive
  type archive (line 806) | struct archive
  type archive (line 807) | struct archive
  type archive (line 808) | struct archive
  type archive (line 809) | struct archive
  type archive (line 810) | struct archive
  type archive (line 811) | struct archive
  type archive (line 812) | struct archive
  type archive (line 813) | struct archive
  type archive (line 814) | struct archive
  type archive (line 815) | struct archive
  type archive (line 817) | struct archive
  type archive (line 818) | struct archive
  type archive (line 819) | struct archive
  type archive (line 820) | struct archive
  type archive (line 821) | struct archive
  type archive (line 822) | struct archive
  type archive (line 823) | struct archive
  type archive (line 824) | struct archive
  type archive (line 825) | struct archive
  type archive (line 826) | struct archive
  type archive (line 827) | struct archive
  type archive (line 828) | struct archive
  type archive (line 829) | struct archive
  type archive (line 830) | struct archive
  type archive (line 832) | struct archive
  type archive (line 835) | struct archive
  type archive (line 838) | struct archive
  type archive (line 839) | struct archive
  type archive (line 840) | struct archive
  type archive (line 843) | struct archive
  type archive (line 845) | struct archive
  type archive (line 848) | struct archive
  type archive (line 855) | struct archive
  type archive_entry (line 856) | struct archive_entry
  type archive (line 857) | struct archive
  type archive (line 861) | struct archive
  type archive (line 864) | struct archive
  type archive (line 865) | struct archive
  type archive (line 869) | struct archive
  type archive (line 872) | struct archive
  type archive (line 875) | struct archive
  type archive (line 882) | struct archive
  type archive (line 886) | struct archive
  type archive (line 890) | struct archive
  type archive (line 894) | struct archive
  type archive (line 900) | struct archive
  type archive (line 901) | struct archive
  type archive (line 922) | struct archive
  type archive (line 926) | struct archive
  type archive (line 945) | struct archive
  type archive (line 951) | struct archive
  type archive (line 955) | struct archive
  type archive (line 959) | struct archive
  type archive (line 960) | struct archive
  type archive (line 971) | struct archive
  type archive (line 973) | struct archive
  type archive (line 975) | struct archive
  type archive (line 977) | struct archive
  type archive_entry (line 978) | struct archive_entry
  type stat (line 978) | struct stat
  type archive (line 981) | struct archive
  type archive (line 982) | struct archive
  type archive (line 985) | struct archive
  type archive (line 987) | struct archive
  type archive (line 991) | struct archive
  type archive (line 996) | struct archive
  type archive (line 997) | struct archive
  type archive (line 1005) | struct archive
  type archive (line 1006) | struct archive
  type archive (line 1007) | struct archive
  type archive (line 1008) | struct archive
  type archive (line 1009) | struct archive
  type archive (line 1011) | struct archive
  type archive (line 1034) | struct archive
  type archive (line 1043) | struct archive
  type archive (line 1044) | struct archive
  type archive (line 1045) | struct archive
  type archive_entry (line 1045) | struct archive_entry
  type archive (line 1047) | struct archive
  type archive (line 1048) | struct archive
  type archive_entry (line 1049) | struct archive_entry
  type archive (line 1053) | struct archive
  type archive (line 1064) | struct archive
  type archive (line 1065) | struct archive
  type archive (line 1066) | struct archive
  type archive (line 1067) | struct archive
  type archive (line 1073) | struct archive
  type archive (line 1076) | struct archive
  type archive (line 1079) | struct archive
  type archive (line 1082) | struct archive
  type archive (line 1086) | struct archive
  type archive (line 1087) | struct archive
  type archive (line 1088) | struct archive
  type archive (line 1089) | struct archive
  type archive (line 1090) | struct archive
  type archive (line 1091) | struct archive
  type archive (line 1093) | struct archive
  type archive (line 1094) | struct archive
  type archive (line 1095) | struct archive
  type archive (line 1101) | struct archive
  type archive (line 1109) | struct archive
  type archive_entry (line 1110) | struct archive_entry
  type archive (line 1115) | struct archive
  type archive_entry (line 1116) | struct archive_entry
  type archive (line 1118) | struct archive
  type archive (line 1120) | struct archive
  type archive (line 1121) | struct archive
  type archive (line 1124) | struct archive
  type archive (line 1126) | struct archive
  type archive (line 1129) | struct archive
  type archive (line 1130) | struct archive
  type archive (line 1133) | struct archive
  type archive (line 1135) | struct archive
  type archive (line 1141) | struct archive
  type archive (line 1145) | struct archive
  type archive (line 1147) | struct archive
  type archive (line 1153) | struct archive
  type archive_entry (line 1154) | struct archive_entry
  type archive (line 1171) | struct archive
  type archive (line 1174) | struct archive
  type archive (line 1176) | struct archive
  type archive (line 1179) | struct archive
  type archive (line 1181) | struct archive
  type archive (line 1184) | struct archive
  type archive_entry (line 1185) | struct archive_entry
  type archive (line 1191) | struct archive
  type archive_entry (line 1192) | struct archive_entry
  type archive (line 1194) | struct archive
  type archive (line 1195) | struct archive
  type archive (line 1196) | struct archive
  type archive (line 1197) | struct archive
  type archive (line 1199) | struct archive
  type archive (line 1200) | struct archive

FILE: Sources/ContainerizationArchive/CArchive/include/archive_bridge.h
  type archive (line 8) | struct archive

FILE: Sources/ContainerizationArchive/CArchive/include/archive_entry.h
  type __int64 (line 57) | typedef __int64 la_int64_t;
  type la_int64_t (line 61) | typedef long long la_int64_t;
  type la_int64_t (line 63) | typedef int64_t la_int64_t;
  type la_ssize_t (line 77) | typedef ssize_t la_ssize_t;
  type __int64 (line 79) | typedef __int64 la_ssize_t;
  type la_ssize_t (line 81) | typedef long la_ssize_t;
  type la_ssize_t (line 85) | typedef ssize_t la_ssize_t;
  type archive (line 156) | struct archive
  type archive_entry (line 157) | struct archive_entry
  type archive_entry (line 204) | struct archive_entry
  type archive_entry (line 206) | struct archive_entry
  type archive_entry (line 207) | struct archive_entry
  type archive (line 217) | struct archive
  type archive_entry (line 238) | struct archive_entry
  type archive_entry (line 239) | struct archive_entry
  type archive_entry (line 240) | struct archive_entry
  type archive_entry (line 241) | struct archive_entry
  type archive_entry (line 242) | struct archive_entry
  type archive_entry (line 243) | struct archive_entry
  type archive_entry (line 244) | struct archive_entry
  type archive_entry (line 245) | struct archive_entry
  type archive_entry (line 246) | struct archive_entry
  type archive_entry (line 247) | struct archive_entry
  type archive_entry (line 248) | struct archive_entry
  type archive_entry (line 249) | struct archive_entry
  type archive_entry (line 250) | struct archive_entry
  type archive_entry (line 251) | struct archive_entry
  type archive_entry (line 252) | struct archive_entry
  type archive_entry (line 253) | struct archive_entry
  type archive_entry (line 256) | struct archive_entry
  type archive_entry (line 257) | struct archive_entry
  type archive_entry (line 258) | struct archive_entry
  type archive_entry (line 259) | struct archive_entry
  type archive_entry (line 260) | struct archive_entry
  type archive_entry (line 261) | struct archive_entry
  type archive_entry (line 262) | struct archive_entry
  type archive_entry (line 263) | struct archive_entry
  type archive_entry (line 264) | struct archive_entry
  type archive_entry (line 265) | struct archive_entry
  type archive_entry (line 266) | struct archive_entry
  type archive_entry (line 267) | struct archive_entry
  type archive_entry (line 268) | struct archive_entry
  type archive_entry (line 269) | struct archive_entry
  type archive_entry (line 270) | struct archive_entry
  type archive_entry (line 271) | struct archive_entry
  type archive_entry (line 272) | struct archive_entry
  type archive_entry (line 273) | struct archive_entry
  type archive_entry (line 274) | struct archive_entry
  type archive_entry (line 275) | struct archive_entry
  type archive_entry (line 276) | struct archive_entry
  type archive_entry (line 277) | struct archive_entry
  type archive_entry (line 278) | struct archive_entry
  type archive_entry (line 279) | struct archive_entry
  type archive_entry (line 280) | struct archive_entry
  type archive_entry (line 281) | struct archive_entry
  type archive_entry (line 282) | struct archive_entry
  type archive_entry (line 283) | struct archive_entry
  type archive_entry (line 284) | struct archive_entry
  type archive_entry (line 285) | struct archive_entry
  type archive_entry (line 286) | struct archive_entry
  type archive_entry (line 287) | struct archive_entry
  type archive_entry (line 288) | struct archive_entry
  type archive_entry (line 289) | struct archive_entry
  type archive_entry (line 290) | struct archive_entry
  type archive_entry (line 291) | struct archive_entry
  type archive_entry (line 292) | struct archive_entry
  type archive_entry (line 293) | struct archive_entry
  type archive_entry (line 294) | struct archive_entry
  type archive_entry (line 295) | struct archive_entry
  type archive_entry (line 296) | struct archive_entry
  type archive_entry (line 297) | struct archive_entry
  type archive_entry (line 298) | struct archive_entry
  type archive_entry (line 299) | struct archive_entry
  type archive_entry (line 300) | struct archive_entry
  type archive_entry (line 301) | struct archive_entry
  type archive_entry (line 312) | struct archive_entry
  type archive_entry (line 313) | struct archive_entry
  type archive_entry (line 315) | struct archive_entry
  type archive_entry (line 317) | struct archive_entry
  type archive_entry (line 318) | struct archive_entry
  type archive_entry (line 319) | struct archive_entry
  type archive_entry (line 320) | struct archive_entry
  type archive_entry (line 321) | struct archive_entry
  type archive_entry (line 322) | struct archive_entry
  type archive_entry (line 323) | struct archive_entry
  type archive_entry (line 324) | struct archive_entry
  type archive_entry (line 325) | struct archive_entry
  type archive_entry (line 329) | struct archive_entry
  type archive_entry (line 331) | struct archive_entry
  type archive_entry (line 333) | struct archive_entry
  type archive_entry (line 335) | struct archive_entry
  type archive_entry (line 336) | struct archive_entry
  type archive_entry (line 337) | struct archive_entry
  type archive_entry (line 338) | struct archive_entry
  type archive_entry (line 339) | struct archive_entry
  type archive_entry (line 340) | struct archive_entry
  type archive_entry (line 341) | struct archive_entry
  type archive_entry (line 342) | struct archive_entry
  type archive_entry (line 343) | struct archive_entry
  type archive_entry (line 344) | struct archive_entry
  type archive_entry (line 345) | struct archive_entry
  type archive_entry (line 346) | struct archive_entry
  type archive_entry (line 347) | struct archive_entry
  type archive_entry (line 348) | struct archive_entry
  type archive_entry (line 349) | struct archive_entry
  type archive_entry (line 350) | struct archive_entry
  type archive_entry (line 351) | struct archive_entry
  type archive_entry (line 352) | struct archive_entry
  type archive_entry (line 353) | struct archive_entry
  type archive_entry (line 354) | struct archive_entry
  type archive_entry (line 355) | struct archive_entry
  type archive_entry (line 356) | struct archive_entry
  type archive_entry (line 357) | struct archive_entry
  type archive_entry (line 358) | struct archive_entry
  type archive_entry (line 359) | struct archive_entry
  type archive_entry (line 360) | struct archive_entry
  type archive_entry (line 361) | struct archive_entry
  type archive_entry (line 362) | struct archive_entry
  type archive_entry (line 363) | struct archive_entry
  type archive_entry (line 364) | struct archive_entry
  type archive_entry (line 365) | struct archive_entry
  type archive_entry (line 366) | struct archive_entry
  type archive_entry (line 367) | struct archive_entry
  type archive_entry (line 368) | struct archive_entry
  type archive_entry (line 369) | struct archive_entry
  type archive_entry (line 370) | struct archive_entry
  type archive_entry (line 371) | struct archive_entry
  type archive_entry (line 372) | struct archive_entry
  type archive_entry (line 373) | struct archive_entry
  type archive_entry (line 374) | struct archive_entry
  type archive_entry (line 375) | struct archive_entry
  type archive_entry (line 376) | struct archive_entry
  type archive_entry (line 377) | struct archive_entry
  type archive_entry (line 378) | struct archive_entry
  type archive_entry (line 379) | struct archive_entry
  type archive_entry (line 380) | struct archive_entry
  type archive_entry (line 381) | struct archive_entry
  type archive_entry (line 382) | struct archive_entry
  type archive_entry (line 383) | struct archive_entry
  type archive_entry (line 396) | struct archive_entry
  type archive_entry (line 397) | struct archive_entry
  type stat (line 397) | struct stat
  type archive_entry (line 406) | struct archive_entry
  type archive_entry (line 407) | struct archive_entry
  type archive_entry (line 420) | struct archive_entry
  type archive_entry (line 533) | struct archive_entry
  type archive_entry (line 534) | struct archive_entry
  type archive_entry (line 537) | struct archive_entry
  type archive_entry (line 546) | struct archive_entry
  type archive_entry (line 547) | struct archive_entry
  type archive_entry (line 579) | struct archive_entry
  type archive_entry (line 581) | struct archive_entry
  type archive_entry (line 583) | struct archive_entry
  type archive_entry (line 585) | struct archive_entry
  type archive_entry (line 593) | struct archive_entry
  type archive_entry (line 595) | struct archive_entry
  type archive_entry (line 599) | struct archive_entry
  type archive_entry (line 602) | struct archive_entry
  type archive_acl (line 606) | struct archive_acl
  type archive_entry (line 607) | struct archive_entry
  type archive_entry (line 613) | struct archive_entry
  type archive_entry (line 614) | struct archive_entry
  type archive_entry (line 623) | struct archive_entry
  type archive_entry (line 624) | struct archive_entry
  type archive_entry (line 625) | struct archive_entry
  type archive_entry (line 632) | struct archive_entry
  type archive_entry (line 633) | struct archive_entry
  type archive_entry (line 641) | struct archive_entry
  type archive_entry (line 642) | struct archive_entry
  type archive_entry (line 643) | struct archive_entry
  type archive_entry_linkresolver (line 674) | struct archive_entry_linkresolver
  type archive_entry_linkresolver (line 718) | struct archive_entry_linkresolver
  type archive_entry_linkresolver (line 719) | struct archive_entry_linkresolver
  type archive_entry_linkresolver (line 720) | struct archive_entry_linkresolver
  type archive_entry (line 721) | struct archive_entry
  type archive_entry (line 721) | struct archive_entry
  type archive_entry_linkresolver (line 723) | struct archive_entry_linkresolver

FILE: vminitd/Sources/LCShim/syscall.c
  function CZ_pivot_root (line 23) | int CZ_pivot_root(const char *new_root, const char *put_old) {
  function CZ_set_sub_reaper (line 27) | int CZ_set_sub_reaper() { return prctl(PR_SET_CHILD_SUBREAPER, 1); }
  function CZ_pidfd_open (line 29) | int CZ_pidfd_open(pid_t pid, unsigned int flags) {
  function CZ_pidfd_getfd (line 34) | int CZ_pidfd_getfd(int pidfd, int targetfd, unsigned int flags) {
  function CZ_prctl_set_no_new_privs (line 39) | int CZ_prctl_set_no_new_privs() {
Condensed preview — 324 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,838K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/01-bug.yml",
    "chars": 2151,
    "preview": "name: Bug report\ndescription: File a bug report.\ntitle: \"[Bug]: \"\ntype: \"Bug\"\nbody:\n  - type: markdown\n    attributes:\n "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/02-feature.yml",
    "chars": 982,
    "preview": "name: Feature or enhancement request\ndescription: File a request for a feature or enhancement\ntitle: \"[Request]: \"\ntype:"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 193,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Containerization community support\n    url: https://github.com/appl"
  },
  {
    "path": ".github/workflows/build-test-images.yml",
    "chars": 2456,
    "preview": "name: Build and publish containerization test images\n\npermissions:\n  contents: read\n\non: \n  workflow_dispatch: \n    inpu"
  },
  {
    "path": ".github/workflows/containerization-build-template.yml",
    "chars": 3861,
    "preview": "name: Build containerization template\n\npermissions:\n  contents: read\n\non: \n  workflow_call:\n    inputs:\n      release:\n "
  },
  {
    "path": ".github/workflows/containerization-build.yml",
    "chars": 1667,
    "preview": "name: Build containerization\n\npermissions:\n  contents: read\n\non:\n  pull_request:\n    types: [opened, reopened, synchroni"
  },
  {
    "path": ".github/workflows/docs-release.yaml",
    "chars": 1178,
    "preview": "# Manual workflow for releasing docs ad-hoc. Workflow can only be run for main or release branches. \n# Workflow does NOT"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 1309,
    "preview": "name: Release containerization\n\npermissions:\n  contents: read\n\non: \n  push: \n    tags:\n      - \"[0-9]+\\\\.[0-9]+\\\\.[0-9]+"
  },
  {
    "path": ".gitignore",
    "chars": 246,
    "preview": ".DS_Store\nbin\nlibexec\n.build\n.local\nxcuserdata/\nDerivedData/\n.swiftpm/\n.netrc\n.swiftpm\nworkdir/\ninstaller/\n.venv/\ntest_r"
  },
  {
    "path": ".spi.yml",
    "chars": 281,
    "preview": "version: 1\nbuilder:\n  configs:\n    - documentation_targets: [Containerization, ContainerizationEXT4, ContainerizationOS,"
  },
  {
    "path": ".swift-format",
    "chars": 2372,
    "preview": "{\n  \"fileScopedDeclarationPrivacy\" : {\n    \"accessLevel\" : \"private\"\n  },\n  \"indentation\" : {\n    \"spaces\" : 4\n  },\n  \"i"
  },
  {
    "path": ".swift-format-nolint",
    "chars": 2395,
    "preview": "{\n  \"fileScopedDeclarationPrivacy\" : {\n    \"accessLevel\" : \"private\"\n  },\n  \"indentation\" : {\n    \"spaces\" : 4\n  },\n  \"i"
  },
  {
    "path": ".swift-version",
    "chars": 23,
    "preview": "6.3-snapshot-2026-02-27"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 6321,
    "preview": "# 🌈 📦️ Welcome to the Containerization community! 📦️ 🌈\n\nContributions to Containerization are welcomed and encouraged.\n\n"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "MAINTAINERS.txt",
    "chars": 622,
    "preview": "This file contains a list of maintainers and past maintainers who have made meaningful changes to this repository.\n\n### "
  },
  {
    "path": "Makefile",
    "chars": 6664,
    "preview": "# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n#\n# Licensed under the Apache License, Vers"
  },
  {
    "path": "Package.resolved",
    "chars": 7063,
    "preview": "{\n  \"originHash\" : \"8b51a9ec068537ab57ce9b8034b5b84a02a4697e4a6be491954e5fbda7e5783b\",\n  \"pins\" : [\n    {\n      \"identit"
  },
  {
    "path": "Package.swift",
    "chars": 11006,
    "preview": "// swift-tools-version: 6.2\n//===----------------------------------------------------------------------===//\n// Copyrigh"
  },
  {
    "path": "Protobuf.Makefile",
    "chars": 2047,
    "preview": "# Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n#\n# Licensed under the Apache License, Vers"
  },
  {
    "path": "README.md",
    "chars": 7290,
    "preview": "# Containerization\n\nThe Containerization package allows applications to use Linux containers.\nContainerization is writte"
  },
  {
    "path": "SECURITY.md",
    "chars": 1489,
    "preview": "# Security disclosure process\n\nIf you believe that you have discovered a security or privacy vulnerability in our open s"
  },
  {
    "path": "Sources/CShim/capability.c",
    "chars": 957,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/CShim/exec_command.c",
    "chars": 9201,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/CShim/include/capability.h",
    "chars": 843,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/CShim/include/exec_command.h",
    "chars": 1770,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/CShim/include/openat2.h",
    "chars": 1098,
    "preview": "/*\n * Copyright © 2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License, Ver"
  },
  {
    "path": "Sources/CShim/include/prctl.h",
    "chars": 991,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/CShim/include/socket_helpers.h",
    "chars": 991,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/CShim/include/vsock.h",
    "chars": 909,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/CShim/openat2.c",
    "chars": 954,
    "preview": "/*\n * Copyright © 2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License, Ver"
  },
  {
    "path": "Sources/CShim/prctl.c",
    "chars": 1431,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/CShim/socket_helpers.c",
    "chars": 974,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/CShim/vsock.c",
    "chars": 736,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/Containerization/AttachedFilesystem.swift",
    "chars": 2110,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Container.swift",
    "chars": 1224,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/ContainerManager.swift",
    "chars": 14328,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/ContainerStatistics.swift",
    "chars": 8190,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/DNSConfiguration.swift",
    "chars": 2257,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/ExitStatus.swift",
    "chars": 1349,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/FileMount.swift",
    "chars": 8931,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/Containerization/Hash.swift",
    "chars": 1354,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/HostsConfiguration.swift",
    "chars": 4587,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/IO/ReaderStream.swift",
    "chars": 941,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/IO/Terminal+ReaderStream.swift",
    "chars": 1321,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/IO/Writer.swift",
    "chars": 956,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/Image.swift",
    "chars": 5832,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/ImageStore/ImageStore+Export.swift",
    "chars": 7555,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/ImageStore/ImageStore+Import.swift",
    "chars": 11890,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/ImageStore/ImageStore+OCILayout.swift",
    "chars": 5698,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/ImageStore/ImageStore+ReferenceManager.swift",
    "chars": 3416,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/ImageStore/ImageStore.swift",
    "chars": 15230,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/InitImage.swift",
    "chars": 4337,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/KernelImage.swift",
    "chars": 4657,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/Unpacker/EXT4Unpacker.swift",
    "chars": 4476,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Image/Unpacker/Unpacker.swift",
    "chars": 1878,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Interface.swift",
    "chars": 1422,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Kernel.swift",
    "chars": 3419,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/LinuxContainer.swift",
    "chars": 55691,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/LinuxPod.swift",
    "chars": 37466,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/LinuxProcess.swift",
    "chars": 15615,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/LinuxProcessConfiguration.swift",
    "chars": 15189,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Mount.swift",
    "chars": 7719,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/NATInterface.swift",
    "chars": 1275,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/NATNetworkInterface.swift",
    "chars": 2884,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Network.swift",
    "chars": 1036,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/Containerization/SandboxContext/SandboxContext.grpc.swift",
    "chars": 149926,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/SandboxContext/SandboxContext.pb.swift",
    "chars": 172528,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/SandboxContext/SandboxContext.proto",
    "chars": 11126,
    "preview": "syntax = \"proto3\";\n\npackage com.apple.containerization.sandbox.v3;\n\nimport \"google/protobuf/timestamp.proto\";\n\n// Contex"
  },
  {
    "path": "Sources/Containerization/SystemPlatform.swift",
    "chars": 1666,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/TimeSyncer.swift",
    "chars": 2507,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/UnixSocketConfiguration.swift",
    "chars": 2748,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/UnixSocketRelay.swift",
    "chars": 7377,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/UnixSocketRelayManager.swift",
    "chars": 2417,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/Containerization/VMConfiguration.swift",
    "chars": 3812,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/VZVirtualMachine+Helpers.swift",
    "chars": 5440,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/VZVirtualMachineInstance.swift",
    "chars": 16632,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/VZVirtualMachineManager.swift",
    "chars": 2869,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/VirtualMachineAgent+Additions.swift",
    "chars": 1101,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/VirtualMachineAgent.swift",
    "chars": 4355,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/VirtualMachineInstance.swift",
    "chars": 2195,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/VirtualMachineManager.swift",
    "chars": 1009,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Vminitd+Rosetta.swift",
    "chars": 1310,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Vminitd+SocketRelay.swift",
    "chars": 2007,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/Vminitd.swift",
    "chars": 20908,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/Containerization/VmnetNetwork.swift",
    "chars": 7812,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/Containerization/VsockListener.swift",
    "chars": 2442,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationArchive/ArchiveError.swift",
    "chars": 4451,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationArchive/ArchiveReader.swift",
    "chars": 16411,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/ContainerizationArchive/ArchiveWriter.swift",
    "chars": 12930,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationArchive/ArchiveWriterConfiguration.swift",
    "chars": 6985,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationArchive/CArchive/COPYING",
    "chars": 3086,
    "preview": "The libarchive distribution as a whole is Copyright by Tim Kientzle\nand is subject to the copyright notice reproduced at"
  },
  {
    "path": "Sources/ContainerizationArchive/CArchive/archive_swift_bridge.c",
    "chars": 2206,
    "preview": "/*\n * Copyright © 2025-2026 Apple Inc. and the Containerization project authors.\n *\n * Licensed under the Apache License"
  },
  {
    "path": "Sources/ContainerizationArchive/CArchive/include/archive.h",
    "chars": 53839,
    "preview": "/*-\n * Copyright (c) 2003-2010 Tim Kientzle\n * All rights reserved.\n *\n * Redistribution and use in source and binary fo"
  },
  {
    "path": "Sources/ContainerizationArchive/CArchive/include/archive_bridge.h",
    "chars": 334,
    "preview": "//\n\n#pragma once\n\n#include \"archive.h\"\n#include <stdint.h>\n\nvoid archive_set_error_wrapper(struct archive *a, int error_"
  },
  {
    "path": "Sources/ContainerizationArchive/CArchive/include/archive_entry.h",
    "chars": 34375,
    "preview": "/*-\n * Copyright (c) 2003-2008 Tim Kientzle\n * Copyright (c) 2016 Martin Matuska\n * All rights reserved.\n *\n * Redistrib"
  },
  {
    "path": "Sources/ContainerizationArchive/TempDir.swift",
    "chars": 1522,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationArchive/WriteEntry.swift",
    "chars": 10088,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/Documentation.docc/ext4.md",
    "chars": 187,
    "preview": "# ``ContainerizationEXT4``\n\n`ContainerizationEXT4` provides functionality to read the superblock of an existing ext4 blo"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4+Extensions.swift",
    "chars": 3218,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4+FileTree.swift",
    "chars": 4197,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4+Formatter.swift",
    "chars": 64600,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4+Ptr.swift",
    "chars": 2607,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4+Reader.swift",
    "chars": 12174,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4+Types.swift",
    "chars": 25146,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4+Xattrs.swift",
    "chars": 12249,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4.swift",
    "chars": 11983,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4Reader+Export.swift",
    "chars": 9445,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/EXT4Reader+IO.swift",
    "chars": 21709,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/FilePath+Extensions.swift",
    "chars": 3671,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/FileTimestamps.swift",
    "chars": 1814,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/Formatter+Unpack.swift",
    "chars": 6856,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/Integer+Extensions.swift",
    "chars": 3693,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationEXT4/README.md",
    "chars": 187,
    "preview": "# ``ContainerizationEXT4``\n\n`ContainerizationEXT4` provides functionality to read the superblock of an existing ext4 blo"
  },
  {
    "path": "Sources/ContainerizationEXT4/UnsafeLittleEndianBytes.swift",
    "chars": 2625,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationError/ContainerizationError.swift",
    "chars": 5276,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/AddressAllocator.swift",
    "chars": 2653,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/AddressError.swift",
    "chars": 1970,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/ContainerizationExtras/AsyncLock.swift",
    "chars": 2308,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/AsyncMutex.swift",
    "chars": 2206,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/CIDR.swift",
    "chars": 5165,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/CIDRv4.swift",
    "chars": 4281,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/CIDRv6.swift",
    "chars": 4437,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/FileManager+Temporary.swift",
    "chars": 1288,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/IPAddress.swift",
    "chars": 4327,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/IPv4Address.swift",
    "chars": 8838,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/IPv6Address+Parse.swift",
    "chars": 13436,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/IPv6Address.swift",
    "chars": 9445,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/IndexedAddressAllocator.swift",
    "chars": 4484,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/MACAddress.swift",
    "chars": 9853,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/ContainerizationExtras/NetworkAddress+Allocator.swift",
    "chars": 4109,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/Prefix.swift",
    "chars": 3046,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/ProgressEvent.swift",
    "chars": 1974,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/ProxyUtils.swift",
    "chars": 3160,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/RotatingAddressAllocator.swift",
    "chars": 4186,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/TLSUtils.swift",
    "chars": 1485,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/Timeout.swift",
    "chars": 2356,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationExtras/UInt8+DataBinding.swift",
    "chars": 3635,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationIO/ReadStream.swift",
    "chars": 4499,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationNetlink/NetlinkSession.swift",
    "chars": 26034,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationNetlink/NetlinkSocket.swift",
    "chars": 4738,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationNetlink/Types.swift",
    "chars": 34346,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/AnnotationKeys.swift",
    "chars": 1382,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Bundle.swift",
    "chars": 4903,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Client/Authentication.swift",
    "chars": 1975,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Client/KeychainHelper.swift",
    "chars": 5643,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Client/LocalOCILayoutClient.swift",
    "chars": 9787,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Client/RegistryClient+Catalog.swift",
    "chars": 3741,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/ContainerizationOCI/Client/RegistryClient+Error.swift",
    "chars": 2707,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Client/RegistryClient+Fetch.swift",
    "chars": 9729,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Client/RegistryClient+Push.swift",
    "chars": 8039,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Client/RegistryClient+Referrers.swift",
    "chars": 3948,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/ContainerizationOCI/Client/RegistryClient+Token.swift",
    "chars": 8701,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Client/RegistryClient.swift",
    "chars": 12105,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Content/AsyncTypes.swift",
    "chars": 1568,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Content/Content.swift",
    "chars": 2071,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Content/ContentStoreProtocol.swift",
    "chars": 3416,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Content/ContentWriter.swift",
    "chars": 2958,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Content/LocalContent.swift",
    "chars": 2639,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Content/LocalContentStore.swift",
    "chars": 8719,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Content/SHA256+Extensions.swift",
    "chars": 1226,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Content/String+Extension.swift",
    "chars": 1073,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Content/URL+Extensions.swift",
    "chars": 1309,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Descriptor.swift",
    "chars": 2484,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/FileManager+Size.swift",
    "chars": 1179,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/ImageConfig.swift",
    "chars": 6547,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Index.swift",
    "chars": 3032,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Manifest.swift",
    "chars": 2539,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/MediaType.swift",
    "chars": 3571,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Platform.swift",
    "chars": 13101,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Reference.swift",
    "chars": 11021,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Spec.swift",
    "chars": 30259,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/State.swift",
    "chars": 2546,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOCI/Version.swift",
    "chars": 1223,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/AsyncSignalHandler.swift",
    "chars": 3472,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/BinaryInteger+Extensions.swift",
    "chars": 1708,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Command.swift",
    "chars": 10109,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/File.swift",
    "chars": 3582,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/FileDescriptor+SecurePath.swift",
    "chars": 8970,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/ContainerizationOS/Keychain/KeychainQuery.swift",
    "chars": 10320,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Keychain/RegistryInfo.swift",
    "chars": 1251,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/ContainerizationOS/Linux/Binfmt.swift",
    "chars": 3751,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Linux/Capabilities.swift",
    "chars": 23120,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Linux/Epoll.swift",
    "chars": 5463,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Mount/Mount.swift",
    "chars": 15247,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/POSIXError+Helpers.swift",
    "chars": 1079,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Path.swift",
    "chars": 2992,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Pipe+Close.swift",
    "chars": 1573,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/README.md",
    "chars": 78,
    "preview": "## OS\n\nThis target contains general useful OS related definitions or wrappers."
  },
  {
    "path": "Sources/ContainerizationOS/Reaper.swift",
    "chars": 1751,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Signals.swift",
    "chars": 4044,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Socket/BidirectionalRelay.swift",
    "chars": 9842,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2026 Apple Inc. and the "
  },
  {
    "path": "Sources/ContainerizationOS/Socket/Socket.swift",
    "chars": 15881,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Socket/SocketType.swift",
    "chars": 1901,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Socket/UnixType.swift",
    "chars": 5266,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Socket/VsockType.swift",
    "chars": 3669,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Syscall.swift",
    "chars": 1348,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Sysctl.swift",
    "chars": 1240,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/Terminal.swift",
    "chars": 6714,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  },
  {
    "path": "Sources/ContainerizationOS/URL+Extensions.swift",
    "chars": 2137,
    "preview": "//===----------------------------------------------------------------------===//\n// Copyright © 2025-2026 Apple Inc. and"
  }
]

// ... and 124 more files (download for full content)

About this extraction

This page contains the full source code of the apple/containerization GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 324 files (2.6 MB), approximately 696.3k tokens, and a symbol index with 501 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!