[
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "content": "name: Bug report\ntitle: \"[Bug] Bug title\"\ndescription: Problems and issues with code of nydus-snapshotter\nlabels: [ \"bug\"]\nbody:\n- type: markdown\n  attributes:\n    value: >\n      Thank you for taking the time to report an issue. To help us resolve it quickly, please fill out the following \n      information.\n\n- type: textarea\n  attributes:\n    label: Problem Description\n    description: A clear and concise description of the bug you've encountered.\n    placeholder: >\n      Please clearly and concisely describe the error you encountered.\n  validations:\n    required: true\n\n- type: textarea\n  attributes:\n    label: Expected Behavior\n    description: What did you expect to happen?\n    placeholder: >\n     Explain the behavior you expected to see.\n  validations:\n    required: true\n\n- type: textarea\n  attributes:\n    label: Actual Behavior\n    description: What actually happened? Please provide any relevant logs, stack traces, or screenshots.\n    placeholder: >\n      Describe the actual behavior. Include logs or screenshots if possible.\n  validations:\n    required: true\n\n- type: textarea\n  attributes:\n    label: How to reproduce\n    description: Provide detailed steps to reproduce the issue.\n    placeholder: >\n      Please make sure you provide a reproducible step-by-step case of how to reproduce the problem\n      as minimally and precisely as possible.\n    value: |\n      1.\n      2.\n      3.\n  validations:\n    required: true\n\n- type: textarea\n  id: environment-details\n  attributes:\n    label: Environment Details\n    description: |\n      Please provide your environment information.\n    value: |\n      - Nydus-snapshotter version: \n      - Nydus version:\n      - Container runtime:\n      - Operating System:\n      - Kernel version:\n  validations:\n    required: true\n\n- type: textarea\n  attributes:\n    label: Additional Information\n    description: Any other context or details that could be helpful.\n    placeholder: >\n      If you have any other information that might help us diagnose the issue, please provide it here.\n\n- type: checkboxes\n  attributes:\n    label: Are you willing to submit PR?\n    description: >\n      This is absolutely not required, but we are happy to guide you in the contribution process\n      especially if you already have a good understanding of how to implement the fix.\n    options:\n      - label: Yes I am willing to submit a PR!\n\n- type: markdown\n  attributes:\n    value: \"Thanks for completing our form!\""
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.yml",
    "content": "name: Feature request\ndescription: Suggest an idea for nydus-snapshotter\ntitle: \"[Feature] Feature title\"\nlabels: [ \"feature\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thank you for suggesting a new feature. Please provide a clear and detailed description.\n\n  - type: textarea\n    attributes:\n      label: Feature Description\n      description: A clear and concise description of the feature you would like to see.\n      placeholder: >\n        Describe the feature you are requesting.\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Problem and Use Case\n      description: What problem does this feature solve? Why is it important to you or other users?\n      placeholder: >\n        Describe the problem and a specific use case.\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Related issues\n      description: Is there currently another issue associated with this?\n\n  - type: checkboxes\n    attributes:\n      label: Are you willing to submit PR?\n      description: >\n        This is absolutely not required, but we are happy to guide you in the contribution process\n        especially if you already have a good understanding of how to implement the fix.\n      options:\n        - label: Yes I am willing to submit a PR!\n\n  - type: markdown\n    attributes:\n      value: \"Thanks for completing our form!\""
  },
  {
    "path": ".github/ISSUE_TEMPLATE/improvement-report.yml",
    "content": "name: Improvement Report\ndescription: Suggest an improvement to an existing feature or process.\ntitle: \"[Improvement] Improvement title\"\nlabels: [\"improvement\"]\nassignees: []\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thank you for helping us improve nydus-snapshotter! Please provide a clear and detailed description of your suggestion.\n\n  - type: textarea\n    id: problem-summary\n    attributes:\n      label: Problem Summary\n      description: A brief, high-level summary of the issue or inefficiency you've identified.\n      placeholder: Describe the problem you want to solve.\n    validations:\n      required: true\n\n  - type: textarea\n    id: proposed-improvement\n    attributes:\n      label: Proposed Improvement\n      description: A detailed description of your proposed change or improvement.\n      placeholder: Explain your proposed solution.\n    validations:\n      required: true\n\n  - type: textarea\n    id: additional-context\n    attributes:\n      label: Additional Context\n      description: Add any other context or references that would be helpful (e.g., links to discussions, related issues).\n      placeholder: Add any additional context here.\n    validations:\n      required: false\n\n  - type: checkboxes\n    attributes:\n      label: Are you willing to submit PR?\n      description: >\n        This is absolutely not required, but we are happy to guide you in the contribution process\n        especially if you already have a good understanding of how to implement the fix.\n      options:\n        - label: Yes I am willing to submit a PR!\n\n  - type: markdown\n    attributes:\n      value: \"Thanks for completing our form!\""
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "## Overview\n_Please briefly describe the changes your pull request makes._\n\n## Related Issues\n_Please link to the relevant issue. For example: `Fix #123` or `Related #456`._\n\n## Change Details\n_Please describe your changes in detail:_\n\n## Test Results\n_If you have any relevant screenshots or videos that can help illustrate your changes, please add them here._\n\n## Change Type\n_Please select the type of change your pull request relates to:_\n- [ ] Bug Fix\n- [ ] Feature Addition\n- [ ] Documentation Update\n- [ ] Code Refactoring\n- [ ] Performance Improvement\n- [ ] Other (please describe)\n\n## Self-Checklist\n_Before submitting a pull request, please ensure you have completed the following:_\n- [ ] I have run a code style check and addressed any warnings/errors.\n- [ ] I have added appropriate comments to my code (if applicable).\n- [ ] I have updated the documentation (if applicable).\n- [ ] I have written appropriate unit tests."
  },
  {
    "path": ".github/codecov.yml",
    "content": "coverage:\n  status:\n    patch: off\n    project:\n      default:\n        enabled: yes\n        target: auto # auto compares coverage to the previous base commit\n        # adjust accordingly based on how flaky your tests are\n        # this allows a 0.3% drop from the previous base commit coverage\n        threshold: 0.3%\n\ncomment:\n  layout: \"reach, diff, flags, files\"\n  behavior: default\n  require_changes: true # if true: only post the comment if coverage changes\n\ncodecov:\n  require_ci_to_pass: false\n  notify:\n    wait_for_ci: true\n# When modifying this file, please validate using\n\n# curl -X POST --data-binary @codecov.yml https://codecov.io/validate\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches: [\"**\", \"stable/**\"]\n  pull_request:\n    branches: [\"**\", \"stable/**\"]\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  security:\n    name: Security scan\n    timeout-minutes: 10\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Check out code\n        uses: actions/checkout@v4\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: govulncheck\n        run: |\n          go install golang.org/x/vuln/cmd/govulncheck@latest\n          \"$(go env GOPATH)/bin/govulncheck\" ./...\n      - name: OSV-Scanner\n        run: |\n          go install github.com/google/osv-scanner/cmd/osv-scanner@v1\n          \"$(go env GOPATH)/bin/osv-scanner\" -r .\n  build:\n    name: Build and Lint\n    timeout-minutes: 10\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Check out code\n        uses: actions/checkout@v4\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: golangci-lint\n        uses: golangci/golangci-lint-action@v9\n        with:\n          # Prebuilt golangci-lint v2.1.x is built with Go 1.24; go.mod requires Go 1.25+.\n          install-mode: goinstall\n          version: v2.1.6\n          skip-cache: true\n      - name: Build\n        run: |\n          make\n          make test\n  build-optimizer:\n    name: Build optimizer\n    timeout-minutes: 10\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Check out code\n        uses: actions/checkout@v4\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: Build\n        run: |\n          rustup component add rustfmt clippy\n          make build-optimizer\n  smoke:\n    name: Smoke\n    timeout-minutes: 10\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Check out code\n        uses: actions/checkout@v4\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: Set up containerd\n        uses: crazy-max/ghaction-setup-containerd@v3\n      - name: Build\n        run: |\n          # Download nydus components\n          NYDUS_VER=v$(curl -fsSL --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \"https://api.github.com/repos/dragonflyoss/nydus/releases/latest\" | jq -r .tag_name | sed 's/^v//')\n          wget -q https://github.com/dragonflyoss/nydus/releases/download/$NYDUS_VER/nydus-static-$NYDUS_VER-linux-amd64.tgz\n          tar xzvf nydus-static-$NYDUS_VER-linux-amd64.tgz\n          mkdir -p /usr/bin\n          sudo mv nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/bin/\n          export PATH=$PATH:$(go env GOPATH)/bin\n          make smoke\n\n  cross-build-test:\n    name: Cross Build Test\n    timeout-minutes: 10\n    runs-on: ubuntu-22.04\n    strategy:\n      matrix:\n        GOOS: [\"linux\", \"windows\", \"darwin\"]\n        GOARCH: [\"amd64\", \"arm64\"]\n    steps:\n      - name: Check out code\n        uses: actions/checkout@v4\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: Build\n        run: |\n          make -e GOOS=${{ matrix.GOOS }} GOARCH=${{ matrix.GOARCH }} converter\n\n  coverage:\n    name: Code coverage\n    timeout-minutes: 10\n    runs-on: ubuntu-22.04\n    needs: [build]\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: Run unit tests.\n        run: make cover\n      - name: Upload coverage to Codecov\n        uses: codecov/codecov-action@v4\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos\n          files: ./coverage.txt\n"
  },
  {
    "path": ".github/workflows/e2e.yml",
    "content": "name: integration test\n\non:\n  push:\n    branches:\n      - \"main\"\n    tags:\n      - v[0-9]+.[0-9]+.[0-9]+\n  pull_request:\n    branches:\n      - \"main\"\n  schedule:\n    # Trigger test every day at 00:03 clock UTC\n    - cron: \"3 0 * * *\"\n  workflow_dispatch:\n\nenv:\n  CARGO_TERM_COLOR: always\n  REGISTRY: ghcr.io\n\njobs:\n  run-e2e-for-cgroups-v1:\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: Log in to container registry\n        uses: docker/login-action@v3\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Run e2e test\n        run: |\n          TAG=$GITHUB_REF_NAME\n          [ \"$TAG\" == \"main\" ] && TAG=\"latest\"\n          [ \"$GITHUB_EVENT_NAME\" == \"pull_request\" ] && TAG=\"local\"\n          make integration\n  \n  run-e2e-for-cgroups-v2:\n    runs-on: ubuntu-24.04\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: Log in to container registry\n        uses: docker/login-action@v3\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Run e2e test\n        run: |\n          TAG=$GITHUB_REF_NAME\n          [ \"$TAG\" == \"main\" ] && TAG=\"latest\"\n          [ \"$GITHUB_EVENT_NAME\" == \"pull_request\" ] && TAG=\"local\"\n          make integration\n"
  },
  {
    "path": ".github/workflows/k8s-e2e-run.yml",
    "content": "name: E2E Test With Kubernetes\n\non:\n  push:\n    branches:\n      - \"main\"\n    tags:\n      - v[0-9]+.[0-9]+.[0-9]+\n  pull_request:\n    branches: [main]\n\njobs:\n  cri_auth:\n    uses: ./.github/workflows/k8s-e2e.yml\n    with:\n      auth-type: cri\n\n  kubeconf_auth:\n    uses: ./.github/workflows/k8s-e2e.yml\n    with:\n      auth-type: kubeconf\n\n  index_detect:\n    uses: ./.github/workflows/k8s-e2e.yml\n    with:\n      auth-type: kubeconf\n      index-detect: true\n"
  },
  {
    "path": ".github/workflows/k8s-e2e.yml",
    "content": "name: E2E Test With Kubernetes Template\n\non:\n  workflow_call:\n    inputs:\n      auth-type:\n        required: true\n        type: string\n      index-detect:\n        required: false\n        type: boolean\n\nenv:\n  DOCKER_USER: testuser\n  DOCKER_PASSWORD: testpassword\n  NAMESPACE: nydus-system\n\njobs:\n  e2e_tests_k8s:\n    runs-on: ubuntu-22.04\n    timeout-minutes: 30\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n        with:\n          submodules: recursive\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: Test\n        env:\n          AUTH_TYPE: ${{ inputs.auth-type }}\n          INDEX_DETECT: ${{ inputs.index-detect }}\n        run: |\n          ./tests/helpers/kind.sh\n      - name: Dump logs\n        if: failure()\n        continue-on-error: true\n        run: |\n          log_dir=\"/tmp/nydus-log\"\n          mkdir -p $log_dir\n          for p in `kubectl --namespace \"$NAMESPACE\" get pods --no-headers -o custom-columns=NAME:metadata.name`; do\n           kubectl --namespace \"$NAMESPACE\" get pod $p -o yaml >> $log_dir/nydus-pods.conf\n           kubectl --namespace \"$NAMESPACE\" describe pod $p  >> $log_dir/nydus-pods.conf\n           kubectl --namespace \"$NAMESPACE\" logs $p -c nydus-snapshotter >> $log_dir/nydus-snapshotter.log || echo \"failed to get snapshotter log\"\n          done\n          kubectl --namespace \"$NAMESPACE\" get secrets -o yaml >> $log_dir/nydus-secrets.log\n\n          docker exec kind-control-plane cat /etc/containerd/config.toml >> $log_dir/containerd-config.toml\n          docker exec kind-control-plane containerd config dump >> $log_dir/containerd-config-dump.toml\n\n          docker exec kind-control-plane journalctl --no-pager -u containerd >> $log_dir/containerd.log\n          docker exec kind-control-plane journalctl --no-pager -u kubelet >> $log_dir/kubelet.log\n          docker exec kind-control-plane ps -ef >> $log_dir/psef.log\n\n          kubectl get pod test-pod -o yaml >> $log_dir/test-pod.log || echo \"test-pod may be deleted or not created\"\n\n          cat ~/.docker/config.json > $log_dir/docker.config.json || echo \"~/.docker/config.json  not found\"\n      - name: Upload Logs\n        uses: actions/upload-artifact@v4\n        if: failure()\n        with:\n          name: k8s-e2e-tests-logs\n          path: |\n            /tmp/nydus-log\n          overwrite: true\n"
  },
  {
    "path": ".github/workflows/optimizer.yml",
    "content": "name: optimizer test\n\non:\n  push:\n    branches:\n      - \"main\"\n    tags:\n      - v[0-9]+.[0-9]+.[0-9]+\n  pull_request:\n    branches:\n      - \"main\"\n  schedule:\n    # Trigger test every day at 00:03 clock UTC\n    - cron: \"3 0 * * *\"\n  workflow_dispatch:\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  run_optimizer:\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n      - name: Setup Golang\n        uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: cache cargo\n        uses: actions/cache@v4\n        with:\n          path: |\n            ~/.cargo/bin/\n            ~/.cargo/registry/index/\n            ~/.cargo/registry/cache/\n            ~/.cargo/git/db/\n            tools/optimizer-server/target/\n          key: ${{ runner.os }}-cargo-${{ hashFiles('tools/optimizer-server/Cargo.lock') }}\n          restore-keys: |\n            ${{ runner.os }}-cargo\n      - name: containerd runc and crictl\n        run: |\n          sudo wget -q https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.26.0/crictl-v1.26.0-linux-amd64.tar.gz\n          sudo tar zxvf ./crictl-v1.26.0-linux-amd64.tar.gz -C /usr/local/bin\n          sudo install -D -m 755 misc/optimizer/crictl.yaml /etc/crictl.yaml\n          sudo wget -q https://github.com/containerd/containerd/releases/download/v1.7.0/containerd-static-1.7.0-linux-amd64.tar.gz\n          sudo systemctl stop containerd\n          sudo tar -zxf ./containerd-static-1.7.0-linux-amd64.tar.gz -C /usr/\n          sudo install -D -m 755 misc/optimizer/containerd-config.toml /etc/containerd/config.toml\n          sudo systemctl restart containerd\n          sudo wget -q https://github.com/opencontainers/runc/releases/download/v1.1.5/runc.amd64 -O /usr/bin/runc\n          sudo chmod +x /usr/bin/runc\n      - name: Setup CNI\n        run: |\n          wget -q https://github.com/containernetworking/plugins/releases/download/v1.2.0/cni-plugins-linux-amd64-v1.2.0.tgz\n          sudo mkdir -p /opt/cni/bin\n          sudo tar xzf cni-plugins-linux-amd64-v1.2.0.tgz -C /opt/cni/bin/\n          sudo install -D -m 755 misc/example/10-containerd-net.conflist /etc/cni/net.d/10-containerd-net.conflist\n      - name: Build and install optimizer\n        run: |\n          rustup component add rustfmt clippy\n          make optimizer\n          sudo chown -R $(id -un):$(id -gn) . ~/.cargo/\n          pwd\n          ls -lh bin/*optimizer*\n          sudo make install-optimizer\n          sudo install -D -m 755 misc/example/optimizer-nri-plugin.conf /etc/nri/conf.d/02-optimizer-nri-plugin.conf\n          sudo systemctl restart containerd\n          systemctl status containerd --no-pager -l\n      - name: Wait containerd ready\n        run: |\n          unset READY\n          for i in $(seq 30); do\n            if eval \"timeout 180 ls /run/containerd/containerd.sock\"; then\n                READY=true\n                break\n            fi\n            echo \"Fail(${i}). Retrying...\"\n            sleep 1\n          done\n          if [ \"$READY\" != \"true\" ];then\n            echo \"containerd is not ready\"\n            exit 1\n          fi\n      - name: Generate accessed files list\n        run: |\n          sed -i \"s|host_path: script|host_path: $(pwd)/misc/optimizer/script|g\" misc/optimizer/nginx.yaml\n          sudo crictl run misc/optimizer/nginx.yaml misc/optimizer/sandbox.yaml\n          sleep 20\n          sudo crictl rmp  -f --all\n          tree /opt/nri/optimizer/results/\n          count=$(cat /opt/nri/optimizer/results/library/nginx:1.23.3 | wc -l)\n          expected=$(cat misc/optimizer/script/file_list.txt | wc -l)\n          echo \"count: $count expected minimum value: $expected\"\n          if [ $count -lt $expected ]; then\n            echo \"failed to generate accessed files list for nginx:1.23.3\"\n            cat misc/optimizer/script/file_list.txt\n            exit 1\n          fi\n          cat /opt/nri/optimizer/results/library/nginx:1.23.3.csv\n      - name: Dump logs\n        if: failure()\n        continue-on-error: true\n        run: |\n          systemctl status containerd --no-pager -l\n          journalctl -xeu containerd --no-pager\n          "
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: release\n\non:\n  push:\n    tags:\n      - v[0-9]+.[0-9]+.[0-9]+*\n\nenv:\n  CARGO_TERM_COLOR: always\n  REGISTRY: ghcr.io\n  IMAGE_NAME: ${{ github.repository }}\n\njobs:\n  build:\n    runs-on: ubuntu-22.04\n    strategy:\n      matrix:\n        include:\n          - build-os: linux\n            build-arch: amd64\n            build-linker: x86-64\n          - build-os: linux\n            build-arch: arm64\n            build-linker: aarch64\n          - build-os: linux\n            build-arch: s390x\n            build-linker: s390x\n          - build-os: linux\n            build-arch: ppc64le\n            build-linker: powerpc64le\n          - build-os: linux\n            build-arch: riscv64\n            build-linker: riscv64\n          - build-os: linux\n            build-arch: static\n            build-linker: static\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-go@v5\n        with:\n          go-version-file: 'go.mod'\n          cache-dependency-path: \"go.sum\"\n      - name: cache go mod\n        uses: actions/cache@v4\n        with:\n          path: ~/go/pkg/mod\n          key: ${{ matrix.build-os }}-go-${{ hashFiles('go.sum') }}\n          restore-keys: |\n            ${{ matrix.build-os }}-go\n      - name: cache cargo\n        uses: actions/cache@v4\n        with:\n          path: |\n            ~/.cargo/bin/\n            ~/.cargo/registry/index/\n            ~/.cargo/registry/cache/\n            ~/.cargo/git/db/\n            tools/optimizer-server/target/\n          key: ${{ matrix.build-os }}-cargo-${{ hashFiles('tools/optimizer-server/Cargo.lock') }}\n          restore-keys: |\n            ${{ matrix.build-os }}-cargo\n      - name: install gnu gcc linker\n        run: |\n          if [ \"${{ matrix.build-linker }}\" != \"static\" ]; then\n            sudo apt-get update && sudo apt-get install -qq gcc-${{ matrix.build-linker }}-linux-gnu\n          fi\n      - name: build nydus-snapshotter and optimizer\n        run: |\n          go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2\n          export PATH=$PATH:$(go env GOPATH)/bin\n          if [ \"${{ matrix.build-arch }}\" == \"static\" ]; then\n            make static-package\n          else\n            make package GOOS=${{ matrix.build-os }} GOARCH=${{ matrix.build-arch }}\n          fi\n      - name: upload artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: release-tars-${{ matrix.build-os }}-${{ matrix.build-arch }}\n          path: |\n            package/*.tar.gz*\n          overwrite: true\n  upload:\n    runs-on: ubuntu-22.04\n    needs: [build]\n    steps:\n      - uses: actions/checkout@v4\n      - name: Download Artifacts\n        uses: actions/download-artifact@v4\n        with:\n          path: builds\n      - name: Release\n        uses: softprops/action-gh-release@v1\n        with:\n          name: \"Nydus Snapshotter ${{ github.ref_name }} Release\"\n          generate_release_notes: true\n          files: |\n            builds/release-tars-**/*\n\n  publish-image:\n    runs-on: ubuntu-22.04\n    needs: [build]\n    strategy:\n      matrix:\n        include:\n          - build-os: linux\n            build-arch: amd64\n          - build-os: linux\n            build-arch: arm64\n          - build-os: linux\n            build-arch: s390x\n          - build-os: linux\n            build-arch: ppc64le\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@v3\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n\n      - name: Log in to the container registry\n        uses: docker/login-action@v3\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: download artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: release-tars-${{ matrix.build-os }}-${{ matrix.build-arch }}\n          path: misc/snapshotter\n      - name: unpack static release\n        run: |\n          cd misc/snapshotter && tar -zxf *.tar.gz && mv bin/* . && rm -rf bin\n      - name: Extract metadata (tags, labels) for Docker\n        id: meta\n        uses: docker/metadata-action@v4\n        with:\n          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\n      - name: Get the nydusd version\n        run: |\n          export NYDUS_STABLE_VER=$(curl -fsSL https://api.github.com/repos/dragonflyoss/nydus/releases/latest | jq -r .tag_name)\n          echo \"NYDUS_STABLE_VER=$NYDUS_STABLE_VER\" >> \"$GITHUB_ENV\"\n          printf 'nydus version is: %s\\n' \"$NYDUS_STABLE_VER\"\n      - name: build and push nydus-snapshotter image\n        uses: docker/build-push-action@v5\n        with:\n          context: misc/snapshotter\n          file: misc/snapshotter/Dockerfile\n          push: true\n          platforms: ${{ matrix.build-os }}/${{ matrix.build-arch }}\n          provenance: false\n          tags: |\n            ${{ fromJSON(steps.meta.outputs.json).tags[0] }}-${{ matrix.build-arch }}\n            ${{ fromJSON(steps.meta.outputs.json).tags[1] }}-${{ matrix.build-arch }}\n          labels: ${{ steps.meta.outputs.labels }}\n          build-args: NYDUS_VER=${{ env.NYDUS_STABLE_VER }}\n\n  publish-manifest:\n    runs-on: ubuntu-22.04\n    needs: [publish-image]\n    steps:\n      - name: Log in to the container registry\n        uses: docker/login-action@v3\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: Extract metadata (tags, labels) for Docker\n        id: meta\n        uses: docker/metadata-action@v4\n        with:\n          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\n      - name: Publish manifest for multi-arch image\n        run: |\n          IFS=',' read -ra tags <<< \"$(echo \"${{ steps.meta.outputs.tags }}\" | tr '\\n' ',')\"\n          for tag in \"${tags[@]}\"; do\n            docker manifest create \"${tag}\" \\\n              --amend \"${tag}-amd64\" \\\n              --amend \"${tag}-arm64\" \\\n              --amend \"${tag}-s390x\" \\\n              --amend \"${tag}-ppc64le\"\n            docker manifest push \"${tag}\"\n          done\n"
  },
  {
    "path": ".gitignore",
    "content": "bin/\npkg/filesystem/stargz/testdata/db/\ncoverage.txt\n.vscode/\ntests/output/\nsmoke.tests\ntools/optimizer-server/target\nvendor/\n.idea/\n.DS_Store"
  },
  {
    "path": ".golangci.yml",
    "content": "# https://golangci-lint.run/usage/configuration#config-file\n\nversion: \"2\"\n\nrun:\n  concurrency: 4\n  timeout: 5m\n  issues-exit-code: 1\n  tests: true\n\nlinters:\n  default: none\n  enable:\n    - depguard      # Checks for imports that shouldn't be used.\n    - staticcheck\n    - unconvert\n    - revive\n    - ineffassign\n    - govet\n    - unused\n    - misspell\n    - bodyclose\n    # - cyclop\n    - dogsled\n    - nilnil\n    - unparam\n    - nilerr\n    # - gosec\n    - gocritic\n    - prealloc\n    # - funlen\n    - exhaustive\n    - errcheck\n  exclusions:\n    paths:\n      - misc\n      # The package is ported from containerd project, let's skip it.\n      - pkg/remote/remotes\n  settings:\n    errcheck:\n      # Don't check errors for these functions (common cleanup patterns)\n      exclude-functions:\n        - (io.Closer).Close\n        - (*os.File).Close\n        - (net.Conn).Close\n        - (*net.UnixListener).Close\n        - (*net.UnixConn).Close\n        - (*http.Response).Body.Close\n        - (*io.PipeWriter).Close\n        - (*compress/gzip.Writer).Close\n        - os.RemoveAll\n        - os.Remove\n        - os.Setenv\n        - fmt.Fprintf\n        - fmt.Fprintln\n        - golang.org/x/sys/unix.Close\n    exhaustive:\n      # Allow default case to be considered exhaustive\n      default-signifies-exhaustive: true\n    revive:\n      rules:\n        # Disable exported comment requirements (too strict for this codebase)\n        - name: exported\n          disabled: true\n        - name: package-comments\n          disabled: true\n    depguard:\n      rules:\n        Main:\n          list-mode: lax\n          files:\n            - $all\n          deny:\n            - pkg: \"github.com/containerd/containerd/errdefs\"\n              desc: The containerd errdefs package was migrated to a separate module. Use github.com/containerd/errdefs instead.\n            - pkg: \"github.com/containerd/containerd/log\"\n              desc: The containerd log package was migrated to a separate module. Use github.com/containerd/log instead.\n            - pkg: \"github.com/containerd/containerd/platforms\"\n              desc: The containerd platforms package was migrated to a separate module. Use github.com/containerd/platforms instead.\n            - pkg: \"github.com/containerd/containerd/reference/docker\"\n              desc: The containerd reference package was migrated to a separate module. Use github.com/distribution/reference instead.\n    #   govet:\n    #     check-shadowing: true\n    #     enable:\n    #       - fieldalignment\n    funlen:\n      # Checks the number of lines in a function.\n      # If lower than 0, disable the check.\n      # Default: 60\n      lines: 100\n      # Checks the number of statements in a function.\n      # If lower than 0, disable the check.\n      # Default: 40\n      statements: 80\n    nilnil:\n      checked-types:\n        - ptr\n        - func\n        - iface\n        - map\n        - chan\n\nformatters:\n  enable:\n    - gofmt\n    - goimports\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "MAINTAINERS",
    "content": "# nydus-snapshotter maintainers\n#\n# As a containerd sub-project, containerd maintainers are also included from https://github.com/containerd/project/blob/main/MAINTAINERS.\n# See https://github.com/containerd/project/blob/main/GOVERNANCE.md for description of maintainer role\n#\n# COMMITTERS\n# GitHub ID, Name, Email address\nchangweige, Changwei Ge, changweige@gmail.com\neryugey, Eryu Guan, eguan@linux.alibaba.com\nimeoer, Yan Song, yansong.ys@antgroup.com\nFricounet, Baptiste Girard-Carrabin, baptiste.girardcarrabin@datadoghq.com\n\n#\n# REVIEWERS\n# GitHub ID, Name, Email address\nsctb512, Bin Tang, tangbin.bin@bytedance.com\nBraveY, Kaiyong Yang, yangkaiyong.yky@antgroup.com\n"
  },
  {
    "path": "Makefile",
    "content": "all: clean build\noptimizer: clean-optimizer build-optimizer\n\nPKG = github.com/containerd/nydus-snapshotter\nPACKAGES ?= $(shell go list ./... | grep -v /tests)\nSUDO = $(shell which sudo)\nGO_EXECUTABLE_PATH ?= $(shell which go)\nNYDUS_BUILDER ?= /usr/bin/nydus-image\nNYDUS_NYDUSD ?= /usr/bin/nydusd\nGOOS ?= linux\nGOARCH ?= $(shell go env GOARCH)\nKERNEL_VER = $(shell uname -r)\n\n# Used to populate variables in version package.\nBUILD_TIMESTAMP=$(shell date '+%Y-%m-%dT%H:%M:%S')\nVERSION=$(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags)\nREVISION=$(shell git rev-parse HEAD)$(shell if ! git diff --no-ext-diff --quiet --exit-code; then echo .m; fi)\n\n\nRELEASE=nydus-snapshotter-v$(VERSION:v%=%)-${GOOS}-${GOARCH}\nSTATIC_RELEASE=nydus-snapshotter-v$(VERSION:v%=%)-${GOOS}-static\n\n# Relpace test target images for e2e tests.\nifdef E2E_TEST_TARGET_IMAGES_FILE\nENV_TARGET_IMAGES_FILE = --env-file ${E2E_TEST_TARGET_IMAGES_FILE}\nendif\n\nifdef E2E_DOWNLOADS_MIRROR\nBUILD_ARG_E2E_DOWNLOADS_MIRROR = --build-arg DOWNLOADS_MIRROR=${E2E_DOWNLOADS_MIRROR}\nendif\n\nifdef GOPROXY\nPROXY := GOPROXY=\"${GOPROXY}\"\nendif\n\nifdef FS_CACHE\nFS_DRIVER = fscache\nelse\nFS_DRIVER = fusedev\nendif\n\nSNAPSHOTTER_CONFIG=/etc/nydus/config.toml\nSOURCE_SNAPSHOTTER_CONFIG=misc/snapshotter/config.toml\nNYDUSD_CONFIG=/etc/nydus/nydusd-config.${FS_DRIVER}.json\nSOURCE_NYDUSD_CONFIG=misc/snapshotter/nydusd-config.${FS_DRIVER}.json\n\nSNAPSHOTTER_SYSTEMD_UNIT_SERVICE=misc/snapshotter/nydus-snapshotter.${FS_DRIVER}.service\n\nLDFLAGS = -s -w -X ${PKG}/version.Version=${VERSION} -X ${PKG}/version.Revision=$(REVISION) -X ${PKG}/version.BuildTimestamp=$(BUILD_TIMESTAMP)\nDEBUG_LDFLAGS = -X ${PKG}/version.Version=${VERSION} -X ${PKG}/version.Revision=$(REVISION) -X ${PKG}/version.BuildTimestamp=$(BUILD_TIMESTAMP)\n\nCARGO ?= $(shell which cargo)\nOPTIMIZER_SERVER = tools/optimizer-server\nOPTIMIZER_SERVER_TOML = ${OPTIMIZER_SERVER}/Cargo.toml\nOPTIMIZER_SERVER_BIN = ${OPTIMIZER_SERVER}/bin/optimizer-server\n.PHONY: build\nbuild:\n\tGOOS=${GOOS} GOARCH=${GOARCH} ${PROXY} go build -ldflags \"$(LDFLAGS)\" -v -o bin/containerd-nydus-grpc ./cmd/containerd-nydus-grpc\n\tGOOS=${GOOS} GOARCH=${GOARCH} ${PROXY} go build -ldflags \"$(LDFLAGS)\" -v -o bin/nydus-overlayfs ./cmd/nydus-overlayfs\n\n.PHONY: static\nstatic:\n\tCGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} ${PROXY} go build -ldflags \"$(LDFLAGS) -extldflags -static\" -v -o bin/containerd-nydus-grpc ./cmd/containerd-nydus-grpc\n\tCGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} ${PROXY} go build -ldflags \"$(LDFLAGS) -extldflags -static\" -v -o bin/nydus-overlayfs ./cmd/nydus-overlayfs\n\ndebug:\n\tGOOS=${GOOS} GOARCH=${GOARCH} ${PROXY} go build -ldflags \"$(DEBUG_LDFLAGS)\" -gcflags \"-N -l\" -v -o bin/containerd-nydus-grpc ./cmd/containerd-nydus-grpc\n\tGOOS=${GOOS} GOARCH=${GOARCH} ${PROXY} go build -ldflags \"$(DEBUG_LDFLAGS)\" -gcflags \"-N -l\" -v -o bin/nydus-overlayfs ./cmd/nydus-overlayfs\n\n.PHONY: build-optimizer\nbuild-optimizer:\n\tGOOS=${GOOS} GOARCH=${GOARCH} ${PROXY} go build -ldflags \"$(LDFLAGS)\" -v -o bin/optimizer-nri-plugin ./cmd/optimizer-nri-plugin\n\tmake -C tools/optimizer-server release OS=$(GOOS) ARCH=$(GOARCH) && cp ${OPTIMIZER_SERVER_BIN} ./bin\n\nstatic-release:\n\tCGO_ENABLED=0 ${PROXY} GOOS=${GOOS} GOARCH=${GOARCH} go build -ldflags \"$(LDFLAGS) -extldflags -static\" -v -o bin/containerd-nydus-grpc ./cmd/containerd-nydus-grpc\n\tCGO_ENABLED=0 ${PROXY} GOOS=${GOOS} GOARCH=${GOARCH} go build -ldflags \"$(LDFLAGS) -extldflags -static\" -v -o bin/nydus-overlayfs ./cmd/nydus-overlayfs\n\tCGO_ENABLED=0 ${PROXY} GOOS=${GOOS} GOARCH=${GOARCH} go build -ldflags \"$(LDFLAGS) -extldflags -static\" -v -o bin/optimizer-nri-plugin ./cmd/optimizer-nri-plugin\n\tmake -C tools/optimizer-server static-release && cp ${OPTIMIZER_SERVER_BIN} ./bin\n\npackage/$(RELEASE).tar.gz: build build-optimizer\n\tmkdir -p package\n\trm -rf package/$(RELEASE) package/$(RELEASE).tar.gz\n\ttar -czf package/$(RELEASE).tar.gz bin\n\trm -rf package/$(RELEASE)\n\npackage/$(STATIC_RELEASE).tar.gz: static-release\n\t@mkdir -p package\n\t@rm -rf package/$(STATIC_RELEASE) package/$(STATIC_RELEASE).tar.gz\n\t@tar -czf package/$(STATIC_RELEASE).tar.gz bin\n\t@rm -rf package/$(STATIC_RELEASE)\n\npackage: package/$(RELEASE).tar.gz\n\tcd package && sha256sum $(RELEASE).tar.gz >$(RELEASE).tar.gz.sha256sum\n\nstatic-package: package/$(STATIC_RELEASE).tar.gz\n\t@cd package && sha256sum $(STATIC_RELEASE).tar.gz >$(STATIC_RELEASE).tar.gz.sha256sum\n\n# Majorly for cross build for converter package since it is imported by other projects\nconverter:\n\tGOOS=${GOOS} GOARCH=${GOARCH} ${PROXY} go build -ldflags \"$(LDFLAGS)\" -v -o bin/converter ./cmd/converter\n\n.PHONY: clean\nclean:\n\trm -f bin/*\n\trm -rf _out\n\n.PHONY: clean-optimizer\nclean-optimizer:\n\trm -rf bin/optimizer-nri-plugin bin/optimizer-server\n\tmake -C tools/optimizer-server clean\n\n.PHONY: install\ninstall:\n\t@echo \"+ $@ bin/containerd-nydus-grpc\"\n\t@sudo install -D -m 755 bin/containerd-nydus-grpc /usr/local/bin/containerd-nydus-grpc\n\t@echo \"+ $@ bin/nydus-overlayfs\"\n\t@sudo install -D -m 755 bin/nydus-overlayfs /usr/local/bin/nydus-overlayfs\n\n\t@if [ ! -e ${NYDUSD_CONFIG} ]; then echo \"+ $@ SOURCE_NYDUSD_CONFIG\"; sudo install -D -m 664 ${SOURCE_NYDUSD_CONFIG} ${NYDUSD_CONFIG}; fi\n\t@if [ ! -e ${SNAPSHOTTER_CONFIG} ]; then echo \"+ $@ ${SOURCE_SNAPSHOTTER_CONFIG}\"; sudo install -D -m 664 ${SOURCE_SNAPSHOTTER_CONFIG} ${SNAPSHOTTER_CONFIG}; fi\n\t@sudo ln -f -s /etc/nydus/nydusd-config.${FS_DRIVER}.json /etc/nydus/nydusd-config.json\n\n\t@echo \"+ $@ ${SNAPSHOTTER_SYSTEMD_UNIT_SERVICE}\"\n\t@sudo install -D -m 644 ${SNAPSHOTTER_SYSTEMD_UNIT_SERVICE} /etc/systemd/system/nydus-snapshotter.service\n\n\t@sudo mkdir -p /etc/nydus/certs.d\n\t@if which systemctl >/dev/null; then sudo systemctl enable /etc/systemd/system/nydus-snapshotter.service; sudo systemctl restart nydus-snapshotter; fi\n\ninstall-optimizer:\n\tsudo install -D -m 755 bin/optimizer-nri-plugin /opt/nri/plugins/02-optimizer-nri-plugin\n\tsudo install -D -m 755 bin/optimizer-server /usr/local/bin/optimizer-server\n\tsudo install -D -m 755 misc/example/optimizer-nri-plugin.conf /etc/nri/conf.d/02-optimizer-nri-plugin.conf\n\n\t@sudo mkdir -p /opt/nri/optimizer/results\n\n.PHONY: vet\nvet:\n\tgo vet $(PACKAGES) ./tests\n\n.PHONY: check\ncheck: vet\n\tgolangci-lint run\n\n.PHONY: test\ntest:\n\tgo test -race -v -mod=mod -cover ${PACKAGES}\n\n.PHONY: cover\ncover:\n\tgo test -v -covermode=atomic -coverprofile=coverage.txt $(PACKAGES)\n\tgo tool cover -func=coverage.txt\n\n# make smoke TESTS=TestPack\nsmoke:\n\t${GO_EXECUTABLE_PATH} test -o smoke.tests -c -race -v -cover ./tests\n\t$(SUDO) -E NYDUS_BUILDER=${NYDUS_BUILDER} NYDUS_NYDUSD=${NYDUS_NYDUSD} ./smoke.tests -test.v -test.timeout 10m -test.parallel=8 -test.run=$(TESTS)\n\n.PHONY: integration\nintegration:\n\tCGO_ENABLED=1 ${PROXY} GOOS=${GOOS} GOARCH=${GOARCH} go build -ldflags '-X \"${PKG}/version.Version=${VERSION}\" -extldflags \"-static\"' -race -v -o bin/containerd-nydus-grpc ./cmd/containerd-nydus-grpc\n\tCGO_ENABLED=1 ${PROXY} GOOS=${GOOS} GOARCH=${GOARCH} go build -ldflags '-X \"${PKG}/version.Version=${VERSION}\" -extldflags \"-static\"' -race -v -o bin/nydus-overlayfs ./cmd/nydus-overlayfs\n\t$(SUDO) docker build ${BUILD_ARG_E2E_DOWNLOADS_MIRROR} -t nydus-snapshotter-e2e:0.1 -f integration/Dockerfile .\n\t$(SUDO) docker run --cap-add SYS_ADMIN --security-opt seccomp=unconfined --cgroup-parent=system.slice --cgroupns private --name nydus-snapshotter_e2e --rm --privileged -v /root/.docker:/root/.docker -v `go env GOMODCACHE`:/go/pkg/mod \\\n\t-v `go env GOCACHE`:/root/.cache/go-build -v `pwd`:/nydus-snapshotter \\\n\t-v /usr/src/linux-headers-${KERNEL_VER}:/usr/src/linux-headers-${KERNEL_VER} \\\n\t${ENV_TARGET_IMAGES_FILE}  \\\n\tnydus-snapshotter-e2e:0.1\n"
  },
  {
    "path": "README.md",
    "content": "[**[⬇️ Download]**](https://github.com/containerd/nydus-snapshotter/releases)\n[**[📖 Website]**](https://nydus.dev/)\n[**[☸ Quick Start (Kubernetes)**]](https://github.com/containerd/nydus-snapshotter/blob/main/docs/run_nydus_in_kubernetes.md)\n[**[🤓 Quick Start (nerdctl)**]](https://github.com/containerd/nerdctl/blob/master/docs/nydus.md)\n[**[❓ FAQs & Troubleshooting]**](https://github.com/dragonflyoss/nydus/wiki/FAQ)\n\n# Nydus Snapshotter\n\n<p><img src=\"https://github.com/dragonflyoss/nydus/blob/master/misc/logo.svg\" width=\"170\"></p>\n\n[![Release Version](https://img.shields.io/github/v/release/containerd/nydus-snapshotter?style=flat)](https://github.com/containerd/nydus-snapshotter/releases)\n[![LICENSE](https://img.shields.io/github/license/containerd/nydus-snapshotter.svg?style=flat)](https://github.com/containerd/nydus-snapshotter/blob/main/LICENSE)\n![CI](https://github.com/containerd/nydus-snapshotter/actions/workflows/ci.yml/badge.svg?event=push)\n[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/nydus-snapshotter?style=flat)](https://goreportcard.com/report/github.com/containerd/nydus-snapshotter)\n[![Twitter](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Ftwitter.com%2Fdragonfly_oss)](https://twitter.com/dragonfly_oss)\n[![Nydus Stars](https://img.shields.io/github/stars/dragonflyoss/nydus?label=Nydus%20Stars&style=social)](https://github.com/dragonflyoss/nydus)\n\nNydus-snapshotter is a **non-core** sub-project of containerd.\n\nNydus snapshotter is an external plugin of containerd for [Nydus image service](https://nydus.dev) which implements a chunk-based content-addressable filesystem on top of a called `RAFS (Registry Acceleration File System)` format that improves the current OCI image specification, in terms of container launching speed, image space, and network bandwidth efficiency, as well as data integrity with several runtime backends: FUSE, virtiofs and in-kernel [EROFS](https://www.kernel.org/doc/html/latest/filesystems/erofs.html).\n\nNydus supports lazy pulling feature since pulling image is one of the time-consuming steps in the container lifecycle. Lazy pulling here means a container can run even the image is partially available and necessary chunks of the image are fetched on-demand. Apart from that, Nydus also supports [(e)Stargz](https://github.com/containerd/stargz-snapshotter) and OCI (by using [zran](https://github.com/dragonflyoss/nydus/blob/master/docs/nydus-zran.md)) lazy pulling directly **WITHOUT** any explicit conversion.\n\nFor more details about how to build Nydus container image, please refer to [nydusify](https://github.com/dragonflyoss/nydus/blob/master/docs/nydusify.md) conversion tool and [acceld](https://github.com/goharbor/acceleration-service).\n\n## Architecture\n\n### Architecture Based on FUSE\n\n![fuse arch](./docs/diagram/nydus_fuse_arch.svg)\n\n### Architecture Based on Fscache/Erofs\n\n![fscache arch](./docs/diagram/nydus_fscache_erofs_arch.svg)\n\n## Building\n\nJust invoke `make` and check out the output executable binary `./bin/containerd-nydus-grpc`\n\n```bash\nmake\n```\n\n## Integrate Nydus-snapshotter into Containerd\n\nThe following document will describe how to manually configure containerd + Nydus snapshotter. If you want to run Nydus snapshotter in Kubernetes cluster, you can try to use helm or run nydus snapshotter as a container. You can refer to [this documentation](./docs/run_nydus_in_kubernetes.md).\n\nContainerd provides a general mechanism to exploit different types of snapshotters. Please ensure your containerd's version is 1.4.0 or above.\nAdd Nydus as a proxy plugin into containerd's configuration file which may be located at `/etc/containerd/config.toml`.\n\n```toml\n# The `address` field specifies through which socket snapshotter and containerd communicate.\n[proxy_plugins]\n  [proxy_plugins.nydus]\n    type = \"snapshot\"\n    address = \"/run/containerd-nydus/containerd-nydus-grpc.sock\"\n```\n\nRestart your containerd service making the change take effect. Assume that your node is systemd based, restart the service as below:\n\n```bash\nsystemctl restart containerd\n```\n\n### Get Nydus Binaries\n\nGet `nydusd` `nydus-image` and `nydusctl` binaries from [nydus releases page](https://github.com/dragonflyoss/nydus/releases).\nIt's suggested to install the binaries to your system path. `nydusd` is FUSE userspace daemon and a vhost-user-fs backend. Nydus-snapshotter\nwill fork a nydusd process when necessary.\n\n### Configure Nydus\n\nPlease follow instructions to [configure nydus](./docs/configure_nydus.md) in order to make it work properly in your environment.\n\n### Start Nydus Snapshotter\n\nNydus-snapshotter is implemented as a [proxy plugin](https://github.com/containerd/containerd/blob/04985039cede6aafbb7dfb3206c9c4d04e2f924d/PLUGINS.md#proxy-plugins) (`containerd-nydus-grpc`) for containerd.\n\nAssume your server is systemd based, install nydus-snapshotter:\nNote: `nydusd` and `nydus-image` should be found from $PATH.\n\n```bash\nmake install\nsystemctl restart containerd\n```\n\nOr you can start nydus-snapshotter manually.\n\n```bash\n# `--nydusd` specifies the path to nydusd binary. If `nydusd` and `nydus-image` are installed, `--nydusd` and `--nydus-image`can be omitted.\n# Otherwise, provide them in below command line.\n# `address` is the domain socket that you configured in containerd configuration file\n# `--nydusd-config` is the path to `nydusd` configuration file\n# The default nydus-snapshotter work directory is located at `/var/lib/containerd/io.containerd.snapshotter.v1.nydus`\n\n$ sudo ./containerd-nydus-grpc --config /etc/nydus/config.toml --nydusd-config /etc/nydus/nydusd-config.json --log-to-stdout\n```\n\n### Validate Nydus-snapshotter Setup\n\nUtilize containerd's `ctr` CLI command to validate if nydus-snapshotter is set up successfully.\n\n```bash\n$ ctr -a /run/containerd/containerd.sock plugin ls\nTYPE                            ID                       PLATFORMS      STATUS\nio.containerd.snapshotter.v1    nydus                    -              ok\n```\n\n### Optimize Nydus Image as per Workload\n\nNydus usually prefetch image data to local filesystem before a real user on-demand read. It helps to improve the performance and availability. A containerd NRI plugin [container image optimizer](docs/optimize_nydus_image.md) can be used to generate nydus image building suggestions to optimize your nydus image making the nydusd runtime match your workload IO pattern. The optimized nydus image has\na better performance.\n\n## Quickstart Container with Lazy Pulling\n\n### Start Container on single Node\n\nStart container using `nerdctl` (>=v0.22) which has native nydus support with `nydus-snapshotter`.\n\n```bash\n# Start container by `nerdctl`\nnerdctl --snapshotter nydus run ghcr.io/dragonflyoss/image-service/nginx:nydus-latest\n```\n\n### Start Container in Kubernetes Cluster\n\nChange containerd's CRI configuration:\n\n```toml\n[plugins.\"io.containerd.grpc.v1.cri\".containerd]\n   snapshotter = \"nydus\"\n   disable_snapshot_annotations = false\n```\n\nUse `crictl` to debug starting container via Kubernetes CRI. Dry run [steps](./docs/crictl_dry_run.md) of using `crictl` can be found in [documents](./docs).\n\n### Setup with nydus-snapshotter image\n\nWe can also use the `nydus-snapshotter` container image when we want to put Nydus stuffs inside a container. See the [nydus-snapshotter example](./misc/example/README.md) for how to setup and use it.\n\n## Integrate with Dragonfly to Distribute Images by P2P\n\nNydus is a sub-project of [Dragonfly](https://github.com/dragonflyoss/dragonfly). So it closely works with Dragonfly to distribute container images in a fast and efficient P2P fashion to reduce network latency and lower the pressure on a single-point of the registry.\n\n### Quickstart Dragonfly & Nydus in Kubernetes\n\nWe recommend using the Dragonfly P2P data distribution system to further improve the runtime performance of Nydus images.\n\nIf you want to deploy Dragonfly and Nydus at the same time, please refer to this **[Quick Start](https://github.com/dragonflyoss/helm-charts/blob/main/INSTALL.md)**.\n\n### Config Dragonfly mode\n\nDragonfly supports both **mirror** mode and HTTP **proxy** mode to boost the containers startup. It is suggested to use Dragonfly mirror mode. To integrate with Dragonfly in the mirror mode, please provide registry mirror in nydusd's json configuration file in section `device.backend.mirrors`\n\n```json\n{\n  \"mirrors\": [\n    {\n      \"host\": \"http://127.0.0.1:65001\",\n      \"headers\": \"https://index.docker.io/v1/\"\n    }\n  ]\n}\n```\n\n### Hot updating mirror configurations\n\n`nydus-snapshotter` supports hot updating mirror configurations. You can set the configuration directory in nydus-snapshotter's toml configuration file with `remote.mirrors_config.dir`. The empty `remote.mirrors_config.dir` means disabling it.\n\n```toml\n[remote.mirrors_config]\ndir = \"/etc/nydus/certs.d\"\n```\n\nConfiguration file is compatible with containerd's configuration file in toml format.\n\n```toml\n[host]\n  [host.\"http://127.0.0.1:65001\"]\n    # Optional: health check URL. If set, the mirror is only used when this URL returns HTTP 2xx.\n    # If not set, the mirror is used unconditionally.\n    ping_url = \"http://127.0.0.1:65001/ping\"\n```\n\nBefore each mount, the snapshotter reads the mirror configuration for the target registry host and rewrites nydusd's backend `host` to the first reachable mirror. If a mirror has no `ping_url` it is selected immediately. If all mirrors fail their health check, the original registry host is used as fallback.\n\n## Community\n\nNydus aims to form a **vendor-neutral opensource** image distribution solution to all communities.\nQuestions, bug reports, technical discussion, feature requests and contribution are always welcomed!\n\nWe're very pleased to hear your use cases any time.\nFeel free to reach/join us via Slack and/or Dingtalk.\n\n- **Slack:** [Nydus Workspace](https://join.slack.com/t/nydusimageservice/shared_invite/zt-pz4qvl4y-WIh4itPNILGhPS8JqdFm_w)\n- **Twitter:** [@dragonfly_oss](https://twitter.com/dragonfly_oss)\n- **Dingtalk:** [34971767](https://qr.dingtalk.com/action/joingroup?code=v1,k1,ioWGzuDZEIO10Bf+/ohz4RcQqAkW0MtOwoG1nbbMxQg=&_dt_no_comment=1&origin=11)\n\n<img src=\"https://github.com/dragonflyoss/nydus/blob/master/misc/dingtalk.jpg\" width=\"250\" height=\"300\"/>\n\n- **Technical Meeting:** Every Wednesday at 06:00 UTC (Beijing, Shanghai 14:00), please see our [HackMD](https://hackmd.io/@Nydus/Bk8u2X0p9) page for more information.\n\n## License\n\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcontainerd%2Fnydus-snapshotter.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcontainerd%2Fnydus-snapshotter?ref=badge_large)\n"
  },
  {
    "path": "cmd/containerd-nydus-grpc/main.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/urfave/cli/v2\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/internal/flags\"\n\t\"github.com/containerd/nydus-snapshotter/internal/logging\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/version\"\n)\n\nfunc main() {\n\tflags := flags.NewFlags()\n\tapp := &cli.App{\n\t\tName:        \"containerd-nydus-grpc\",\n\t\tUsage:       \"Nydus remote snapshotter for containerd\",\n\t\tVersion:     version.Version,\n\t\tFlags:       flags.F,\n\t\tHideVersion: true,\n\t\tAction: func(_ *cli.Context) error {\n\t\t\tif flags.Args.PrintVersion {\n\t\t\t\tfmt.Println(\"Version:    \", version.Version)\n\t\t\t\tfmt.Println(\"Revision:   \", version.Revision)\n\t\t\t\tfmt.Println(\"Go version: \", version.GoVersion)\n\t\t\t\tfmt.Println(\"Build time: \", version.BuildTimestamp)\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tsnapshotterConfigPath := flags.Args.SnapshotterConfigPath\n\t\t\tvar defaultSnapshotterConfig config.SnapshotterConfig\n\t\t\tvar snapshotterConfig config.SnapshotterConfig\n\n\t\t\tif err := defaultSnapshotterConfig.FillUpWithDefaults(); err != nil {\n\t\t\t\treturn errors.New(\"failed to generate nydus default configuration\")\n\t\t\t}\n\n\t\t\t// Once snapshotter's configuration file is provided, parse it and let command line parameters override it.\n\t\t\tif snapshotterConfigPath != \"\" {\n\t\t\t\tif c, err := config.LoadSnapshotterConfig(snapshotterConfigPath); err == nil {\n\t\t\t\t\t// Command line parameters override the snapshotter's configurations for backwards compatibility\n\t\t\t\t\tif err := config.ParseParameters(flags.Args, c); err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"failed to parse commandline options\")\n\t\t\t\t\t}\n\t\t\t\t\tsnapshotterConfig = *c\n\t\t\t\t} else {\n\t\t\t\t\treturn errors.Wrapf(err, \"failed to load snapshotter configuration from %q\", snapshotterConfigPath)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif err := config.ParseParameters(flags.Args, &snapshotterConfig); err != nil {\n\t\t\t\t\treturn errors.Wrap(err, \"failed to parse commandline options\")\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif err := config.MergeConfig(&snapshotterConfig, &defaultSnapshotterConfig); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"failed to merge configurations\")\n\t\t\t}\n\n\t\t\tif err := config.ValidateConfig(&snapshotterConfig); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"failed to validate configurations\")\n\t\t\t}\n\n\t\t\tconfig.PrepareLogDir(&snapshotterConfig)\n\n\t\t\tctx := logging.WithContext()\n\t\t\tlogConfig := &snapshotterConfig.LoggingConfig\n\t\t\tlogRotateArgs := &logging.RotateLogArgs{\n\t\t\t\tRotateLogMaxSize:    logConfig.RotateLogMaxSize,\n\t\t\t\tRotateLogMaxBackups: logConfig.RotateLogMaxBackups,\n\t\t\t\tRotateLogMaxAge:     logConfig.RotateLogMaxAge,\n\t\t\t\tRotateLogLocalTime:  logConfig.RotateLogLocalTime,\n\t\t\t\tRotateLogCompress:   logConfig.RotateLogCompress,\n\t\t\t}\n\n\t\t\tif err := logging.SetUp(logConfig.LogLevel, logConfig.LogToStdout, logConfig.LogDir, logRotateArgs); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"failed to setup logger\")\n\t\t\t}\n\n\t\t\tlog.L.Infof(\"Logger successfully set up. Proceeding to process nydus-snapshotter configurations\")\n\n\t\t\tif err := config.ProcessConfigurations(&snapshotterConfig); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"failed to process configurations\")\n\t\t\t}\n\n\t\t\tif err := config.SetUpEnvironment(&snapshotterConfig); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"failed to setup environment\")\n\t\t\t}\n\n\t\t\tlog.L.Infof(\"Start nydus-snapshotter. Version: %s, PID: %d, FsDriver: %s, DaemonMode: %s\",\n\t\t\t\tversion.Version, os.Getpid(), config.GetFsDriver(), snapshotterConfig.DaemonMode)\n\n\t\t\treturn Start(ctx, &snapshotterConfig)\n\t\t},\n\t}\n\tif err := app.Run(os.Args); err != nil {\n\t\tif errdefs.IsConnectionClosed(err) {\n\t\t\tlog.L.Info(\"nydus-snapshotter exited\")\n\t\t} else {\n\t\t\tlog.L.WithError(err).Fatal(\"failed to start nydus-snapshotter\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/containerd-nydus-grpc/snapshotter.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage main\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/signals\"\n\t\"github.com/containerd/nydus-snapshotter/snapshot\"\n\n\tapi \"github.com/containerd/containerd/api/services/snapshots/v1\"\n\t\"github.com/containerd/containerd/v2/contrib/snapshotservice\"\n\t\"github.com/containerd/containerd/v2/core/snapshots\"\n\t\"github.com/containerd/log\"\n\t\"google.golang.org/grpc\"\n)\n\nfunc Start(ctx context.Context, cfg *config.SnapshotterConfig) error {\n\tctx, cancel := context.WithCancel(ctx)\n\tdefer cancel()\n\trs, err := snapshot.NewSnapshotter(ctx, cfg)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to initialize snapshotter\")\n\t}\n\n\tstopSignal := signals.SetupSignalHandler()\n\topt := ServeOptions{\n\t\tListeningSocketPath: cfg.Address,\n\t\tListeningSocketUID:  cfg.UID,\n\t\tListeningSocketGID:  cfg.GID,\n\t\tEnableCRIKeychain:   cfg.RemoteConfig.AuthConfig.EnableCRIKeychain,\n\t\tImageServiceAddress: cfg.RemoteConfig.AuthConfig.ImageServiceAddress,\n\t}\n\n\tif cfg.RemoteConfig.AuthConfig.EnableKubeconfigKeychain {\n\t\tif err := auth.InitKubeSecretListener(ctx, cfg.RemoteConfig.AuthConfig.KubeconfigPath); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif cfg.RemoteConfig.AuthConfig.EnableKubeletCredentialProviders {\n\t\tif err := auth.InitKubeletProvider(\n\t\t\tcfg.RemoteConfig.AuthConfig.CredentialProviderConfig,\n\t\t\tcfg.RemoteConfig.AuthConfig.CredentialProviderBinDir,\n\t\t); err != nil {\n\t\t\treturn errors.Wrap(err, \"failed to initialize kubelet credential provider\")\n\t\t}\n\t}\n\n\treturn Serve(ctx, rs, opt, stopSignal)\n}\n\ntype ServeOptions struct {\n\tListeningSocketPath string\n\tListeningSocketUID  int\n\tListeningSocketGID  int\n\tEnableCRIKeychain   bool\n\tImageServiceAddress string\n}\n\nfunc Serve(ctx context.Context, sn snapshots.Snapshotter, options ServeOptions, stop <-chan struct{}) error {\n\terr := ensureSocketNotExists(options.ListeningSocketPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\trpc := grpc.NewServer()\n\tif rpc == nil {\n\t\treturn errors.New(\"start gRPC server\")\n\t}\n\tapi.RegisterSnapshotsServer(rpc, snapshotservice.FromSnapshotter(sn))\n\tlistener, err := net.Listen(\"unix\", options.ListeningSocketPath)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"listen socket %q\", options.ListeningSocketPath)\n\t}\n\n\tif err := os.Chown(options.ListeningSocketPath, options.ListeningSocketUID, options.ListeningSocketGID); err != nil {\n\t\treturn errors.Wrap(err, \"chown socket\")\n\t}\n\n\tif options.EnableCRIKeychain {\n\t\tauth.AddImageProxy(ctx, rpc, options.ImageServiceAddress)\n\t}\n\n\tgo func() {\n\t\t<-stop\n\n\t\tlog.L.Infof(\"Shutting down nydus-snapshotter!\")\n\n\t\tif err := sn.Close(); err != nil {\n\t\t\tlog.L.WithError(err).Errorf(\"Closing snapshotter error\")\n\t\t}\n\n\t\tif err := listener.Close(); err != nil {\n\t\t\tlog.L.Errorf(\"Failed to close listener %s, err: %v\", options.ListeningSocketPath, err)\n\t\t}\n\t}()\n\n\treturn rpc.Serve(listener)\n}\n\nfunc ensureSocketNotExists(listeningSocketPath string) error {\n\tif err := os.MkdirAll(filepath.Dir(listeningSocketPath), 0700); err != nil {\n\t\treturn errors.Wrapf(err, \"failed to create directory %q\", filepath.Dir(listeningSocketPath))\n\t}\n\tfinfo, err := os.Stat(listeningSocketPath)\n\t// err is nil means listening socket path exists, remove before serve\n\tif err == nil {\n\t\tif finfo.Mode()&os.ModeSocket == 0 {\n\t\t\treturn errors.Errorf(\"file %s is not a socket\", listeningSocketPath)\n\t\t}\n\t\terr := os.Remove(listeningSocketPath)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "cmd/converter/main.go",
    "content": "package main\n\n// Import the converter package so that it can be compiled during\n// `go build` to ensure cross-compilation compatibility.\nimport (\n\t_ \"github.com/containerd/nydus-snapshotter/pkg/converter\"\n)\n\nfunc main() {\n}\n"
  },
  {
    "path": "cmd/nydus-overlayfs/main.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path\"\n\t\"strings\"\n\t\"syscall\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/urfave/cli/v2\"\n\t\"golang.org/x/sys/unix\"\n)\n\nconst (\n\t// Extra mount option to pass Nydus specific information from snapshotter to runtime through containerd.\n\textraOptionKey = \"extraoption=\"\n\t// Kata virtual volume infmation passed from snapshotter to runtime through containerd, superset of `extraOptionKey`.\n\t// Please refer to `KataVirtualVolume` in https://github.com/kata-containers/kata-containers/blob/main/src/libs/kata-types/src/mount.rs\n\tkataVolumeOptionKey = \"io.katacontainers.volume=\"\n)\n\nvar (\n\tVersion   = \"v0.1\"\n\tBuildTime = \"unknown\"\n\tpagesize  = os.Getpagesize()\n)\n\n/*\ncontainerd run fuse.mount format: nydus-overlayfs overlay /tmp/ctd-volume107067851\n-o lowerdir=/foo/lower2:/foo/lower1,upperdir=/foo/upper,workdir=/foo/work,extraoption={...},dev,suid]\n*/\ntype mountArgs struct {\n\tfsType  string\n\ttarget  string\n\toptions []string\n}\n\nfunc parseArgs(args []string) (*mountArgs, error) {\n\tmargs := &mountArgs{\n\t\tfsType: args[0],\n\t\ttarget: args[1],\n\t}\n\tif margs.fsType != \"overlay\" {\n\t\treturn nil, errors.Errorf(\"invalid filesystem type %s for overlayfs\", margs.fsType)\n\t}\n\tif len(margs.target) == 0 {\n\t\treturn nil, errors.New(\"empty overlayfs mount target\")\n\t}\n\n\tif args[2] == \"-o\" && len(args[3]) != 0 {\n\t\tfor _, opt := range strings.Split(args[3], \",\") {\n\t\t\t// filter Nydus specific options\n\t\t\tif strings.HasPrefix(opt, extraOptionKey) || strings.HasPrefix(opt, kataVolumeOptionKey) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmargs.options = append(margs.options, opt)\n\t\t}\n\t}\n\tif len(margs.options) == 0 {\n\t\treturn nil, errors.New(\"empty overlayfs mount options\")\n\t}\n\n\treturn margs, nil\n}\n\nfunc parseOptions(options []string) (int, string) {\n\tflagsTable := map[string]int{\n\t\t\"async\":         unix.MS_SYNCHRONOUS,\n\t\t\"atime\":         unix.MS_NOATIME,\n\t\t\"bind\":          unix.MS_BIND,\n\t\t\"defaults\":      0,\n\t\t\"dev\":           unix.MS_NODEV,\n\t\t\"diratime\":      unix.MS_NODIRATIME,\n\t\t\"dirsync\":       unix.MS_DIRSYNC,\n\t\t\"exec\":          unix.MS_NOEXEC,\n\t\t\"mand\":          unix.MS_MANDLOCK,\n\t\t\"noatime\":       unix.MS_NOATIME,\n\t\t\"nodev\":         unix.MS_NODEV,\n\t\t\"nodiratime\":    unix.MS_NODIRATIME,\n\t\t\"noexec\":        unix.MS_NOEXEC,\n\t\t\"nomand\":        unix.MS_MANDLOCK,\n\t\t\"norelatime\":    unix.MS_RELATIME,\n\t\t\"nostrictatime\": unix.MS_STRICTATIME,\n\t\t\"nosuid\":        unix.MS_NOSUID,\n\t\t\"rbind\":         unix.MS_BIND | unix.MS_REC,\n\t\t\"relatime\":      unix.MS_RELATIME,\n\t\t\"remount\":       unix.MS_REMOUNT,\n\t\t\"ro\":            unix.MS_RDONLY,\n\t\t\"rw\":            unix.MS_RDONLY,\n\t\t\"strictatime\":   unix.MS_STRICTATIME,\n\t\t\"suid\":          unix.MS_NOSUID,\n\t\t\"sync\":          unix.MS_SYNCHRONOUS,\n\t}\n\n\tvar (\n\t\tflags int\n\t\tdata  []string\n\t)\n\tfor _, o := range options {\n\t\tif f, exist := flagsTable[o]; exist {\n\t\t\tflags |= f\n\t\t} else {\n\t\t\tdata = append(data, o)\n\t\t}\n\t}\n\treturn flags, strings.Join(data, \",\")\n}\n\n// longestCommonPrefix finds the longest common prefix in the string slice.\nfunc longestCommonPrefix(strs []string) string {\n\tif len(strs) == 0 {\n\t\treturn \"\"\n\t} else if len(strs) == 1 {\n\t\treturn strs[0]\n\t}\n\n\tmin, max := strs[0], strs[0]\n\tfor _, str := range strs[1:] {\n\t\tif min > str {\n\t\t\tmin = str\n\t\t}\n\t\tif max < str {\n\t\t\tmax = str\n\t\t}\n\t}\n\n\tfor i := 0; i < len(min) && i < len(max); i++ {\n\t\tif min[i] != max[i] {\n\t\t\treturn min[:i]\n\t\t}\n\t}\n\treturn min\n}\n\n// compactLowerdirOption shortens lowerdir paths by extracting the longest\n// common directory prefix across all lowerdirs, upperdir, and workdir. The\n// caller chdir's into that prefix before calling mount so the kernel receives\n// shorter, relative paths that fit within the mount-data page-size limit.\n// Ported from containerd's core/mount/mount_linux.go.\nfunc compactLowerdirOption(options []string) (string, []string) {\n\tvar lowerdirIdx = -1\n\tfor i, opt := range options {\n\t\tif strings.HasPrefix(opt, \"lowerdir=\") {\n\t\t\tlowerdirIdx = i\n\t\t\tbreak\n\t\t}\n\t}\n\tif lowerdirIdx == -1 {\n\t\treturn \"\", options\n\t}\n\n\tdirs := strings.Split(options[lowerdirIdx][len(\"lowerdir=\"):], \":\")\n\tif len(dirs) <= 1 {\n\t\treturn \"\", options\n\t}\n\n\t// Collect all paths that participate in the overlay: lowerdirs + upperdir + workdir.\n\tallPaths := make([]string, 0, len(dirs)+2)\n\tallPaths = append(allPaths, dirs...)\n\tfor _, opt := range options {\n\t\tif strings.HasPrefix(opt, \"upperdir=\") {\n\t\t\tallPaths = append(allPaths, opt[len(\"upperdir=\"):])\n\t\t} else if strings.HasPrefix(opt, \"workdir=\") {\n\t\t\tallPaths = append(allPaths, opt[len(\"workdir=\"):])\n\t\t}\n\t}\n\n\tcommondir := longestCommonPrefix(allPaths)\n\tif commondir == \"\" {\n\t\treturn \"\", options\n\t}\n\n\t// Back up to the parent directory to avoid partial snapshot-id matches.\n\tcommondir = path.Dir(commondir)\n\tif commondir == \"/\" || commondir == \".\" {\n\t\treturn \"\", options\n\t}\n\tcommondir += \"/\"\n\n\t// Rebuild options with relative paths.\n\tnewopts := make([]string, 0, len(options))\n\tfor i, opt := range options {\n\t\tswitch {\n\t\tcase i == lowerdirIdx:\n\t\t\tnewdirs := make([]string, 0, len(dirs))\n\t\t\tfor _, dir := range dirs {\n\t\t\t\tif len(dir) <= len(commondir) {\n\t\t\t\t\treturn \"\", options\n\t\t\t\t}\n\t\t\t\tnewdirs = append(newdirs, dir[len(commondir):])\n\t\t\t}\n\t\t\tnewopts = append(newopts, fmt.Sprintf(\"lowerdir=%s\", strings.Join(newdirs, \":\")))\n\t\tcase strings.HasPrefix(opt, \"upperdir=\"):\n\t\t\tp := opt[len(\"upperdir=\"):]\n\t\t\tif len(p) <= len(commondir) {\n\t\t\t\treturn \"\", options\n\t\t\t}\n\t\t\tnewopts = append(newopts, fmt.Sprintf(\"upperdir=%s\", p[len(commondir):]))\n\t\tcase strings.HasPrefix(opt, \"workdir=\"):\n\t\t\tp := opt[len(\"workdir=\"):]\n\t\t\tif len(p) <= len(commondir) {\n\t\t\t\treturn \"\", options\n\t\t\t}\n\t\t\tnewopts = append(newopts, fmt.Sprintf(\"workdir=%s\", p[len(commondir):]))\n\t\tdefault:\n\t\t\tnewopts = append(newopts, opt)\n\t\t}\n\t}\n\treturn commondir, newopts\n}\n\nfunc run(args cli.Args) error {\n\tmargs, err := parseArgs(args.Slice())\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"parse mount options\")\n\t}\n\n\tflags, data := parseOptions(margs.options)\n\n\t// When the mount data string exceeds the kernel's page-size limit, compact\n\t// overlay paths by chdir'ing into their common prefix and using relative\n\t// paths — the same approach containerd uses for direct overlay mounts.\n\tvar chdir string\n\tif len(data) >= pagesize-512 {\n\t\tchdir, margs.options = compactLowerdirOption(margs.options)\n\t\tif chdir != \"\" {\n\t\t\t_, data = parseOptions(margs.options)\n\t\t}\n\t}\n\n\tif chdir != \"\" {\n\t\tif err := os.Chdir(chdir); err != nil {\n\t\t\treturn errors.Wrapf(err, \"chdir to common overlay dir %s\", chdir)\n\t\t}\n\t}\n\n\terr = syscall.Mount(margs.fsType, margs.target, margs.fsType, uintptr(flags), data)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"mount overlayfs by syscall\")\n\t}\n\treturn nil\n}\n\nfunc main() {\n\tapp := &cli.App{\n\t\tName:      \"NydusOverlayfs\",\n\t\tUsage:     \"FUSE mount helper for containerd to filter out Nydus specific options\",\n\t\tVersion:   fmt.Sprintf(\"%s.%s\", Version, BuildTime),\n\t\tUsageText: \"[Usage]: nydus-overlayfs overlay <target> -o <options>\",\n\t\tAction: func(c *cli.Context) error {\n\t\t\treturn run(c.Args())\n\t\t},\n\t\tBefore: func(c *cli.Context) error {\n\t\t\tif c.NArg() != 4 {\n\t\t\t\tcli.ShowAppHelpAndExit(c, 1)\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\n\terr := app.Run(os.Args)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tos.Exit(0)\n}\n"
  },
  {
    "path": "cmd/nydus-overlayfs/main_test.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestLongestCommonPrefix(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tinput    []string\n\t\texpected string\n\t}{\n\t\t{\n\t\t\tname:     \"empty slice\",\n\t\t\tinput:    []string{},\n\t\t\texpected: \"\",\n\t\t},\n\t\t{\n\t\t\tname:     \"single element\",\n\t\t\tinput:    []string{\"/var/lib/snapshots/1/fs\"},\n\t\t\texpected: \"/var/lib/snapshots/1/fs\",\n\t\t},\n\t\t{\n\t\t\tname:     \"common prefix across snapshot ids\",\n\t\t\tinput:    []string{\"/var/lib/snapshots/128/fs\", \"/var/lib/snapshots/21/fs\", \"/var/lib/snapshots/99/fs\"},\n\t\t\texpected: \"/var/lib/snapshots/\",\n\t\t},\n\t\t{\n\t\t\tname:     \"no common prefix\",\n\t\t\tinput:    []string{\"/foo/bar\", \"/baz/qux\"},\n\t\t\texpected: \"/\",\n\t\t},\n\t\t{\n\t\t\tname:     \"identical strings\",\n\t\t\tinput:    []string{\"/a/b/c\", \"/a/b/c\"},\n\t\t\texpected: \"/a/b/c\",\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tresult := longestCommonPrefix(tc.input)\n\t\t\tassert.Equal(t, tc.expected, result)\n\t\t})\n\t}\n}\n\nfunc TestCompactLowerdirOption(t *testing.T) {\n\ttests := []struct {\n\t\tname            string\n\t\toptions         []string\n\t\texpectedChdir   string\n\t\texpectedOptions []string\n\t}{\n\t\t{\n\t\t\tname:            \"no lowerdir option\",\n\t\t\toptions:         []string{\"ro\", \"dev\"},\n\t\t\texpectedChdir:   \"\",\n\t\t\texpectedOptions: []string{\"ro\", \"dev\"},\n\t\t},\n\t\t{\n\t\t\tname:            \"single lowerdir - no compaction needed\",\n\t\t\toptions:         []string{\"lowerdir=/var/lib/snapshots/1/fs\"},\n\t\t\texpectedChdir:   \"\",\n\t\t\texpectedOptions: []string{\"lowerdir=/var/lib/snapshots/1/fs\"},\n\t\t},\n\t\t{\n\t\t\tname: \"two lowerdirs with common prefix\",\n\t\t\toptions: []string{\n\t\t\t\t\"workdir=/var/lib/snapshots/3/work\",\n\t\t\t\t\"upperdir=/var/lib/snapshots/3/fs\",\n\t\t\t\t\"lowerdir=/var/lib/snapshots/2/fs:/var/lib/snapshots/1/fs\",\n\t\t\t},\n\t\t\texpectedChdir: \"/var/lib/snapshots/\",\n\t\t\texpectedOptions: []string{\n\t\t\t\t\"workdir=3/work\",\n\t\t\t\t\"upperdir=3/fs\",\n\t\t\t\t\"lowerdir=2/fs:1/fs\",\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"many lowerdirs simulating real nydus case\",\n\t\t\toptions: func() []string {\n\t\t\t\tlowerdirs := make([]string, 0, 108)\n\t\t\t\tfor i := 128; i >= 21; i-- {\n\t\t\t\t\tlowerdirs = append(lowerdirs, fmt.Sprintf(\"/var/lib/nydus-snapshotter/snapshots/%d/fs\", i))\n\t\t\t\t}\n\t\t\t\treturn []string{\n\t\t\t\t\t\"workdir=/var/lib/nydus-snapshotter/snapshots/129/work\",\n\t\t\t\t\t\"upperdir=/var/lib/nydus-snapshotter/snapshots/129/fs\",\n\t\t\t\t\tfmt.Sprintf(\"lowerdir=%s\", strings.Join(lowerdirs, \":\")),\n\t\t\t\t\t\"ro\",\n\t\t\t\t}\n\t\t\t}(),\n\t\t\texpectedChdir: \"/var/lib/nydus-snapshotter/snapshots/\",\n\t\t\texpectedOptions: func() []string {\n\t\t\t\tlowerdirs := make([]string, 0, 108)\n\t\t\t\tfor i := 128; i >= 21; i-- {\n\t\t\t\t\tlowerdirs = append(lowerdirs, fmt.Sprintf(\"%d/fs\", i))\n\t\t\t\t}\n\t\t\t\treturn []string{\n\t\t\t\t\t\"workdir=129/work\",\n\t\t\t\t\t\"upperdir=129/fs\",\n\t\t\t\t\tfmt.Sprintf(\"lowerdir=%s\", strings.Join(lowerdirs, \":\")),\n\t\t\t\t\t\"ro\",\n\t\t\t\t}\n\t\t\t}(),\n\t\t},\n\t\t{\n\t\t\tname: \"disjoint paths - no compaction possible\",\n\t\t\toptions: []string{\n\t\t\t\t\"workdir=/tmp/work\",\n\t\t\t\t\"upperdir=/tmp/upper\",\n\t\t\t\t\"lowerdir=/var/lib/snapshots/2/fs:/var/lib/snapshots/1/fs\",\n\t\t\t},\n\t\t\texpectedChdir:   \"\",\n\t\t\texpectedOptions: nil, // same as input\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tchdir, newopts := compactLowerdirOption(tc.options)\n\t\t\tassert.Equal(t, tc.expectedChdir, chdir)\n\t\t\tif tc.expectedOptions != nil {\n\t\t\t\tassert.Equal(t, tc.expectedOptions, newopts)\n\t\t\t}\n\n\t\t\tif chdir != \"\" {\n\t\t\t\t_, newdata := parseOptions(newopts)\n\t\t\t\tassert.Less(t, len(newdata), len(strings.Join(tc.options, \",\")),\n\t\t\t\t\t\"compacted options should be shorter than original\")\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestCompactLowerdirOption_RealWorldSizeSavings(t *testing.T) {\n\tlowerdirs := make([]string, 0, 108)\n\tfor i := 128; i >= 21; i-- {\n\t\tlowerdirs = append(lowerdirs, fmt.Sprintf(\"/var/lib/nydus-snapshotter/snapshots/%d/fs\", i))\n\t}\n\toptions := []string{\n\t\t\"workdir=/var/lib/nydus-snapshotter/snapshots/129/work\",\n\t\t\"upperdir=/var/lib/nydus-snapshotter/snapshots/129/fs\",\n\t\tfmt.Sprintf(\"lowerdir=%s\", strings.Join(lowerdirs, \":\")),\n\t}\n\n\t_, origdata := parseOptions(options)\n\tchdir, newopts := compactLowerdirOption(options)\n\trequire.NotEmpty(t, chdir)\n\n\t_, compactdata := parseOptions(newopts)\n\n\tassert.Greater(t, len(origdata), 4096, \"original data should exceed page size\")\n\tassert.Less(t, len(compactdata), 4096, \"compacted data should fit within page size\")\n}\n\nfunc TestParseArgs(t *testing.T) {\n\ttests := []struct {\n\t\tname            string\n\t\targs            []string\n\t\texpectedType    string\n\t\texpectedTarget  string\n\t\texpectedOptions []string\n\t\texpectErr       bool\n\t}{\n\t\t{\n\t\t\tname:            \"basic overlay\",\n\t\t\targs:            []string{\"overlay\", \"/tmp/merged\", \"-o\", \"lowerdir=/a:/b,upperdir=/c,workdir=/d\"},\n\t\t\texpectedType:    \"overlay\",\n\t\t\texpectedTarget:  \"/tmp/merged\",\n\t\t\texpectedOptions: []string{\"lowerdir=/a:/b\", \"upperdir=/c\", \"workdir=/d\"},\n\t\t},\n\t\t{\n\t\t\tname:            \"filters extraoption\",\n\t\t\targs:            []string{\"overlay\", \"/tmp/merged\", \"-o\", \"lowerdir=/a:/b,extraoption=abc123,ro\"},\n\t\t\texpectedType:    \"overlay\",\n\t\t\texpectedTarget:  \"/tmp/merged\",\n\t\t\texpectedOptions: []string{\"lowerdir=/a:/b\", \"ro\"},\n\t\t},\n\t\t{\n\t\t\tname:            \"filters kata volume option\",\n\t\t\targs:            []string{\"overlay\", \"/tmp/merged\", \"-o\", \"lowerdir=/a:/b,io.katacontainers.volume=abc123,ro\"},\n\t\t\texpectedType:    \"overlay\",\n\t\t\texpectedTarget:  \"/tmp/merged\",\n\t\t\texpectedOptions: []string{\"lowerdir=/a:/b\", \"ro\"},\n\t\t},\n\t\t{\n\t\t\tname:      \"invalid fs type\",\n\t\t\targs:      []string{\"ext4\", \"/tmp/merged\", \"-o\", \"lowerdir=/a\"},\n\t\t\texpectErr: true,\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tmargs, err := parseArgs(tc.args)\n\t\t\tif tc.expectErr {\n\t\t\t\tassert.Error(t, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\trequire.NoError(t, err)\n\t\t\tassert.Equal(t, tc.expectedType, margs.fsType)\n\t\t\tassert.Equal(t, tc.expectedTarget, margs.target)\n\t\t\tassert.Equal(t, tc.expectedOptions, margs.options)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "cmd/optimizer-nri-plugin/main.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"log/syslog\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\tdistribution \"github.com/distribution/reference\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/urfave/cli/v2\"\n\n\t\"github.com/containerd/nri/pkg/api\"\n\t\"github.com/containerd/nri/pkg/stub\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/fanotify\"\n\t\"github.com/containerd/nydus-snapshotter/version\"\n\t\"github.com/pelletier/go-toml\"\n)\n\nconst (\n\tdefaultEvents     = \"StartContainer,StopContainer\"\n\tdefaultServerPath = \"/usr/local/bin/optimizer-server\"\n\tdefaultPersistDir = \"/opt/nri/optimizer/results\"\n)\n\ntype PluginConfig struct {\n\tEvents []string `toml:\"events\"`\n\n\tServerPath string `toml:\"server_path\"`\n\tPersistDir string `toml:\"persist_dir\"`\n\tReadable   bool   `toml:\"readable\"`\n\tTimeout    int    `toml:\"timeout\"`\n\tOverwrite  bool   `toml:\"overwrite\"`\n}\n\ntype PluginArgs struct {\n\tPluginName   string\n\tPluginIdx    string\n\tPluginEvents string\n\tConfig       PluginConfig\n}\n\ntype Flags struct {\n\tArgs *PluginArgs\n\tF    []cli.Flag\n}\n\nfunc buildFlags(args *PluginArgs) []cli.Flag {\n\treturn []cli.Flag{\n\t\t&cli.StringFlag{\n\t\t\tName:        \"name\",\n\t\t\tUsage:       \"plugin name to register to NRI\",\n\t\t\tDestination: &args.PluginName,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"idx\",\n\t\t\tUsage:       \"plugin index to register to NRI\",\n\t\t\tDestination: &args.PluginIdx,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"events\",\n\t\t\tValue:       defaultEvents,\n\t\t\tUsage:       \"the events that containerd subscribes to. DO NOT CHANGE THIS.\",\n\t\t\tDestination: &args.PluginEvents,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"server-path\",\n\t\t\tValue:       defaultServerPath,\n\t\t\tUsage:       \"the path of optimizer server binary\",\n\t\t\tDestination: &args.Config.ServerPath,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"persist-dir\",\n\t\t\tValue:       defaultPersistDir,\n\t\t\tUsage:       \"the directory to persist accessed files list for container\",\n\t\t\tDestination: &args.Config.PersistDir,\n\t\t},\n\t\t&cli.BoolFlag{\n\t\t\tName:        \"readable\",\n\t\t\tValue:       false,\n\t\t\tUsage:       \"whether to make the csv file human readable\",\n\t\t\tDestination: &args.Config.Readable,\n\t\t},\n\t\t&cli.IntFlag{\n\t\t\tName:        \"timeout\",\n\t\t\tValue:       0,\n\t\t\tUsage:       \"the timeout to kill optimizer server, 0 to disable it\",\n\t\t\tDestination: &args.Config.Timeout,\n\t\t},\n\t\t&cli.BoolFlag{\n\t\t\tName:        \"overwrite\",\n\t\t\tUsage:       \"whether to overwrite the existed persistent files\",\n\t\t\tDestination: &args.Config.Overwrite,\n\t\t},\n\t}\n}\n\nfunc NewPluginFlags() *Flags {\n\tvar args PluginArgs\n\treturn &Flags{\n\t\tArgs: &args,\n\t\tF:    buildFlags(&args),\n\t}\n}\n\ntype plugin struct {\n\tstub stub.Stub\n\tmask stub.EventMask\n}\n\nvar (\n\tcfg                  PluginConfig\n\tlogWriter            *syslog.Writer\n\tglobalFanotifyServer = make(map[string]*fanotify.Server)\n\n\t_ = stub.ConfigureInterface(&plugin{})\n\t_ = stub.StartContainerInterface(&plugin{})\n\t_ = stub.StopContainerInterface(&plugin{})\n)\n\nconst (\n\timageNameLabel = \"io.kubernetes.cri.image-name\"\n)\n\nfunc (p *plugin) Configure(ctx context.Context, config, runtime, version string) (stub.EventMask, error) {\n\tlog.G(ctx).Infof(\"got configuration data: %q from runtime %s %s\", config, runtime, version)\n\tif config == \"\" {\n\t\treturn p.mask, nil\n\t}\n\n\ttree, err := toml.Load(config)\n\tif err != nil {\n\t\treturn 0, errors.Wrap(err, \"parse TOML\")\n\t}\n\tif err := tree.Unmarshal(&cfg); err != nil {\n\t\treturn 0, err\n\t}\n\n\tp.mask, err = api.ParseEventMask(cfg.Events...)\n\tif err != nil {\n\t\treturn 0, errors.Wrap(err, \"parse events in configuration\")\n\t}\n\n\tlog.G(ctx).Infof(\"configuration: %#v\", cfg)\n\n\treturn p.mask, nil\n}\n\nfunc (p *plugin) StartContainer(_ context.Context, _ *api.PodSandbox, container *api.Container) error {\n\tdir, imageName, err := GetImageName(container.Annotations)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tpersistDir := filepath.Join(cfg.PersistDir, dir)\n\tif err := os.MkdirAll(persistDir, os.ModePerm); err != nil {\n\t\treturn err\n\t}\n\n\tpersistFile := filepath.Join(persistDir, imageName)\n\tif cfg.Timeout > 0 {\n\t\tpersistFile = fmt.Sprintf(\"%s.timeout%ds\", persistFile, cfg.Timeout)\n\t}\n\n\tfanotifyServer := fanotify.NewServer(cfg.ServerPath, container.Pid, imageName, persistFile, cfg.Readable, cfg.Overwrite, time.Duration(cfg.Timeout)*time.Second, logWriter)\n\n\tif err := fanotifyServer.RunServer(); err != nil {\n\t\treturn err\n\t}\n\n\tglobalFanotifyServer[imageName] = fanotifyServer\n\n\treturn nil\n}\n\nfunc (p *plugin) StopContainer(_ context.Context, _ *api.PodSandbox, container *api.Container) ([]*api.ContainerUpdate, error) {\n\tvar update = []*api.ContainerUpdate{}\n\t_, imageName, err := GetImageName(container.Annotations)\n\tif err != nil {\n\t\treturn update, err\n\t}\n\tif fanotifyServer, ok := globalFanotifyServer[imageName]; ok {\n\t\tfanotifyServer.StopServer()\n\t} else {\n\t\treturn nil, errors.New(\"can not find fanotify server for container image \" + imageName)\n\t}\n\n\treturn update, nil\n}\n\nfunc GetImageName(annotations map[string]string) (string, string, error) {\n\tnamed, err := distribution.ParseDockerRef(annotations[imageNameLabel])\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\tnameTagged := named.(distribution.NamedTagged)\n\trepo := distribution.Path(nameTagged)\n\n\tdir := filepath.Dir(repo)\n\timage := filepath.Base(repo)\n\n\timageName := image + \":\" + nameTagged.Tag()\n\n\treturn dir, imageName, nil\n}\n\nfunc (p *plugin) onClose() {\n\tfor _, fanotifyServer := range globalFanotifyServer {\n\t\tfanotifyServer.StopServer()\n\t}\n\tos.Exit(0)\n}\n\nfunc main() {\n\tflags := NewPluginFlags()\n\tapp := &cli.App{\n\t\tName:        \"optimizer-nri-plugin\",\n\t\tUsage:       \"Optimizer client for NRI plugin to manage optimizer server\",\n\t\tVersion:     version.Version,\n\t\tFlags:       flags.F,\n\t\tHideVersion: true,\n\t\tAction: func(_ *cli.Context) error {\n\t\t\tvar (\n\t\t\t\topts []stub.Option\n\t\t\t\terr  error\n\t\t\t)\n\n\t\t\tcfg = flags.Args.Config\n\n\t\t\t// FIXME(thaJeztah): ucontainerd's log does not set \"PadLevelText: true\"\n\t\t\t_ = log.SetFormat(log.TextFormat)\n\t\t\tctx := log.WithLogger(context.Background(), log.L)\n\n\t\t\tlogWriter, err = syslog.New(syslog.LOG_INFO, \"optimizer-nri-plugin\")\n\t\t\tif err == nil {\n\t\t\t\tlog.G(ctx).Logger.SetOutput(io.MultiWriter(os.Stdout, logWriter))\n\t\t\t}\n\n\t\t\tif flags.Args.PluginName != \"\" {\n\t\t\t\topts = append(opts, stub.WithPluginName(flags.Args.PluginName))\n\t\t\t}\n\t\t\tif flags.Args.PluginIdx != \"\" {\n\t\t\t\topts = append(opts, stub.WithPluginIdx(flags.Args.PluginIdx))\n\t\t\t}\n\n\t\t\tp := &plugin{}\n\n\t\t\tif p.mask, err = api.ParseEventMask(flags.Args.PluginEvents); err != nil {\n\t\t\t\tlog.G(ctx).Fatalf(\"failed to parse events: %v\", err)\n\t\t\t}\n\t\t\tcfg.Events = strings.Split(flags.Args.PluginEvents, \",\")\n\n\t\t\tif p.stub, err = stub.New(p, append(opts, stub.WithOnClose(p.onClose))...); err != nil {\n\t\t\t\tlog.G(ctx).Fatalf(\"failed to create plugin stub: %v\", err)\n\t\t\t}\n\n\t\t\terr = p.stub.Run(context.Background())\n\t\t\tif err != nil {\n\t\t\t\tlog.G(ctx).Errorf(\"plugin exited with error %v\", err)\n\t\t\t\tos.Exit(1)\n\t\t\t}\n\n\t\t\treturn nil\n\t\t},\n\t}\n\tif err := app.Run(os.Args); err != nil {\n\t\tif errdefs.IsConnectionClosed(err) {\n\t\t\tlog.L.Info(\"optimizer NRI plugin exited\")\n\t\t} else {\n\t\t\tlog.L.WithError(err).Fatal(\"failed to start optimizer NRI plugin\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmd/prefetchfiles-nri-plugin/main.go",
    "content": "/*\n* Copyright (c) 2023. Nydus Developers. All rights reserved.\n*\n* SPDX-License-Identifier: Apache-2.0\n */\n\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"log/syslog\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nri/pkg/api\"\n\t\"github.com/containerd/nri/pkg/stub\"\n\t\"github.com/pelletier/go-toml\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/urfave/cli/v2\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/version\"\n)\n\nconst (\n\tendpointPrefetch               = \"/api/v1/prefetch\"\n\tdefaultEvents                  = \"RunPodSandbox\"\n\tdefaultSystemControllerAddress = \"/run/containerd-nydus/system.sock\"\n\tdefaultPrefetchConfigDir       = \"/etc/nydus\"\n\tnydusPrefetchAnnotation        = \"containerd.io/nydus-prefetch\"\n)\n\ntype PluginArgs struct {\n\tPluginName    string\n\tPluginIdx     string\n\tSocketAddress string\n}\n\ntype Flags struct {\n\tArgs *PluginArgs\n\tFlag []cli.Flag\n}\n\nfunc buildFlags(args *PluginArgs) []cli.Flag {\n\treturn []cli.Flag{\n\t\t&cli.StringFlag{\n\t\t\tName:        \"name\",\n\t\t\tUsage:       \"plugin name to register to NRI\",\n\t\t\tDestination: &args.PluginName,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"idx\",\n\t\t\tUsage:       \"plugin index to register to NRI\",\n\t\t\tDestination: &args.PluginIdx,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"socket-addr\",\n\t\t\tValue:       defaultSystemControllerAddress,\n\t\t\tUsage:       \"unix domain socket address. If defined in the configuration file, there is no need to add \",\n\t\t\tDestination: &args.SocketAddress,\n\t\t},\n\t}\n}\n\nfunc NewPluginFlags() *Flags {\n\tvar args PluginArgs\n\treturn &Flags{\n\t\tArgs: &args,\n\t\tFlag: buildFlags(&args),\n\t}\n}\n\ntype plugin struct {\n\tstub stub.Stub\n\tmask stub.EventMask\n}\n\nvar (\n\tglobalSocket string\n\tlogWriter    *syslog.Writer\n\n\t_ = stub.RunPodInterface(&plugin{})\n)\n\n// sendDataOverHTTP sends the prefetch data to the specified endpoint over HTTP using a Unix socket.\nfunc sendDataOverHTTP(data string, endpoint, sock string) error {\n\turl := fmt.Sprintf(\"http://unix%s\", endpoint)\n\n\treq, err := http.NewRequest(http.MethodPut, url, strings.NewReader(data))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tclient := &http.Client{\n\t\tTransport: &http.Transport{\n\t\t\tDialContext: func(_ context.Context, _, _ string) (net.Conn, error) {\n\t\t\t\treturn net.Dial(\"unix\", sock)\n\t\t\t},\n\t\t},\n\t}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to send data, status code: %d\", resp.StatusCode)\n\t}\n\tresp.Body.Close()\n\n\treturn nil\n}\n\nfunc (p *plugin) RunPodSandbox(ctx context.Context, pod *api.PodSandbox) error {\n\tprefetchList, ok := pod.Annotations[nydusPrefetchAnnotation]\n\tif !ok {\n\t\treturn nil\n\t}\n\n\terr := sendDataOverHTTP(prefetchList, endpointPrefetch, globalSocket)\n\tif err != nil {\n\t\tlog.G(ctx).Errorf(\"failed to send data: %v\", err)\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc main() {\n\tflags := NewPluginFlags()\n\n\tapp := &cli.App{\n\t\tName:        \"prefetch-nri-plugin\",\n\t\tUsage:       \"NRI plugin for obtaining and transmitting prefetch files path\",\n\t\tVersion:     version.Version,\n\t\tFlags:       flags.Flag,\n\t\tHideVersion: true,\n\t\tAction: func(_ *cli.Context) error {\n\t\t\tvar (\n\t\t\t\topts []stub.Option\n\t\t\t\terr  error\n\t\t\t)\n\n\t\t\t// FIXME(thaJeztah): ucontainerd's log does not set \"PadLevelText: true\"\n\t\t\t_ = log.SetFormat(log.TextFormat)\n\t\t\tctx := log.WithLogger(context.Background(), log.L)\n\n\t\t\tconfigFileName := \"prefetchConfig.toml\"\n\t\t\tconfigDir := defaultPrefetchConfigDir\n\t\t\tconfigFilePath := filepath.Join(configDir, configFileName)\n\n\t\t\tconfig, err := toml.LoadFile(configFilePath)\n\t\t\tif err != nil {\n\t\t\t\tlog.G(ctx).Warnf(\"failed to read config file: %v\", err)\n\t\t\t}\n\n\t\t\tconfigSocketAddrRaw := config.Get(\"file_prefetch.socket_address\")\n\t\t\tif configSocketAddrRaw != nil {\n\t\t\t\tif configSocketAddr, ok := configSocketAddrRaw.(string); ok {\n\t\t\t\t\tglobalSocket = configSocketAddr\n\t\t\t\t} else {\n\t\t\t\t\tlog.G(ctx).Warnf(\"failed to read config: 'file_prefetch.socket_address' is not a string\")\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tglobalSocket = flags.Args.SocketAddress\n\t\t\t}\n\n\t\t\tlogWriter, err = syslog.New(syslog.LOG_INFO, \"prefetch-nri-plugin\")\n\t\t\tif err == nil {\n\t\t\t\tlog.G(ctx).Logger.SetOutput(io.MultiWriter(os.Stdout, logWriter))\n\t\t\t}\n\n\t\t\tif flags.Args.PluginName != \"\" {\n\t\t\t\topts = append(opts, stub.WithPluginName(flags.Args.PluginName))\n\t\t\t}\n\t\t\tif flags.Args.PluginIdx != \"\" {\n\t\t\t\topts = append(opts, stub.WithPluginIdx(flags.Args.PluginIdx))\n\t\t\t}\n\n\t\t\tp := &plugin{}\n\n\t\t\tif p.mask, err = api.ParseEventMask(defaultEvents); err != nil {\n\t\t\t\tlog.G(ctx).Fatalf(\"failed to parse events: %v\", err)\n\t\t\t}\n\n\t\t\tif p.stub, err = stub.New(p, opts...); err != nil {\n\t\t\t\tlog.G(ctx).Fatalf(\"failed to create plugin stub: %v\", err)\n\t\t\t}\n\n\t\t\terr = p.stub.Run(context.Background())\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"plugin exited\")\n\t\t\t}\n\t\t\treturn nil\n\t\t},\n\t}\n\tif err := app.Run(os.Args); err != nil {\n\t\tif errdefs.IsConnectionClosed(err) {\n\t\t\tlog.L.Info(\"prefetch NRI plugin exited\")\n\t\t} else {\n\t\t\tlog.L.WithError(err).Fatal(\"failed to start prefetch NRI plugin\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "config/config.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage config\n\nimport (\n\t\"os\"\n\t\"time\"\n\n\t\"dario.cat/mergo\"\n\t\"github.com/pelletier/go-toml\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/internal/constant\"\n\t\"github.com/containerd/nydus-snapshotter/internal/flags\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/cgroup\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/file\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/parser\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/sysinfo\"\n)\n\nfunc init() {\n\trecoverPolicyParser = map[string]DaemonRecoverPolicy{\n\t\tRecoverPolicyNone.String():     RecoverPolicyNone,\n\t\tRecoverPolicyRestart.String():  RecoverPolicyRestart,\n\t\tRecoverPolicyFailover.String(): RecoverPolicyFailover}\n}\n\n// Define a policy how to fork nydusd daemon and attach file system instances to serve.\ntype DaemonMode string\n\nconst (\n\t// Spawn a dedicated nydusd for each RAFS instance.\n\tDaemonModeMultiple DaemonMode = DaemonMode(constant.DaemonModeMultiple)\n\t// Spawn a dedicated nydusd for each RAFS instance.\n\tDaemonModeDedicated DaemonMode = DaemonMode(constant.DaemonModeDedicated)\n\t// Share a global nydusd to serve all RAFS instances.\n\tDaemonModeShared DaemonMode = DaemonMode(constant.DaemonModeShared)\n\t// Do not spawn nydusd for RAFS instances.\n\t//\n\t// For tarfs and rund, there's no need to create nydusd to serve RAFS instances,\n\t// the snapshotter just returns mount slices with additional information for runC/runD\n\t// to manage those snapshots.\n\tDaemonModeNone    DaemonMode = DaemonMode(constant.DaemonModeNone)\n\tDaemonModeInvalid DaemonMode = DaemonMode(constant.DaemonModeInvalid)\n\t// MaxRootPathLen defines the maximum allowed length of the root portion of a Unix domain socket path.\n\t//\n\t// This value is calculated based on the hard length limit of `sun_path` on Linux systems (108 bytes).\n\t// Nydusd's socket path format is \"${rootPath}/socket/${xid}/api?.sock\".\n\t// - The length of the fixed part \"/socket/${xid}/api?.sock\" is 38 bytes.\n\t//\n\t// Since the maximum upper limit of the total path length is 108 bytes, in order to avoid exceeding the limit, the maximum allowed length of rootPath is:\n\t// 108 - len(\"/socket/${xid}/api?.sock\") = 108 - 38 = 70.\n\t// Therefore, we must set the effective maximum length of the root path to 70 bytes.\n\tMaxRootPathLen = 70\n)\n\nfunc parseDaemonMode(m string) (DaemonMode, error) {\n\tswitch m {\n\tcase string(DaemonModeMultiple):\n\t\treturn DaemonModeDedicated, nil\n\tcase string(DaemonModeDedicated):\n\t\treturn DaemonModeDedicated, nil\n\tcase string(DaemonModeShared):\n\t\treturn DaemonModeShared, nil\n\tcase string(DaemonModeNone):\n\t\treturn DaemonModeNone, nil\n\tdefault:\n\t\treturn DaemonModeInvalid, errors.Errorf(\"invalid daemon mode %q\", m)\n\t}\n}\n\ntype DaemonRecoverPolicy int\n\nconst (\n\tRecoverPolicyInvalid DaemonRecoverPolicy = iota\n\tRecoverPolicyNone\n\tRecoverPolicyRestart\n\tRecoverPolicyFailover\n)\n\nfunc (p DaemonRecoverPolicy) String() string {\n\tswitch p {\n\tcase RecoverPolicyNone:\n\t\treturn \"none\"\n\tcase RecoverPolicyRestart:\n\t\treturn \"restart\"\n\tcase RecoverPolicyFailover:\n\t\treturn \"failover\"\n\tcase RecoverPolicyInvalid:\n\t\tfallthrough\n\tdefault:\n\t\treturn \"\"\n\t}\n}\n\nvar recoverPolicyParser map[string]DaemonRecoverPolicy\n\nfunc ParseRecoverPolicy(p string) (DaemonRecoverPolicy, error) {\n\tpolicy, ok := recoverPolicyParser[p]\n\tif !ok {\n\t\treturn RecoverPolicyInvalid, errors.Errorf(\"invalid recover policy %q\", p)\n\t}\n\n\treturn policy, nil\n}\n\nconst (\n\tFsDriverBlockdev string = constant.FsDriverBlockdev\n\tFsDriverFusedev  string = constant.FsDriverFusedev\n\tFsDriverFscache  string = constant.FsDriverFscache\n\tFsDriverNodev    string = constant.FsDriverNodev\n\tFsDriverProxy    string = constant.FsDriverProxy\n)\n\nconst (\n\tFailoverPolicyNone   string = constant.FailoverPolicyNone\n\tFailoverPolicyResend string = constant.FailoverPolicyResend\n\tFailoverPolicyFlush  string = constant.FailoverPolicyFlush\n)\n\ntype Experimental struct {\n\tEnableStargz         bool        `toml:\"enable_stargz\"`\n\tEnableReferrerDetect bool        `toml:\"enable_referrer_detect\"`\n\tEnableIndexDetect    bool        `toml:\"enable_index_detect\"`\n\tTarfsConfig          TarfsConfig `toml:\"tarfs\"`\n\tEnableBackendSource  bool        `toml:\"enable_backend_source\"`\n}\n\ntype TarfsConfig struct {\n\tEnableTarfs       bool   `toml:\"enable_tarfs\"`\n\tMountTarfsOnHost  bool   `toml:\"mount_tarfs_on_host\"`\n\tTarfsHint         bool   `toml:\"tarfs_hint\"`\n\tMaxConcurrentProc int    `toml:\"max_concurrent_proc\"`\n\tExportMode        string `toml:\"export_mode\"`\n}\n\ntype CgroupConfig struct {\n\tEnable      bool   `toml:\"enable\"`\n\tMemoryLimit string `toml:\"memory_limit\"`\n}\n\n// Configure how to start and recover nydusd daemons\ntype DaemonConfig struct {\n\tNydusdPath       string `toml:\"nydusd_path\"`\n\tNydusdConfigPath string `toml:\"nydusd_config\"`\n\tNydusImagePath   string `toml:\"nydusimage_path\"`\n\tRecoverPolicy    string `toml:\"recover_policy\"`\n\tFsDriver         string `toml:\"fs_driver\"`\n\tThreadsNumber    int    `toml:\"threads_number\"`\n\tLogRotationSize  int    `toml:\"log_rotation_size\"`\n\tFailoverPolicy   string `toml:\"failover_policy\"`\n}\n\ntype LoggingConfig struct {\n\tLogToStdout         bool   `toml:\"log_to_stdout\"`\n\tLogLevel            string `toml:\"level\"`\n\tLogDir              string `toml:\"dir\"`\n\tRotateLogMaxSize    int    `toml:\"log_rotation_max_size\"`\n\tRotateLogMaxBackups int    `toml:\"log_rotation_max_backups\"`\n\tRotateLogMaxAge     int    `toml:\"log_rotation_max_age\"`\n\tRotateLogLocalTime  bool   `toml:\"log_rotation_local_time\"`\n\tRotateLogCompress   bool   `toml:\"log_rotation_compress\"`\n}\n\n// Nydus image layers additional process\ntype ImageConfig struct {\n\tPublicKeyFile     string `toml:\"public_key_file\"`\n\tValidateSignature bool   `toml:\"validate_signature\"`\n}\n\n// Configure containerd snapshots interfaces and how to process the snapshots\n// requests from containerd\ntype SnapshotConfig struct {\n\tEnableNydusOverlayFS bool   `toml:\"enable_nydus_overlayfs\"`\n\tNydusOverlayFSPath   string `toml:\"nydus_overlayfs_path\"`\n\tEnableKataVolume     bool   `toml:\"enable_kata_volume\"`\n\tSyncRemove           bool   `toml:\"sync_remove\"`\n\t// EnableOverlayfsVolatile globally enables the \"volatile\" overlayfs mount option\n\t// on all writable snapshots. This skips sync on the upper layer, improving\n\t// write performance for ephemeral container filesystems at the cost of crash consistency.\n\tEnableOverlayfsVolatile bool `toml:\"enable_overlayfs_volatile\"`\n}\n\n// Configure cache manager that manages the cache files lifecycle\ntype CacheManagerConfig struct {\n\tDisable bool `toml:\"disable\"`\n\t// Trigger GC gc_period after the specified period.\n\t// Example format: 24h, 120min\n\tGCPeriod time.Duration `toml:\"gc_period\"`\n\tCacheDir string        `toml:\"cache_dir\"`\n}\n\n// Configure how nydus-snapshotter receive auth information\ntype AuthConfig struct {\n\t// based on kubeconfig or ServiceAccount\n\tEnableKubeconfigKeychain bool   `toml:\"enable_kubeconfig_keychain\"`\n\tKubeconfigPath           string `toml:\"kubeconfig_path\"`\n\t// CRI proxy mode\n\tEnableCRIKeychain   bool   `toml:\"enable_cri_keychain\"`\n\tImageServiceAddress string `toml:\"image_service_address\"`\n\t// Kubelet credential provider plugins\n\tEnableKubeletCredentialProviders bool   `toml:\"enable_kubelet_credential_providers\"`\n\tCredentialProviderConfig         string `toml:\"credential_provider_config\"`\n\tCredentialProviderBinDir         string `toml:\"credential_provider_bin_dir\"`\n\t// Periodic credential renewal interval. When set to a positive duration,\n\t// the snapshotter caches credentials from configured renewable providers and\n\t// refreshes them at this interval. Set to 0 (default) to disable.\n\tCredentialRenewalInterval time.Duration `toml:\"credential_renewal_interval\"`\n}\n\n// Configure remote storage like container registry\ntype RemoteConfig struct {\n\tAuthConfig         AuthConfig    `toml:\"auth\"`\n\tConvertVpcRegistry bool          `toml:\"convert_vpc_registry\"`\n\tSkipSSLVerify      bool          `toml:\"skip_ssl_verify\"`\n\tMirrorsConfig      MirrorsConfig `toml:\"mirrors_config\"`\n}\n\ntype MirrorsConfig struct {\n\tDir string `toml:\"dir\"`\n}\n\ntype MetricsConfig struct {\n\t// Address is the network address for the metrics server. Empty indicates the server is disabled.\n\tAddress string `toml:\"address\"`\n\t// HungIOInterval defines the timeout for a single I/O operation to be considered \"hung\".\n\tHungIOInterval time.Duration `toml:\"hung_io_interval\"`\n\t// CollectInterval defines how often metrics are collected and reported.\n\tCollectInterval time.Duration `toml:\"collect_interval\"`\n}\n\ntype DebugConfig struct {\n\tProfileDuration int64  `toml:\"daemon_cpu_profile_duration_secs\"`\n\tPprofAddress    string `toml:\"pprof_address\"`\n}\n\ntype SystemControllerConfig struct {\n\tEnable  bool   `toml:\"enable\"`\n\tAddress string `toml:\"address\"`\n\t// UID to set on the system controller socket\n\tUID int `toml:\"uid\"`\n\t// GID to set on the system controller socket\n\tGID         int         `toml:\"gid\"`\n\tDebugConfig DebugConfig `toml:\"debug\"`\n}\n\ntype SnapshotterConfig struct {\n\t// Configuration format version\n\tVersion int `toml:\"version\"`\n\t// Snapshotter's root work directory\n\tRoot    string `toml:\"root\"`\n\tAddress string `toml:\"address\"`\n\t// UID to set on the snapshotter socket\n\tUID int `toml:\"uid\"`\n\t// GID to set on the snapshotter socket\n\tGID        int    `toml:\"gid\"`\n\tDaemonMode string `toml:\"daemon_mode\"`\n\t// Clean up all the resources when snapshotter is closed\n\tCleanupOnClose bool `toml:\"cleanup_on_close\"`\n\n\tSystemControllerConfig SystemControllerConfig `toml:\"system\"`\n\tMetricsConfig          MetricsConfig          `toml:\"metrics\"`\n\tDaemonConfig           DaemonConfig           `toml:\"daemon\"`\n\tSnapshotsConfig        SnapshotConfig         `toml:\"snapshot\"`\n\tRemoteConfig           RemoteConfig           `toml:\"remote\"`\n\tImageConfig            ImageConfig            `toml:\"image\"`\n\tCacheManagerConfig     CacheManagerConfig     `toml:\"cache_manager\"`\n\tLoggingConfig          LoggingConfig          `toml:\"log\"`\n\tCgroupConfig           CgroupConfig           `toml:\"cgroup\"`\n\tExperimental           Experimental           `toml:\"experimental\"`\n}\n\nfunc LoadSnapshotterConfig(path string) (*SnapshotterConfig, error) {\n\tvar config SnapshotterConfig\n\t// get nydus-snapshotter configuration from specified path of toml file\n\tif path == \"\" {\n\t\treturn nil, errors.New(\"snapshotter configuration path cannot be empty\")\n\t}\n\ttree, err := toml.LoadFile(path)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"load toml configuration from file %q\", path)\n\t}\n\n\tif err = tree.Unmarshal(&config); err != nil {\n\t\treturn nil, errors.Wrap(err, \"unmarshal snapshotter configuration\")\n\t}\n\tif config.Version != 1 {\n\t\treturn nil, errors.Errorf(\"unsupported configuration version %d\", config.Version)\n\t}\n\treturn &config, nil\n}\n\nfunc MergeConfig(to, from *SnapshotterConfig) error {\n\terr := mergo.Merge(to, from)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc ValidateConfig(c *SnapshotterConfig) error {\n\tif c == nil {\n\t\treturn errors.Wrapf(errdefs.ErrInvalidArgument, \"configuration is none\")\n\t}\n\n\tif c.ImageConfig.ValidateSignature {\n\t\tif c.ImageConfig.PublicKeyFile == \"\" {\n\t\t\treturn errors.New(\"public key file for signature validation is not provided\")\n\t\t} else if _, err := os.Stat(c.ImageConfig.PublicKeyFile); err != nil {\n\t\t\treturn errors.Wrapf(err, \"check publicKey file %q\", c.ImageConfig.PublicKeyFile)\n\t\t}\n\t}\n\n\trootPathLen := len(c.Root)\n\tif rootPathLen == 0 {\n\t\treturn errors.New(\"empty root directory\")\n\t}\n\tif rootPathLen > MaxRootPathLen {\n\t\treturn errors.Errorf(\"root directory path is too long: %d bytes, max is %d bytes\", rootPathLen, MaxRootPathLen)\n\t}\n\n\tif c.DaemonConfig.FsDriver != FsDriverFscache && c.DaemonConfig.FsDriver != FsDriverFusedev &&\n\t\tc.DaemonConfig.FsDriver != FsDriverBlockdev && c.DaemonConfig.FsDriver != FsDriverNodev &&\n\t\tc.DaemonConfig.FsDriver != FsDriverProxy {\n\t\treturn errors.Errorf(\"invalid filesystem driver %q\", c.DaemonConfig.FsDriver)\n\t}\n\tif _, err := ParseRecoverPolicy(c.DaemonConfig.RecoverPolicy); err != nil {\n\t\treturn err\n\t}\n\tif c.DaemonConfig.ThreadsNumber > 1024 {\n\t\treturn errors.Errorf(\"nydusd worker thread number %d is too big, max 1024\", c.DaemonConfig.ThreadsNumber)\n\t}\n\tif c.DaemonConfig.FailoverPolicy != FailoverPolicyNone &&\n\t\tc.DaemonConfig.FailoverPolicy != FailoverPolicyResend &&\n\t\tc.DaemonConfig.FailoverPolicy != FailoverPolicyFlush {\n\t\treturn errors.Errorf(\"invalid failover policy %q\", c.DaemonConfig.FailoverPolicy)\n\t}\n\n\tif c.RemoteConfig.AuthConfig.EnableCRIKeychain && c.RemoteConfig.AuthConfig.EnableKubeconfigKeychain {\n\t\treturn errors.Wrapf(errdefs.ErrInvalidArgument,\n\t\t\t\"\\\"enable_cri_keychain\\\" and \\\"enable_kubeconfig_keychain\\\" can't be set at the same time\")\n\t}\n\n\tif c.RemoteConfig.MirrorsConfig.Dir != \"\" {\n\t\tdirExisted, err := file.IsDirExisted(c.RemoteConfig.MirrorsConfig.Dir)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !dirExisted {\n\t\t\treturn errors.Errorf(\"mirrors config directory %s does not exist\", c.RemoteConfig.MirrorsConfig.Dir)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Parse command line arguments and fill the nydus-snapshotter configuration\n// Always let options from CLI override those from configuration file.\nfunc ParseParameters(args *flags.Args, cfg *SnapshotterConfig) error {\n\t// --- essential configuration\n\tif args.Address != \"\" {\n\t\tcfg.Address = args.Address\n\t}\n\tif args.RootDir != \"\" {\n\t\tcfg.Root = args.RootDir\n\t}\n\n\t// Give --shared-daemon higher priority\n\tif args.DaemonMode != \"\" {\n\t\tcfg.DaemonMode = args.DaemonMode\n\t}\n\n\t// --- image processor configuration\n\t// empty\n\n\t// --- daemon configuration\n\tdaemonConfig := &cfg.DaemonConfig\n\tif args.NydusdConfigPath != \"\" {\n\t\tdaemonConfig.NydusdConfigPath = args.NydusdConfigPath\n\t}\n\tif args.NydusdPath != \"\" {\n\t\tdaemonConfig.NydusdPath = args.NydusdPath\n\t}\n\tif args.NydusImagePath != \"\" {\n\t\tdaemonConfig.NydusImagePath = args.NydusImagePath\n\t}\n\tif args.FsDriver != \"\" {\n\t\tdaemonConfig.FsDriver = args.FsDriver\n\t}\n\n\t// --- cache manager configuration\n\t// empty\n\n\t// --- logging configuration\n\tlogConfig := &cfg.LoggingConfig\n\tif args.LogLevel != \"\" {\n\t\tlogConfig.LogLevel = args.LogLevel\n\t}\n\tif args.LogToStdoutCount > 0 {\n\t\tlogConfig.LogToStdout = args.LogToStdout\n\t}\n\n\t// --- remote storage configuration\n\t// empty\n\n\t// --- snapshot configuration\n\tif args.NydusOverlayFSPath != \"\" {\n\t\tcfg.SnapshotsConfig.NydusOverlayFSPath = args.NydusOverlayFSPath\n\t}\n\n\t// --- metrics configuration\n\t// empty\n\n\treturn nil\n}\n\nfunc ParseCgroupConfig(config CgroupConfig) (cgroup.Config, error) {\n\ttotalMemory, err := sysinfo.GetTotalMemoryBytes()\n\tif err != nil {\n\t\treturn cgroup.Config{}, errors.Wrap(err, \"Failed  to get total memory bytes\")\n\t}\n\n\tmemoryLimitInBytes, err := parser.MemoryConfigToBytes(config.MemoryLimit, totalMemory)\n\tif err != nil {\n\t\treturn cgroup.Config{}, err\n\t}\n\n\treturn cgroup.Config{\n\t\tMemoryLimitInBytes: memoryLimitInBytes,\n\t}, nil\n}\n"
  },
  {
    "path": "config/config_test.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage config\n\nimport (\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/containerd/nydus-snapshotter/internal/constant\"\n\t\"github.com/containerd/nydus-snapshotter/internal/flags\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestLoadSnapshotterTOMLConfig(t *testing.T) {\n\tA := assert.New(t)\n\n\tcfg, err := LoadSnapshotterConfig(\"../misc/snapshotter/config.toml\")\n\tA.NoError(err)\n\n\texampleConfig := SnapshotterConfig{\n\t\tVersion:    1,\n\t\tRoot:       \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\",\n\t\tAddress:    \"/run/containerd-nydus/containerd-nydus-grpc.sock\",\n\t\tUID:        0,\n\t\tGID:        0,\n\t\tDaemonMode: \"dedicated\",\n\t\tExperimental: Experimental{\n\t\t\tEnableStargz:         false,\n\t\t\tEnableReferrerDetect: false,\n\t\t\tEnableIndexDetect:    false,\n\t\t},\n\t\tCleanupOnClose: false,\n\t\tSystemControllerConfig: SystemControllerConfig{\n\t\t\tEnable:  true,\n\t\t\tAddress: \"/run/containerd-nydus/system.sock\",\n\t\t\tUID:     0,\n\t\t\tGID:     0,\n\t\t\tDebugConfig: DebugConfig{\n\t\t\t\tProfileDuration: 5,\n\t\t\t\tPprofAddress:    \"\",\n\t\t\t},\n\t\t},\n\t\tDaemonConfig: DaemonConfig{\n\t\t\tNydusdPath:       \"/usr/local/bin/nydusd\",\n\t\t\tNydusImagePath:   \"/usr/local/bin/nydus-image\",\n\t\t\tFsDriver:         \"fusedev\",\n\t\t\tRecoverPolicy:    \"failover\",\n\t\t\tNydusdConfigPath: \"/etc/nydus/nydusd-config.fusedev.json\",\n\t\t\tThreadsNumber:    4,\n\t\t\tLogRotationSize:  100,\n\t\t\tFailoverPolicy:   \"resend\",\n\t\t},\n\t\tSnapshotsConfig: SnapshotConfig{\n\t\t\tEnableNydusOverlayFS: false,\n\t\t\tNydusOverlayFSPath:   \"nydus-overlayfs\",\n\t\t\tSyncRemove:           false,\n\t\t},\n\t\tRemoteConfig: RemoteConfig{\n\t\t\tConvertVpcRegistry: false,\n\t\t\tAuthConfig: AuthConfig{\n\t\t\t\tEnableKubeconfigKeychain: false,\n\t\t\t\tKubeconfigPath:           \"\",\n\t\t\t},\n\t\t\tMirrorsConfig: MirrorsConfig{\n\t\t\t\tDir: \"\",\n\t\t\t},\n\t\t},\n\t\tImageConfig: ImageConfig{\n\t\t\tPublicKeyFile:     \"\",\n\t\t\tValidateSignature: false,\n\t\t},\n\t\tCacheManagerConfig: CacheManagerConfig{\n\t\t\tDisable:  false,\n\t\t\tGCPeriod: constant.DefaultGCPeriod,\n\t\t\tCacheDir: \"\",\n\t\t},\n\t\tLoggingConfig: LoggingConfig{\n\t\t\tLogLevel:            \"info\",\n\t\t\tRotateLogCompress:   true,\n\t\t\tRotateLogLocalTime:  true,\n\t\t\tRotateLogMaxAge:     7,\n\t\t\tRotateLogMaxBackups: 5,\n\t\t\tRotateLogMaxSize:    100,\n\t\t\tLogToStdout:         false,\n\t\t},\n\t\tMetricsConfig: MetricsConfig{\n\t\t\tAddress:         \":9110\",\n\t\t\tHungIOInterval:  constant.DefaultHungIOInterval,\n\t\t\tCollectInterval: constant.DefaultCollectInterval,\n\t\t},\n\t\tCgroupConfig: CgroupConfig{\n\t\t\tEnable:      true,\n\t\t\tMemoryLimit: \"\",\n\t\t},\n\t}\n\n\tA.EqualValues(cfg, &exampleConfig)\n\n\targs := flags.Args{}\n\targs.RootDir = \"/var/lib/containerd/nydus\"\n\texampleConfig.Root = \"/var/lib/containerd/nydus\"\n\n\terr = ParseParameters(&args, cfg)\n\tA.NoError(err)\n\tA.EqualValues(cfg, &exampleConfig)\n\n\tA.EqualValues(cfg.LoggingConfig.LogToStdout, false)\n\n\targs.LogToStdout = true\n\targs.LogToStdoutCount = 1\n\terr = ParseParameters(&args, cfg)\n\tA.NoError(err)\n\tA.EqualValues(cfg.LoggingConfig.LogToStdout, true)\n\n\terr = ProcessConfigurations(cfg)\n\tA.NoError(err)\n\n\tA.Equal(cfg.CacheManagerConfig.GCPeriod, constant.DefaultGCPeriod)\n\n\tA.Equal(cfg.MetricsConfig.HungIOInterval, constant.DefaultHungIOInterval)\n\n\tA.Equal(cfg.MetricsConfig.CollectInterval, constant.DefaultCollectInterval)\n}\n\nfunc TestSnapshotterConfig(t *testing.T) {\n\tA := assert.New(t)\n\n\tvar cfg SnapshotterConfig\n\tvar args flags.Args\n\n\t// The log_to_stdout is false in toml file without --log-to-stdout flag.\n\t// Expected false.\n\tcfg.LoggingConfig.LogToStdout = false\n\targs.LogToStdoutCount = 0\n\terr := ParseParameters(&args, &cfg)\n\tA.NoError(err)\n\tA.EqualValues(cfg.LoggingConfig.LogToStdout, false)\n\n\t// The log_to_stdout is true in toml file without --log-to-stdout flag.\n\t// Expected true.\n\t// This case is failed.\n\tcfg.LoggingConfig.LogToStdout = true\n\targs.LogToStdoutCount = 0\n\terr = ParseParameters(&args, &cfg)\n\tA.NoError(err)\n\tA.EqualValues(cfg.LoggingConfig.LogToStdout, true)\n\n\t// The log_to_stdout is false in toml file with --log-to-stdout=true.\n\t// Expected true (command flag has higher priority).\n\targs.LogToStdout = true\n\targs.LogToStdoutCount = 1\n\tcfg.LoggingConfig.LogToStdout = false\n\terr = ParseParameters(&args, &cfg)\n\tA.NoError(err)\n\tA.EqualValues(cfg.LoggingConfig.LogToStdout, true)\n\n\t// The log_to_stdout is true in toml file with --log-to-stdout=true.\n\t// Expected true (command flag has higher priority).\n\targs.LogToStdout = true\n\targs.LogToStdoutCount = 1\n\tcfg.LoggingConfig.LogToStdout = true\n\terr = ParseParameters(&args, &cfg)\n\tA.NoError(err)\n\tA.EqualValues(cfg.LoggingConfig.LogToStdout, true)\n\n\t// The log_to_stdout is false in toml file with --log-to-stdout=false.\n\t// Expected false (command flag has higher priority).\n\targs.LogToStdout = false\n\targs.LogToStdoutCount = 1\n\tcfg.LoggingConfig.LogToStdout = false\n\terr = ParseParameters(&args, &cfg)\n\tA.NoError(err)\n\tA.EqualValues(cfg.LoggingConfig.LogToStdout, false)\n\n\t// The log_to_stdout is true in toml file with --log-to-stdout=false.\n\t// Expected false (command flag has higher priority).\n\targs.LogToStdout = false\n\targs.LogToStdoutCount = 1\n\tcfg.LoggingConfig.LogToStdout = true\n\terr = ParseParameters(&args, &cfg)\n\tA.NoError(err)\n\tA.EqualValues(cfg.LoggingConfig.LogToStdout, false)\n}\n\nfunc TestMergeConfig(t *testing.T) {\n\tA := assert.New(t)\n\tvar defaultSnapshotterConfig SnapshotterConfig\n\tvar snapshotterConfig1 SnapshotterConfig\n\n\terr := defaultSnapshotterConfig.FillUpWithDefaults()\n\tA.NoError(err)\n\n\terr = MergeConfig(&snapshotterConfig1, &defaultSnapshotterConfig)\n\tA.NoError(err)\n\tA.Equal(snapshotterConfig1.Root, constant.DefaultRootDir)\n\tA.Equal(snapshotterConfig1.LoggingConfig.LogDir, \"\")\n\tA.Equal(snapshotterConfig1.CacheManagerConfig.CacheDir, \"\")\n\n\tA.Equal(snapshotterConfig1.DaemonMode, constant.DefaultDaemonMode)\n\tA.Equal(snapshotterConfig1.SystemControllerConfig.Address, constant.DefaultSystemControllerAddress)\n\tA.Equal(snapshotterConfig1.LoggingConfig.LogLevel, constant.DefaultLogLevel)\n\tA.Equal(snapshotterConfig1.LoggingConfig.RotateLogMaxSize, constant.DefaultRotateLogMaxSize)\n\tA.Equal(snapshotterConfig1.LoggingConfig.RotateLogMaxBackups, constant.DefaultRotateLogMaxBackups)\n\tA.Equal(snapshotterConfig1.LoggingConfig.RotateLogMaxAge, constant.DefaultRotateLogMaxAge)\n\tA.Equal(snapshotterConfig1.LoggingConfig.RotateLogCompress, constant.DefaultRotateLogCompress)\n\n\tA.Equal(snapshotterConfig1.DaemonConfig.NydusdConfigPath, constant.DefaultNydusDaemonConfigPath)\n\tA.Equal(snapshotterConfig1.DaemonConfig.RecoverPolicy, RecoverPolicyRestart.String())\n\tA.Equal(snapshotterConfig1.CacheManagerConfig.GCPeriod, constant.DefaultGCPeriod)\n\n\tA.Equal(snapshotterConfig1.MetricsConfig.HungIOInterval, constant.DefaultHungIOInterval)\n\tA.Equal(snapshotterConfig1.MetricsConfig.CollectInterval, constant.DefaultCollectInterval)\n\n\tvar snapshotterConfig2 SnapshotterConfig\n\tsnapshotterConfig2.Root = \"/snapshotter/root\"\n\n\terr = MergeConfig(&snapshotterConfig2, &defaultSnapshotterConfig)\n\tA.NoError(err)\n\tA.Equal(snapshotterConfig2.Root, \"/snapshotter/root\")\n\tA.Equal(snapshotterConfig2.LoggingConfig.LogDir, \"\")\n\tA.Equal(snapshotterConfig2.CacheManagerConfig.CacheDir, \"\")\n}\n\nfunc TestProcessConfigurations(t *testing.T) {\n\tA := assert.New(t)\n\tvar defaultSnapshotterConfig SnapshotterConfig\n\tvar snapshotterConfig1 SnapshotterConfig\n\n\terr := defaultSnapshotterConfig.FillUpWithDefaults()\n\tA.NoError(err)\n\terr = MergeConfig(&snapshotterConfig1, &defaultSnapshotterConfig)\n\tA.NoError(err)\n\terr = ValidateConfig(&snapshotterConfig1)\n\tA.NoError(err)\n\n\tPrepareLogDir(&snapshotterConfig1)\n\n\terr = ProcessConfigurations(&snapshotterConfig1)\n\tA.NoError(err)\n\n\tA.Equal(snapshotterConfig1.LoggingConfig.LogDir, filepath.Join(snapshotterConfig1.Root, \"logs\"))\n\tA.Equal(snapshotterConfig1.CacheManagerConfig.CacheDir, filepath.Join(snapshotterConfig1.Root, \"cache\"))\n\n\tvar snapshotterConfig2 SnapshotterConfig\n\tsnapshotterConfig2.Root = \"/snapshotter/root\"\n\n\terr = MergeConfig(&snapshotterConfig2, &defaultSnapshotterConfig)\n\tA.NoError(err)\n\terr = ValidateConfig(&snapshotterConfig2)\n\tA.NoError(err)\n\n\tPrepareLogDir(&snapshotterConfig2)\n\n\terr = ProcessConfigurations(&snapshotterConfig2)\n\tA.NoError(err)\n\n\tA.Equal(snapshotterConfig2.LoggingConfig.LogDir, filepath.Join(snapshotterConfig2.Root, \"logs\"))\n\tA.Equal(snapshotterConfig2.CacheManagerConfig.CacheDir, filepath.Join(snapshotterConfig2.Root, \"cache\"))\n\n\tvar snapshotterConfig3 SnapshotterConfig\n\tsnapshotterConfig3.Root = \"./snapshotter/root\"\n\n\terr = MergeConfig(&snapshotterConfig3, &defaultSnapshotterConfig)\n\tA.NoError(err)\n\terr = ValidateConfig(&snapshotterConfig3)\n\tA.NoError(err)\n\n\terr = ProcessConfigurations(&snapshotterConfig3)\n\tA.NoError(err)\n\n\tvar snapshotterConfig4 SnapshotterConfig\n\toversizedPath := \"/path/to/very/long/root/directory/that/exceed/the/max/nydus-snapshotter\"\n\tA.Equal(MaxRootPathLen+1, len(oversizedPath))\n\n\tsnapshotterConfig4.Root = oversizedPath\n\n\terr = MergeConfig(&snapshotterConfig4, &defaultSnapshotterConfig)\n\tA.NoError(err)\n\terr = ValidateConfig(&snapshotterConfig4)\n\tA.Error(err)\n}\n"
  },
  {
    "path": "config/daemonconfig/daemonconfig.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemonconfig\n\nimport (\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/registry\"\n)\n\ntype StorageBackendType = string\n\nconst (\n\tbackendTypeLocalfs  StorageBackendType = \"localfs\"\n\tbackendTypeOss      StorageBackendType = \"oss\"\n\tbackendTypeRegistry StorageBackendType = \"registry\"\n\tbackendTypeS3       StorageBackendType = \"s3\"\n)\n\ntype DaemonConfig interface {\n\t// Provide stuffs relevant to accessing registry apart from auth\n\tSupplement(host, repo, snapshotID string, params map[string]string)\n\t// Provide auth\n\tFillAuth(kc *auth.PassKeyChain)\n\tStorageBackend() (StorageBackendType, *BackendConfig)\n\tDumpString() (string, error)\n\tDumpFile(path string) error\n}\n\n// Daemon configurations factory\nfunc NewDaemonConfig(fsDriver, path string) (DaemonConfig, error) {\n\tswitch fsDriver {\n\tcase config.FsDriverFscache:\n\t\tcfg, err := LoadFscacheConfig(path)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn cfg, nil\n\tcase config.FsDriverFusedev:\n\t\tcfg, err := LoadFuseConfig(path)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn cfg, nil\n\tdefault:\n\t\treturn nil, errors.Errorf(\"unsupported, fs driver %q\", fsDriver)\n\t}\n}\n\ntype BackendConfig struct {\n\t// Localfs backend configs\n\tBlobFile     string `json:\"blob_file,omitempty\"`\n\tDir          string `json:\"dir,omitempty\"`\n\tReadAhead    bool   `json:\"readahead\"`\n\tReadAheadSec int    `json:\"readahead_sec,omitempty\"`\n\n\t// Registry backend configs\n\tHost               string `json:\"host,omitempty\"`\n\tRepo               string `json:\"repo,omitempty\"`\n\tAuth               string `json:\"auth,omitempty\" secret:\"true\"`\n\tRegistryToken      string `json:\"registry_token,omitempty\" secret:\"true\"`\n\tBlobURLScheme      string `json:\"blob_url_scheme,omitempty\"`\n\tBlobRedirectedHost string `json:\"blob_redirected_host,omitempty\"`\n\n\t// Shared by oss and s3 backend configs\n\tEndPoint        string `json:\"endpoint,omitempty\"`\n\tAccessKeyID     string `json:\"access_key_id,omitempty\" secret:\"true\"`\n\tAccessKeySecret string `json:\"access_key_secret,omitempty\" secret:\"true\"`\n\tBucketName      string `json:\"bucket_name,omitempty\"`\n\tObjectPrefix    string `json:\"object_prefix,omitempty\"`\n\n\t// S3-specific config\n\tRegion string `json:\"region,omitempty\"`\n\n\t// Shared by registry, oss, and s3\n\tScheme      string   `json:\"scheme,omitempty\"`\n\tSkipVerify  bool     `json:\"skip_verify,omitempty\"`\n\tCACertFiles []string `json:\"ca_cert_files,omitempty\"`\n\n\t// Below configs are common configs shared by all backends\n\tProxy struct {\n\t\tURL           string `json:\"url,omitempty\"`\n\t\tFallback      bool   `json:\"fallback\"`\n\t\tPingURL       string `json:\"ping_url,omitempty\"`\n\t\tCheckInterval int    `json:\"check_interval,omitempty\"`\n\t\tUseHTTP       bool   `json:\"use_http,omitempty\"`\n\t} `json:\"proxy,omitempty\"`\n\tTimeout        int `json:\"timeout,omitempty\"`\n\tConnectTimeout int `json:\"connect_timeout,omitempty\"`\n\tRetryLimit     int `json:\"retry_limit,omitempty\"`\n}\n\ntype DeviceConfig struct {\n\tID      string `json:\"id,omitempty\"`\n\tBackend struct {\n\t\tBackendType string        `json:\"type\"`\n\t\tConfig      BackendConfig `json:\"config\"`\n\t} `json:\"backend\"`\n\tCache struct {\n\t\tCacheType  string `json:\"type\"`\n\t\tCompressed bool   `json:\"compressed,omitempty\"`\n\t\tConfig     struct {\n\t\t\tWorkDir           string `json:\"work_dir\"`\n\t\t\tDisableIndexedMap bool   `json:\"disable_indexed_map\"`\n\t\t} `json:\"config\"`\n\t} `json:\"cache\"`\n}\n\n// For nydusd as FUSE daemon. Serialize Daemon info and persist to a json file\n// We don't have to persist configuration file for fscache since its configuration\n// is passed through HTTP API.\nfunc DumpConfigFile(c interface{}, path string) error {\n\tif config.IsBackendSourceEnabled() {\n\t\tc = serializeWithSecretFilter(c)\n\t}\n\tb, err := json.Marshal(c)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"marshal config\")\n\t}\n\n\treturn os.WriteFile(path, b, 0600)\n}\n\nfunc DumpConfigString(c interface{}) (string, error) {\n\tb, err := json.Marshal(c)\n\treturn string(b), err\n}\n\n// Achieve a daemon configuration from template or snapshotter's configuration\nfunc SupplementDaemonConfig(c DaemonConfig, imageID, snapshotID string,\n\tvpcRegistry bool, labels map[string]string, params map[string]string) error {\n\n\timage, err := registry.ParseImage(imageID)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"parse image %s\", imageID)\n\t}\n\n\tbackendType, _ := c.StorageBackend()\n\n\tswitch backendType {\n\tcase backendTypeRegistry:\n\t\tregistryHost := image.Host\n\t\tif vpcRegistry {\n\t\t\tregistryHost = registry.ConvertToVPCHost(registryHost)\n\t\t} else if registryHost == \"docker.io\" {\n\t\t\t// For docker.io images, we should use index.docker.io\n\t\t\tregistryHost = \"index.docker.io\"\n\t\t}\n\n\t\teffectiveScheme, effectiveHost, caCerts := selectMirrorHost(config.GetMirrorsConfigDir(), registryHost)\n\t\t// No mirror configured use the original registry host\n\t\tif effectiveHost == \"\" {\n\t\t\teffectiveHost = registryHost\n\t\t}\n\t\t// If no auth is provided, don't touch auth from provided nydusd configuration file.\n\t\t// We don't validate the original nydusd auth from configuration file since it can be empty\n\t\t// when repository is public.\n\t\tkeyChain := auth.GetRegistryKeyChain(imageID, labels)\n\t\tc.Supplement(effectiveHost, image.Repo, snapshotID, params)\n\t\tc.FillAuth(keyChain)\n\t\t_, bc := c.StorageBackend()\n\t\tif len(caCerts) > 0 {\n\t\t\tbc.CACertFiles = caCerts\n\t\t}\n\t\tif effectiveScheme != \"\" {\n\t\t\tbc.Scheme = effectiveScheme\n\t\t}\n\n\t// For Localfs, OSS, and S3 backends, only the WorkDir needs to be supplemented.\n\tcase backendTypeLocalfs, backendTypeOss, backendTypeS3:\n\t\tc.Supplement(\"\", \"\", snapshotID, params)\n\tdefault:\n\t\treturn errors.Errorf(\"unknown backend type %s\", backendType)\n\t}\n\n\treturn nil\n}\n\n// selectMirrorHost loads mirror configs for the given registry host and returns the host and\n// scheme of the first reachable mirror. If a mirror has no PingURL it is used unconditionally.\n// Falls back to (registryHost, \"\") when no mirror is configured or reachable.\nfunc selectMirrorHost(mirrorsConfigDir, registryHost string) (scheme string, host string, caCerts []string) {\n\tmirrors, caCerts, err := LoadMirrorsConfig(mirrorsConfigDir, registryHost)\n\tif err != nil {\n\t\tlog.L.Warnf(\"Failed to load mirrors config for %s: %v, falling back to origin\", registryHost, err)\n\t\treturn \"\", registryHost, nil\n\t}\n\n\tclient := &http.Client{Timeout: 3 * time.Second}\n\tfor _, mirror := range mirrors {\n\t\tscheme, host, err = splitMirrorURL(mirror.Host)\n\t\tif err != nil {\n\t\t\tlog.L.Warnf(\"Skipping due to Failing to split mirror host %s: %v\", mirror.Host, err)\n\t\t\tcontinue\n\t\t}\n\t\tif mirror.PingURL == \"\" {\n\t\t\treturn scheme, host, caCerts\n\t\t}\n\t\tresp, pingErr := client.Get(mirror.PingURL)\n\t\tif pingErr == nil {\n\t\t\tresp.Body.Close()\n\t\t\tif resp.StatusCode >= 200 && resp.StatusCode < 300 {\n\t\t\t\treturn scheme, host, caCerts\n\t\t\t}\n\t\t}\n\n\t\tif resp != nil {\n\t\t\tpingBody, _ := io.ReadAll(resp.Body)\n\t\t\tlog.L.Warnf(\"Mirror %s ping URL %s check failed with error %v, statusCode %d, response '%s', trying next mirror\",\n\t\t\t\tmirror.Host,\n\t\t\t\tmirror.PingURL,\n\t\t\t\terr,\n\t\t\t\tresp.StatusCode,\n\t\t\t\tstring(pingBody),\n\t\t\t)\n\t\t} else {\n\t\t\tlog.L.Warnf(\"Mirror %s ping URL %s check failed with error %v, trying next mirror\",\n\t\t\t\tmirror.Host,\n\t\t\t\tmirror.PingURL,\n\t\t\t\terr,\n\t\t\t)\n\t\t}\n\t}\n\n\treturn \"\", registryHost, nil\n}\n\n// splitMirrorURL splits a mirror host URL (e.g. \"http://mirror:5000\") into scheme and bare host.\n// Scheme is forced to be https if not present.\nfunc splitMirrorURL(mirrorHost string) (scheme, host string, err error) {\n\t// url.Parse requires a scheme to properly works even if it doesn't returns an error\n\tif !strings.HasPrefix(mirrorHost, \"http://\") && !strings.HasPrefix(mirrorHost, \"https://\") {\n\t\tmirrorHost = \"https://\" + mirrorHost\n\t}\n\tvalue, err := url.Parse(mirrorHost)\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\treturn value.Scheme, value.Host, nil\n}\n\nfunc serializeWithSecretFilter(obj interface{}) map[string]interface{} {\n\tresult := make(map[string]interface{})\n\tvalue := reflect.ValueOf(obj)\n\ttypeOfObj := reflect.TypeOf(obj)\n\n\tif value.Kind() == reflect.Ptr {\n\t\tvalue = value.Elem()\n\t\ttypeOfObj = typeOfObj.Elem()\n\t}\n\n\tfor i := 0; i < value.NumField(); i++ {\n\t\tfield := value.Field(i)\n\t\tfieldType := typeOfObj.Field(i)\n\t\tsecretTag := fieldType.Tag.Get(\"secret\")\n\t\tjsonTags := strings.Split(fieldType.Tag.Get(\"json\"), \",\")\n\t\tomitemptyTag := false\n\n\t\tfor _, tag := range jsonTags {\n\t\t\tif tag == \"omitempty\" {\n\t\t\t\tomitemptyTag = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif secretTag == \"true\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tif field.Kind() == reflect.Ptr && field.IsNil() {\n\t\t\tcontinue\n\t\t}\n\n\t\tif omitemptyTag && reflect.DeepEqual(reflect.Zero(field.Type()).Interface(), field.Interface()) {\n\t\t\tcontinue\n\t\t}\n\n\t\t//nolint:exhaustive\n\t\tswitch fieldType.Type.Kind() {\n\t\tcase reflect.Struct:\n\t\t\tresult[jsonTags[0]] = serializeWithSecretFilter(field.Interface())\n\t\tcase reflect.Ptr:\n\t\t\tif fieldType.Type.Elem().Kind() == reflect.Struct {\n\t\t\t\tresult[jsonTags[0]] = serializeWithSecretFilter(field.Elem().Interface())\n\t\t\t} else {\n\t\t\t\tresult[jsonTags[0]] = field.Elem().Interface()\n\t\t\t}\n\t\tdefault:\n\t\t\tresult[jsonTags[0]] = field.Interface()\n\t\t}\n\t}\n\n\treturn result\n}\n"
  },
  {
    "path": "config/daemonconfig/daemonconfig_test.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemonconfig\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestLoadConfig(t *testing.T) {\n\tbuf := []byte(`{\n  \"device\": {\n    \"backend\": {\n      \"type\": \"registry\",\n      \"config\": {\n        \"skip_verify\": true,\n        \"host\": \"acr-nydus-registry-vpc.cn-hangzhou.cr.aliyuncs.com\",\n        \"repo\": \"test/myserver\",\n        \"auth\": \"\",\n        \"blob_url_scheme\": \"http\",\n        \"proxy\": {\n          \"url\": \"http://p2p-proxy:65001\",\n          \"fallback\": true,\n          \"ping_url\": \"http://p2p-proxy:40901/server/ping\",\n          \"check_interval\": 5\n        },\n        \"timeout\": 5,\n        \"connect_timeout\": 5,\n        \"retry_limit\": 0\n      }\n    },\n    \"cache\": {\n      \"type\": \"blobcache\",\n      \"config\": {\n        \"work_dir\": \"/cache\"\n      }\n    }\n  },\n  \"mode\": \"direct\",\n  \"digest_validate\": true,\n  \"iostats_files\": true,\n  \"enable_xattr\": true,\n  \"amplify_io\": 1048576,\n  \"fs_prefetch\": {\n    \"enable\": true,\n    \"threads_count\": 10,\n    \"merging_size\": 131072\n  }\n}`)\n\tvar cfg FuseDaemonConfig\n\terr := json.Unmarshal(buf, &cfg)\n\trequire.Nil(t, err)\n\trequire.Equal(t, cfg.Enable, true)\n\trequire.Equal(t, cfg.MergingSize, 131072)\n\trequire.Equal(t, cfg.ThreadsCount, 10)\n\trequire.Equal(t, cfg.Device.Backend.Config.BlobURLScheme, \"http\")\n\trequire.Equal(t, cfg.Device.Backend.Config.SkipVerify, true)\n\trequire.Equal(t, cfg.Device.Backend.Config.Proxy.CheckInterval, 5)\n}\n\nfunc TestAmplifyIo(t *testing.T) {\n\t// Test non-zero value\n\tinput1 := []byte(`{\"amplify_io\": 1048576}`)\n\tvar cfg1 FuseDaemonConfig\n\terr1 := json.Unmarshal(input1, &cfg1)\n\trequire.Nil(t, err1)\n\trequire.Equal(t, *cfg1.AmplifyIo, 1048576)\n\toutput1, _ := json.Marshal(cfg1)\n\trequire.Contains(t, string(output1), `\"amplify_io\":1048576`)\n\n\t// Test zero value\n\tinput2 := []byte(`{\"amplify_io\": 0}`)\n\tvar cfg2 FuseDaemonConfig\n\terr2 := json.Unmarshal(input2, &cfg2)\n\trequire.Nil(t, err2)\n\trequire.Equal(t, *cfg2.AmplifyIo, 0)\n\toutput2, _ := json.Marshal(cfg2)\n\trequire.Contains(t, string(output2), `\"amplify_io\":0`)\n\n\t// Test nil value\n\tinput3 := []byte(`{}`)\n\tvar cfg3 FuseDaemonConfig\n\terr3 := json.Unmarshal(input3, &cfg3)\n\trequire.Nil(t, err3)\n\trequire.Nil(t, cfg3.AmplifyIo)\n\toutput3, _ := json.Marshal(cfg3)\n\trequire.NotContains(t, string(output3), `amplify_io`)\n}\n\nfunc TestSerializeWithSecretFilter(t *testing.T) {\n\tbuf := []byte(`{\n  \"device\": {\n    \"backend\": {\n      \"type\": \"registry\",\n      \"config\": {\n        \"skip_verify\": true,\n        \"host\": \"acr-nydus-registry-vpc.cn-hangzhou.cr.aliyuncs.com\",\n        \"repo\": \"test/myserver\",\n        \"auth\": \"token_token\",\n        \"blob_url_scheme\": \"http\",\n        \"proxy\": {\n          \"url\": \"http://p2p-proxy:65001\",\n          \"fallback\": true,\n          \"ping_url\": \"http://p2p-proxy:40901/server/ping\",\n          \"check_interval\": 5\n        },\n        \"timeout\": 5,\n        \"connect_timeout\": 5,\n        \"retry_limit\": 0\n      }\n    },\n    \"cache\": {\n      \"type\": \"blobcache\",\n      \"config\": {\n        \"work_dir\": \"/cache\"\n      }\n    }\n  },\n  \"mode\": \"direct\",\n  \"digest_validate\": true,\n  \"iostats_files\": true,\n  \"enable_xattr\": true,\n  \"amplify_io\": 1048576,\n  \"fs_prefetch\": {\n    \"enable\": true,\n    \"threads_count\": 10,\n    \"merging_size\": 131072\n  }\n}`)\n\tvar cfg FuseDaemonConfig\n\t_ = json.Unmarshal(buf, &cfg)\n\tfilter := serializeWithSecretFilter(&cfg)\n\tjsonData, err := json.Marshal(filter)\n\trequire.Nil(t, err)\n\tvar newCfg FuseDaemonConfig\n\terr = json.Unmarshal(jsonData, &newCfg)\n\trequire.Nil(t, err)\n\trequire.Equal(t, newCfg.FSPrefetch, cfg.FSPrefetch)\n\trequire.Equal(t, newCfg.Device.Cache.CacheType, cfg.Device.Cache.CacheType)\n\trequire.Equal(t, newCfg.Device.Cache.Config, cfg.Device.Cache.Config)\n\trequire.Equal(t, newCfg.Mode, cfg.Mode)\n\trequire.Equal(t, newCfg.DigestValidate, cfg.DigestValidate)\n\trequire.Equal(t, newCfg.IOStatsFiles, cfg.IOStatsFiles)\n\trequire.Equal(t, newCfg.Device.Backend.Config.Host, cfg.Device.Backend.Config.Host)\n\trequire.Equal(t, newCfg.Device.Backend.Config.Repo, cfg.Device.Backend.Config.Repo)\n\trequire.Equal(t, newCfg.Device.Backend.Config.Proxy, cfg.Device.Backend.Config.Proxy)\n\trequire.Equal(t, newCfg.Device.Backend.Config.BlobURLScheme, cfg.Device.Backend.Config.BlobURLScheme)\n\trequire.Equal(t, newCfg.Device.Backend.Config.Auth, \"\")\n\trequire.NotEqual(t, newCfg.Device.Backend.Config.Auth, cfg.Device.Backend.Config.Auth)\n\trequire.NotNil(t, newCfg.AmplifyIo)\n\trequire.Equal(t, *newCfg.AmplifyIo, *cfg.AmplifyIo)\n}\n"
  },
  {
    "path": "config/daemonconfig/fscache.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemonconfig\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/erofs\"\n\n\t\"github.com/pkg/errors\"\n)\n\nconst (\n\tWorkDir   string = \"workdir\"\n\tBootstrap string = \"bootstrap\"\n)\n\ntype BlobPrefetchConfig struct {\n\tEnable        bool `json:\"enable\"`\n\tThreadsCount  int  `json:\"threads_count\"`\n\tMergingSize   int  `json:\"merging_size\"`\n\tBandwidthRate int  `json:\"bandwidth_rate\"`\n\tPrefetchAll   bool `json:\"prefetch_all\"`\n}\n\ntype FscacheDaemonConfig struct {\n\t// These fields is only for fscache daemon.\n\tType string `json:\"type\"`\n\t// Snapshotter fills\n\tID       string `json:\"id\"`\n\tDomainID string `json:\"domain_id\"`\n\tConfig   *struct {\n\t\tID            string        `json:\"id\"`\n\t\tBackendType   string        `json:\"backend_type\"`\n\t\tBackendConfig BackendConfig `json:\"backend_config\"`\n\t\tCacheType     string        `json:\"cache_type\"`\n\t\t// Snapshotter fills\n\t\tCacheConfig struct {\n\t\t\tWorkDir string `json:\"work_dir\"`\n\t\t} `json:\"cache_config\"`\n\t\tBlobPrefetchConfig BlobPrefetchConfig `json:\"prefetch_config\"`\n\t\tMetadataPath       string             `json:\"metadata_path\"`\n\t} `json:\"config\"`\n}\n\n// Load Fscache configuration template file\nfunc LoadFscacheConfig(p string) (*FscacheDaemonConfig, error) {\n\tvar cfg FscacheDaemonConfig\n\tb, err := os.ReadFile(p)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"read fscache configuration file %s\", p)\n\t}\n\tif err = json.Unmarshal(b, &cfg); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"unmarshal\")\n\t}\n\n\tif cfg.Config == nil {\n\t\treturn nil, errors.New(\"invalid fscache configuration\")\n\t}\n\n\treturn &cfg, nil\n}\n\nfunc (c *FscacheDaemonConfig) StorageBackend() (string, *BackendConfig) {\n\treturn c.Config.BackendType, &c.Config.BackendConfig\n}\n\n// Each fscache/erofs has a configuration with different fscache ID built from snapshot ID.\nfunc (c *FscacheDaemonConfig) Supplement(host, repo, snapshotID string, params map[string]string) {\n\tif host != \"\" {\n\t\tc.Config.BackendConfig.Host = host\n\t}\n\tif repo != \"\" {\n\t\tc.Config.BackendConfig.Repo = repo\n\t}\n\n\tfscacheID := erofs.FscacheID(snapshotID)\n\tc.ID = fscacheID\n\n\tif c.DomainID != \"\" {\n\t\tlog.L.Warnf(\"Linux Kernel Shared Domain feature in use. make sure your kernel version >= 6.1\")\n\t} else {\n\t\tc.DomainID = fscacheID\n\t}\n\n\tc.Config.ID = fscacheID\n\n\tif WorkDir, ok := params[WorkDir]; ok {\n\t\tc.Config.CacheConfig.WorkDir = WorkDir\n\t}\n\n\tif bootstrap, ok := params[Bootstrap]; ok {\n\t\tc.Config.MetadataPath = bootstrap\n\t}\n}\n\nfunc (c *FscacheDaemonConfig) FillAuth(kc *auth.PassKeyChain) {\n\tif kc != nil {\n\t\tif kc.TokenBase() {\n\t\t\tc.Config.BackendConfig.RegistryToken = kc.Password\n\t\t} else {\n\t\t\tc.Config.BackendConfig.Auth = kc.ToBase64()\n\t\t}\n\t}\n}\n\nfunc (c *FscacheDaemonConfig) DumpString() (string, error) {\n\treturn DumpConfigString(c)\n}\n\nfunc (c *FscacheDaemonConfig) DumpFile(f string) error {\n\tif err := os.MkdirAll(path.Dir(f), 0755); err != nil {\n\t\treturn err\n\t}\n\n\treturn DumpConfigFile(c, f)\n}\n"
  },
  {
    "path": "config/daemonconfig/fuse.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemonconfig\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"path\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n)\n\nconst CacheDir string = \"cachedir\"\n\n// Used when nydusd works as a FUSE daemon or vhost-user-fs backend\ntype FuseDaemonConfig struct {\n\tDevice          *DeviceConfig `json:\"device\"`\n\tMode            string        `json:\"mode\"`\n\tDigestValidate  bool          `json:\"digest_validate\"`\n\tIOStatsFiles    bool          `json:\"iostats_files,omitempty\"`\n\tEnableXattr     bool          `json:\"enable_xattr,omitempty\"`\n\tAccessPattern   bool          `json:\"access_pattern,omitempty\"`\n\tLatestReadFiles bool          `json:\"latest_read_files,omitempty\"`\n\tAmplifyIo       *int          `json:\"amplify_io,omitempty\"`\n\tFSPrefetch      `json:\"fs_prefetch,omitempty\"`\n\t// (experimental) The nydus daemon could cache more data to increase hit ratio when enabled the warmup feature.\n\tWarmup uint64 `json:\"warmup,omitempty\"`\n}\n\n// Control how to perform prefetch from file system layer\ntype FSPrefetch struct {\n\tEnable        bool `json:\"enable\"`\n\tPrefetchAll   bool `json:\"prefetch_all\"`\n\tThreadsCount  int  `json:\"threads_count,omitempty\"`\n\tMergingSize   int  `json:\"merging_size,omitempty\"`\n\tBandwidthRate int  `json:\"bandwidth_rate,omitempty\"`\n}\n\n// Load fuse daemon configuration from template file\nfunc LoadFuseConfig(p string) (*FuseDaemonConfig, error) {\n\tb, err := os.ReadFile(p)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"read FUSE configuration file %s\", p)\n\t}\n\tvar cfg FuseDaemonConfig\n\tif err := json.Unmarshal(b, &cfg); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"unmarshal %s\", p)\n\t}\n\n\tif cfg.Device == nil {\n\t\treturn nil, errors.New(\"invalid fuse daemon configuration\")\n\t}\n\n\treturn &cfg, nil\n}\n\nfunc (c *FuseDaemonConfig) Supplement(host, repo, snapshotID string, params map[string]string) {\n\tif host != \"\" {\n\t\tc.Device.Backend.Config.Host = host\n\t}\n\tif repo != \"\" {\n\t\tc.Device.Backend.Config.Repo = repo\n\t}\n\t// Temporary fix while https://github.com/containerd/nydus-snapshotter/issues/712 is being addressed\n\tif snapshotID != \"\" {\n\t\tc.Device.ID = \"/\" + snapshotID\n\t}\n\tc.Device.Cache.Config.WorkDir = params[CacheDir]\n}\n\nfunc (c *FuseDaemonConfig) FillAuth(kc *auth.PassKeyChain) {\n\tif kc != nil {\n\t\tif kc.TokenBase() {\n\t\t\tc.Device.Backend.Config.RegistryToken = kc.Password\n\t\t} else {\n\t\t\tc.Device.Backend.Config.Auth = kc.ToBase64()\n\t\t}\n\t}\n}\n\nfunc (c *FuseDaemonConfig) StorageBackend() (string, *BackendConfig) {\n\treturn c.Device.Backend.BackendType, &c.Device.Backend.Config\n}\n\nfunc (c *FuseDaemonConfig) DumpString() (string, error) {\n\treturn DumpConfigString(c)\n}\n\nfunc (c *FuseDaemonConfig) DumpFile(f string) error {\n\tif err := os.MkdirAll(path.Dir(f), 0755); err != nil {\n\t\treturn err\n\t}\n\treturn DumpConfigFile(c, f)\n}\n"
  },
  {
    "path": "config/daemonconfig/mirror_select_test.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemonconfig\n\nimport (\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nvar testRegistryHost = \"fake-test.registry.com\"\n\nfunc writeMirrorHostsToml(t *testing.T, dir, content string) {\n\tt.Helper()\n\thostDir := filepath.Join(dir, testRegistryHost)\n\trequire.NoError(t, os.MkdirAll(hostDir, 0755))\n\trequire.NoError(t, os.WriteFile(filepath.Join(hostDir, \"hosts.toml\"), []byte(content), 0600))\n}\n\nfunc TestSplitMirrorURL(t *testing.T) {\n\tcases := []struct {\n\t\tname           string\n\t\tinput          string\n\t\texpectedScheme string\n\t\texpectedHost   string\n\t\texpectErr      bool\n\t}{\n\t\t{\n\t\t\tname:           \"http with port\",\n\t\t\tinput:          \"http://mirror:5000\",\n\t\t\texpectedScheme: \"http\",\n\t\t\texpectedHost:   \"mirror:5000\",\n\t\t},\n\t\t{\n\t\t\tname:           \"https without port\",\n\t\t\tinput:          \"https://mirror.example.com\",\n\t\t\texpectedScheme: \"https\",\n\t\t\texpectedHost:   \"mirror.example.com\",\n\t\t},\n\t\t{\n\t\t\tname:           \"no scheme, host only\",\n\t\t\tinput:          \"mirror.example.com\",\n\t\t\texpectedScheme: \"https\",\n\t\t\texpectedHost:   \"mirror.example.com\",\n\t\t},\n\t\t{\n\t\t\tname:           \"no scheme, host with port\",\n\t\t\tinput:          \"mirror:5000\",\n\t\t\texpectedScheme: \"https\",\n\t\t\texpectedHost:   \"mirror:5000\",\n\t\t},\n\t\t{\n\t\t\tname:           \"https with port\",\n\t\t\tinput:          \"https://mirror.example.com:5000\",\n\t\t\texpectedScheme: \"https\",\n\t\t\texpectedHost:   \"mirror.example.com:5000\",\n\t\t},\n\t\t{\n\t\t\tname:           \"http with path\",\n\t\t\tinput:          \"http://mirror.example.com/v2\",\n\t\t\texpectedScheme: \"http\",\n\t\t\texpectedHost:   \"mirror.example.com\",\n\t\t},\n\t}\n\tfor _, tc := range cases {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tscheme, host, err := splitMirrorURL(tc.input)\n\t\t\tif tc.expectErr {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.Equal(t, tc.expectedScheme, scheme, \"scheme for %s\", tc.input)\n\t\t\trequire.Equal(t, tc.expectedHost, host, \"host for %s\", tc.input)\n\t\t})\n\t}\n}\n\nfunc TestSelectMirrorHost_NoConfig(t *testing.T) {\n\tscheme, host, _ := selectMirrorHost(\"\", testRegistryHost)\n\trequire.Equal(t, testRegistryHost, host)\n\trequire.Equal(t, \"\", scheme)\n}\n\nfunc TestSelectMirrorHost_EmptyDir(t *testing.T) {\n\ttmpDir := t.TempDir()\n\tscheme, host, _ := selectMirrorHost(tmpDir, testRegistryHost)\n\trequire.Equal(t, testRegistryHost, host)\n\trequire.Equal(t, \"\", scheme)\n}\n\nfunc TestSelectMirrorHost_MirrorNoPingURL(t *testing.T) {\n\ttmpDir := t.TempDir()\n\twriteMirrorHostsToml(t, tmpDir, `\n[host]\n  [host.\"http://mirror1:5000\"]\n`)\n\tscheme, host, _ := selectMirrorHost(tmpDir, testRegistryHost)\n\trequire.Equal(t, \"mirror1:5000\", host)\n\trequire.Equal(t, \"http\", scheme)\n}\n\nfunc TestSelectMirrorHost_MirrorPingSucceeds(t *testing.T) {\n\tsrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tw.WriteHeader(http.StatusOK)\n\t}))\n\tdefer srv.Close()\n\n\ttmpDir := t.TempDir()\n\twriteMirrorHostsToml(t, tmpDir, `\n[host]\n  [host.\"http://mirror1:5000\"]\n    ping_url = \"`+srv.URL+`\"\n`)\n\tscheme, host, _ := selectMirrorHost(tmpDir, testRegistryHost)\n\trequire.Equal(t, \"mirror1:5000\", host)\n\trequire.Equal(t, \"http\", scheme)\n}\n\nfunc TestSelectMirrorHost_MirrorPingFails_FallbackToOrigin(t *testing.T) {\n\tsrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tw.WriteHeader(http.StatusServiceUnavailable)\n\t}))\n\tdefer srv.Close()\n\n\ttmpDir := t.TempDir()\n\twriteMirrorHostsToml(t, tmpDir, `\n[host]\n  [host.\"http://mirror1:5000\"]\n    ping_url = \"`+srv.URL+`\"\n`)\n\tscheme, host, _ := selectMirrorHost(tmpDir, testRegistryHost)\n\trequire.Equal(t, testRegistryHost, host)\n\trequire.Equal(t, \"\", scheme)\n}\n\nfunc TestSelectMirrorHost_FirstMirrorFails_SecondMirrorNoPing(t *testing.T) {\n\tsrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tw.WriteHeader(http.StatusServiceUnavailable)\n\t}))\n\tdefer srv.Close()\n\n\ttmpDir := t.TempDir()\n\twriteMirrorHostsToml(t, tmpDir, `\n[host]\n  [host.\"http://mirror1:5000\"]\n    ping_url = \"`+srv.URL+`\"\n  [host.\"https://mirror2.example.com\"]\n`)\n\tscheme, host, _ := selectMirrorHost(tmpDir, testRegistryHost)\n\trequire.Equal(t, \"mirror2.example.com\", host)\n\trequire.Equal(t, \"https\", scheme)\n}\n"
  },
  {
    "path": "config/daemonconfig/mirrors.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemonconfig\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/pelletier/go-toml\"\n\t\"github.com/pkg/errors\"\n)\n\ntype MirrorConfig struct {\n\tHost                string\n\tHeaders             map[string]string\n\tHealthCheckInterval int\n\tFailureLimit        uint8\n\tPingURL             string\n}\n\n// Copied from containerd, for compatibility with containerd's toml configuration file.\ntype HostFileConfig struct {\n\tCapabilities []string               `toml:\"capabilities\"`\n\tCACert       interface{}            `toml:\"ca\"`\n\tClient       interface{}            `toml:\"client\"`\n\tSkipVerify   *bool                  `toml:\"skip_verify\"`\n\tHeader       map[string]interface{} `toml:\"header\"`\n\tOverridePath bool                   `toml:\"override_path\"`\n\n\t// The following configuration items are specific to nydus.\n\tHealthCheckInterval int    `toml:\"health_check_interval,omitempty\"`\n\tFailureLimit        uint8  `toml:\"failure_limit,omitempty\"`\n\tPingURL             string `toml:\"ping_url,omitempty\"`\n}\n\ntype hostConfig struct {\n\tScheme string\n\tHost   string\n\tHeader http.Header\n\n\tCACerts             []string\n\tHealthCheckInterval int\n\tFailureLimit        uint8\n\tPingURL             string\n}\n\nfunc makeStringSlice(slice []interface{}, cb func(string) string) ([]string, error) {\n\tout := make([]string, len(slice))\n\tfor i, value := range slice {\n\t\tstr, ok := value.(string)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"unable to cast %v to string\", value)\n\t\t}\n\n\t\tif cb != nil {\n\t\t\tout[i] = cb(str)\n\t\t} else {\n\t\t\tout[i] = str\n\t\t}\n\t}\n\treturn out, nil\n}\n\nfunc parseMirrorsConfig(hosts []hostConfig) []MirrorConfig {\n\tvar parsedMirrors = make([]MirrorConfig, len(hosts))\n\n\tfor i, host := range hosts {\n\t\tparsedMirrors[i].Host = fmt.Sprintf(\"%s://%s\", host.Scheme, host.Host)\n\t\tparsedMirrors[i].HealthCheckInterval = host.HealthCheckInterval\n\t\tparsedMirrors[i].FailureLimit = host.FailureLimit\n\t\tparsedMirrors[i].PingURL = host.PingURL\n\n\t\tif len(host.Header) > 0 {\n\t\t\tmirrorHeader := make(map[string]string, len(host.Header))\n\t\t\tfor key, value := range host.Header {\n\t\t\t\tif len(value) > 1 {\n\t\t\t\t\tlog.L.Warnf(\"some values of the header[%q] are omitted: %#v\", key, value[1:])\n\t\t\t\t}\n\t\t\t\tmirrorHeader[key] = host.Header.Get(key)\n\t\t\t}\n\t\t\tparsedMirrors[i].Headers = mirrorHeader\n\t\t}\n\t}\n\n\treturn parsedMirrors\n}\n\n// hostDirectory converts \":port\" to \"_port_\" in directory names\nfunc hostDirectory(host string) string {\n\tidx := strings.LastIndex(host, \":\")\n\tif idx > 0 {\n\t\treturn host[:idx] + \"_\" + host[idx+1:] + \"_\"\n\t}\n\treturn host\n}\n\nfunc hostPaths(root, host string) []string {\n\tvar hosts []string\n\tch := hostDirectory(host)\n\tif ch != host {\n\t\thosts = append(hosts, filepath.Join(root, ch))\n\t}\n\treturn append(hosts,\n\t\tfilepath.Join(root, host),\n\t\tfilepath.Join(root, \"_default\"),\n\t)\n}\n\nfunc hostDirFromRoot(root, host string) (string, error) {\n\tfor _, p := range hostPaths(root, host) {\n\t\tif _, err := os.Stat(p); err == nil {\n\t\t\treturn p, nil\n\t\t} else if !os.IsNotExist(err) {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\treturn \"\", nil\n}\n\n// getSortedHosts returns the list of hosts as they defined in the file.\nfunc getSortedHosts(root *toml.Tree) ([]string, error) {\n\titer, ok := root.Get(\"host\").(*toml.Tree)\n\tif !ok {\n\t\treturn nil, errors.New(\"invalid `host` tree\")\n\t}\n\n\tlist := append([]string{}, iter.Keys()...)\n\n\t// go-toml stores TOML sections in the map object, so no order guaranteed.\n\t// We retrieve line number for each key and sort the keys by position.\n\tsort.Slice(list, func(i, j int) bool {\n\t\th1 := iter.GetPath([]string{list[i]}).(*toml.Tree)\n\t\th2 := iter.GetPath([]string{list[j]}).(*toml.Tree)\n\t\treturn h1.Position().Line < h2.Position().Line\n\t})\n\n\treturn list, nil\n}\n\n// parseHostConfig returns the parsed host configuration, make sure the server is not null.\nfunc parseHostConfig(server string, config HostFileConfig) (hostConfig, error) {\n\tvar (\n\t\tresult = hostConfig{}\n\t\terr    error\n\t)\n\n\tif !strings.HasPrefix(server, \"http\") {\n\t\tserver = \"https://\" + server\n\t}\n\tu, err := url.Parse(server)\n\tif err != nil {\n\t\treturn hostConfig{}, fmt.Errorf(\"unable to parse server %v: %w\", server, err)\n\t}\n\tresult.Scheme = u.Scheme\n\tresult.Host = u.Host\n\n\tif config.Header != nil {\n\t\theader := http.Header{}\n\t\tfor key, ty := range config.Header {\n\t\t\tswitch value := ty.(type) {\n\t\t\tcase string:\n\t\t\t\theader[key] = []string{value}\n\t\t\tcase []interface{}:\n\t\t\t\theader[key], err = makeStringSlice(value, nil)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn hostConfig{}, err\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn hostConfig{}, fmt.Errorf(\"invalid type %v for header %q\", ty, key)\n\t\t\t}\n\t\t}\n\t\tresult.Header = header\n\t}\n\n\tif config.CACert != nil {\n\t\tswitch cert := config.CACert.(type) {\n\t\tcase string:\n\t\t\tresult.CACerts = []string{cert}\n\t\tcase []interface{}:\n\t\t\tcerts, err := makeStringSlice(cert, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn hostConfig{}, fmt.Errorf(\"invalid type for ca: %w\", err)\n\t\t\t}\n\t\t\tresult.CACerts = certs\n\t\tdefault:\n\t\t\treturn hostConfig{}, fmt.Errorf(\"invalid type %v for ca\", config.CACert)\n\t\t}\n\t}\n\n\tresult.HealthCheckInterval = config.HealthCheckInterval\n\tresult.FailureLimit = config.FailureLimit\n\tresult.PingURL = config.PingURL\n\n\treturn result, nil\n}\n\nfunc parseHostsFile(b []byte) ([]hostConfig, error) {\n\ttree, err := toml.LoadBytes(b)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse TOML: %w\", err)\n\t}\n\tc := struct {\n\t\t// HostConfigs store the per-host configuration\n\t\tHostConfigs map[string]HostFileConfig `toml:\"host\"`\n\t}{}\n\n\torderedHosts, err := getSortedHosts(tree)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar (\n\t\thosts []hostConfig\n\t)\n\n\tif err := tree.Unmarshal(&c); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Parse hosts array\n\tfor _, host := range orderedHosts {\n\t\tif host != \"\" {\n\t\t\tconfig := c.HostConfigs[host]\n\t\t\tparsed, err := parseHostConfig(host, config)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\thosts = append(hosts, parsed)\n\t\t}\n\t}\n\n\treturn hosts, nil\n}\n\nfunc loadHostDir(hostsDir string) ([]hostConfig, error) {\n\tb, err := os.ReadFile(filepath.Join(hostsDir, \"hosts.toml\"))\n\tif err != nil {\n\t\tif !os.IsNotExist(err) {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn []hostConfig{}, nil\n\t}\n\n\thosts, err := parseHostsFile(b)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn hosts, nil\n}\n\nfunc LoadMirrorsConfig(mirrorsConfigDir, registryHost string) ([]MirrorConfig, []string, error) {\n\tif mirrorsConfigDir == \"\" {\n\t\treturn nil, nil, nil\n\t}\n\thostDir, err := hostDirFromRoot(mirrorsConfigDir, registryHost)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif hostDir == \"\" {\n\t\treturn nil, nil, nil\n\t}\n\n\thosts, err := loadHostDir(hostDir)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\t// Collect CA certs from all host entries and deduplicate.\n\tseen := make(map[string]struct{})\n\tvar caCerts []string\n\tfor _, h := range hosts {\n\t\tfor _, ca := range h.CACerts {\n\t\t\tif _, ok := seen[ca]; !ok {\n\t\t\t\tseen[ca] = struct{}{}\n\t\t\t\tcaCerts = append(caCerts, ca)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parseMirrorsConfig(hosts), caCerts, nil\n}\n"
  },
  {
    "path": "config/daemonconfig/mirrors_test.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemonconfig\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestLoadMirrorConfigCACerts(t *testing.T) {\n\tregistryHost := \"registry.example.com\"\n\n\tt.Run(\"single CA cert as absolute path\", func(t *testing.T) {\n\t\ttmpDir := t.TempDir()\n\t\thostDir := filepath.Join(tmpDir, \"certs.d\", registryHost)\n\t\trequire.NoError(t, os.MkdirAll(hostDir, os.ModePerm))\n\n\t\tcaPath := filepath.Join(tmpDir, \"my-ca.pem\")\n\t\trequire.NoError(t, os.WriteFile(caPath, []byte(\"\"), 0600))\n\n\t\thosts := fmt.Sprintf(`\n[host.\"https://mirror.example.com\"]\n  ca = %q\n`, caPath)\n\t\trequire.NoError(t, os.WriteFile(filepath.Join(hostDir, \"hosts.toml\"), []byte(hosts), 0600))\n\n\t\t_, caCerts, err := LoadMirrorsConfig(filepath.Join(tmpDir, \"certs.d\"), registryHost)\n\t\trequire.NoError(t, err)\n\t\trequire.Equal(t, []string{caPath}, caCerts)\n\t})\n\n\tt.Run(\"multiple CA certs as array\", func(t *testing.T) {\n\t\ttmpDir := t.TempDir()\n\t\thostDir := filepath.Join(tmpDir, \"certs.d\", registryHost)\n\t\trequire.NoError(t, os.MkdirAll(hostDir, os.ModePerm))\n\n\t\tca1 := filepath.Join(tmpDir, \"ca1.pem\")\n\t\tca2 := filepath.Join(tmpDir, \"ca2.pem\")\n\n\t\thosts := fmt.Sprintf(`\n[host.\"https://mirror.example.com\"]\n  ca = [%q, %q]\n`, ca1, ca2)\n\t\trequire.NoError(t, os.WriteFile(filepath.Join(hostDir, \"hosts.toml\"), []byte(hosts), 0600))\n\n\t\t_, caCerts, err := LoadMirrorsConfig(filepath.Join(tmpDir, \"certs.d\"), registryHost)\n\t\trequire.NoError(t, err)\n\t\trequire.Equal(t, []string{ca1, ca2}, caCerts)\n\t})\n\n\tt.Run(\"CA certs deduplicated across multiple hosts\", func(t *testing.T) {\n\t\ttmpDir := t.TempDir()\n\t\thostDir := filepath.Join(tmpDir, \"certs.d\", registryHost)\n\t\trequire.NoError(t, os.MkdirAll(hostDir, os.ModePerm))\n\n\t\tca1 := filepath.Join(tmpDir, \"ca1.pem\")\n\t\tca2 := filepath.Join(tmpDir, \"ca2.pem\")\n\n\t\thosts := fmt.Sprintf(`\n[host.\"https://mirror1.example.com\"]\n  ca = %q\n\n[host.\"https://mirror2.example.com\"]\n  ca = [%q, %q]\n`, ca1, ca1, ca2)\n\t\trequire.NoError(t, os.WriteFile(filepath.Join(hostDir, \"hosts.toml\"), []byte(hosts), 0600))\n\n\t\t_, caCerts, err := LoadMirrorsConfig(filepath.Join(tmpDir, \"certs.d\"), registryHost)\n\t\trequire.NoError(t, err)\n\t\trequire.Equal(t, []string{ca1, ca2}, caCerts)\n\t})\n\n\tt.Run(\"no CA cert field returns nil caCerts\", func(t *testing.T) {\n\t\ttmpDir := t.TempDir()\n\t\thostDir := filepath.Join(tmpDir, \"certs.d\", registryHost)\n\t\trequire.NoError(t, os.MkdirAll(hostDir, os.ModePerm))\n\n\t\thosts := `\n[host.\"https://mirror.example.com\"]\n`\n\t\trequire.NoError(t, os.WriteFile(filepath.Join(hostDir, \"hosts.toml\"), []byte(hosts), 0600))\n\n\t\t_, caCerts, err := LoadMirrorsConfig(filepath.Join(tmpDir, \"certs.d\"), registryHost)\n\t\trequire.NoError(t, err)\n\t\trequire.Nil(t, caCerts)\n\t})\n}\n\nfunc TestLoadMirrorConfig(t *testing.T) {\n\ttmpDir := t.TempDir()\n\tdefer os.RemoveAll(tmpDir)\n\n\tregistryHost := \"registry.docker.io\"\n\n\tmirrorsConfigDir := filepath.Join(tmpDir, \"certs.d\")\n\tregistryHostConfigDir := filepath.Join(mirrorsConfigDir, registryHost)\n\tdefaultHostConfigDir := filepath.Join(mirrorsConfigDir, \"_default\")\n\n\tmirrors, _, err := LoadMirrorsConfig(\"\", registryHost)\n\trequire.NoError(t, err)\n\trequire.Nil(t, mirrors)\n\n\tmirrors, _, err = LoadMirrorsConfig(mirrorsConfigDir, registryHost)\n\trequire.NoError(t, err)\n\trequire.Nil(t, mirrors)\n\n\terr = os.MkdirAll(defaultHostConfigDir, os.ModePerm)\n\tassert.NoError(t, err)\n\n\tmirrors, _, err = LoadMirrorsConfig(mirrorsConfigDir, registryHost)\n\trequire.NoError(t, err)\n\trequire.Equal(t, len(mirrors), 0)\n\n\tbuf1 := []byte(`server = \"https://default-docker.hub.com\"\n\t[host]\n\t  [host.\"http://default-p2p-mirror1:65001\"]\n\t\t[host.\"http://default-p2p-mirror1:65001\".header]\n\t\t  X-Dragonfly-Registry = [\"https://default-docker.hub.com\"]\n\t`)\n\terr = os.WriteFile(filepath.Join(defaultHostConfigDir, \"hosts.toml\"), buf1, 0600)\n\tassert.NoError(t, err)\n\tmirrors, _, err = LoadMirrorsConfig(mirrorsConfigDir, registryHost)\n\trequire.NoError(t, err)\n\trequire.Equal(t, len(mirrors), 1)\n\trequire.Equal(t, mirrors[0].Host, \"http://default-p2p-mirror1:65001\")\n\trequire.Equal(t, mirrors[0].Headers[\"X-Dragonfly-Registry\"], \"https://default-docker.hub.com\")\n\n\terr = os.MkdirAll(registryHostConfigDir, os.ModePerm)\n\tassert.NoError(t, err)\n\n\tbuf2 := []byte(`server = \"https://docker.hub.com\"\n\t[host]\n\t  [host.\"http://p2p-mirror1:65001\"]\n\t\t[host.\"http://p2p-mirror1:65001\".header]\n\t\t  X-Dragonfly-Registry = [\"https://docker.hub.com\"]\n\t`)\n\terr = os.WriteFile(filepath.Join(registryHostConfigDir, \"hosts.toml\"), buf2, 0600)\n\tassert.NoError(t, err)\n\tmirrors, _, err = LoadMirrorsConfig(mirrorsConfigDir, registryHost)\n\trequire.NoError(t, err)\n\trequire.Equal(t, len(mirrors), 1)\n\trequire.Equal(t, mirrors[0].Host, \"http://p2p-mirror1:65001\")\n\trequire.Equal(t, mirrors[0].Headers[\"X-Dragonfly-Registry\"], \"https://docker.hub.com\")\n\n\tbuf3 := []byte(`\n\t\t[host.\"http://p2p-mirror2:65001\"]\n\t\t[host.\"http://p2p-mirror2:65001\".header]\n\t\t\tX-Dragonfly-Registry = [\"https://docker.hub.com\"]\n\t`)\n\terr = os.WriteFile(filepath.Join(registryHostConfigDir, \"hosts.toml\"), buf3, 0600)\n\tassert.NoError(t, err)\n\tmirrors, _, err = LoadMirrorsConfig(mirrorsConfigDir, registryHost)\n\trequire.NoError(t, err)\n\trequire.Equal(t, len(mirrors), 1)\n\trequire.Equal(t, mirrors[0].Host, \"http://p2p-mirror2:65001\")\n\trequire.Equal(t, mirrors[0].Headers[\"X-Dragonfly-Registry\"], \"https://docker.hub.com\")\n}\n"
  },
  {
    "path": "config/default.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage config\n\nimport (\n\t\"os/exec\"\n\n\t\"github.com/containerd/nydus-snapshotter/internal/constant\"\n)\n\nfunc (c *SnapshotterConfig) FillUpWithDefaults() error {\n\tc.Version = 1\n\tc.Root = constant.DefaultRootDir\n\tc.Address = constant.DefaultAddress\n\n\t// essential configuration\n\tif c.DaemonMode == \"\" {\n\t\tc.DaemonMode = constant.DefaultDaemonMode\n\t}\n\n\t// system controller configuration\n\tc.SystemControllerConfig.Address = constant.DefaultSystemControllerAddress\n\n\t// logging configuration\n\tlogConfig := &c.LoggingConfig\n\tif logConfig.LogLevel == \"\" {\n\t\tlogConfig.LogLevel = constant.DefaultLogLevel\n\t}\n\tlogConfig.RotateLogMaxSize = constant.DefaultRotateLogMaxSize\n\tlogConfig.RotateLogMaxBackups = constant.DefaultRotateLogMaxBackups\n\tlogConfig.RotateLogMaxAge = constant.DefaultRotateLogMaxAge\n\tlogConfig.RotateLogLocalTime = constant.DefaultRotateLogLocalTime\n\tlogConfig.RotateLogCompress = constant.DefaultRotateLogCompress\n\n\t// daemon configuration\n\tdaemonConfig := &c.DaemonConfig\n\tif daemonConfig.NydusdConfigPath == \"\" {\n\t\tdaemonConfig.NydusdConfigPath = constant.DefaultNydusDaemonConfigPath\n\t}\n\tdaemonConfig.RecoverPolicy = RecoverPolicyRestart.String()\n\tdaemonConfig.FsDriver = constant.DefaultFsDriver\n\tdaemonConfig.LogRotationSize = constant.DefaultDaemonRotateLogMaxSize\n\tdaemonConfig.FailoverPolicy = constant.DefaultFailoverPolicy\n\n\t// cache configuration\n\tcacheConfig := &c.CacheManagerConfig\n\tcacheConfig.GCPeriod = constant.DefaultGCPeriod\n\n\t// metrics configuration\n\tmetricsConfig := &c.MetricsConfig\n\tmetricsConfig.HungIOInterval = constant.DefaultHungIOInterval\n\tmetricsConfig.CollectInterval = constant.DefaultCollectInterval\n\n\treturn c.SetupNydusBinaryPaths()\n}\n\nfunc (c *SnapshotterConfig) SetupNydusBinaryPaths() error {\n\t// resolve nydusd path\n\tif path, err := exec.LookPath(constant.NydusdBinaryName); err == nil {\n\t\tc.DaemonConfig.NydusdPath = path\n\t}\n\n\t// resolve nydus-image path\n\tif path, err := exec.LookPath(constant.NydusImageBinaryName); err == nil {\n\t\tc.DaemonConfig.NydusImagePath = path\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "config/global.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Expose configurations across nydus-snapshotter, the configurations is parsed\n// and extracted from nydus-snapshotter toml based configuration file or command line\n\npackage config\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/internal/logging\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/mount\"\n\t\"github.com/pkg/errors\"\n)\n\nvar (\n\tglobalConfig GlobalConfig\n)\n\n// Global cached configuration information to help:\n// - access configuration information without passing a configuration object\n// - avoid frequent generation of information from configuration information\ntype GlobalConfig struct {\n\torigin           *SnapshotterConfig\n\tSnapshotsDir     string\n\tDaemonMode       DaemonMode\n\tSocketRoot       string\n\tConfigRoot       string\n\tRootMountpoint   string\n\tDaemonThreadsNum int\n\tMirrorsConfig    MirrorsConfig\n}\n\nfunc IsFusedevSharedModeEnabled() bool {\n\treturn globalConfig.DaemonMode == DaemonModeShared\n}\n\nfunc GetDaemonMode() DaemonMode {\n\treturn globalConfig.DaemonMode\n}\n\nfunc GetSnapshotsRootDir() string {\n\treturn globalConfig.SnapshotsDir\n}\n\nfunc GetRootMountpoint() string {\n\treturn globalConfig.RootMountpoint\n}\n\nfunc GetSocketRoot() string {\n\treturn globalConfig.SocketRoot\n}\n\nfunc GetConfigRoot() string {\n\treturn globalConfig.ConfigRoot\n}\n\nfunc GetMirrorsConfigDir() string {\n\treturn globalConfig.MirrorsConfig.Dir\n}\n\nfunc GetFsDriver() string {\n\treturn globalConfig.origin.DaemonConfig.FsDriver\n}\n\nfunc GetLogDir() string {\n\treturn globalConfig.origin.LoggingConfig.LogDir\n}\n\nfunc GetLogLevel() string {\n\treturn globalConfig.origin.LoggingConfig.LogLevel\n}\n\nfunc GetDaemonLogRotationSize() int {\n\treturn globalConfig.origin.DaemonConfig.LogRotationSize\n}\n\nfunc GetDaemonThreadsNumber() int {\n\treturn globalConfig.origin.DaemonConfig.ThreadsNumber\n}\n\nfunc GetDaemonFailoverPolicy() string {\n\treturn globalConfig.origin.DaemonConfig.FailoverPolicy\n}\n\nfunc GetLogToStdout() bool {\n\treturn globalConfig.origin.LoggingConfig.LogToStdout\n}\n\nfunc IsBackendSourceEnabled() bool {\n\treturn globalConfig.origin.Experimental.EnableBackendSource && globalConfig.origin.SystemControllerConfig.Enable\n}\n\nfunc IsSystemControllerEnabled() bool {\n\treturn globalConfig.origin.SystemControllerConfig.Enable\n}\n\nfunc SystemControllerAddress() string {\n\treturn globalConfig.origin.SystemControllerConfig.Address\n}\n\nfunc SystemControllerPprofAddress() string {\n\treturn globalConfig.origin.SystemControllerConfig.DebugConfig.PprofAddress\n}\n\nfunc GetDaemonProfileCPUDuration() int64 {\n\treturn globalConfig.origin.SystemControllerConfig.DebugConfig.ProfileDuration\n}\n\nfunc GetSkipSSLVerify() bool {\n\treturn globalConfig.origin.RemoteConfig.SkipSSLVerify\n}\n\nconst (\n\tTarfsLayerVerityOnly      string = \"layer_verity_only\"\n\tTarfsImageVerityOnly      string = \"image_verity_only\"\n\tTarfsLayerBlockDevice     string = \"layer_block\"\n\tTarfsImageBlockDevice     string = \"image_block\"\n\tTarfsLayerBlockWithVerity string = \"layer_block_with_verity\"\n\tTarfsImageBlockWithVerity string = \"image_block_with_verity\"\n)\n\nfunc GetTarfsMountOnHost() bool {\n\treturn globalConfig.origin.Experimental.TarfsConfig.MountTarfsOnHost\n}\n\nfunc GetTarfsExportEnabled() bool {\n\tswitch globalConfig.origin.Experimental.TarfsConfig.ExportMode {\n\tcase TarfsLayerVerityOnly, TarfsLayerBlockDevice, TarfsLayerBlockWithVerity:\n\t\treturn true\n\tcase TarfsImageVerityOnly, TarfsImageBlockDevice, TarfsImageBlockWithVerity:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\n// Returns (wholeImage, generateBlockImage, withVerityInfo)\n// wholeImage: generate tarfs for the whole image instead of of a specific layer.\n// generateBlockImage: generate a block image file.\n// withVerityInfo: generate disk verity information.\nfunc GetTarfsExportFlags() (bool, bool, bool) {\n\tswitch globalConfig.origin.Experimental.TarfsConfig.ExportMode {\n\tcase \"layer_verity_only\":\n\t\treturn false, false, true\n\tcase \"image_verity_only\":\n\t\treturn true, false, true\n\tcase \"layer_block\":\n\t\treturn false, true, false\n\tcase \"image_block\":\n\t\treturn true, true, false\n\tcase \"layer_block_with_verity\":\n\t\treturn false, true, true\n\tcase \"image_block_with_verity\":\n\t\treturn true, true, true\n\tdefault:\n\t\treturn false, false, false\n\t}\n}\n\nfunc ProcessConfigurations(c *SnapshotterConfig) error {\n\tif c.CacheManagerConfig.CacheDir == \"\" {\n\t\tc.CacheManagerConfig.CacheDir = filepath.Join(c.Root, \"cache\")\n\t}\n\n\tglobalConfig.origin = c\n\n\tglobalConfig.SnapshotsDir = filepath.Join(c.Root, \"snapshots\")\n\tglobalConfig.ConfigRoot = filepath.Join(c.Root, \"config\")\n\tglobalConfig.SocketRoot = filepath.Join(c.Root, \"socket\")\n\tglobalConfig.RootMountpoint = filepath.Join(c.Root, \"mnt\")\n\n\tglobalConfig.MirrorsConfig = c.RemoteConfig.MirrorsConfig\n\n\tm, err := parseDaemonMode(c.DaemonMode)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif c.DaemonConfig.FsDriver == FsDriverFscache && m != DaemonModeShared {\n\t\tlog.L.Infof(\"fscache driver only supports 'shared' mode, override daemon mode from '%s' to 'shared'\", m)\n\t\tm = DaemonModeShared\n\t}\n\n\tglobalConfig.DaemonMode = m\n\n\treturn nil\n}\n\nfunc PrepareLogDir(c *SnapshotterConfig) {\n\tif c.LoggingConfig.LogDir == \"\" {\n\t\tc.LoggingConfig.LogDir = filepath.Join(c.Root, logging.DefaultLogDirName)\n\t}\n}\n\nfunc SetUpEnvironment(c *SnapshotterConfig) error {\n\tif err := os.MkdirAll(c.Root, 0700); err != nil {\n\t\treturn errors.Wrapf(err, \"create root dir %s\", c.Root)\n\t}\n\n\trealPath, err := mount.NormalizePath(c.Root)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"invalid root path\")\n\t}\n\tc.Root = realPath\n\treturn nil\n}\n"
  },
  {
    "path": "docs/configure_nydus.md",
    "content": "# Configure Nydus-snapshotter\n\nNydus-snapshotter can receive a toml file as its configurations to start providing image service through CLI parameter `--config`. An example configuration file can be found [here](../misc/snapshotter/config.toml). Besides nydus-snapshotter's configuration, `nydusd`'s configuration has to be provided to nydus-snapshotter too. Nydusd is started by nydus-snapshotter and it is configured by the provided json configuration file. A minimal configuration file can be found [here](../misc/snapshotter/nydusd-config.fusedev.json)\n\n## Authentication\n\nSee [Registry Authentication](registry_authentication.md) for the full reference covering Docker config, CRI, kubeconfig, kubelet credential providers, and automatic credential renewal.\n\n## Metrics\n\nNydusd records metrics in its own format. The metrics are exported via a HTTP server on top of unix domain socket. Nydus-snapshotter fetches the metrics and convert them in to Prometheus format which is exported via a network address. Nydus-snapshotter by default does not fetch metrics from nydusd. You can enable the nydusd metrics download by assigning a network address to `metrics.address` in nydus-snapshotter's toml [configuration file](../misc/snapshotter/config.toml).\n\nOnce this entry is enabled, not only nydusd metrics, but also some information about the nydus-snapshotter\nruntime and snapshot related events are exported in Prometheus format as well.\n\n## Diagnose\n\nA system controller can be ran insides nydus-snapshotter.\nBy setting `system.enable` to `true`,  nydus-snapshotter will start a simple HTTP server on unix domain socket `system.address` path and exports some internal working status to users. The address defaults to `/var/run/containerd-nydus/system.sock`\n"
  },
  {
    "path": "docs/crictl_dry_run.md",
    "content": "# Start Container by crictl\n\n## Create crictl Config\n\nThe runtime endpoint can be set in the config file. Please refer to [crictl](https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md) document for more details.\n\nCompose your `crictl` configuration file named as `crictl.yaml`:\n\n```yml\nruntime-endpoint: unix:///run/containerd/containerd.sock\nimage-endpoint: unix:///run/containerd/containerd.sock\ntimeout: 10\ndebug: true\n```\n\nCompose a pod configuration which can be named as `pod.yaml`\n\n```yml\nmetadata:\n  attempt: 1\n  name: nydus-sandbox\n  namespace: default\n  uid: hdishd83djaidwnduwk28bcsb\nlog_directory: /tmp\nlinux:\n  security_context:\n    namespace_options:\n      network: 2\n```\n\nCompose a container configuration which can be named as `container.yaml`\n\n```yml\nmetadata:\n  name: nydus-container\nimage:\n  image: <nydus-image>\ncommand:\n  - /bin/sleep\nargs:\n  - 600\nlog_path: container.1.log\n```\n\nStart a container based on nydus image.\n\n```bash\n# auth is base64 encoded string from \"username:password\"\n$ crictl --config ./crictl.yaml run --auth <base64 of registry auth> ./container.yaml ./pod.yaml\n```\n"
  },
  {
    "path": "docs/index_detection.md",
    "content": "# Index Detection\n\n## Overview\n\nIndex Detection is a feature that automatically discovers Nydus alternative manifests within OCI index manifests. This enables transparent fallback to optimized Nydus images when available while keeping the original index manifest OCI compliant, allowing non-Nydus clients to pull regular OCI images.\n\n## Motivation\n\nThe Index Detection feature addresses several limitations of the existing Referrer API-based detection:\n\n- **Registry Support**: Not all registries support the Referrer API\n- **Supply Chain Security**: Referrer API relies on external changes to the manifest, creating potential supply chain risks\n- **Universal Compatibility**: Index detection works with all OCI-compliant registries\n\nUnlike referrer-based detection, Index Detection packages everything into a single manifest, eliminating supply chain concerns while maintaining universal registry support.\n\n## How It Works\n\n### Detection Process\n\n1. **Index Manifest Parsing**: When a manifest digest is encountered, the system fetches and parses the original OCI index manifest\n2. **Platform Matching**: The system finds the original manifest descriptor within the index\n3. **Nydus Alternative Search**: It searches for platform-compatible manifests that contain:\n   - `platform.os.features` containing `nydus.remoteimage.v1`, or\n   - `artifactType` set to `application/vnd.nydus.image.manifest.v1+json`\n4. **Validation**: The found manifest is validated to ensure it's a valid Nydus manifest with metadata layers\n5. **Caching**: Results are cached to avoid repeated API calls for the same digest\n\nBoth `platform.os.features` and `artifactType` are looked at because index manifests built using `merge-platform` before acceleration-service: v0.2.19 or nydus: v2.3.5 will have `platform.os.features` configured while images built after will have `artifactType` configured.\n\n### Detection Priority\n\nWhen both Index Detection and Referrer Detection are available, Index Detection takes priority due to its superior supply chain security properties.\n\n## Configuration\n\nIndex Detection is controlled by the `EnableIndexDetect` configuration option in the experimental features section:\n\n```toml\n[experimental]\nenable_index_detect = true\n```\n\n## Building Compatible Images\n\nTo create images compatible with Index Detection, use the `nydusify convert` command with the `--merge-platform` flag:\n\n```bash\nnydusify convert --merge-platform <source-image> <target-image>\n```\n\nThis creates an OCI index manifest containing both the original image and the Nydus alternative:\n\n```json\n{\n  \"schemaVersion\": 2,\n  \"manifests\": [\n    {\n      \"mediaType\": \"application/vnd.oci.image.manifest.v1+json\",\n      \"digest\": \"sha256:a63dfddecc661e4ad05896418b2f3774022269c3bf5b7e01baaa6e851a3a4a23\",\n      \"size\": 2320,\n      \"platform\": {\n        \"architecture\": \"amd64\",\n        \"os\": \"linux\"\n      }\n    },\n    {\n      \"mediaType\": \"application/vnd.oci.image.manifest.v1+json\",\n      \"digest\": \"sha256:bb82dd8ee111bfe5fdf12145b6ed553da9c15de17f54b1f658d95ff26a65a01c\",\n      \"size\": 3229,\n      \"platform\": {\n        \"architecture\": \"amd64\",\n        \"os\": \"linux\"\n      },\n      \"artifactType\": \"application/vnd.nydus.image.manifest.v1+json\"\n    }\n  ]\n}\n```\n\n## Comparison with Referrer Detection\n\n| Aspect | Index Detection | Referrer Detection |\n|--------|----------------|-------------------|\n| Registry Support | Universal | Limited |\n| Supply Chain Security | Secure (single manifest) | Potential risks (external refs) |\n| OCI Compliance | Full compliance | Requires Referrer API |\n| Cache Behavior | Immutable (digest-based) | May require invalidation |\n| Detection Priority | Higher | Lower |\n"
  },
  {
    "path": "docs/optimize_nydus_image.md",
    "content": "# Optimize a nydus image\n\nTo improve the prefetch hit rate, we can specify a prefetch table when converting an OCI image to a nydus image. The prefetch table is workload related and we should generate the list of accessed files in order when the workload is running. Nydus-snapshotter has implemented an optimizer with Containerd NRI plugin to optimize the nydus image. The optimizer is image format independent and requires NRI 2.0, which is available in containerd (>=v1.7.0). The optimizer subscribes container events to watch what files are opened and read, etc. during container application is starting up. This enables nydus image build tools to optimize the nydus image making it put the necessary and prioritized files into a special region of nydus image with extra image metadata. So nydus runtime can pull this files into local disk in top priority, thus to boost the performance further.\n\n## Requirements\n\n- [NRI 2.0](https://github.com/containerd/nri): Which has been integrated into containerd since [v1.7.0](https://github.com/containerd/containerd/tree/v1.7.0-beta.1).\n\n## Workflow\n\n![optimizer workload](./diagram/optmizer_workflow.svg)\n\n1. Run the optimizer as a NRI plugin to run optimizer server when the StartContainer event occurs.\n2. Optimizer server joins container mount namespace and starts fanotify server.\n3. Optimizer server detects fanotify event and sends the accessed file descriptor to client.\n4. Optimizer client converts file descriptor to path.\n5. Generate list of accessed files on local disk.\n6. Convert OCI images with accessed files list to nydus image.\n\n## Generate an accessed files list\n\nTo install the optimizer and optimizer-server, invoke below command:\n\n```console\nmake optimizer && make install-optimizer\n```\n\nThis command installs the optimizer's default toml configuration file in `/etc/nri/conf.d/02-optimizer-nri-plugin.conf`. Here is an example:\n\n```toml\n# The directory to persist accessed files list for container.\npersist_dir = \"/opt/nri/optimizer/results\"\n# Whether to make the csv file human readable.\nreadable = false\n# The path of optimizer server binary.\nserver_path = \"/usr/local/bin/optimizer-server\"\n# The timeout to kill optimizer server, 0 to disable it.\ntimeout = 0\n# Whether to overwrite the existed persistent files.\noverwrite = false\n# The events that containerd subscribes to.\n# Do not change this element.\nevents = [ \"StartContainer\", \"StopContainer\" ]\n```\n\nModify containerd's toml configuration file to enable NRI.\n\n```console\nsudo tee -a /etc/containerd/config.toml <<- EOF\n[plugins.\"io.containerd.nri.v1.nri\"]\n  config_file = \"/etc/nri/nri.conf\"\n  disable = false\n  plugin_path = \"/opt/nri/plugins\"\n  socket_path = \"/var/run/nri.sock\"\nEOF\n\n```\n\nContainerd will load all NRI plugins in the `plugin_path` directory on startup. If you want to start a NRI plugin manually, please add the following configuration to allow other NRI plugins to connect via `socket_path`.\n\n```console\nsudo tee /etc/nri/nri.conf <<- EOF\ndisableConnections: false\nEOF\n\n```\n\nRestart the containerd service.\n\n```console\nsudo systemctl restart containerd\n\n```\n\nNow, just run a container workload in sandbox and you will get the list of accessed files in `persist_dir`.\nNote that NRI plugin can only be called from containerd/CRI. So start a container using `crictl` as below.\n\n```console\nsudo tee nginx.yaml <<- EOF\nmetadata:\n  name: nginx\nimage:\n  image: nginx:latest\nlog_path: nginx.0.log\nlinux: {}\nEOF\n\nsudo tee pod.yaml <<- EOF\nmetadata:\n  name: nginx-sandbox\n  namespace: default\n  attempt: 1\n  uid: hdishd83djaidwnduwk28bcsb\nlog_directory: /tmp\nlinux: {}\nEOF\n\ncrictl run nginx.yaml pod.yaml\n\n```\n\nThe result file for the nginx image is `/opt/nri/optimizer/results/library/nginx:latest`.\n\n## Build Nydus Image with Optimizer's Suggestions\n\nNydus provides a [nydusify](https://github.com/dragonflyoss/nydus/blob/master/docs/nydusify.md) CLI tool to convert OCI images from the source registry or local file system to nydus format and push them to the target registry.\n\nWe can install the `nydusify` cli tool from the nydus package.\n\n```console\nVERSION=v2.3.0\n\nwget https://github.com/dragonflyoss/nydus/releases/download/$VERSION/nydus-static-$VERSION-linux-amd64.tgz\ntar -zxvf nydus-static-$VERSION-linux-amd64.tgz\nsudo install -D -m 755 nydus-static/nydusify /usr/local/bin/nydusify\nsudo install -D -m 755 nydus-static/nydus-image /usr/local/bin/nydus-image\n```\n\nA simple example converts the OCI image nginx to nydus format in RAFS V6.\n\n```console\nsudo nydusify convert --source nginx --target sctb512/nginx:nydusv6 --fs-version 6\n```\n\nWith the `--prefetch-patterns` argument, we can specify the list of files to be written in the front of the nydus image and be prefetched in order when starting a container.\n\n```console\nsudo nydusify convert --source nginx --target sctb512/nginx:optimized-nydusv6 --fs-version 6 --prefetch-patterns < /opt/nri/optimizer/results/library/nginx:latest\n```\n\nOn a host with nydus-snapshotter installed and configured properly, start a container with an optimized nydus image.\n\n```console\nsudo nerdctl --snapshotter nydus run --rm --net host -it sctb512/nginx:optimized-nydusv6\n```\n"
  },
  {
    "path": "docs/registry_authentication.md",
    "content": "# Registry Authentication\n\nAs [containerd#3731](https://github.com/containerd/containerd/issues/3731) discussed, containerd doesn't share credentials with third-party snapshotters. Like [stargz snapshotter](https://github.com/containerd/stargz-snapshotter/blob/main/docs/overview.md#authentication), nydus-snapshotter supports multiple ways to access private registries with custom configurations.\n\nCredentials are looked up in the following priority order:\n\n1. Snapshot labels (username and password)\n2. CRI request interception\n3. Docker config (enabled by default)\n4. Kubelet credential provider plugins\n5. Kubernetes docker config secrets\n\n## Docker config\n\nBy default, the snapshotter reads credentials from `$DOCKER_CONFIG` or `~/.docker/config.json`.\n\n```console\n# docker login\n(Enter username and password)\n# crictl pull --creds USERNAME[:PASSWORD] docker.io/<your-repository>/ubuntu:22.04\n(Here the credential is only used by containerd)\n```\n\n## CRI-based authentication\n\nThe following configuration enables nydus-snapshotter to pull private images via CRI requests.\n\n```toml\n[remote.auth]\n# Fetch the private registry auth as CRI image service proxy\nenable_cri_keychain = true\nimage_service_address = \"/run/containerd/containerd.sock\"\n```\n\nThe snapshotter acts as a proxy of the CRI Image Service, exposing the CRI Image Service API on the snapshotter's unix socket (i.e. `/run/containerd/containerd-nydus-grpc.sock`). It acquires registry credentials by scanning requests. `image_service_address` defaults to `/run/containerd/containerd.sock` if omitted.\n\nYou **must** specify `--image-service-endpoint=unix:///run/containerd-nydus/containerd-nydus-grpc.sock` to kubelet when using Kubernetes, or set `image-endpoint: \"unix:////run/containerd-nydus/containerd-nydus-grpc.sock\"` in `crictl.yaml` when using `crictl`.\n\n## Kubeconfig-based authentication\n\nNydus snapshotter can watch Kubernetes secrets (type `kubernetes.io/dockerconfigjson`) for private registry credentials.\n\n### Using a kubeconfig file\n\n```toml\n[remote.auth]\nenable_kubeconfig_keychain = true\nkubeconfig_path = \"/path/to/.kubeconfig\"\n```\n\nIf `kubeconfig_path` is omitted, the snapshotter searches `$KUBECONFIG` or `~/.kube/config`.\n\n> **Note:** This requires additional privilege (a kubeconfig with permission to list/watch secrets) on the node. It does not work if kubelet retrieves credentials outside the API server (e.g. via a [credential provider](https://kubernetes.io/docs/tasks/kubelet-credential-provider/kubelet-credential-provider/)). For that use case, see the [kubelet credential provider](#kubelet-credential-provider) section.\n\n### Using a ServiceAccount\n\nIf nydus-snapshotter runs inside a Kubernetes cluster you can use a ServiceAccount instead of a kubeconfig:\n\n```yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: nydus-snapshotter-sa\n  namespace: nydus-system\n---\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: nydus-snapshotter-role\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - secrets\n  verbs:\n  - get\n  - list\n  - watch\n---\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: nydus-snapshotter-role-binding\nroleRef:\n  kind: ClusterRole\n  name: nydus-snapshotter-role\n  apiGroup: rbac.authorization.k8s.io\nsubjects:\n- kind: ServiceAccount\n  name: nydus-snapshotter-sa\n  namespace: nydus-system\n```\n\nThen reference the ServiceAccount in the nydus-snapshotter Pod spec:\n\n```yaml\nspec:\n  serviceAccountName: nydus-snapshotter-sa\n```\n\n### Creating secrets\n\nIf you have logged into a private registry, create a secret from the local config file:\n\n```bash\nkubectl create --namespace nydus-system secret generic regcred \\\n    --from-file=.dockerconfigjson=$HOME/.docker/config.json \\\n    --type=kubernetes.io/dockerconfigjson\n```\n\nThe snapshotter will pick up the secret and use it for subsequent image pulls from the matched registry.\n\n## Kubelet credential provider\n\nNydus snapshotter supports [Kubernetes kubelet credential provider plugins](https://kubernetes.io/docs/tasks/kubelet-credential-provider/kubelet-credential-provider/), which allow dynamic credential retrieval from external sources such as cloud provider identity services or secrets managers.\n\n> **Note:** This implementation supports **exec-based credential provider plugins** (GA since [Kubernetes v1.26](https://kubernetes.io/blog/2022/12/22/kubelet-credential-providers/)) but does **not** support the [service account token integration](https://kubernetes.io/blog/2025/05/07/kubernetes-v1-33-wi-for-image-pulls/) introduced in Kubernetes v1.33+. Plugins must retrieve credentials via other means (instance metadata, environment variables, local credential files, etc.).\n\nThis authentication method is well-suited for:\n\n- Frequently rotated credentials managed by external systems\n- Cloud provider-managed registries (ECR, GCR, ACR) using instance or workload identity\n- Enterprise secrets management integrations\n\n### Configuration\n\n```toml\n[remote.auth]\nenable_kubelet_credential_providers = true\ncredential_provider_config = \"/etc/nydus/credential-provider-config.yaml\"\ncredential_provider_bin_dir = \"/usr/local/bin/credential-providers\"\n```\n\n| Parameter | Description |\n|---|---|\n| `enable_kubelet_credential_providers` | Enable kubelet credential provider support (default: `false`) |\n| `credential_provider_config` | Path to the credential provider configuration file |\n| `credential_provider_bin_dir` | Directory containing credential provider plugin binaries |\n\n### Credential provider configuration file\n\nFollow the [Kubernetes spec](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1/#kubelet-config-k8s-io-v1-CredentialProviderConfig):\n\n```yaml\napiVersion: kubelet.config.k8s.io/v1\nkind: CredentialProviderConfig\nproviders:\n  - name: ecr-credential-provider\n    apiVersion: credentialprovider.kubelet.k8s.io/v1\n    matchImages:\n      - \"*.dkr.ecr.*.amazonaws.com\"\n    defaultCacheDuration: \"12h\"\n    args:\n      - get-credentials\n\n  - name: gcr-credential-provider\n    apiVersion: credentialprovider.kubelet.k8s.io/v1\n    matchImages:\n      - \"gcr.io\"\n      - \"*.gcr.io\"\n    defaultCacheDuration: \"1h\"\n```\n\n### Plugin installation\n\n1. Place credential provider binaries in the `credential_provider_bin_dir` directory and ensure they are executable.\n2. Configure `matchImages` patterns to match your registry URLs. Wildcards are supported (e.g. `*.dkr.ecr.*.amazonaws.com`).\n\nFor AWS ECR, use the official [ECR credential provider](https://github.com/kubernetes/cloud-provider-aws/tree/master/cmd/ecr-credential-provider):\n\n```bash\nmkdir -p /usr/local/bin/credential-providers\nwget https://artifacts.k8s.io/binaries/cloud-provider-aws/v1.30.0/linux/amd64/ecr-credential-provider\nchmod +x ecr-credential-provider\nmv ecr-credential-provider /usr/local/bin/credential-providers/\n```\n\n### Plugin protocol\n\nPlugins communicate via stdin/stdout using JSON.\n\n**Request:**\n\n```json\n{\n  \"kind\": \"CredentialProviderRequest\",\n  \"apiVersion\": \"credentialprovider.kubelet.k8s.io/v1\",\n  \"image\": \"123456789.dkr.ecr.us-east-1.amazonaws.com/my-image:latest\"\n}\n```\n\n**Response:**\n\n```json\n{\n  \"kind\": \"CredentialProviderResponse\",\n  \"apiVersion\": \"credentialprovider.kubelet.k8s.io/v1\",\n  \"cacheKeyType\": \"Image\",\n  \"cacheDuration\": \"12h\",\n  \"auth\": {\n    \"123456789.dkr.ecr.us-east-1.amazonaws.com\": {\n      \"username\": \"AWS\",\n      \"password\": \"<token>\"\n    }\n  }\n}\n```\n\nSet `auth` to `null` if no credentials are available for the requested image.\n\n### Troubleshooting\n\n- Plugin execution failures are logged but don't halt the authentication chain — the snapshotter tries the next provider.\n- Check logs for: `level=warning msg=\"failed to execute credential provider plugin\"`\n- Test plugins manually by sending a JSON request on stdin to verify output.\n\n## Credential renewal\n\nFor providers that issue short-lived tokens (such as the kubelet credential provider with cloud IAM backends), nydus-snapshotter can automatically renew credentials in the background before they expire.\n\nWhen enabled, a background goroutine periodically reconciles the set of active RAFS instances against an in-memory credential store, renewing credentials for images currently in use and evicting entries for images that are no longer mounted. On each renewal tick the goroutine re-queries the renewable providers (Docker config, kubelet credential providers, Kubernetes secrets) in priority order.\n\nOnly providers that support renewal participate: Docker config, kubelet credential providers, and Kubernetes secret-based providers. CRI-based and label-based credentials are not renewed. The kubelet provider being\nexpiration aware, it will only renew tokens when they are about to expire.\nEntries are evicted when the corresponding RAFS instance is no longer mounted; the credential store itself does not expire entries.\n\n### Configuration\n\n```toml\n[remote.auth]\n# How often to renew credentials. Set to 0 (the default) to disable.\ncredential_renewal_interval = \"30m\"\n```\n\nSet `credential_renewal_interval` to at most one third of your token lifetime. This ensures at least two renewal attempts before a token expires, so a single transient failure (network blip, metadata service hiccup) does not cause an auth outage. For example, if ECR tokens are valid for 12 hours, use an interval of 4 hours or less.\n\n> **Future improvement:** The current configuration conflates two concerns into a single interval: how frequently the renewal loop runs, and how early before expiry a token should be renewed. A future version may separate these into a `credential_renewal_check_interval` (the loop cadence, kept short) and a `credential_renewal_lead_time` (how far before expiry to trigger renewal, e.g. 2 hours before a 12-hour token expires). This would allow fine-grained control without the lifetime/3 approximation.\n\n### Metrics\n\nWhen credential renewal is enabled, the following Prometheus metrics are exported:\n\n| Metric | Type | Description |\n|---|---|---|\n| `snapshotter_credential_renewals_total` | Counter | Renewal attempts, labeled by `image_ref` and `result` (`success` or `failure`) |\n| `snapshotter_credential_store_entries` | Gauge | Number of credentials tracked per `image_ref` |\n\nA rising `failure` count in `snapshotter_credential_renewals_total` indicates that a provider is failing to renew credentials and warrants investigation before the current tokens expire.\n"
  },
  {
    "path": "docs/run_nydus_in_kubernetes.md",
    "content": "# Run Dragonfly & Nydus in Kubernetes\n\nWe recommend using the Dragonfly P2P data distribution system to further improve the runtime performance of Nydus images.\n\nIf you want to deploy Dragonfly and Nydus at the same time through Helm, please refer to the **[Quick Start](https://github.com/dragonflyoss/helm-charts/blob/main/INSTALL.md)**.\n\n# Run Nydus snapshotter in Kubernetes\n\nThis document will introduce how to run Nydus snapshotter in Kubernetes cluster, you can use helm to deploy Nydus snapshotter container.\n\n**NOTE:** This document is mainly to allow everyone to quickly deploy and experience Nydus snapshotter in the Kubernetes cluster. You cannot use it as a deployment and configuration solution for the production environment.\n\n## Setup Kubernetes using kind\n\n[kind](https://kind.sigs.k8s.io/) is a tool for running local Kubernetes clusters using Docker container “nodes”.\nkind was primarily designed for testing Kubernetes itself, but may be used for local development or CI.\n\nFirst, we need to prepare a configuration file(`kind-config.yaml`) for kind to specify the devices and files we need to mount to the kind node.\n\n```yaml\nkind: Cluster\napiVersion: kind.x-k8s.io/v1alpha4\nnetworking:\n  ipFamily: dual\nnodes:\n  - role: control-plane\n    image: kindest/node:v1.30.2\n    extraMounts:\n      - hostPath: ./containerd-config.toml\n        containerPath: /etc/containerd/config.toml\n      - hostPath: /dev/fuse\n        containerPath: /dev/fuse\n```\n\nNext, we also need a config for containerd(`containerd-config.toml`).\n\n**NOTE:** It may be necessary to explain here why `disable_snapshot_annotations` and `discard_unpacked_layers` need to be configured in containerd.\n- `disable_snapshot_annotations`: This variable disables to pass additional annotations (image related information) to snapshotters in containerd (default value is `true`). In nydus snapshotter, we need these annotations to pull images. Therefore, we need to set it to `false`.\n- `discard_unpacked_layers`: This variable allows GC to remove layers from the content store after successfully unpacking these layers to the snapshotter in containerd (default value is `true`). In nydus snapshotter, we need to preserve layers for demand pulling and sharing even after they are unpacked. Therefore, we need to set it to `false`.\n\n```toml\nversion = 2\n[debug]\n  level = \"debug\"\n\n[plugins.\"io.containerd.grpc.v1.cri\".containerd]\n  discard_unpacked_layers = false\n  disable_snapshot_annotations = false\n  snapshotter = \"overlayfs\"\n  default_runtime_name = \"runc\"\n[plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runc]\n  runtime_type = \"io.containerd.runc.v2\"\n\n[plugins.\"io.containerd.grpc.v1.cri\"]\n  sandbox_image = \"registry.k8s.io/pause:3.6\"\n```\n\nWith these two configuration files, we can create a kind cluster.\n\n```bash\n$ kind create cluster --config=kind-config.yaml\n```\n\nIf everything is fine, kind should have prepared the configuration for us, and we can run the `kubectl` command directly on the host machine, such as:\n\n```bash\n$ kubectl get nodes\nNAME                 STATUS   ROLES                  AGE   VERSION\nkind-control-plane   Ready    control-plane,master   19m   v1.23.4\n```\n\n## Use helm to install Nydus snapshotter\n\nBefore proceeding, you need to make sure [`helm` is installed](https://helm.sh/docs/intro/quickstart/#install-helm).\n\nFirst, you need to create a `config-nydus.yaml` for helm to install Nydus-snapshotter.\n\n```yaml\nname: nydus-snapshotter\npullPolicy: Always\nhostNetwork: true\ndragonfly:\n  enable: false\n\ncontainerRuntime:\n  containerd:\n    enable: true\n```\n\nThen clone the Nydus snapshotter helm chart.\n\n```bash\n$ git clone https://github.com/dragonflyoss/helm-charts.git\n```\n\nLast run helm to create Nydus snapshotter.\n\n```bash\n$ cd helm-charts\n$ helm install --wait --timeout 10m --dependency-update \\\n    --create-namespace --namespace nydus-system \\\n    -f config-nydus.yaml \\\n    nydus-snapshotter charts/nydus-snapshotter\n```\n\n## Run Nydus containers\n\nWe can then create a Pod(`nydus-pod.yaml`) config file that runs Nydus image.\n\n```yaml\napiVersion: v1\nkind: Pod\nmetadata:\n  name: nydus-pod\nspec:\n  containers:\n    - name: nginx\n      image: ghcr.io/dragonflyoss/image-service/nginx:nydus-latest\n      imagePullPolicy: Always\n      command: [\"sh\", \"-c\"]\n      args:\n        - tail -f /dev/null\n```\n\nUse `kubectl` to create the Pod.\n\n```bash\n$ kubectl create -f nydus-pod.yaml\n$ kubectl get pods -w\n```\n\nThe `-w` options will block the console and wait for the changes of the status of the pod. If everything is normal, you can see that the pod will become `Running` after a while.\n\n```bash\nNAME       READY   STATUS              RESTARTS   AGE\nnydus-pod  1/1     Running             0          51s\n```\n"
  },
  {
    "path": "docs/setup_snapshotter_by_daemonset.md",
    "content": "# Setup Nydus Snapshotter by DaemonSet\n\nThis document will guide you through the simple steps of setting up and cleaning up the nydus snapshotter in a kubernetes cluster that runs on the host.\n\n## Steps for Setting up Nydus Snapshotter \n\nTo begin, let's clone the Nydus Snapshotter repository.\n\n```bash\ngit clone https://github.com/containerd/nydus-snapshotter\ncd nydus-snapshotter\n```\n\nWe can build the docker image locally. (optional)\n```bash\n$ export NYDUS_VER=$(curl -s \"https://api.github.com/repos/dragonflyoss/nydus/releases/latest\" | jq -r .tag_name)\n$ make  # build snapshotter binaries\n$ cp bin/* misc/snapshotter/\n$ pushd misc/snapshotter/\n$ docker build --build-arg NYDUS_VER=\"${NYDUS_VER}\" -t ghcr.io/containerd/nydus-snapshotter:latest .\n$ popd\n```\n**NOTE:** By default, the nydus snapshotter would use the latest release nydus version. If you want to use a specific version, you can set `NYDUS_VER` on your side.\n\nNext, we can configure access control for nydus snapshotter.\n```bash\nkubectl apply -f misc/snapshotter/nydus-snapshotter-rbac.yaml\n```\n\nAfterward, we can deploy a DaemonSet for nydus snapshotter, according to the kubernetes flavour you're using.\n\n```bash\n# Vanilla kubernetes\nkubectl apply -f misc/snapshotter/base/nydus-snapshotter.yaml\n```\n\n```bash\n# k3s\nkubectl apply -k misc/snapshotter/overlays/k3s/\n```\n\n```bash\n# rke2\nkubectl apply -k misc/snapshotter/overlays/rke2/\n```\n\nThen, we can confirm that nydus snapshotter is running through the DaemonSet.\n```bash\n$ kubectl get pods -n nydus-system \nNAME                      READY   STATUS    RESTARTS   AGE\nnydus-snapshotter-26rf7   1/1     Running   0          18s\n```\n\nFinally, we can view the logs in the pod.\n```bash\n$ kubectl logs nydus-snapshotter-26rf7 -n nydus-system\ninstall nydus snapshotter artifacts\nthere is no proxy plugin!\nCreated symlink /etc/systemd/system/multi-user.target.wants/nydus-snapshotter.service → /etc/systemd/system/nydus-snapshotter.service.\n```\n\nAnd we can see the nydus snapshotter service on the host.\n```bash\n$ systemctl status nydus-snapshotter\n● nydus-snapshotter.service - nydus snapshotter\n     Loaded: loaded (/etc/systemd/system/nydus-snapshotter.service; enabled; vendor preset: enabled)\n    Drop-In: /etc/systemd/system/nydus-snapshotter.service.d\n             └─proxy.conf\n     Active: active (running) since Wed 2024-01-17 16:14:22 UTC; 56s ago\n   Main PID: 1100169 (containerd-nydu)\n      Tasks: 11 (limit: 96376)\n     Memory: 8.6M\n        CPU: 35ms\n     CGroup: /system.slice/nydus-snapshotter.service\n             └─1100169 /opt/nydus/bin/containerd-nydus-grpc --config /etc/nydus/config.toml\n\nJan 17 16:14:22 worker systemd[1]: Started nydus snapshotter.\nJan 17 16:14:22 worker containerd-nydus-grpc[1100169]: time=\"2024-01-17T16:14:22.998798369Z\" level=info msg=\"Start nydus-snapshotter. Version: v0.7.0-308-g106a6cb, PID: 1100169, FsDriver: fusedev, DaemonMode: dedicated\"\nJan 17 16:14:23 worker containerd-nydus-grpc[1100169]: time=\"2024-01-17T16:14:23.000186538Z\" level=info msg=\"Run daemons monitor...\"\n```\n\n**NOTE:** By default, the nydus snapshotter operates as a systemd service. If you prefer to run nydus snapshotter as a standalone process, you can set `ENABLE_SYSTEMD_SERVICE` to `false` in `nydus-snapshotter.yaml`.\n\n## Steps for Cleaning up Nydus Snapshotter \n\nWe use `preStop`` hook in the DaemonSet to uninstall nydus snapshotter and roll back the containerd configuration.\n\n```bash\n# Vanilla kubernetes\n$ kubectl delete -f misc/snapshotter/base/nydus-snapshotter.yaml \n```\n\n```bash\n# k3s\n$ kubectl delete -k misc/snapshotter/overlays/k3s/ \n```\n\n```bash\n# rke2\n$ kubectl delete -k misc/snapshotter/overlays/rke2/\n```\n\n```bash\n$ kubectl delete -f misc/snapshotter/nydus-snapshotter-rbac.yaml \n$ systemd restart containerd.service\n```\n\n## Customized Setup\n\nAs we know, nydus snapshotter supports four filesystem drivers (fs_driver): `fusedev`, `fscache`, `blockdev`, `proxy`. Within the container image, we have included configurations for these snapshotter drivers, as well as the corresponding nydusd configurations. By default, the fusedev driver is enabled in the nydus snapshotter, using the snapshotter configuration [`config-fusedev.toml`](../misc/snapshotter/config-fusedev.toml) and the nydusd configuration [`nydusd-config.fusedev.json`](../misc/snapshotter/nydusd-config.fusedev.json).\n\n### Other filesystem driver with related default configuration\n\nIf we want to setup the nydus snapshotter with the default configuration for different fs_driver (such as `proxy`), we can modify the values in the `Configmap` in `nydus-snapshotter.yaml`:\n```yaml\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: nydus-snapshotter-configs\n  labels:\n    app: nydus-snapshotter\n  namespace: nydus-snapshotter\ndata:\n  FS_DRIVER: \"proxy\"\n  NYDUSD_DAEMON_MODE: \"none\"\n```\n\nThen we can run the nydus snapshotter enabling `proxy` `fs_driver` with the snapshotter configuration [`config-proxy.toml`](../misc/snapshotter/config-proxy.toml).\n\n**NOTE:** The fs_driver (`blockdev` and `proxy`) do not need nydusd, so they do not need nydusd config.\n\n### Same filesystem with different snapshotter configuration and different nydusd configuration\n\nIf we want to setup the nydus snapshotter for the same fs_driver (such as `fusedev`) with different snapshotter configuration and different nydusd configuration, we can enable `ENABLE_CONFIG_FROM_VOLUME` and add the snapshotter configuration [`config.toml`](../misc/snapshotter/config.toml) and nydusd configuration [`nydusd-config.json`](../misc/snapshotter/nydusd-config.fusedev.json) in the `Configmap` in `nydus-snapshotter.yaml`:\n\n```yaml\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: nydus-snapshotter-configs\n  labels:\n    app: nydus-snapshotter\n  namespace: nydus-snapshotter\ndata:\n  ENABLE_CONFIG_FROM_VOLUME: \"true\"\n\n  config.toml: |-\n    # The snapshotter config content copied here\n\n  nydusd-config.json: |-\n    # The nydusd config content copied here\n```\n\n**NOTE:** We need to set `nydusd_config` to `/etc/nydus/nydusd-config.json` in the `config.toml`, so that snapshotter can find the nydusd configuration from configmap.\n\n### Customized Options\n\n| Options                             | Type   | Default                               | Comment                                                                                                                                         |\n| ----------------------------------- | ------ | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |\n| FS_DRIVER                           | string | \"fusedev\"                             | the filesystem driver of snapshotter                                                                                                            |\n| ENABLE_CONFIG_FROM_VOLUME           | bool   | false                                 | enabling to use the configurations from volume                                                                                                  |\n| ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER | bool   | false                                 | enabling to skip to set `plugins.\"io.containerd.grpc.v1.cri\".containerd` to `nydus` for runtime specific snapshotter feature in containerd 1.7+ |\n| ENABLE_SYSTEMD_SERVICE              | bool   | true                                  | enabling to run nydus snapshotter as a systemd service                                                                                          |\n"
  },
  {
    "path": "docs/tarfs.md",
    "content": "# Nydus Tarfs Mode\n\n`Nydus Tarfs Mode` or `Tarfs` is a working mode for Nydus Image, which uses tar files as Nydus data blobs instead of generating native Nydus data blobs.\n\n### Enable Tarfs\n`Nydus Tarfs Mode` is still an experiment feature, please edit the snapshotter configuration file to enable the feature:\n```\n[experimental.tarfs]\nenable_tarfs = true\n```\n\n### Generate Raw Disk Image for Each Layer of a Container Image\n`Tarfs` supports generating a raw disk image for each layer of a container image, which can be directly mounted as EROFS filesystem through loopdev. Please edit the snapshotter configuration file to enable this submode:\n```\n[experimental.tarfs]\nenable_tarfs = true\nexport_mode = \"layer_block\"\n```\n\nThis is an example to generate and verify raw disk image for each layer of a container image:\n```\n$ containerd-nydus-grpc --config /etc/nydus/config.toml &\n$ nerdctl run --snapshotter nydus --rm nginx\n\n# Show mounted rootfs a container\n$ mount\n/dev/loop17 on /var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/7/mnt type erofs (ro,relatime,user_xattr,acl,cache_strategy=readaround)\n\n# Show loop devices used to mount layers and bootstrap for a container image\n$ losetup \nNAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                                                                       DIO LOG-SEC\n/dev/loop11 0      0         0  0 /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa 0     512\n/dev/loop12 0      0         0  0 /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3 0     512\n/dev/loop13 0      0         0  0 /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd 0     512\n/dev/loop14 0      0         0  0 /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4 0     512\n/dev/loop15 0      0         0  0 /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665 0     512\n/dev/loop16 0      0         0  0 /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75 0     512\n/dev/loop17 0      0         0  0 /var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/7/fs/image/image.boot                         0     512\n\n# Files without suffix are tar files, files with suffix `layer.disk` are raw disk image for container image layers\n$ ls -l /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/\ntotal 376800\n-rw-r--r-- 1 root root      3584 Aug 30 23:18 055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3\n-rw-r--r-- 1 root root    527872 Aug 30 23:18 055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3.layer.disk\n-rw-r--r-- 1 root root  77814784 Aug 30 23:18 52d2b7f179e32b4cbd579ee3c4958027988f9a8274850ab0c7c24661e3adaac5\n-rw-r--r-- 1 root root  78863360 Aug 30 23:18 52d2b7f179e32b4cbd579ee3c4958027988f9a8274850ab0c7c24661e3adaac5.layer.disk\n-rw-r--r-- 1 root root      4608 Aug 30 23:18 96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd\n-rw-r--r-- 1 root root    528896 Aug 30 23:18 96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd.layer.disk\n-rw-r--r-- 1 root root      2560 Aug 30 23:18 a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4\n-rw-r--r-- 1 root root    526848 Aug 30 23:18 a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4.layer.disk\n-rw-r--r-- 1 root root      7168 Aug 30 23:18 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75\n-rw-r--r-- 1 root root    531456 Aug 30 23:18 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.layer.disk\n-rw-r--r-- 1 root root      5120 Aug 30 23:18 e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665\n-rw-r--r-- 1 root root    529408 Aug 30 23:18 e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665.layer.disk\n-rw-r--r-- 1 root root 112968704 Aug 30 23:18 fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa\n-rw-r--r-- 1 root root 113492992 Aug 30 23:18 fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa.layer.disk\n$ file /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3\n/var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3: POSIX tar archive\n\n# Mount the raw disk image for a container image layer\n$ losetup /dev/loop100 /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3.layer.disk \n$ mount -t erofs /dev/loop100 ./mnt/\n$ mount\ntmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=1544836k,nr_inodes=386209,mode=700,inode64)\n/dev/loop17 on /var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/7/mnt type erofs (ro,relatime,user_xattr,acl,cache_strategy=readaround)\n/dev/loop100 on /root/ws/nydus-snapshotter.git/mnt type erofs (ro,relatime,user_xattr,acl,cache_strategy=readaround)\n\n```\n\n### Generate Raw Disk Image for a Container Image\n`Tarfs` supports generating a raw disk image a container image, which can be directly mounted as EROFS filesystem through loopdev. Please edit the snapshotter configuration file to enable this submode:\n```\n[experimental.tarfs]\nenable_tarfs = true\nexport_mode = \"image_block\"\n```\n\nThis is an example to generate and verify raw disk image for a container image:\n```\n$ containerd-nydus-grpc --config /etc/nydus/config.toml &\n$ nerdctl run --snapshotter nydus --rm nginx\n\n# Files without suffix are tar files, files with suffix `image.disk` are raw disk image for a container image\n$ ls -l /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/\ntotal 376320\n-rw-r--r-- 1 root root      3584 Aug 30 23:35 055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3\n-rw-r--r-- 1 root root  77814784 Aug 30 23:35 52d2b7f179e32b4cbd579ee3c4958027988f9a8274850ab0c7c24661e3adaac5\n-rw-r--r-- 1 root root      4608 Aug 30 23:35 96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd\n-rw-r--r-- 1 root root      2560 Aug 30 23:35 a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4\n-rw-r--r-- 1 root root      7168 Aug 30 23:35 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75\n-rw-r--r-- 1 root root 194518016 Aug 30 23:36 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk\n-rw-r--r-- 1 root root      5120 Aug 30 23:35 e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665\n-rw-r--r-- 1 root root 112968704 Aug 30 23:36 fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa\n\n```\n\n### Generate Raw Disk Image with dm-verity Information\n`Tarfs` supports generating raw disk images with dm-verity information, to enable runtime data integrity validation. Please change `export_mode` in snapshotter configuration file to `layer_block_with_verity` or `image_block_with_verity`.\n\n```\n[experimental.tarfs]\nenable_tarfs = true\nexport_mode = \"image_block_with_verity\"\n```\n\nThis is an example to generate and verify raw disk image for a container image with dm-verity information:\n```\n$ containerd-nydus-grpc --config /etc/nydus/config.toml &\n$ nerdctl run --snapshotter nydus --rm nginx\n\n# Files without suffix are tar files, files with suffix `image.disk` are raw disk image for a container image\n$ ls -l /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/\ntotal 388296\n-rw-r--r-- 1 root root      3584 Aug 30 23:45 055fa98b43638b67d10c58d41094d99c8696cc34b7a960c7a0cc5d9d152d12b3\n-rw-r--r-- 1 root root  77814784 Aug 30 23:46 52d2b7f179e32b4cbd579ee3c4958027988f9a8274850ab0c7c24661e3adaac5\n-rw-r--r-- 1 root root      4608 Aug 30 23:45 96576293dd2954ff84251aa0455687c8643358ba1b190ea1818f56b41884bdbd\n-rw-r--r-- 1 root root      2560 Aug 30 23:45 a7c4092be9044bd4eef78f27c95785ef3a9f345d01fd4512bc94ddaaefc359f4\n-rw-r--r-- 1 root root      7168 Aug 30 23:45 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75\n-rw-r--r-- 1 root root 206782464 Aug 30 23:46 da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk\n-rw-r--r-- 1 root root      5120 Aug 30 23:45 e3b6889c89547ec9ba653ab44ed32a99370940d51df956968c0d578dd61ab665\n-rw-r--r-- 1 root root 112968704 Aug 30 23:46 fd9f026c631046113bd492f69761c3ba6042c791c35a60e7c7f3b8f254592daa\n\n$ losetup /dev/loop100 /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk\n$  veritysetup open --no-superblock --format=1 -s \"\" --hash=sha256 --data-block-size=512 --hash-block-size=4096 --data-blocks 379918 --hash-offset 194519040 /dev/loop100 image1 /dev/loop100 8113799aaf9a5d14feca1eadc3b7e6ea98bdaf61e3a2e4a8ef8c24e26a551efd\n$ lsblk\nloop100   7:100  0 197.2M  0 loop  \n└─dm-0  252:0    0 185.5M  1 crypt \n\n$ veritysetup status dm-0\n/dev/mapper/dm-0 is active and is in use.\n  type:        VERITY\n  status:      verified\n  hash type:   1\n  data block:  512\n  hash block:  4096\n  hash name:   sha256\n  salt:        -\n  data device: /dev/loop100\n  data loop:   /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk\n  size:        379918 sectors\n  mode:        readonly\n  hash device: /dev/loop100\n  hash loop:   /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/da761d9a302b21dc50767b67d46f737f5072fb4490c525b4a7ae6f18e1dbbf75.image.disk\n  hash offset: 379920 sectors\n  root hash:   8113799aaf9a5d14feca1eadc3b7e6ea98bdaf61e3a2e4a8ef8c24e26a551efd\n\n$ mount -t erofs /dev/dm-0 ./mnt/\nmount: /root/ws/nydus-snapshotter.git/mnt: WARNING: source write-protected, mounted read-only.\n$ ls -l mnt/\ntotal 14\nlrwxrwxrwx  1 root root    7 Aug 14 08:00 bin -> usr/bin\ndrwxr-xr-x  2 root root   27 Jul 15 00:00 boot\ndrwxr-xr-x  2 root root   27 Aug 14 08:00 dev\ndrwxr-xr-x  2 root root  184 Aug 16 17:50 docker-entrypoint.d\n-rwxrwxr-x  1 root root 1620 Aug 16 17:50 docker-entrypoint.sh\ndrwxr-xr-x 34 root root 1524 Aug 16 17:50 etc\ndrwxr-xr-x  2 root root   27 Jul 15 00:00 home\nlrwxrwxrwx  1 root root    7 Aug 14 08:00 lib -> usr/lib\nlrwxrwxrwx  1 root root    9 Aug 14 08:00 lib32 -> usr/lib32\nlrwxrwxrwx  1 root root    9 Aug 14 08:00 lib64 -> usr/lib64\nlrwxrwxrwx  1 root root   10 Aug 14 08:00 libx32 -> usr/libx32\ndrwxr-xr-x  2 root root   27 Aug 14 08:00 media\ndrwxr-xr-x  2 root root   27 Aug 14 08:00 mnt\ndrwxr-xr-x  2 root root   27 Aug 14 08:00 opt\ndrwxr-xr-x  2 root root   27 Jul 15 00:00 proc\ndrwx------  2 root root   66 Aug 14 08:00 root\ndrwxr-xr-x  3 root root   43 Aug 14 08:00 run\nlrwxrwxrwx  1 root root    8 Aug 14 08:00 sbin -> usr/sbin\ndrwxr-xr-x  2 root root   27 Aug 14 08:00 srv\ndrwxr-xr-x  2 root root   27 Jul 15 00:00 sys\ndrwxrwxrwt  2 root root   27 Aug 16 17:50 tmp\ndrwxr-xr-x 14 root root  229 Aug 14 08:00 usr\ndrwxr-xr-x 11 root root  204 Aug 14 08:00 var\n\n```"
  },
  {
    "path": "export/snapshotter/snapshotter.go",
    "content": "package snapshotter\n\nimport (\n\t\"github.com/containerd/containerd/v2/plugins\"\n\t\"github.com/containerd/platforms\"\n\t\"github.com/containerd/plugin\"\n\t\"github.com/containerd/plugin/registry\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/snapshot\"\n)\n\nfunc init() {\n\tregistry.Register(&plugin.Registration{\n\t\tType:   plugins.SnapshotPlugin,\n\t\tID:     \"nydus\",\n\t\tConfig: &config.SnapshotterConfig{},\n\t\tInitFn: func(ic *plugin.InitContext) (interface{}, error) {\n\t\t\tic.Meta.Platforms = append(ic.Meta.Platforms, platforms.DefaultSpec())\n\n\t\t\tcfg, ok := ic.Config.(*config.SnapshotterConfig)\n\t\t\tif !ok {\n\t\t\t\treturn nil, errors.New(\"invalid nydus snapshotter configuration\")\n\t\t\t}\n\n\t\t\troot := ic.Properties[plugins.PropertyRootDir]\n\t\t\tif root == \"\" {\n\t\t\t\tcfg.Root = root\n\t\t\t}\n\n\t\t\tif err := cfg.FillUpWithDefaults(); err != nil {\n\t\t\t\treturn nil, errors.New(\"failed to fill up nydus configuration with defaults\")\n\t\t\t}\n\n\t\t\trs, err := snapshot.NewSnapshotter(ic.Context, cfg)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"failed to initialize snapshotter\")\n\t\t\t}\n\t\t\treturn rs, nil\n\n\t\t},\n\t})\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/containerd/nydus-snapshotter\n\ngo 1.25.9\n\nrequire (\n\tdario.cat/mergo v1.0.1\n\tgithub.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6\n\tgithub.com/KarpelesLab/reflink v1.0.1\n\tgithub.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible\n\tgithub.com/aws/aws-sdk-go-v2 v1.41.5\n\tgithub.com/aws/aws-sdk-go-v2/config v1.32.15\n\tgithub.com/aws/aws-sdk-go-v2/credentials v1.19.14\n\tgithub.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.1.16\n\tgithub.com/aws/aws-sdk-go-v2/service/s3 v1.99.0\n\tgithub.com/containerd/cgroups/v3 v3.0.3\n\tgithub.com/containerd/containerd/api v1.8.0\n\tgithub.com/containerd/containerd/v2 v2.0.7\n\tgithub.com/containerd/continuity v0.4.4\n\tgithub.com/containerd/errdefs v1.0.0\n\tgithub.com/containerd/fifo v1.1.0\n\tgithub.com/containerd/log v0.1.0\n\tgithub.com/containerd/nri v0.8.0\n\tgithub.com/containerd/platforms v1.0.0-rc.1\n\tgithub.com/containerd/plugin v1.0.0\n\tgithub.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319\n\tgithub.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319\n\tgithub.com/containers/ocicrypt v1.2.1\n\tgithub.com/distribution/reference v0.6.0\n\tgithub.com/docker/cli v29.4.0+incompatible\n\tgithub.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db\n\tgithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da\n\tgithub.com/google/go-containerregistry v0.20.1\n\tgithub.com/gorilla/mux v1.8.1\n\tgithub.com/hashicorp/go-retryablehttp v0.7.7\n\tgithub.com/klauspost/compress v1.17.11\n\tgithub.com/moby/locker v1.0.1\n\tgithub.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826\n\tgithub.com/opencontainers/go-digest v1.0.0\n\tgithub.com/opencontainers/image-spec v1.1.0\n\tgithub.com/opencontainers/runtime-spec v1.2.0\n\tgithub.com/pelletier/go-toml v1.9.5\n\tgithub.com/pkg/errors v0.9.1\n\tgithub.com/prometheus/client_golang v1.20.5\n\tgithub.com/prometheus/client_model v0.6.1\n\tgithub.com/rs/xid v1.5.0\n\tgithub.com/sirupsen/logrus v1.9.3\n\tgithub.com/stretchr/testify v1.11.1\n\tgithub.com/urfave/cli/v2 v2.27.5\n\tgo.etcd.io/bbolt v1.3.11\n\tgo.opentelemetry.io/otel v1.39.0\n\tgolang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc\n\tgolang.org/x/sync v0.20.0\n\tgolang.org/x/sys v0.43.0\n\tgoogle.golang.org/grpc v1.79.3\n\tgopkg.in/natefinch/lumberjack.v2 v2.2.1\n\tgotest.tools v2.2.0+incompatible\n\tk8s.io/api v0.31.2\n\tk8s.io/apimachinery v0.31.2\n\tk8s.io/client-go v0.31.2\n\tk8s.io/cri-api v0.31.2\n\tk8s.io/kubelet v0.31.2\n\tk8s.io/utils v0.0.0-20240711033017-18e509b52bc8\n\tsigs.k8s.io/yaml v1.4.0\n)\n\nrequire (\n\tgithub.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect\n\tgithub.com/Microsoft/go-winio v0.6.2 // indirect\n\tgithub.com/Microsoft/hcsshim v0.12.9 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/signin v1.0.9 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/sso v1.30.15 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/sts v1.41.10 // indirect\n\tgithub.com/aws/smithy-go v1.24.2 // indirect\n\tgithub.com/beorn7/perks v1.0.1 // indirect\n\tgithub.com/cespare/xxhash/v2 v2.3.0 // indirect\n\tgithub.com/cilium/ebpf v0.11.0 // indirect\n\tgithub.com/containerd/errdefs/pkg v0.3.0 // indirect\n\tgithub.com/containerd/ttrpc v1.2.7 // indirect\n\tgithub.com/containerd/typeurl/v2 v2.2.3 // indirect\n\tgithub.com/coreos/go-systemd/v22 v22.5.0 // indirect\n\tgithub.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect\n\tgithub.com/cyphar/filepath-securejoin v0.5.1 // indirect\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/docker/distribution v2.8.2+incompatible // indirect\n\tgithub.com/docker/docker-credential-helpers v0.7.0 // indirect\n\tgithub.com/docker/go-units v0.5.0 // indirect\n\tgithub.com/emicklei/go-restful/v3 v3.11.0 // indirect\n\tgithub.com/felixge/httpsnoop v1.0.4 // indirect\n\tgithub.com/fxamacker/cbor/v2 v2.7.0 // indirect\n\tgithub.com/go-jose/go-jose/v4 v4.1.4 // indirect\n\tgithub.com/go-logr/logr v1.4.3 // indirect\n\tgithub.com/go-logr/stdr v1.2.2 // indirect\n\tgithub.com/go-openapi/jsonpointer v0.19.6 // indirect\n\tgithub.com/go-openapi/jsonreference v0.20.2 // indirect\n\tgithub.com/go-openapi/swag v0.22.4 // indirect\n\tgithub.com/godbus/dbus/v5 v5.1.0 // indirect\n\tgithub.com/gogo/protobuf v1.3.2 // indirect\n\tgithub.com/golang/protobuf v1.5.4 // indirect\n\tgithub.com/google/gnostic-models v0.6.8 // indirect\n\tgithub.com/google/go-cmp v0.7.0 // indirect\n\tgithub.com/google/gofuzz v1.2.0 // indirect\n\tgithub.com/google/uuid v1.6.0 // indirect\n\tgithub.com/hashicorp/go-cleanhttp v0.5.2 // indirect\n\tgithub.com/imdario/mergo v0.3.13 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/json-iterator/go v1.1.12 // indirect\n\tgithub.com/mailru/easyjson v0.7.7 // indirect\n\tgithub.com/miekg/pkcs11 v1.1.1 // indirect\n\tgithub.com/mitchellh/go-homedir v1.1.0 // indirect\n\tgithub.com/moby/sys/mountinfo v0.7.2 // indirect\n\tgithub.com/moby/sys/sequential v0.6.0 // indirect\n\tgithub.com/moby/sys/signal v0.7.1 // indirect\n\tgithub.com/moby/sys/user v0.3.0 // indirect\n\tgithub.com/moby/sys/userns v0.1.0 // indirect\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect\n\tgithub.com/modern-go/reflect2 v1.0.2 // indirect\n\tgithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect\n\tgithub.com/opencontainers/selinux v1.13.1 // indirect\n\tgithub.com/pelletier/go-toml/v2 v2.2.3 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.0 // indirect\n\tgithub.com/prometheus/common v0.55.0 // indirect\n\tgithub.com/prometheus/procfs v0.15.1 // indirect\n\tgithub.com/russross/blackfriday/v2 v2.1.0 // indirect\n\tgithub.com/smallstep/pkcs7 v0.1.1 // indirect\n\tgithub.com/spf13/pflag v1.0.5 // indirect\n\tgithub.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect\n\tgithub.com/vbatts/tar-split v0.11.5 // indirect\n\tgithub.com/x448/float16 v0.8.4 // indirect\n\tgithub.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect\n\tgo.opencensus.io v0.24.0 // indirect\n\tgo.opentelemetry.io/auto/sdk v1.2.1 // indirect\n\tgo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect\n\tgo.opentelemetry.io/otel/metric v1.39.0 // indirect\n\tgo.opentelemetry.io/otel/trace v1.39.0 // indirect\n\tgolang.org/x/crypto v0.50.0 // indirect\n\tgolang.org/x/net v0.53.0 // indirect\n\tgolang.org/x/oauth2 v0.36.0 // indirect\n\tgolang.org/x/term v0.42.0 // indirect\n\tgolang.org/x/text v0.36.0 // indirect\n\tgolang.org/x/time v0.12.0 // indirect\n\tgoogle.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect\n\tgoogle.golang.org/protobuf v1.36.10 // indirect\n\tgopkg.in/inf.v0 v0.9.1 // indirect\n\tgopkg.in/yaml.v2 v2.4.0 // indirect\n\tgopkg.in/yaml.v3 v3.0.1 // indirect\n\tk8s.io/klog/v2 v2.130.1 // indirect\n\tk8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect\n\tsigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect\n\tsigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect\n)\n\nretract (\n\tv0.11.3\n\tv0.11.2\n\tv0.11.1\n\tv0.11.0\n\tv0.3.0 // retagged: cd604c1b597558ea045a79c4f80a8c780909801b -> 85653575c7dafb6b06548478ee1dc61ac5905d00\n)\n\nexclude (\n\t// These dependencies were updated to \"master\" in some modules we depend on,\n\t// but have no code-changes since their last release. Unfortunately, this also\n\t// causes a ripple effect, forcing all users of the containerd module to also\n\t// update these dependencies to an unrelease / un-tagged version.\n\t//\n\t// Both these dependencies will unlikely do a new release in the near future,\n\t// so exclude these versions so that we can downgrade to the current release.\n\t//\n\t// For additional details, see this PR and links mentioned in that PR:\n\t// https://github.com/kubernetes-sigs/kustomize/pull/5830#issuecomment-2569960859\n\tgithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc\n\tgithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2\n)\n"
  },
  {
    "path": "go.sum",
    "content": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ndario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=\ndario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=\ngithub.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=\ngithub.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=\ngithub.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 h1:dIScnXFlF784X79oi7MzVT6GWqr/W1uUt0pB5CsDs9M=\ngithub.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2/go.mod h1:gCLVsLfv1egrcZu+GoJATN5ts75F2s62ih/457eWzOw=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/KarpelesLab/reflink v1.0.1 h1:d+tdjliwOCqvub9bl0Y02GxahWkNqejNb3TZTTUcQWA=\ngithub.com/KarpelesLab/reflink v1.0.1/go.mod h1:WGkTOKNjd1FsJKBw3mu4JvrPEDJyJJ+JPtxBkbPoCok=\ngithub.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=\ngithub.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=\ngithub.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=\ngithub.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y=\ngithub.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g=\ngithub.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=\ngithub.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY=\ngithub.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=\ngithub.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o=\ngithub.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI=\ngithub.com/aws/aws-sdk-go-v2/config v1.32.15 h1:i7rHbaySnBXGvCkDndaBU8f3EAlRVgViwNfkwFUrXgE=\ngithub.com/aws/aws-sdk-go-v2/config v1.32.15/go.mod h1:yLJzL0IkI9+4BwjPSOueyHzppJj3t0dhK5tbmmcFk5Q=\ngithub.com/aws/aws-sdk-go-v2/credentials v1.19.14 h1:n+UcGWAIZHkXzYt87uMFBv/l8THYELoX6gVcUvgl6fI=\ngithub.com/aws/aws-sdk-go-v2/credentials v1.19.14/go.mod h1:cJKuyWB59Mqi0jM3nFYQRmnHVQIcgoxjEMAbLkpr62w=\ngithub.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 h1:NUS3K4BTDArQqNu2ih7yeDLaS3bmHD0YndtA6UP884g=\ngithub.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21/go.mod h1:YWNWJQNjKigKY1RHVJCuupeWDrrHjRqHm0N9rdrWzYI=\ngithub.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.1.16 h1:n8TmP5vlknh1B/mVNrNgQfSvQy0isR9B9IgADdwuhhY=\ngithub.com/aws/aws-sdk-go-v2/feature/s3/transfermanager v0.1.16/go.mod h1:Iu9wL4lqscFF6ByhqyDO8mgvCUwGn5bqWr7fuOgUjTA=\ngithub.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4=\ngithub.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c=\ngithub.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A=\ngithub.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps=\ngithub.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ=\ngithub.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y=\ngithub.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY=\ngithub.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI=\ngithub.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM=\ngithub.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM=\ngithub.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto=\ngithub.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA=\ngithub.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM=\ngithub.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ=\ngithub.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 h1:hlSuz394kV0vhv9drL5lhuEFbEOEP1VyQpy15qWh1Pk=\ngithub.com/aws/aws-sdk-go-v2/service/s3 v1.99.0/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM=\ngithub.com/aws/aws-sdk-go-v2/service/signin v1.0.9 h1:QKZH0S178gCmFEgst8hN0mCX1KxLgHBKKY/CLqwP8lg=\ngithub.com/aws/aws-sdk-go-v2/service/signin v1.0.9/go.mod h1:7yuQJoT+OoH8aqIxw9vwF+8KpvLZ8AWmvmUWHsGQZvI=\ngithub.com/aws/aws-sdk-go-v2/service/sso v1.30.15 h1:lFd1+ZSEYJZYvv9d6kXzhkZu07si3f+GQ1AaYwa2LUM=\ngithub.com/aws/aws-sdk-go-v2/service/sso v1.30.15/go.mod h1:WSvS1NLr7JaPunCXqpJnWk1Bjo7IxzZXrZi1QQCkuqM=\ngithub.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19 h1:dzztQ1YmfPrxdrOiuZRMF6fuOwWlWpD2StNLTceKpys=\ngithub.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.19/go.mod h1:YO8TrYtFdl5w/4vmjL8zaBSsiNp3w0L1FfKVKenZT7w=\ngithub.com/aws/aws-sdk-go-v2/service/sts v1.41.10 h1:p8ogvvLugcR/zLBXTXrTkj0RYBUdErbMnAFFp12Lm/U=\ngithub.com/aws/aws-sdk-go-v2/service/sts v1.41.10/go.mod h1:60dv0eZJfeVXfbT1tFJinbHrDfSJ2GZl4Q//OSSNAVw=\ngithub.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng=\ngithub.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=\ngithub.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=\ngithub.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=\ngithub.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y=\ngithub.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs=\ngithub.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=\ngithub.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=\ngithub.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=\ngithub.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=\ngithub.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=\ngithub.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=\ngithub.com/containerd/containerd/v2 v2.0.7 h1:55JsNhqP/L7VZOijyfq6Qn0O8Oeff0UizfRuP+2pc90=\ngithub.com/containerd/containerd/v2 v2.0.7/go.mod h1:su8B0Z1NFQMEIztOIbHwy7xtznbCms/kFlfsxIcQrZ8=\ngithub.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=\ngithub.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=\ngithub.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=\ngithub.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=\ngithub.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=\ngithub.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=\ngithub.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=\ngithub.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=\ngithub.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=\ngithub.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=\ngithub.com/containerd/nri v0.8.0 h1:n1S753B9lX8RFrHYeSgwVvS1yaUcHjxbB+f+xzEncRI=\ngithub.com/containerd/nri v0.8.0/go.mod h1:uSkgBrCdEtAiEz4vnrq8gmAC4EnVAM5Klt0OuK5rZYQ=\ngithub.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=\ngithub.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=\ngithub.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=\ngithub.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=\ngithub.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319 h1:Td/dlhRp/kIk9W1rjXHSL87zZZiBQaKPV18OnoEREUA=\ngithub.com/containerd/stargz-snapshotter v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:dgo5lVziOOnWX8SxxHqYuc8ShsQou54eKLdahxFlHVc=\ngithub.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319 h1:BRxgmkGWi5vAvajiCwEK+xit4FeFU3GRjbiX4DKTLtM=\ngithub.com/containerd/stargz-snapshotter/estargz v0.15.2-0.20240709063920-1dac5ef89319/go.mod h1:9WSor0wu2swhtYoFkrjy3GHt7aNgKR2A7FhnpP+CH5o=\ngithub.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=\ngithub.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=\ngithub.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=\ngithub.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=\ngithub.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM=\ngithub.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ=\ngithub.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=\ngithub.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48=\ngithub.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=\ngithub.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=\ngithub.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM=\ngithub.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=\ngithub.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=\ngithub.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=\ngithub.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=\ngithub.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=\ngithub.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=\ngithub.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=\ngithub.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=\ngithub.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=\ngithub.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=\ngithub.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=\ngithub.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=\ngithub.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=\ngithub.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=\ngithub.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=\ngithub.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=\ngithub.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db h1:StM6A9LvaVrFS2chAGcfRVDoBB6rHYPIGJ3GknpB25c=\ngithub.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db/go.mod h1:pwuQfHWn6j2Fpl2AWw/bPLlKfojHxIIEa5TeKIgDFW4=\ngithub.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=\ngithub.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=\ngithub.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=\ngithub.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=\ngithub.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=\ngithub.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=\ngithub.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=\ngithub.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=\ngithub.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=\ngithub.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=\ngithub.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=\ngithub.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=\ngithub.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=\ngithub.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=\ngithub.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=\ngithub.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=\ngithub.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=\ngithub.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=\ngithub.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=\ngithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=\ngithub.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=\ngithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=\ngithub.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=\ngithub.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=\ngithub.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=\ngithub.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=\ngithub.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=\ngithub.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=\ngithub.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=\ngithub.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=\ngithub.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=\ngithub.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\ngithub.com/google/go-containerregistry v0.20.1 h1:eTgx9QNYugV4DN5mz4U8hiAGTi1ybXn0TPi4Smd8du0=\ngithub.com/google/go-containerregistry v0.20.1/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=\ngithub.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=\ngithub.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=\ngithub.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=\ngithub.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=\ngithub.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=\ngithub.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=\ngithub.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=\ngithub.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=\ngithub.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=\ngithub.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=\ngithub.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=\ngithub.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=\ngithub.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=\ngithub.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=\ngithub.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=\ngithub.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=\ngithub.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=\ngithub.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=\ngithub.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=\ngithub.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=\ngithub.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=\ngithub.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=\ngithub.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=\ngithub.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=\ngithub.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=\ngithub.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=\ngithub.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=\ngithub.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=\ngithub.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=\ngithub.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=\ngithub.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5XtQ50mQp8=\ngithub.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=\ngithub.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=\ngithub.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=\ngithub.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=\ngithub.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/onsi/ginkgo/v2 v2.19.1 h1:QXgq3Z8Crl5EL1WBAC98A5sEBHARrAJNzAmMxzLcRF0=\ngithub.com/onsi/ginkgo/v2 v2.19.1/go.mod h1:O3DtEWQkPa/F7fBMgmZQKKsluAy8pd3rEQdrjkPb9zA=\ngithub.com/onsi/gomega v1.34.0 h1:eSSPsPNp6ZpsG8X1OVmOTxig+CblTc4AxpPBykhe2Os=\ngithub.com/onsi/gomega v1.34.0/go.mod h1:MIKI8c+f+QLWk+hxbePD4i0LMJSExPaZOVfkoex4cAo=\ngithub.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=\ngithub.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=\ngithub.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=\ngithub.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=\ngithub.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=\ngithub.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=\ngithub.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE=\ngithub.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg=\ngithub.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=\ngithub.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=\ngithub.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=\ngithub.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=\ngithub.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=\ngithub.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=\ngithub.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=\ngithub.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=\ngithub.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=\ngithub.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=\ngithub.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=\ngithub.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=\ngithub.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=\ngithub.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=\ngithub.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=\ngithub.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=\ngithub.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=\ngithub.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU=\ngithub.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA=\ngithub.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw=\ngithub.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngithub.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=\ngithub.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=\ngithub.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=\ngithub.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=\ngithub.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=\ngithub.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=\ngithub.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=\ngithub.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=\ngithub.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=\ngithub.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=\ngo.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=\ngo.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=\ngo.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=\ngo.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=\ngo.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=\ngo.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=\ngo.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=\ngo.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=\ngo.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=\ngo.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=\ngo.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=\ngo.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=\ngo.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=\ngo.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=\ngo.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=\ngo.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=\ngo.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=\ngo.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=\ngolang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=\ngolang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=\ngolang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=\ngolang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=\ngolang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=\ngolang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc h1:TS73t7x3KarrNd5qAipmspBDS1rkMcgVG/fS1aRb4Rc=\ngolang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc=\ngolang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=\ngolang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=\ngolang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=\ngolang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=\ngolang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=\ngolang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=\ngolang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=\ngolang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=\ngolang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=\ngolang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=\ngolang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=\ngolang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=\ngolang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=\ngolang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=\ngolang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=\ngolang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=\ngolang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=\ngolang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=\ngolang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=\ngolang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=\ngolang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=\ngolang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=\ngolang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=\ngolang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=\ngolang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=\ngolang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=\ngolang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngolang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=\ngolang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=\ngolang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=\ngolang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=\ngolang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=\ngolang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=\ngolang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=\ngolang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=\ngolang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=\ngolang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=\ngolang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=\ngolang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s=\ngolang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=\ngonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=\ngoogle.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=\ngoogle.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=\ngoogle.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=\ngoogle.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=\ngoogle.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=\ngoogle.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=\ngoogle.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=\ngoogle.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=\ngoogle.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=\ngoogle.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=\ngoogle.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=\ngoogle.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=\ngoogle.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=\ngoogle.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=\ngoogle.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=\ngoogle.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=\ngopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=\ngopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=\ngopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=\ngopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=\ngotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=\ngotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=\ngotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=\nhonnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nk8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0=\nk8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk=\nk8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw=\nk8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=\nk8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc=\nk8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs=\nk8s.io/component-base v0.31.2 h1:Z1J1LIaC0AV+nzcPRFqfK09af6bZ4D1nAOpWsy9owlA=\nk8s.io/component-base v0.31.2/go.mod h1:9PeyyFN/drHjtJZMCTkSpQJS3U9OXORnHQqMLDz0sUQ=\nk8s.io/cri-api v0.31.2 h1:O/weUnSHvM59nTio0unxIUFyRHMRKkYn96YDILSQKmo=\nk8s.io/cri-api v0.31.2/go.mod h1:Po3TMAYH/+KrZabi7QiwQI4a692oZcUOUThd/rqwxrI=\nk8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=\nk8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=\nk8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=\nk8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=\nk8s.io/kubelet v0.31.2 h1:6Hytyw4LqWqhgzoi7sPfpDGClu2UfxmPmaiXPC4FRgI=\nk8s.io/kubelet v0.31.2/go.mod h1:0E4++3cMWi2cJxOwuaQP3eMBa7PSOvAFgkTPlVc/2FA=\nk8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=\nk8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=\nsigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=\nsigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=\nsigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=\nsigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=\nsigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=\nsigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=\n"
  },
  {
    "path": "integration/Dockerfile",
    "content": "ARG CONTAINERD_VER=2.0.0-rc.3\nARG CONTAINERD_PROJECT=/containerd\nARG RUNC_VER=1.1.4\nARG NYDUS_SNAPSHOTTER_PROJECT=/nydus-snapshotter\nARG DOWNLOADS_MIRROR=\"https://github.com\"\nARG NYDUS_VER=2.3.0\nARG NERDCTL_VER=1.7.6\nARG DELVE_VER=1.23.0\nARG GO_VER=1.24.0-bookworm\n\nFROM golang:$GO_VER AS golang-base\nARG TARGETARCH\nARG CONTAINERD_VER\nARG CONTAINERD_PROJECT\nARG RUNC_VER\nARG NYDUS_SNAPSHOTTER_PROJECT\nARG DOWNLOADS_MIRROR\nARG NYDUS_VER\nARG NERDCTL_VER\nARG DELVE_VER\n\n# RUN echo '\\\n# deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free\\n\\\n# deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free\\n\\\n# deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free\\n\\\n# deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bullseye-security main contrib non-free\\n' > /etc/apt/sources.list\n\nRUN apt-get update -qq && apt-get install -qq libbtrfs-dev libseccomp-dev sudo psmisc jq lsof net-tools\n\nRUN go install github.com/go-delve/delve/cmd/dlv@v\"$DELVE_VER\"\n\n# Install containerd\nRUN wget -q \"$DOWNLOADS_MIRROR\"/containerd/containerd/releases/download/v\"$CONTAINERD_VER\"/containerd-\"$CONTAINERD_VER\"-linux-\"$TARGETARCH\".tar.gz && \\\n  tar xzf containerd-\"$CONTAINERD_VER\"-linux-\"$TARGETARCH\".tar.gz && \\\n  install -D -m 755 bin/* /usr/local/bin/\nCOPY misc/example/containerd-config.toml /etc/containerd/config.toml\n\n# Install runc\nRUN wget -q \"$DOWNLOADS_MIRROR\"/opencontainers/runc/releases/download/v\"$RUNC_VER\"/runc.\"$TARGETARCH\" && \\\n  install -D -m 755 runc.\"$TARGETARCH\" /usr/local/bin/runc\n\n# Install nydusd nydus-image\nRUN  wget -q \"$DOWNLOADS_MIRROR\"/dragonflyoss/nydus/releases/download/v\"$NYDUS_VER\"/nydus-static-v\"$NYDUS_VER\"-linux-\"$TARGETARCH\".tgz && \\\n  tar xzf nydus-static-v\"$NYDUS_VER\"-linux-\"$TARGETARCH\".tgz && \\\n  install -D -m 755 nydus-static/nydusd /usr/local/bin/nydusd && \\\n  install -D -m 755 nydus-static/nydus-image /usr/local/bin/nydus-image && \\\n  install -D -m 755 nydus-static/nydusctl /usr/local/bin/nydusctl\n\n# Install nerdctl\nRUN wget -q \"$DOWNLOADS_MIRROR\"/containerd/nerdctl/releases/download/v\"$NERDCTL_VER\"/nerdctl-\"$NERDCTL_VER\"-linux-\"$TARGETARCH\".tar.gz && \\\n  tar xzf nerdctl-\"$NERDCTL_VER\"-linux-\"$TARGETARCH\".tar.gz && \\\n  install -D -m 755 nerdctl /usr/local/bin/nerdctl\n\n# Install fscache driver configuration file\nCOPY misc/snapshotter/nydusd-config.fscache.json /etc/nydus/nydusd-config.fscache.json\nCOPY misc/snapshotter/nydusd-config-localfs.json /etc/nydus/nydusd-config-localfs.json\nCOPY misc/snapshotter/config.toml /etc/nydus/config.toml\n\nVOLUME [ \"/var/lib\" ]\n\nCOPY integration/entrypoint.sh /\n\nWORKDIR /nydus-snapshotter\n\nENV PATH=\"${PATH}:/usr/local/bin/\"\n\n# Prevent git from complaining about ownership\nRUN git config --global --add safe.directory /nydus-snapshotter\n\nENTRYPOINT [ \"/bin/bash\",  \"-c\",  \"make install && /entrypoint.sh\"]\n"
  },
  {
    "path": "integration/entrypoint.sh",
    "content": "#!/bin/bash\n\n# Copyright (c) 2022. Nydus Developers. All rights reserved.\n#\n# SPDX-License-Identifier: Apache-2.0\n\nset -eEuo pipefail\n\nFSCACHE_NYDUSD_CONFIG=/etc/nydus/nydusd-config.fscache.json\nFUSE_NYDUSD_LOCALFS_CONFIG=/etc/nydus/nydusd-config-localfs.json\nSNAPSHOTTER_CONFIG=/etc/nydus/config.toml\n\nCONTAINERD_ROOT=/var/lib/containerd/\nCONTAINERD_STATUS=/run/containerd/\nREMOTE_SNAPSHOTTER_SOCKET=/run/containerd-nydus/containerd-nydus-grpc.sock\nREMOTE_SNAPSHOTTER_ROOT=/var/lib/containerd/io.containerd.snapshotter.v1.nydus\nCONTAINERD_SOCKET=/run/containerd/containerd.sock\nSNAPSHOTTER_SHARED_MNT=${REMOTE_SNAPSHOTTER_ROOT}/mnt\nSNAPSHOTTER_CACHE_DIR=${REMOTE_SNAPSHOTTER_ROOT}/cache\n\nJAVA_IMAGE=${JAVA_IMAGE:-ghcr.io/dragonflyoss/image-service/java:nydus-nightly-v6}\nWORDPRESS_IMAGE=${WORDPRESS_IMAGE:-ghcr.io/dragonflyoss/image-service/wordpress:nydus-nightly-v6}\nTOMCAT_IMAGE=${TOMCAT_IMAGE:-ghcr.io/dragonflyoss/image-service/tomcat:nydus-nightly-v5}\nSTARGZ_IMAGE=${STARGZ_IMAGE:-ghcr.io/stargz-containers/wordpress:5.9.2-esgz}\nREDIS_OCI_IMAGE=${REDIS_OCI_IMAGE:-ghcr.io/stargz-containers/redis:6.2.6-org}\nWORDPRESS_OCI_IMAGE=${WORDPRESS_OCI_IMAGE:-ghcr.io/dragonflyoss/image-service/wordpress:latest}\n\nPLUGIN=nydus\n\nRETRYNUM=30\nRETRYINTERVAL=1\nTIMEOUTSEC=180\n\nGORACE_REPORT=\"$(pwd)/go_race_report\"\nexport GORACE=\"log_path=${GORACE_REPORT}\"\n\n# trap \"{ pause 1000; }\" ERR\n\nfunction detect_go_race {\n    if [ -n \"$(ls -A ${GORACE_REPORT}.* 2>/dev/null)\" ]; then\n        echo \"go race detected\"\n        reports=$(ls -A ${GORACE_REPORT}.* 2>/dev/null)\n        for r in ${reports}; do\n            cat \"$r\"\n        done\n        exit 1\n    fi\n}\n\nfunction stop_all_containers {\n    containers=$(nerdctl ps -q | tr '\\n' ' ')\n    if [[ ${containers} == \"\" ]]; then\n        return 0\n    else\n        echo \"Killing containers ${containers}\"\n        for C in ${containers}; do\n            nerdctl kill \"${C}\" || true\n            nerdctl stop \"${C}\" || true\n            nerdctl rm \"${C}\" || true\n        done\n        return 1\n    fi\n}\n\nfunction pause {\n    echo \"I am going to wait for ${1} seconds only ...\"\n    sleep \"${1}\"\n}\n\nfunction func_retry {\n    local SUCCESS=false\n    for i in $(seq ${RETRYNUM}); do\n        if \"${*}\"; then\n            SUCCESS=true\n            break\n        fi\n        echo \"Fail(${i}). Retrying function...\"\n        sleep ${RETRYINTERVAL}\n    done\n    if [ \"${SUCCESS}\" == \"true\" ]; then\n        return 0\n    else\n        return 1\n    fi\n}\n\nfunction retry {\n    local SUCCESS=false\n    for i in $(seq ${RETRYNUM}); do\n        if eval \"timeout ${TIMEOUTSEC} ${@}\"; then\n            SUCCESS=true\n            break\n        fi\n        echo \"Fail(${i}). Retrying...\"\n        sleep ${RETRYINTERVAL}\n    done\n    if [ \"${SUCCESS}\" == \"true\" ]; then\n        return 0\n    else\n        return 1\n    fi\n}\n\nfunction can_erofs_ondemand_read {\n    return 1\n    # grep 'CONFIG_EROFS_FS_ONDEMAND=[ym]' /usr/src/linux-headers-\"$(uname -r)\"/.config 1>/dev/null\n    # echo $?\n}\n\nfunction validate_mnt_number {\n    expected=\"${1}\"\n    found=$(mount -t fuse | wc -l)\n    if [[ $found != \"$expected\" ]]; then\n        echo \"expecting $expected mountpoints, but found $found\"\n        return 1\n    else\n        return 0\n    fi\n}\n\nfunction set_config_option {\n    KEY=\"${1}\"\n    VALUE=\"${2}\"\n\n    sed -i \"s/\\($KEY *= *\\).*/\\1$VALUE/\" \"${SNAPSHOTTER_CONFIG}\"\n}\n\nfunction set_recover_policy {\n    policy=\"${1}\"\n\n    set_config_option \"recover_policy\" \\\"${policy}\\\"\n}\n\nfunction set_enable_referrer_detect {\n    set_config_option \"enable_referrer_detect\" \"true\"\n}\n\nfunction reboot_containerd {\n    killall \"containerd\" || true\n    killall \"containerd-nydus-grpc\" || true\n    # In case nydusd is using cache dir\n    killall \"nydusd\" || true\n\n    # Let snapshotter shutdown all its services.\n    sleep 2\n\n    # FIXME\n    echo \"umount globally shared mountpoint\"\n    umount_global_shared_mnt\n\n    rm -rf \"${CONTAINERD_STATUS}\"*\n    rm -rf \"${CONTAINERD_ROOT}\"*\n    if [ -f \"${REMOTE_SNAPSHOTTER_SOCKET}\" ]; then\n        rm \"${REMOTE_SNAPSHOTTER_SOCKET}\"\n    fi\n\n    local daemon_mode=${1}\n    local fs_driver=${2:-fusedev}\n    local recover_policy=${3:-none}\n\n    if [ -d \"${REMOTE_SNAPSHOTTER_ROOT:?}/snapshotter/snapshots/\" ]; then\n        umount -t fuse --all\n    fi\n\n    if [[ \"${fs_driver}\" == fusedev ]]; then\n        nydusd_config=/etc/nydus/nydusd-config.json\n    else\n        nydusd_config=\"$FSCACHE_NYDUSD_CONFIG\"\n    fi\n\n    # Override nydus configuration, this configuration is usually set by each case\n    if [[ -n ${NYDUS_CONFIG_PATH:-} ]]; then\n        nydusd_config=${NYDUS_CONFIG_PATH}\n    fi\n\n    # rm -rf \"${REMOTE_SNAPSHOTTER_ROOT:?}\"/* || fuser -m \"${REMOTE_SNAPSHOTTER_ROOT}/mnt\" && false\n    rm -rf \"${REMOTE_SNAPSHOTTER_ROOT:?}\"/*\n\n    set_recover_policy \"${recover_policy}\"\n\n    containerd-nydus-grpc --log-to-stdout \\\n        --daemon-mode \"${daemon_mode}\" --fs-driver \"${fs_driver}\" \\\n        --config \"${SNAPSHOTTER_CONFIG}\" --nydusd-config \"${nydusd_config}\" &\n\n    retry ls \"${REMOTE_SNAPSHOTTER_SOCKET}\"\n    containerd --log-level info --config=/etc/containerd/config.toml &\n    retry ls \"${CONTAINERD_SOCKET}\"\n\n    # Makes sure containerd and containerd-nydus-grpc are up-and-running.\n    UNIQUE_SUFFIX=$(date +%s%N | shasum | base64 | fold -w 10 | head -1)\n    retry ctr snapshots --snapshotter=\"${PLUGIN}\" prepare \"connectiontest-dummy-${UNIQUE_SUFFIX}\" \"\"\n}\n\nfunction restart_snapshotter {\n    killall -INT containerd-nydus-grpc\n    local daemon_mode=$1\n}\n\nfunction umount_global_shared_mnt {\n    umount \"${SNAPSHOTTER_SHARED_MNT}\" || true\n}\n\nfunction is_cache_cleared {\n    # With fscache driver, 2.1 nydusd don't have API to release the cache files.\n    # Thy locate at directory ${SNAPSHOTTER_CACHE_DIR}/cache\n    if [[ $(ls -A -p \"${SNAPSHOTTER_CACHE_DIR}\" | grep -v /) == \"\" ]]; then\n        true\n    else\n        echo \"ERROR: Cache is not cleared\"\n        false\n    fi\n}\n\nfunction nerdctl_prune_images {\n    # Wait for containers observation.\n    sleep 1\n    func_retry stop_all_containers\n    nerdctl container prune -f\n    nerdctl image prune --all -f\n    nerdctl images\n    is_cache_cleared\n}\n\nfunction start_single_container_multiple_daemons {\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd multiple\n\n    nerdctl --snapshotter nydus run -d --net none \"${JAVA_IMAGE}\"\n\n    detect_go_race\n}\n\nfunction start_multiple_containers_multiple_daemons {\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd multiple\n\n    nerdctl --snapshotter nydus run -d --net none \"${JAVA_IMAGE}\"\n    nerdctl --snapshotter nydus run -d --net none \"${WORDPRESS_IMAGE}\"\n    nerdctl --snapshotter nydus run -d --net none \"${TOMCAT_IMAGE}\"\n\n    nerdctl_prune_images\n\n    nerdctl --snapshotter nydus run -d --net none \"${TOMCAT_IMAGE}\"\n    nerdctl --snapshotter nydus run -d --net none \"${JAVA_IMAGE}\"\n    nerdctl --snapshotter nydus run -d --net none \"${WORDPRESS_IMAGE}\"\n\n    detect_go_race\n}\n\nfunction start_multiple_containers_shared_daemon {\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd shared\n\n    nerdctl --snapshotter nydus run -d --net none \"${JAVA_IMAGE}\"\n    nerdctl --snapshotter nydus run -d --net none \"${WORDPRESS_IMAGE}\"\n    nerdctl --snapshotter nydus run -d --net none \"${TOMCAT_IMAGE}\"\n\n    detect_go_race\n}\n\nfunction start_single_container_on_stargz {\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd multiple\n\n    killall \"containerd-nydus-grpc\" || true\n    sleep 2\n\n    containerd-nydus-grpc --enable-stargz --daemon-mode multiple --fs-driver fusedev \\\n        --recover-policy none --log-to-stdout --config-path /etc/nydus/nydusd-config.json &\n\n    nerdctl --snapshotter nydus run -d --net none \"${STARGZ_IMAGE}\"\n    detect_go_race\n}\n\nfunction start_container_on_oci {\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd multiple\n\n    nerdctl --snapshotter nydus run -d --net none \"${REDIS_OCI_IMAGE}\"\n    nerdctl --snapshotter nydus run -d --net none \"${WORDPRESS_OCI_IMAGE}\"\n    pause 2\n\n    func_retry stop_all_containers\n\n    # Deleteing with flag --async as a fuzzer\n    nerdctl image rm --async --force \"${REDIS_OCI_IMAGE}\"\n    nerdctl image rm --force \"${WORDPRESS_OCI_IMAGE}\"\n}\n\nfunction start_container_with_referrer_detect {\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd multiple\n\n    set_enable_referrer_detect\n    nerdctl --snapshotter nydus run -d --net none \"${WORDPRESS_OCI_IMAGE}\"\n\n    detect_go_race\n}\n\nfunction pull_remove_one_image {\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd multiple\n\n    nerdctl --snapshotter nydus image pull \"${JAVA_IMAGE}\"\n    nerdctl --snapshotter nydus image rm \"${JAVA_IMAGE}\"\n\n    detect_go_race\n}\n\nfunction pull_remove_multiple_images {\n    local daemon_mode=$1\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd \"${daemon_mode}\"\n\n    # Because nydusd is not started right after image pull.\n    # Nydusd is started when preparing the writable active snapshot as the\n    # uppermost layer. So we must create a container to start nydusd.\n    # Then to test if snapshotter's nydusd daemons management works well\n\n    nerdctl --snapshotter nydus image pull \"${JAVA_IMAGE}\"\n    nerdctl --snapshotter nydus image pull \"${WORDPRESS_IMAGE}\"\n    nerdctl --snapshotter nydus image pull \"${TOMCAT_IMAGE}\"\n\n    nerdctl --snapshotter nydus create --rm --net none \"${TOMCAT_IMAGE}\"\n    nerdctl --snapshotter nydus create --rm --net none \"${WORDPRESS_IMAGE}\"\n\n    nerdctl --snapshotter nydus image rm --force \"${JAVA_IMAGE}\"\n    nerdctl --snapshotter nydus image rm --force \"${WORDPRESS_IMAGE}\"\n\n    # Deleteing with flag --async as a fuzzer\n    nerdctl --snapshotter nydus image rm --force --async \"${TOMCAT_IMAGE}\"\n    nerdctl --snapshotter nydus image pull \"${TOMCAT_IMAGE}\"\n    nerdctl --snapshotter nydus create --net none \"${TOMCAT_IMAGE}\"\n\n    detect_go_race\n\n    # TODO: Validate running nydusd number\n}\n\nfunction start_multiple_containers_shared_daemon_fscache {\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd shared fscache\n\n    nerdctl --snapshotter nydus run -d --net none \"${JAVA_IMAGE}\"\n    nerdctl --snapshotter nydus run -d --net none \"${WORDPRESS_IMAGE}\"\n\n    detect_go_race\n}\n\nfunction kill_snapshotter_and_nydusd_recover {\n    local daemon_mode=$1\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd \"${daemon_mode}\"\n\n    nerdctl --snapshotter nydus image pull \"${WORDPRESS_IMAGE}\"\n    nerdctl --snapshotter nydus image pull \"${JAVA_IMAGE}\"\n    c1=$(nerdctl --snapshotter nydus create --net none \"${JAVA_IMAGE}\")\n    c2=$(nerdctl --snapshotter nydus create --net none \"${WORDPRESS_IMAGE}\")\n\n    sleep 1\n\n    echo \"killing nydusd\"\n    killall -9 nydusd || true\n\n    echo \"killing nydus-snapshotter\"\n    killall -9 containerd-nydus-grpc || true\n\n    rm \"${REMOTE_SNAPSHOTTER_SOCKET:?}\"\n    containerd-nydus-grpc --config \"${SNAPSHOTTER_CONFIG}\" \\\n        --daemon-mode \"${daemon_mode}\" --log-to-stdout --config-path /etc/nydus/nydusd-config.json &\n    retry ls \"${REMOTE_SNAPSHOTTER_SOCKET}\"\n\n    echo \"start new containers\"\n    nerdctl --snapshotter nydus start \"$c1\"\n    nerdctl --snapshotter nydus start \"$c2\"\n\n    detect_go_race\n}\n\n# No restart or failover recover policy. Just let snapshotter start a new nydusd when it refreshes.\nfunction fscache_kill_snapshotter_and_nydusd_recover {\n    local daemon_mode=$1\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd \"${daemon_mode}\" fscache\n\n    nerdctl --snapshotter nydus image pull \"${WORDPRESS_IMAGE}\"\n    nerdctl --snapshotter nydus image pull \"${JAVA_IMAGE}\"\n    c1=$(nerdctl --snapshotter nydus create --net none \"${JAVA_IMAGE}\")\n    c2=$(nerdctl --snapshotter nydus create --net none \"${WORDPRESS_IMAGE}\")\n\n    sleep 1\n\n    echo \"killing nydusd\"\n    killall -9 nydusd || true\n    killall -9 containerd-nydus-grpc || true\n\n    sleep 1\n\n    rm \"${REMOTE_SNAPSHOTTER_SOCKET:?}\"\n    containerd-nydus-grpc --log-to-stdout --config \"${SNAPSHOTTER_CONFIG}\" \\\n        --daemon-mode \"${daemon_mode}\" --fs-driver fscache --config-path /etc/nydus/nydusd-config.fscache.json &\n    retry ls \"${REMOTE_SNAPSHOTTER_SOCKET}\"\n\n    echo \"start new containers\"\n    nerdctl --snapshotter nydus start \"$c1\"\n    nerdctl --snapshotter nydus start \"$c2\"\n\n    # killall -9 nydusd\n    sleep 0.2\n    detect_go_race\n}\n\nfunction fscache_kill_nydusd_failover() {\n    local daemon_mode=shared\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n    reboot_containerd \"${daemon_mode}\" fscache failover\n\n    nerdctl --snapshotter nydus image pull \"${WORDPRESS_IMAGE}\"\n    nerdctl --snapshotter nydus image pull \"${JAVA_IMAGE}\"\n    c1=$(nerdctl --snapshotter nydus create --net none \"${JAVA_IMAGE}\")\n    c2=$(nerdctl --snapshotter nydus create --net none \"${WORDPRESS_IMAGE}\")\n\n    killall -9 nydusd\n\n    echo \"start new containers\"\n    nerdctl --snapshotter nydus start \"$c1\"\n    nerdctl --snapshotter nydus start \"$c2\"\n\n    sleep 1\n\n    detect_go_race\n}\n\nfunction only_restart_snapshotter {\n    local daemon_mode=$1\n    echo \"testing $FUNCNAME ${daemon_mode}\"\n    nerdctl_prune_images\n    reboot_containerd \"${daemon_mode}\"\n\n    nerdctl --snapshotter nydus image pull \"${WORDPRESS_IMAGE}\"\n    nerdctl --snapshotter nydus image pull \"${JAVA_IMAGE}\"\n    c1=$(nerdctl --snapshotter nydus create --net none \"${JAVA_IMAGE}\")\n    c2=$(nerdctl --snapshotter nydus create --net none \"${WORDPRESS_IMAGE}\")\n\n    echo \"killing snapshotter\"\n    killall -9 containerd-nydus-grpc || true\n\n    rm \"${REMOTE_SNAPSHOTTER_SOCKET:?}\"\n    containerd-nydus-grpc --config \"${SNAPSHOTTER_CONFIG}\" --daemon-mode \\\n        \"${daemon_mode}\" --log-to-stdout --config-path /etc/nydus/nydusd-config.json &\n    retry ls \"${REMOTE_SNAPSHOTTER_SOCKET}\"\n\n    if [[ \"${daemon_mode}\" == \"shared\" ]]; then\n        validate_mnt_number 1\n    else\n        validate_mnt_number 2\n    fi\n\n    echo \"start new containers\"\n    nerdctl --snapshotter nydus start \"$c1\"\n    nerdctl --snapshotter nydus start \"$c2\"\n\n    detect_go_race\n}\n\nfunction kill_nydusd_recover_nydusd {\n    local daemon_mode=$1\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n\n    reboot_containerd \"${daemon_mode}\" fusedev restart\n\n    nerdctl --snapshotter nydus image pull \"${WORDPRESS_IMAGE}\"\n    nerdctl --snapshotter nydus image pull \"${JAVA_IMAGE}\"\n    c1=$(nerdctl --snapshotter nydus create --net none \"${JAVA_IMAGE}\")\n    c2=$(nerdctl --snapshotter nydus create --net none \"${WORDPRESS_IMAGE}\")\n\n    pause 1\n\n    echo \"killing nydusd\"\n    killall -9 nydusd || true\n\n    echo \"start new containers\"\n    nerdctl --snapshotter nydus start \"$c1\"\n    nerdctl --snapshotter nydus start \"$c2\"\n\n    detect_go_race\n}\n\nfunction ctr_snapshot_usage {\n    local daemon_mode=$1\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n\n    reboot_containerd \"${daemon_mode}\" fusedev restart\n\n    nerdctl --snapshotter nydus image pull \"${WORDPRESS_IMAGE}\"\n    nerdctl --snapshotter nydus image pull \"${JAVA_IMAGE}\"\n    c1=$(nerdctl --snapshotter nydus create --net none \"${JAVA_IMAGE}\")\n    c2=$(nerdctl --snapshotter nydus create --net none \"${WORDPRESS_IMAGE}\")\n\n    pause 1\n\n    ctr snapshot --snapshotter nydus ls\n    ctr snapshot --snapshotter nydus usage\n\n    echo \"start new containers\"\n    nerdctl --snapshotter nydus start \"$c1\"\n    nerdctl --snapshotter nydus start \"$c2\"\n\n    ctr snapshot --snapshotter nydus ls\n    ctr snapshot --snapshotter nydus usage\n\n    detect_go_race\n}\n\nfunction kill_multiple_nydusd_recover_failover {\n    local daemon_mode=$1\n    echo \"testing $FUNCNAME\"\n    nerdctl_prune_images\n\n    reboot_containerd \"${daemon_mode}\" fusedev failover\n\n    c1=$(nerdctl --snapshotter nydus run -d --net none \"${JAVA_IMAGE}\")\n    c2=$(nerdctl --snapshotter nydus run -d --net none \"${WORDPRESS_IMAGE}\")\n\n    pause 1\n\n    nerdctl kill \"$c1\" || true\n    nerdctl kill \"$c2 \" || true\n\n    echo \"killing nydusd\"\n    killall -9 nydusd || true\n\n    echo \"start new containers\"\n\n    c1=$(nerdctl --snapshotter nydus run -d --net none \"${JAVA_IMAGE}\")\n    c2=$(nerdctl --snapshotter nydus run -d --net none \"${WORDPRESS_IMAGE}\")\n\n    pause 1\n\n    nerdctl kill \"$c1\" || true\n    nerdctl kill \"$c2 \" || true\n\n    echo \"killing nydusd again\"\n    killall -9 nydusd || true\n\n    c1=$(nerdctl --snapshotter nydus run -d --net none \"${JAVA_IMAGE}\")\n    c2=$(nerdctl --snapshotter nydus run -d --net none \"${WORDPRESS_IMAGE}\")\n\n    detect_go_race\n}\n\n# Refer to https://github.com/moby/moby/blob/088afc99e4bf8adb78e29733396182417d67ada2/hack/dind#L28-L38\nfunction enable_nesting_for_cgroup_v2() {\n    if [ -f /sys/fs/cgroup/cgroup.controllers ]; then\n        mkdir -p /sys/fs/cgroup/init\n        xargs -rn1 </sys/fs/cgroup/cgroup.procs >/sys/fs/cgroup/init/cgroup.procs || :\n        sed -e 's/ / +/g' -e 's/^/-/' </sys/fs/cgroup/cgroup.controllers \\\n            >/sys/fs/cgroup/cgroup.subtree_control\n    fi\n}\n\nenable_nesting_for_cgroup_v2\n\nreboot_containerd multiple\n\nstart_single_container_multiple_daemons\nstart_multiple_containers_multiple_daemons\nstart_multiple_containers_shared_daemon\n\npull_remove_one_image\n\npull_remove_multiple_images shared\npull_remove_multiple_images multiple\n\n# start_single_container_on_stargz\n\nonly_restart_snapshotter shared\nonly_restart_snapshotter multiple\n\nkill_snapshotter_and_nydusd_recover shared\nkill_snapshotter_and_nydusd_recover multiple\n\nctr_snapshot_usage multiple\nctr_snapshot_usage shared\n\nif [[ $(can_erofs_ondemand_read) == 0 ]]; then\n    kill_multiple_nydusd_recover_failover multiple\n    kill_multiple_nydusd_recover_failover shared\n\n    start_multiple_containers_shared_daemon_fscache\n    fscache_kill_snapshotter_and_nydusd_recover shared\n    fscache_kill_nydusd_failover\nfi\n\nstart_container_on_oci\n\nstart_container_with_referrer_detect\n"
  },
  {
    "path": "internal/constant/values.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// constants of nydus snapshotter CLI config\n\npackage constant\n\nimport \"time\"\n\nconst (\n\tDaemonModeMultiple  string = \"multiple\"\n\tDaemonModeDedicated string = \"dedicated\"\n\tDaemonModeShared    string = \"shared\"\n\tDaemonModeNone      string = \"none\"\n\tDaemonModeInvalid   string = \"\"\n)\n\nconst (\n\t// Mount RAFS filesystem by using EROFS over block devices.\n\tFsDriverBlockdev string = \"blockdev\"\n\t// Mount RAFS filesystem by using FUSE subsystem\n\tFsDriverFusedev string = \"fusedev\"\n\t// Mount RAFS filesystem by using fscache/EROFS.\n\tFsDriverFscache string = \"fscache\"\n\t// Only prepare/supply meta/data blobs, do not mount RAFS filesystem.\n\tFsDriverNodev string = \"nodev\"\n\t// Relay layer content download operation to other agents.\n\tFsDriverProxy string = \"proxy\"\n)\n\nconst (\n\tDefaultDaemonMode = DaemonModeMultiple\n\n\tDefaultFsDriver = FsDriverFusedev\n\n\tDefaultLogLevel string = \"info\"\n\tDefaultGCPeriod        = 24 * time.Hour\n\n\tDefaultNydusDaemonConfigPath string = \"/etc/nydus/nydusd-config.json\"\n\tNydusdBinaryName             string = \"nydusd\"\n\tNydusImageBinaryName         string = \"nydus-image\"\n\n\tDefaultRootDir                 = \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\"\n\tDefaultAddress                 = \"/run/containerd-nydus/containerd-nydus-grpc.sock\"\n\tDefaultSystemControllerAddress = \"/run/containerd-nydus/system.sock\"\n\n\t// Log rotation\n\tDefaultDaemonRotateLogMaxSize = 100 // 100 megabytes\n\tDefaultRotateLogMaxSize       = 200 // 200 megabytes\n\tDefaultRotateLogMaxBackups    = 5\n\tDefaultRotateLogMaxAge        = 0 // days\n\tDefaultRotateLogLocalTime     = true\n\tDefaultRotateLogCompress      = true\n\n\t// metrics configuration\n\tDefaultHungIOInterval  = 10 * time.Second\n\tDefaultCollectInterval = 1 * time.Minute\n)\n\nconst (\n\tFailoverPolicyNone    string = \"none\"\n\tFailoverPolicyResend  string = \"resend\"\n\tFailoverPolicyFlush   string = \"flush\"\n\tDefaultFailoverPolicy string = FailoverPolicyResend\n)\n"
  },
  {
    "path": "internal/flags/flags.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage flags\n\nimport (\n\t\"github.com/containerd/nydus-snapshotter/internal/constant\"\n\t\"github.com/urfave/cli/v2\"\n)\n\ntype Args struct {\n\tAddress               string\n\tNydusdConfigPath      string\n\tSnapshotterConfigPath string\n\tRootDir               string\n\tNydusdPath            string\n\tNydusImagePath        string\n\tNydusOverlayFSPath    string\n\tDaemonMode            string\n\tFsDriver              string\n\tLogLevel              string\n\tLogToStdout           bool\n\tLogToStdoutCount      int\n\tPrintVersion          bool\n}\n\ntype Flags struct {\n\tArgs *Args\n\tF    []cli.Flag\n}\n\nfunc buildFlags(args *Args) []cli.Flag {\n\treturn []cli.Flag{\n\t\t&cli.StringFlag{\n\t\t\tName:        \"root\",\n\t\t\tUsage:       \"directory to store snapshotter data and working states\",\n\t\t\tDestination: &args.RootDir,\n\t\t\tDefaultText: constant.DefaultRootDir,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"address\",\n\t\t\tUsage:       \"remote snapshotter gRPC socket path\",\n\t\t\tDestination: &args.Address,\n\t\t\tDefaultText: constant.DefaultAddress,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"config\",\n\t\t\tUsage:       \"path to nydus-snapshotter configuration (such as: config.toml)\",\n\t\t\tDestination: &args.SnapshotterConfigPath,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"nydus-image\",\n\t\t\tUsage:       \"path to `nydus-image` binary, default to search in $PATH (such as: /usr/local/bin/nydus-image)\",\n\t\t\tDestination: &args.NydusImagePath,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"nydusd\",\n\t\t\tUsage:       \"path to `nydusd` binary, default to search in $PATH (such as: /usr/local/bin/nydusd)\",\n\t\t\tDestination: &args.NydusdPath,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"nydusd-config\",\n\t\t\tAliases:     []string{\"config-path\"},\n\t\t\tUsage:       \"path to nydusd configuration (such as: nydusd-config.json or nydusd-config-v2.toml)\",\n\t\t\tDestination: &args.NydusdConfigPath,\n\t\t\tDefaultText: constant.DefaultNydusDaemonConfigPath,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"nydus-overlayfs-path\",\n\t\t\tUsage:       \"path of nydus-overlayfs or name of binary from $PATH, defaults to 'nydus-overlayfs'\",\n\t\t\tDestination: &args.NydusOverlayFSPath,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"daemon-mode\",\n\t\t\tUsage:       \"nydusd daemon working mode, possible values: \\\"dedicated\\\", \\\"multiple\\\", \\\"shared\\\" or \\\"none\\\". \\\"multiple\\\" is an alias of \\\"dedicated\\\" and will be deprecated in v1.0\",\n\t\t\tDestination: &args.DaemonMode,\n\t\t\tDefaultText: constant.DaemonModeMultiple,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"fs-driver\",\n\t\t\tUsage:       \"driver to mount RAFS filesystem, possible values: \\\"fusedev\\\", \\\"fscache\\\"\",\n\t\t\tDestination: &args.FsDriver,\n\t\t\tDefaultText: constant.FsDriverFusedev,\n\t\t},\n\t\t&cli.StringFlag{\n\t\t\tName:        \"log-level\",\n\t\t\tUsage:       \"logging level, possible values: \\\"trace\\\", \\\"debug\\\", \\\"info\\\", \\\"warn\\\", \\\"error\\\"\",\n\t\t\tDestination: &args.LogLevel,\n\t\t\tDefaultText: constant.DefaultLogLevel,\n\t\t},\n\t\t&cli.BoolFlag{\n\t\t\tName:        \"log-to-stdout\",\n\t\t\tUsage:       \"print log messages to standard output\",\n\t\t\tDestination: &args.LogToStdout,\n\t\t\tCount:       &args.LogToStdoutCount,\n\t\t},\n\t\t&cli.BoolFlag{\n\t\t\tName:        \"version\",\n\t\t\tUsage:       \"print version and build information\",\n\t\t\tDestination: &args.PrintVersion,\n\t\t},\n\t}\n}\n\nfunc NewFlags() *Flags {\n\tvar args Args\n\treturn &Flags{\n\t\tArgs: &args,\n\t\tF:    buildFlags(&args),\n\t}\n}\n"
  },
  {
    "path": "internal/flags/flags_test.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage flags\n\nimport (\n\t\"flag\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestNewFlags(t *testing.T) {\n\tset := flag.NewFlagSet(\"test\", 0)\n\tflags := NewFlags()\n\tfor _, i := range flags.F {\n\t\terr := i.Apply(set)\n\t\tassert.Nil(t, err)\n\t}\n\terr := set.Parse([]string{\"--config-path\", \"/etc/testconfig\", \"--root\", \"/root\", \"--log-level\", \"info\"})\n\tassert.Nil(t, err)\n\tassert.Equal(t, flags.Args.NydusdConfigPath, \"/etc/testconfig\")\n\tassert.Equal(t, flags.Args.LogLevel, \"info\")\n\tassert.Equal(t, flags.Args.RootDir, \"/root\")\n}\n"
  },
  {
    "path": "internal/logging/setup.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage logging\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/sirupsen/logrus\"\n\tlumberjack \"gopkg.in/natefinch/lumberjack.v2\"\n)\n\nconst (\n\tDefaultLogDirName  = \"logs\"\n\tdefaultLogFileName = \"nydus-snapshotter.log\"\n)\n\ntype RotateLogArgs struct {\n\tRotateLogMaxSize    int\n\tRotateLogMaxBackups int\n\tRotateLogMaxAge     int\n\tRotateLogLocalTime  bool\n\tRotateLogCompress   bool\n}\n\nfunc SetUp(logLevel string, logToStdout bool, logDir string, logRotateArgs *RotateLogArgs) error {\n\tlvl, err := logrus.ParseLevel(logLevel)\n\tif err != nil {\n\t\treturn err\n\t}\n\tlogrus.SetLevel(lvl)\n\n\tif logToStdout {\n\t\tlogrus.SetOutput(os.Stdout)\n\t} else {\n\t\tif logRotateArgs == nil {\n\t\t\treturn errors.New(\"logRotateArgs is needed when logToStdout is false\")\n\t\t}\n\n\t\tif err := os.MkdirAll(logDir, 0755); err != nil {\n\t\t\treturn errors.Wrapf(err, \"create log dir %s\", logDir)\n\t\t}\n\t\tlogFile := filepath.Join(logDir, defaultLogFileName)\n\n\t\tlumberjackLogger := &lumberjack.Logger{\n\t\t\tFilename:   logFile,\n\t\t\tMaxSize:    logRotateArgs.RotateLogMaxSize,\n\t\t\tMaxBackups: logRotateArgs.RotateLogMaxBackups,\n\t\t\tMaxAge:     logRotateArgs.RotateLogMaxAge,\n\t\t\tCompress:   logRotateArgs.RotateLogCompress,\n\t\t\tLocalTime:  logRotateArgs.RotateLogLocalTime,\n\t\t}\n\t\tlogrus.SetOutput(lumberjackLogger)\n\t}\n\n\tlogrus.SetFormatter(&logrus.TextFormatter{\n\t\tTimestampFormat: log.RFC3339NanoFixed,\n\t\tFullTimestamp:   true,\n\t})\n\treturn nil\n}\n\nfunc WithContext() context.Context {\n\treturn log.WithLogger(context.Background(), log.L)\n}\n"
  },
  {
    "path": "internal/logging/setup_test.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage logging\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/sirupsen/logrus\"\n\t\"gotest.tools/assert\"\n)\n\nconst (\n\tTestLogDirName  = \"test-rotate-logs\"\n\tTestRootDirName = \"test-root\"\n)\n\nfunc GetRotateLogFileNumbers(testLogDir string, suffix string) int {\n\ti := 0\n\terr := filepath.Walk(testLogDir, func(fname string, fi os.FileInfo, _ error) error {\n\t\tif !fi.IsDir() && strings.HasSuffix(fname, suffix) {\n\t\t\ti++\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\tlog.L.Fatal(\"walk path\")\n\t}\n\treturn i\n}\n\nfunc TestSetUp(t *testing.T) {\n\t// Try to clean previously created test directory.\n\tos.RemoveAll(TestLogDirName)\n\n\tlogRotateArgs := &RotateLogArgs{\n\t\tRotateLogMaxSize:    1, // 1MB\n\t\tRotateLogMaxBackups: 5,\n\t\tRotateLogMaxAge:     0,\n\t\tRotateLogLocalTime:  true,\n\t\tRotateLogCompress:   true,\n\t}\n\tlogLevel := logrus.InfoLevel.String()\n\n\terr := SetUp(logLevel, true, TestLogDirName, nil)\n\tassert.NilError(t, err, nil)\n\n\terr = SetUp(logLevel, false, TestLogDirName, nil)\n\tassert.ErrorContains(t, err, \"logRotateArgs is needed when logToStdout is false\")\n\n\terr = SetUp(logLevel, false, TestLogDirName, logRotateArgs)\n\tassert.NilError(t, err)\n\tfor i := 0; i < 100000; i++ { // total 9.1MB\n\t\tlog.L.Infof(\"test log, now: %s\", time.Now().Format(\"2006-01-02 15:04:05\"))\n\t}\n\tassert.Equal(t, GetRotateLogFileNumbers(TestLogDirName, \"log.gz\"), logRotateArgs.RotateLogMaxBackups)\n\n\tos.RemoveAll(TestLogDirName)\n}\n"
  },
  {
    "path": "misc/example/10-containerd-net.conflist",
    "content": "{\n  \"cniVersion\": \"1.0.0\",\n  \"name\": \"containerd-net\",\n  \"plugins\": [\n    {\n      \"type\": \"bridge\",\n      \"bridge\": \"cni0\",\n      \"isGateway\": true,\n      \"ipMasq\": true,\n      \"promiscMode\": true,\n      \"ipam\": {\n        \"type\": \"host-local\",\n        \"subnet\": \"10.88.0.0/16\",\n        \"routes\": [\n          { \"dst\": \"0.0.0.0/0\" }\n        ]\n      }\n    },\n    {\n      \"type\": \"portmap\",\n      \"capabilities\": {\"portMappings\": true}\n    }\n  ]\n}\n"
  },
  {
    "path": "misc/example/README.md",
    "content": "## Example to setup and test nydus-snapshotter\n\nThe directory holds a few example config files to setup a nydus POC environment that saves its all state files in `/var/lib/containerd-test`, as specified in `containerd-test-config.toml`.\nFor now it contains following files:\n\n* crictl.yaml: `crictl` tool config\n* containerd-config.toml: `containerd` config\n* containerd-config-v1.toml: `containerd` config in the deprecated v1 format, provided for old containerd versions\n* containerd-test-config.toml: `containerd` config for testing\n* 10-containerd-net.conflist: `containerd` cni config\n* pod.yaml: pod spec yaml to be used by `crictl`\n* container.yaml: container spec yaml to be used by `crictl`\n\nWith these config files, users can setup a nydus environment by doing:\n```\nexport CNI_VERSION=v1.1.0\nexport CRICTL_VERSION=v1.23.0\nsudo mkdir -p /var/lib/containerd-test/ /etc/containerd/ /opt/cni/bin/ /etc/cni/net.d/\nsudo cp misc/example/containerd-test-config.toml /etc/containerd/\nsudo cp misc/example/crictl.yaml /etc/\nsudo cp misc/example/10-containerd-net.conflist /etc/cni/net.d/\n# install cni plugin\nwget https://github.com/containernetworking/plugins/releases/download/$CNI_VERSION/cni-plugins-linux-amd64-$CNI_VERSION.tgz\nsudo tar xzf cni-plugins-linux-amd64-$CNI_VERSION.tgz -C /opt/cni/bin/\n# install crictl\nwget https://github.com/kubernetes-sigs/cri-tools/releases/download/$CRICTL_VERSION/crictl-$CRICTL_VERSION-linux-amd64.tar.gz\ntar xzf crictl-$CRICTL_VERSION-linux-amd64.tar.gz -C /usr/local/bin/\n# install nydus-overlayfs\nNYDUS_VER=v$(curl -s \"https://api.github.com/repos/dragonflyoss/nydus/releases/latest\" | jq -r .tag_name | sed 's/^v//')\nwget https://github.com/dragonflyoss/nydus/releases/download/$NYDUS_VER/nydus-static-$NYDUS_VER-linux-amd64.tgz\ntar xzf nydus-static-$NYDUS_VER-linux-amd64.tgz\nsudo cp nydus-static/nydus-overlayfs /usr/local/sbin/\n```\n\nThen start a `nydus-snapshotter` container with:\n```\ndocker run -d --device /dev/fuse --cap-add SYS_ADMIN --security-opt apparmor:unconfined -e CONTAINERD_ROOT=/var/lib/containerd-test -v /var/lib/containerd-test:/var/lib/containerd-test:shared ghcr.io/containerd/nydus-snapshotter/nydus-snapshotter:latest\n```\nIt will bindmount host directory `/var/lib/containerd-test` inside the container and share all the nydus mountpoints from there.\n`containerd` config in `containerd-test-config.toml` has been setup to use the `nydus-snapshotter` grpc unix domain socket at `/var/lib/containerd-test/io.containerd.snapshotter.v1.nydus/containerd-nydus-grpc.sock`.\n\nThen start containerd with:\n```\nsudo containerd --config /etc/containerd/containerd-test-config.toml\n```\n\nNow we can use `crictl` to test against the POC environment.\n\n## Deploy in production\nWhen deploying `nydus-snapshotter` in production, following changes need to be applied:\n1. remove the `CONTAINERD_ROOT` environment variable when starting `nydus-snapshotter` container, and bindmount `/var/lib/containerd` to `/var/lib/containerd` in the container.\n2. use `containerd-config.toml` instead of `containerd-test-config.toml` to start containerd.\n"
  },
  {
    "path": "misc/example/container.yaml",
    "content": "metadata:\n  name: foobar-container\nimage:\n  image: ghcr.io/dragonflyoss/image-service/ubuntu:nydus-latest\ncommand: [\"tail\", \"-f\", \"/dev/null\"]\nlog_path: log.0\n"
  },
  {
    "path": "misc/example/containerd-config.toml",
    "content": "version = 2\nroot = \"/var/lib/containerd\"\nstate = \"/run/containerd\"\noom_score = 0\n\n[debug]\n  level = \"debug\"\n\n[plugins.\"io.containerd.grpc.v1.cri\"]\n  [plugins.\"io.containerd.grpc.v1.cri\".containerd]\n      snapshotter = \"nydus\"\n      disable_snapshot_annotations = false\n  [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runc]\n      runtime_type = \"io.containerd.runc.v2\"\n  [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.kata]\n      runtime_type = \"io.containerd.kata.v2\"\n      privileged_without_host_devices = true\n  [plugins.\"io.containerd.grpc.v1.cri\".cni]\n      bin_dir = \"/opt/cni/bin\"\n      conf_dir = \"/etc/cni/net.d\"\n\n[proxy_plugins]\n  [proxy_plugins.nydus]\n      type = \"snapshot\"\n      address = \"/run/containerd-nydus/containerd-nydus-grpc.sock\"\n\n"
  },
  {
    "path": "misc/example/containerd-test-config.toml",
    "content": "version = 2\nroot = \"/var/lib/containerd-test\"\nstate = \"/run/containerd-test\"\noom_score = 0\n\n[grpc]\n  address = \"/run/containerd-test/containerd.sock\"\n\n[debug]\n  level = \"debug\"\n\n[plugins.\"io.containerd.grpc.v1.cri\"]\n  [plugins.\"io.containerd.grpc.v1.cri\".containerd]\n      snapshotter = \"nydus\"\n      disable_snapshot_annotations = false\n  [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runc]\n      runtime_type = \"io.containerd.runc.v2\"\n  [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.kata]\n      runtime_type = \"io.containerd.kata.v2\"\n      privileged_without_host_devices = true\n  [plugins.\"io.containerd.grpc.v1.cri\".cni]\n      bin_dir = \"/opt/cni/bin\"\n      conf_dir = \"/etc/cni/net.d\"\n\n[proxy_plugins]\n  [proxy_plugins.nydus]\n      type = \"snapshot\"\n      address = \"/var/lib/containerd-test/io.containerd.snapshotter.v1.nydus/containerd-nydus-grpc.sock\"\n"
  },
  {
    "path": "misc/example/crictl.yaml",
    "content": "runtime-endpoint: unix:///run/containerd-test/containerd.sock\n"
  },
  {
    "path": "misc/example/optimizer-nri-plugin.conf",
    "content": "# The directory to persist accessed files list for container.\npersist_dir = \"/opt/nri/optimizer/results\"\n# Whether to make the csv file human readable.\nreadable = false\n# The path of optimizer server binary.\nserver_path = \"/usr/local/bin/optimizer-server\"\n# The timeout to kill optimizer server, 0 to disable it.\ntimeout = 0\n# Whether to overwrite the existed persistent files.\noverwrite = false\n# The events that containerd subscribes to.\n# Do not change this element.\nevents = [ \"StartContainer\", \"StopContainer\" ]"
  },
  {
    "path": "misc/example/pod.yaml",
    "content": "metadata:\n  attempt: 1\n  name: foobar\n  namespace: default\nlog_directory: /tmp\nlinux:\n  namespaces:\n    options: {}\n"
  },
  {
    "path": "misc/nri-prefetch/prefetchConfig.toml",
    "content": "[file_prefetch]\n# This is used to configure the socket address for the file prefetch.\nsocket_address = \"/run/containerd-nydus/system.sock\""
  },
  {
    "path": "misc/optimizer/containerd-config.toml",
    "content": "#   Copyright 2018-2022 Docker Inc.\n\n#   Licensed under the Apache License, Version 2.0 (the \"License\");\n#   you may not use this file except in compliance with the License.\n#   You may obtain a copy of the License at\n\n#       http://www.apache.org/licenses/LICENSE-2.0\n\n#   Unless required by applicable law or agreed to in writing, software\n#   distributed under the License is distributed on an \"AS IS\" BASIS,\n#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#   See the License for the specific language governing permissions and\n#   limitations under the License.\n\nversion = 2\n\n[proxy_plugins]\n  [proxy_plugins.nydus]\n    type = \"snapshot\"\n    address = \"/run/containerd-nydus/containerd-nydus-grpc.sock\"\n\n[plugins.\"io.containerd.nri.v1.nri\"]\n  config_file = \"/etc/nri/nri.conf\"\n  disable = false\n  plugin_path = \"/opt/nri/plugins\"\n  socket_path = \"/var/run/nri.sock\""
  },
  {
    "path": "misc/optimizer/crictl.yaml",
    "content": "runtime-endpoint: unix:///run/containerd/containerd.sock\nimage-endpoint: unix:////run/containerd/containerd.sock\ntimeout: 2\ndebug: false\npull-image-on-create: false"
  },
  {
    "path": "misc/optimizer/nginx.yaml",
    "content": "metadata:\n  name: nginx\n\nimage:\n  image: nginx:1.23.3\n\nmounts:\n  - host_path: script\n    container_path: /script\n\ncommand:\n  - /script/entrypoint.sh\n\nargs:\n - /script/file_list.txt\n\nlog_path: nginx.0.log\nlinux: {}"
  },
  {
    "path": "misc/optimizer/sandbox.yaml",
    "content": "metadata:\n  name: nginx-sandbox\n  namespace: default\n  attempt: 1\n  uid: hdishd83djaidwnduwk28bcsb\nlog_directory: /tmp\nlinux: {}"
  },
  {
    "path": "misc/optimizer/script/entrypoint.sh",
    "content": "#!/usr/bin/env bash\n\npath=$1\n\ndefault_path=file_list_path.txt\nif [[ $# -eq 0 ]]; then\n    path=${default_path}\nfi\n\nfiles=($(cat ${path} | tr \"\\n\" \" \"))\nfiles_number=${#files[@]}\necho \"file number: $files_number\"\n\nfor file in \"${files[@]}\"; do\n    file_size=$(stat -c%s \"${file}\")\n    echo \"file: ${file} size: ${file_size}\"\n    cat ${file} >/dev/null\ndone\n\necho \"Read file list done.\"\n"
  },
  {
    "path": "misc/optimizer/script/file_list.txt",
    "content": "/lib/x86_64-linux-gnu/ld-2.31.so\n/lib/x86_64-linux-gnu/libc-2.31.so\n/lib/x86_64-linux-gnu/libtinfo.so.6.2\n/lib/x86_64-linux-gnu/libdl-2.31.so\n/lib/x86_64-linux-gnu/libnss_files-2.31.so\n/lib/x86_64-linux-gnu/libselinux.so.1\n/usr/lib/x86_64-linux-gnu/libpcre2-8.so.0.10.1\n/lib/x86_64-linux-gnu/libpthread-2.31.so\n/docker-entrypoint.sh\n/docker-entrypoint.d/10-listen-on-ipv6-by-default.sh\n/docker-entrypoint.d/20-envsubst-on-templates.sh\n/docker-entrypoint.d/30-tune-worker-processes.sh\n"
  },
  {
    "path": "misc/snapshotter/Dockerfile",
    "content": "FROM alpine:3.17.0 AS base\n\nFROM base AS sourcer\nARG TARGETARCH\nARG NYDUS_VER=v2.3.0\n\nRUN apk add -q --no-cache curl && \\\n    apk add -q --no-cache --upgrade grep && \\\n    curl -fsSL -O https://github.com/dragonflyoss/nydus/releases/download/$NYDUS_VER/nydus-static-$NYDUS_VER-linux-amd64.tgz && \\\n    echo $NYDUS_VER > /.nydus_version && \\\n    tar xzf nydus-static-$NYDUS_VER-linux-amd64.tgz && \\\n    rm nydus-static-$NYDUS_VER-linux-amd64.tgz && \\\n    mv nydus-static/* / \\\n    && rm -rf /nydus-overlayfs\n\nFROM base AS kubectl-sourcer\nARG TARGETARCH\nARG KUBE_VER=v1.30.2\n\nRUN apk add -q --no-cache curl && \\\n    curl -fsSL -o /usr/bin/kubectl https://dl.k8s.io/release/${KUBE_VER}/bin/linux/${TARGETARCH}/kubectl && \\\n    chmod +x /usr/bin/kubectl\n\nFROM base\nARG DESTINATION=/opt/nydus-artifacts\nARG CONFIG_DESTINATION=${DESTINATION}/etc/nydus\nARG BINARY_DESTINATION=${DESTINATION}/usr/local/bin\nARG SCRIPT_DESTINATION=${DESTINATION}/opt/nydus\n\nWORKDIR /root/\nRUN apk add -q --no-cache libc6-compat bash\n\nVOLUME /var/lib/containerd/io.containerd.snapshotter.v1.nydus\nVOLUME /run/containerd-nydus\n\nCOPY --from=sourcer /.nydus_version /.nydus_version\nCOPY --from=kubectl-sourcer /usr/bin/kubectl /usr/bin/kubectl\n\nRUN mkdir -p ${CONFIG_DESTINATION} ${BINARY_DESTINATION} ${SCRIPT_DESTINATION} /var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache /tmp/blobs/\nCOPY --from=sourcer /nydus* ${BINARY_DESTINATION}/\nCOPY --chmod=755 containerd-nydus-grpc nydus-overlayfs ${BINARY_DESTINATION}/\nCOPY --chmod=755 snapshotter.sh ${SCRIPT_DESTINATION}/snapshotter.sh\nCOPY nydusd-config.fusedev.json ${CONFIG_DESTINATION}/nydusd-fusedev.json\nCOPY nydusd-config-localfs.json ${CONFIG_DESTINATION}/nydusd-localfs.json\nCOPY nydusd-config.fscache.json ${CONFIG_DESTINATION}/nydusd-fscache.json\nCOPY config.toml ${CONFIG_DESTINATION}/config.toml\nCOPY nydus-snapshotter.service ${DESTINATION}/etc/systemd/system/nydus-snapshotter.service\n"
  },
  {
    "path": "misc/snapshotter/base/kustomization.yaml",
    "content": "resources:\n- nydus-snapshotter.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\n"
  },
  {
    "path": "misc/snapshotter/base/nydus-snapshotter.yaml",
    "content": "---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: nydus-snapshotter-configs\n  labels:\n    app: nydus-snapshotter\n  namespace: nydus-system\ndata:\n  FS_DRIVER: \"fusedev\"\n  ENABLE_CONFIG_FROM_VOLUME: \"false\"\n  ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER: \"false\"\n  ENABLE_SYSTEMD_SERVICE: \"true\"\n\n---\napiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n  name: nydus-snapshotter\n  namespace: nydus-system\n  labels:\n    app: nydus-snapshotter\nspec:\n  selector:\n    matchLabels:\n      app: nydus-snapshotter\n  updateStrategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 1\n  template:\n    metadata:\n      labels:\n        app: nydus-snapshotter\n\n    spec:\n      serviceAccountName: nydus-snapshotter-sa\n      hostNetwork: true\n      hostPID: true\n      containers:\n      - name: nydus-snapshotter\n        image: \"ghcr.io/containerd/nydus-snapshotter:latest\"\n        imagePullPolicy: Always\n        env:\n          - name: NODE_NAME\n            valueFrom:\n              fieldRef:\n                fieldPath: spec.nodeName\n          - name: FS_DRIVER\n            valueFrom:\n              configMapKeyRef:\n                name: nydus-snapshotter-configs\n                key: FS_DRIVER\n                optional: true\n          - name: ENABLE_CONFIG_FROM_VOLUME\n            valueFrom:\n              configMapKeyRef:\n                name: nydus-snapshotter-configs\n                key: ENABLE_CONFIG_FROM_VOLUME\n                optional: true \n          - name: ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER\n            valueFrom:\n              configMapKeyRef:\n                name: nydus-snapshotter-configs\n                key: ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER\n                optional: true\n          - name: ENABLE_SYSTEMD_SERVICE\n            valueFrom:\n              configMapKeyRef:\n                name: nydus-snapshotter-configs\n                key: ENABLE_SYSTEMD_SERVICE\n                optional: true                    \n        lifecycle:\n          preStop:\n            exec:\n              command:\n              - \"bash\"\n              - \"-c\"\n              - |\n                /opt/nydus-artifacts/opt/nydus/snapshotter.sh cleanup\n        command: \n         - bash\n         - -c\n         - |-\n           /opt/nydus-artifacts/opt/nydus/snapshotter.sh deploy\n        volumeMounts:\n        - name: config-volume\n          mountPath: \"/etc/nydus-snapshotter\"\n        - name: nydus-lib\n          mountPath: \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\"\n          mountPropagation: Bidirectional\n        - name: nydus-run\n          mountPath: \"/run/containerd-nydus\"\n          mountPropagation: Bidirectional\n        - name: nydus-opt\n          mountPath: \"/opt/nydus\"\n          mountPropagation: Bidirectional\n        - name: nydus-etc\n          mountPath: \"/etc/nydus\"\n          mountPropagation: Bidirectional     \n        - name: containerd-conf\n          mountPath: \"/etc/containerd/\"\n        - name: local-bin\n          mountPath: \"/usr/local/bin/\"\n        - name: etc-systemd-system\n          mountPath: \"/etc/systemd/system/\"\n        securityContext:\n          privileged: true\n\n      volumes:\n      - name: config-volume\n        configMap:\n          name: nydus-snapshotter-configs\n          optional: true\n      - name: nydus-run\n        hostPath:\n          path: /run/containerd-nydus\n          type: DirectoryOrCreate\n      - name: nydus-lib\n        hostPath:\n          path: /var/lib/containerd/io.containerd.snapshotter.v1.nydus\n          type: DirectoryOrCreate\n      - name: nydus-opt\n        hostPath:\n          path: /opt/nydus\n          type: DirectoryOrCreate\n      - name: nydus-etc\n        hostPath:\n          path: /etc/nydus\n          type: DirectoryOrCreate\n      - name: containerd-conf\n        hostPath:\n          path: /etc/containerd/\n      - name: local-bin\n        hostPath:\n          path: /usr/local/bin/\n      - name: etc-systemd-system\n        hostPath:\n          path: /etc/systemd/system/\n      \n"
  },
  {
    "path": "misc/snapshotter/config-blockdev.toml",
    "content": "version = 1\n# Snapshotter's own home directory where it stores and creates necessary resources\nroot = \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\"\n# The snapshotter's GRPC server socket, containerd will connect to plugin on this socket\naddress = \"/run/containerd-nydus/containerd-nydus-grpc.sock\"\n# No nydusd daemon needed\ndaemon_mode = \"none\"\n\n[daemon]\n# Use `blockdev` for tarfs\nfs_driver = \"blockdev\"\n# Path to nydus-image binary\nnydusimage_path = \"/usr/local/bin/nydus-image\"\n\n[remote]\nskip_ssl_verify = true\n\n[snapshot]\n# Insert Kata volume information to `Mount.Options`\nenable_kata_volume = true\n\n[experimental.tarfs]\n# Whether to enable nydus tarfs mode. Tarfs is supported by:\n# - The EROFS filesystem driver since Linux 6.4\n# - Nydus Image Service release v2.3\nenable_tarfs = true\n\n# Mount rafs on host by loopdev and EROFS\nmount_tarfs_on_host = false\n\n# Mode to export tarfs images:\n# - \"none\" or \"\": do not export tarfs\n# - \"layer_verity_only\": only generate disk verity information for a layer blob\n# - \"image_verity_only\": only generate disk verity information for all blobs of an image\n# - \"layer_block\": generate a raw block disk image with tarfs for a layer\n# - \"image_block\": generate a raw block disk image with tarfs for an image\n# - \"layer_block_with_verity\": generate a raw block disk image with tarfs for a layer with dm-verity info\n# - \"image_block_with_verity\": generate a raw block disk image with tarfs for an image with dm-verity info\nexport_mode = \"image_block_with_verity\"\n"
  },
  {
    "path": "misc/snapshotter/config-proxy.toml",
    "content": "version = 1\n# Snapshotter's own home directory where it stores and creates necessary resources\nroot = \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\"\n# The snapshotter's GRPC server socket, containerd will connect to plugin on this socket\naddress = \"/run/containerd-nydus/containerd-nydus-grpc.sock\"\n# No nydusd daemon needed\ndaemon_mode = \"none\"\n\n[daemon]\n# Enable proxy mode\nfs_driver = \"proxy\"\n\n[snapshot]\n# Insert Kata volume information to `Mount.Options`\nenable_kata_volume = true\n"
  },
  {
    "path": "misc/snapshotter/config.toml",
    "content": "version = 1\n# Snapshotter's own home directory where it stores and creates necessary resources\nroot = \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\"\n# The snapshotter's GRPC server socket, containerd will connect to plugin on this socket\naddress = \"/run/containerd-nydus/containerd-nydus-grpc.sock\"\n# The nydus daemon mode can be one of the following options: multiple, dedicated, shared, or none.\n# If `daemon_mode` option is not specified, the default value is multiple.\ndaemon_mode = \"dedicated\"\n# Whether snapshotter should try to clean up resources when it is closed\ncleanup_on_close = false\n\n[system]\n# Snapshotter's debug and trace HTTP server interface\nenable = true\n# Unix domain socket path where system controller is listening on\naddress = \"/run/containerd-nydus/system.sock\"\n\n[system.debug]\n# Snapshotter can profile the CPU utilization of each nydusd daemon when it is being started.\n# This option specifies the profile duration when nydusd is downloading and uncomproessing data.\ndaemon_cpu_profile_duration_secs = 5\n# Enable by assigning an address, empty indicates pprof server is disabled\npprof_address = \"\"\n\n[daemon]\n# Specify a configuration file for nydusd\nnydusd_config = \"/etc/nydus/nydusd-config.fusedev.json\"\nnydusd_path = \"/usr/local/bin/nydusd\"\nnydusimage_path = \"/usr/local/bin/nydus-image\"\n# The fs driver can be one of the following options: fusedev, fscache, blockdev, proxy, or nodev.\n# If `fs_driver` option is not specified, the default value is fusedev.\nfs_driver = \"fusedev\"\n# How to process when daemon dies: \"none\", \"restart\" or \"failover\"\nrecover_policy = \"failover\"\n# Nydusd worker thread number to handle FUSE or fscache requests, [0-1024].\n# Setting to 0 will use the default configuration of nydusd.\nthreads_number = 4\n# Log rotation size for nydusd, in unit MB(megabytes). (default 100MB)\nlog_rotation_size = 100\n# Nydusd failover policy, can be \"none\", \"resend\" or \"flush\"\nfailover_policy = \"resend\"\n\n[cgroup]\n# Whether to use separate cgroup for nydusd.\nenable = true\n# The memory limit for nydusd cgroup, which contains all nydusd processes.\n# Percentage is supported as well, please ensure it is end with \"%\".\n# The default unit is bytes. Acceptable values include \"209715200\", \"200MiB\", \"200Mi\" and \"10%\".\nmemory_limit = \"\"\n\n[log]\n# Print logs to stdout rather than logging files\nlog_to_stdout = false\n# Snapshotter's log level\nlevel = \"info\"\nlog_rotation_compress = true\nlog_rotation_local_time = true\n# Max number of days to retain logs\nlog_rotation_max_age = 7\nlog_rotation_max_backups = 5\n# In unit MB(megabytes)\nlog_rotation_max_size = 100\n\n[metrics]\n# Enable by assigning an address, empty indicates metrics server is disabled\naddress = \":9110\"\n# The maximum duration an I/O operation can be pending before it's considered hung.\nhung_io_interval = \"10s\"\n# The interval at which metrics are collected and updated.\ncollect_interval = \"1m\"\n\n[remote]\nconvert_vpc_registry = false\n\n[remote.mirrors_config]\n# Snapshotter will rewrite nydusd's backend host to the first reachable mirror\n# loaded from this directory before each mount. Mirror selection is done by the\n# snapshotter (ping_url health check) and falls back to the origin registry host\n# when no mirror is available. Set to \"\" or an empty directory to disable it.\n#dir = \"/etc/nydus/certs.d\"\n\n[remote.auth]\n# Fetch the private registry auth by listening to K8s API server\nenable_kubeconfig_keychain = false\n# synchronize `kubernetes.io/dockerconfigjson` secret from kubernetes API server with specified kubeconfig (default `$KUBECONFIG` or `~/.kube/config`)\nkubeconfig_path = \"\"\n# Fetch the private registry auth as CRI image service proxy\nenable_cri_keychain = false\n# the target image service when using image proxy\n#image_service_address = \"/run/containerd/containerd.sock\"\n# Periodically renew cached credentials from renewable providers.\n# Set to a positive duration (e.g., \"10m\", \"1h\") to enable. 0 disables.\ncredential_renewal_interval = \"0s\"\n\n[snapshot]\n# Let containerd use nydus-overlayfs mount helper\nenable_nydus_overlayfs = false\n# Path to the nydus-overlayfs binary or name of the binary in $PATH\nnydus_overlayfs_path = \"nydus-overlayfs\"\n# Insert Kata Virtual Volume option to `Mount.Options`\nenable_kata_volume = false\n# Whether to remove resources when a snapshot is removed\nsync_remove = false\n# Globally enable the \"volatile\" overlayfs mount option on all writable snapshots.\n# This skips sync on the upper layer, improving write performance for ephemeral\n# container filesystems. Safe for most workloads where the writable layer does not\n# need to survive a crash.\nenable_overlayfs_volatile = false\n\n[cache_manager]\n# Disable or enable recyclebin\ndisable = false\n# How long to keep deleted files in recyclebin\ngc_period = \"24h\"\n# Directory to host cached files\ncache_dir = \"\"\n\n[image]\npublic_key_file = \"\"\nvalidate_signature = false\n\n# The configuraions for features that are not production ready\n[experimental]\n# Whether to enable stargz support\nenable_stargz = false\n# Whether to enable referrers support\n# The option enables trying to fetch the Nydus image associated with the OCI image and run it.\n# Also see https://github.com/opencontainers/distribution-spec/blob/main/spec.md#listing-referrers\nenable_referrer_detect = false\n# Whether to enable index detection support\n# The option enables trying to fetch the Nydus image present in the same OCI index as the original OCI image and run it.\n# Also see https://github.com/containerd/nydus-snapshotter/blob/main/docs/index-detection.md\nenable_index_detect = false\n# Whether to enable authentication support\n# The option enables nydus snapshot to provide backend information to nydusd.\nenable_backend_source = false\n[experimental.tarfs]\n# Whether to enable nydus tarfs mode. Tarfs is supported by:\n# - The EROFS filesystem driver since Linux 6.4\n# - Nydus Image Service release v2.3\nenable_tarfs = false\n# Mount rafs on host by loopdev and EROFS\nmount_tarfs_on_host = false\n# Only enable nydus tarfs mode for images with `tarfs hint` label when true\ntarfs_hint = false\n# Maximum of concurrence to converting OCIv1 images to tarfs, 0 means default\nmax_concurrent_proc = 0\n# Mode to export tarfs images:\n# - \"none\" or \"\": do not export tarfs\n# - \"layer_verity_only\": only generate disk verity information for a layer blob\n# - \"image_verity_only\": only generate disk verity information for all blobs of an image\n# - \"layer_block\": generate a raw block disk image with tarfs for a layer\n# - \"image_block\": generate a raw block disk image with tarfs for an image\n# - \"layer_block_with_verity\": generate a raw block disk image with tarfs for a layer with dm-verity info\n# - \"image_block_with_verity\": generate a raw block disk image with tarfs for an image with dm-verity info\nexport_mode = \"\"\n"
  },
  {
    "path": "misc/snapshotter/nydus-snapshotter-rbac.yaml",
    "content": "---\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: nydus-system\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: nydus-snapshotter-sa\n  namespace: nydus-system\n---\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: nydus-snapshotter-role\nrules:\n- apiGroups: [\"\"]\n  resources: [\"nodes\"]\n  verbs: [\"get\", \"patch\"]\n\n---\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: nydus-snapshotter-role-binding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: nydus-snapshotter-role\nsubjects:\n- kind: ServiceAccount\n  name: nydus-snapshotter-sa\n  namespace: nydus-system\n"
  },
  {
    "path": "misc/snapshotter/nydus-snapshotter.fscache.service",
    "content": "[Unit]\nDescription=nydus snapshotter\nAfter=network.target\nBefore=containerd.service\n\n[Service]\nType=simple\nEnvironment=HOME=/root\nExecStart=/usr/local/bin/containerd-nydus-grpc --config /etc/nydus/config.toml --fs-driver fscache --nydusd-config /etc/nydus/nydusd-config.fscache.json\nRestart=always\nRestartSec=1\nKillMode=process\nOOMScoreAdjust=-999\nStandardOutput=journal\nStandardError=journal\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "misc/snapshotter/nydus-snapshotter.fusedev.service",
    "content": "[Unit]\nDescription=nydus snapshotter\nAfter=network.target\nBefore=containerd.service\n\n[Service]\nType=simple\nEnvironment=HOME=/root\nExecStart=/usr/local/bin/containerd-nydus-grpc --config /etc/nydus/config.toml\nRestart=always\nRestartSec=1\nKillMode=process\nOOMScoreAdjust=-999\nStandardOutput=journal\nStandardError=journal\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "misc/snapshotter/nydus-snapshotter.service",
    "content": "[Unit]\nDescription=nydus snapshotter\nAfter=network.target\nBefore=containerd.service\n\n[Service]\nType=simple\nEnvironment=HOME=/root\nExecStart=/usr/local/bin/containerd-nydus-grpc --config /etc/nydus/config-proxy.toml\nRestart=always\nRestartSec=1\nKillMode=process\nOOMScoreAdjust=-999\nStandardOutput=journal\nStandardError=journal\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "misc/snapshotter/nydusd-config-localfs.json",
    "content": "{\n  \"device\": {\n    \"backend\": {\n      \"type\": \"localfs\",\n      \"config\": {\n        \"dir\": \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus/cache/\"\n      }\n    },\n    \"cache\": {\n      \"type\": \"blobcache\"\n    }\n  },\n  \"mode\": \"direct\",\n  \"digest_validate\": false,\n  \"iostats_files\": false,\n  \"enable_xattr\": true,\n  \"amplify_io\": 1048576,\n  \"fs_prefetch\": {\n    \"enable\": true,\n    \"threads_count\": 2\n  }\n}"
  },
  {
    "path": "misc/snapshotter/nydusd-config.fscache.json",
    "content": "{\n    \"type\": \"bootstrap\",\n    \"config\": {\n        \"backend_type\": \"registry\",\n        \"backend_config\": {},\n        \"cache_type\": \"fscache\",\n        \"prefetch_config\": {\n            \"enable\": true,\n            \"threads_count\": 8,\n            \"merging_size\": 1048576\n        }\n    }\n}\n"
  },
  {
    "path": "misc/snapshotter/nydusd-config.fusedev.json",
    "content": "{\n  \"device\": {\n    \"backend\": {\n      \"type\": \"registry\",\n      \"config\": {\n        \"timeout\": 5,\n        \"connect_timeout\": 5,\n        \"retry_limit\": 2\n      }\n    },\n    \"cache\": {\n      \"type\": \"blobcache\"\n    }\n  },\n  \"mode\": \"direct\",\n  \"digest_validate\": false,\n  \"iostats_files\": false,\n  \"enable_xattr\": true,\n  \"amplify_io\": 1048576,\n  \"fs_prefetch\": {\n    \"enable\": true,\n    \"threads_count\": 8,\n    \"merging_size\": 1048576,\n    \"prefetch_all\": true\n  }\n}\n"
  },
  {
    "path": "misc/snapshotter/overlays/k3s/kustomization.yaml",
    "content": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nresources:\n- ../../base\npatches:\n- path: mount_k3s_conf.yaml\n"
  },
  {
    "path": "misc/snapshotter/overlays/k3s/mount_k3s_conf.yaml",
    "content": "apiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n  name: nydus-snapshotter\n  namespace: nydus-system\nspec:\n  template:\n    spec:\n      volumes:\n        - name: containerd-conf\n          hostPath:\n            path: /var/lib/rancher/k3s/agent/etc/containerd/\n"
  },
  {
    "path": "misc/snapshotter/overlays/rke2/kustomization.yaml",
    "content": "apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nresources:\n- ../../base\npatches:\n- path: mount_rke2_conf.yaml\n"
  },
  {
    "path": "misc/snapshotter/overlays/rke2/mount_rke2_conf.yaml",
    "content": "apiVersion: apps/v1\nkind: DaemonSet\nmetadata:\n  name: nydus-snapshotter\n  namespace: nydus-system\nspec:\n  template:\n    spec:\n      volumes:\n        - name: containerd-conf\n          hostPath:\n            path: /var/lib/rancher/rke2/agent/etc/containerd/\n"
  },
  {
    "path": "misc/snapshotter/snapshotter.sh",
    "content": "#!/usr/bin/env bash\n# Copyright (c) 2023. Nydus Developers. All rights reserved.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\nset -o errexit\nset -o pipefail\nset -o nounset\n\nSNAPSHOTTER_ARTIFACTS_DIR=\"/opt/nydus-artifacts\"\n\n# Container runtime config, the default container runtime is containerd\nCONTAINER_RUNTIME=\"${CONTAINER_RUNTIME:-containerd}\"\nCONTAINER_RUNTIME_CONFIG=\"/etc/containerd/config.toml\"\n\n# Common nydus snapshotter config options\nFS_DRIVER=\"${FS_DRIVER:-fusedev}\"\nSNAPSHOTTER_GRPC_SOCKET=\"${SNAPSHOTTER_GRPC_SOCKET:-/run/containerd-nydus/containerd-nydus-grpc.sock}\"\n\n# The directory about nydus and nydus snapshotter\nNYDUS_CONFIG_DIR=\"${NYDUS_CONFIG_DIR:-/etc/nydus}\"\nNYDUS_LIB_DIR=\"${NYDUS_LIB_DIR:-/var/lib/containerd/io.containerd.snapshotter.v1.nydus}\"\nNYDUS_BINARY_DIR=\"${NYDUS_BINARY_DIR:-/usr/local/bin}\"\nSNAPSHOTTER_SCRYPT_DIR=\"${SNAPSHOTTER_SCRYPT_DIR:-/opt/nydus}\"\n\n# The binary about nydus-snapshotter\nSNAPSHOTTER_BINARY=\"${SNAPSHOTTER_BINARY:-${NYDUS_BINARY_DIR}/containerd-nydus-grpc}\"\n\n# The config about nydus snapshotter\nSNAPSHOTTER_CONFIG=\"${SNAPSHOTTER_CONFIG:-${NYDUS_CONFIG_DIR}/config.toml}\"\n# The systemd service config about nydus snapshotter\nSNAPSHOTTER_SERVICE=\"${SNAPSHOTTER_SERVICE:-/etc/systemd/system/nydus-snapshotter.service}\"\n# If true, the script would read the config from env.\nENABLE_CONFIG_FROM_VOLUME=\"${ENABLE_CONFIG_FROM_VOLUME:-false}\"\n# If true, the script would enable the \"runtime specific snapshotter\" in containerd config.\nENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER=\"${ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER:-false}\"\n# If true, the snapshotter would be running as a systemd service\nENABLE_SYSTEMD_SERVICE=\"${ENABLE_SYSTEMD_SERVICE:-false}\"\n\nCOMMANDLINE=\"\"\n\n# If we fail for any reason a message will be displayed\ndie() {\n    msg=\"$*\"\n    echo \"ERROR: $msg\" >&2\n    exit 1\n}\n\nprint_usage() {\n    echo \"Usage: $0 [deploy/cleanup]\"\n}\n\nwait_service_active(){\n    local wait_time=\"$1\"\n    local sleep_time=\"$2\"\n    local service=\"$3\"\n\n    nsenter -t 1 -m systemctl restart $service\n\n    # Wait for containerd to be running\n    while [ \"$wait_time\" -gt 0 ]; do\n        if nsenter -t 1 -m systemctl is-active --quiet $service; then\n            echo \"$service is running\"\n            return 0  \n        else\n            sleep \"$sleep_time\"\n            wait_time=$((wait_time-sleep_time))\n        fi\n    done\n\n    echo \"Timeout reached. $service may not be running.\"\n    nsenter -t 1 -m systemctl status $service\n    return 1  \n}\n\nfunction fs_driver_handler() {\n    if [ \"${ENABLE_CONFIG_FROM_VOLUME}\" == \"true\" ]; then\n        SNAPSHOTTER_CONFIG=\"${NYDUS_CONFIG_DIR}/config.toml\"\n    else\n        case \"${FS_DRIVER}\" in\n        fusedev) \n            sed -i -e \"s|nydusd_config = .*|nydusd_config = \\\"${NYDUS_CONFIG_DIR}/nydusd-fusedev.json\\\"|\" \"${SNAPSHOTTER_CONFIG}\" \n            sed -i -e \"s|fs_driver = .*|fs_driver = \\\"fusedev\\\"|\" \"${SNAPSHOTTER_CONFIG}\" \n            sed -i -e \"s|daemon_mode = .*|daemon_mode = \\\"multiple\\\"|\" \"${SNAPSHOTTER_CONFIG}\" \n            ;;\n        fscache) \n            sed -i -e \"s|nydusd_config = .*|nydusd_config = \\\"${NYDUS_CONFIG_DIR}/nydusd-fscache.json\\\"|\" \"${SNAPSHOTTER_CONFIG}\" \n            sed -i -e \"s|fs_driver = .*|fs_driver = \\\"fscache\\\"|\" \"${SNAPSHOTTER_CONFIG}\"\n            sed -i -e \"s|daemon_mode = .*|daemon_mode = \\\"multiple\\\"|\" \"${SNAPSHOTTER_CONFIG}\"  \n            ;;\n        blockdev) \n            sed -i -e \"s|fs_driver = .*|fs_driver = \\\"blockdev\\\"|\" \"${SNAPSHOTTER_CONFIG}\" \n            sed -i -e \"s|enable_kata_volume = .*|enable_kata_volume = true|\" \"${SNAPSHOTTER_CONFIG}\" \n            sed -i -e \"s|enable_tarfs = .*|enable_tarfs = true|\" \"${SNAPSHOTTER_CONFIG}\" \n            sed -i -e \"s|daemon_mode = .*|daemon_mode = \\\"none\\\"|\" \"${SNAPSHOTTER_CONFIG}\"  \n            sed -i -e \"s|export_mode = .*|export_mode = \\\"layer_block_with_verity\\\"|\" \"${SNAPSHOTTER_CONFIG}\"  \n            ;;\n        proxy) \n            sed -i -e \"s|fs_driver = .*|fs_driver = \\\"proxy\\\"|\" \"${SNAPSHOTTER_CONFIG}\" \n            sed -i -e \"s|enable_kata_volume = .*|enable_kata_volume = true|\" \"${SNAPSHOTTER_CONFIG}\" \n            sed -i -e \"s|daemon_mode = .*|daemon_mode = \\\"none\\\"|\" \"${SNAPSHOTTER_CONFIG}\"  \n            ;;\n        *) die \"invalid fs driver ${FS_DRIVER}\" ;;\n        esac\n    fi\n    COMMANDLINE+=\" --config ${SNAPSHOTTER_CONFIG}\"\n}\n\nfunction configure_snapshotter() {\n\n    echo \"configuring snapshotter\"\n\n    # Copy the container runtime config to a backup\n    cp \"$CONTAINER_RUNTIME_CONFIG\" \"$CONTAINER_RUNTIME_CONFIG\".bak.nydus\n\n\n    # When trying to edit the config file that is mounted by docker with `sed -i`, the error would happend:\n    # sed: cannot rename /etc/containerd/config.tomlpmdkIP: Device or resource busy  \n    # The reason is that `sed`` with option `-i` creates new file, and then replaces the old file with the new one, \n    # which definitely will change the file inode. But the file is mounted by docker, which means we are not allowed to \n    # change its inode from within docker container.\n    # \n    # So we copy the original file to a backup, make changes to the backup, and then overwrite the original file with the backup.\n    cp \"$CONTAINER_RUNTIME_CONFIG\" \"$CONTAINER_RUNTIME_CONFIG\".bak\n    # Check and add nydus proxy plugin in the config\n    if grep -q '\\[proxy_plugins.nydus\\]' \"$CONTAINER_RUNTIME_CONFIG\".bak; then\n        echo \"the config has configured the nydus proxy plugin!\"\n    else\n        echo \"Not found nydus proxy plugin!\"\n        cat <<EOF >>\"$CONTAINER_RUNTIME_CONFIG\".bak\n        \n    [proxy_plugins.nydus]\n        type = \"snapshot\"\n        address = \"$SNAPSHOTTER_GRPC_SOCKET\"\nEOF\n    fi\n\n    if grep -q 'disable_snapshot_annotations' \"$CONTAINER_RUNTIME_CONFIG\".bak; then\n        sed -i -e \"s|disable_snapshot_annotations = .*|disable_snapshot_annotations = false|\" \\\n                \"${CONTAINER_RUNTIME_CONFIG}\".bak\n    else\n        sed -i '/\\[plugins\\..*\\.containerd\\]/a\\disable_snapshot_annotations = false' \\\n                \"${CONTAINER_RUNTIME_CONFIG}\".bak\n    fi\n    if grep -q 'discard_unpacked_layers' \"$CONTAINER_RUNTIME_CONFIG\".bak; then\n        sed -i -e \"s|discard_unpacked_layers = .*|discard_unpacked_layers = false|\" \\\n                \"${CONTAINER_RUNTIME_CONFIG}\".bak\n    else\n        sed -i '/\\[plugins\\..*\\.containerd\\]/a\\discard_unpacked_layers = false' \\\n                \"${CONTAINER_RUNTIME_CONFIG}\".bak\n    fi\n\n    if [ \"${ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER}\" == \"false\" ]; then\n        sed -i -e '/\\[plugins\\..*\\.containerd\\]/,/snapshotter =/ s/snapshotter = \"[^\"]*\"/snapshotter = \"nydus\"/' \"${CONTAINER_RUNTIME_CONFIG}\".bak\n    fi\n    \n    cat \"${CONTAINER_RUNTIME_CONFIG}\".bak >  \"${CONTAINER_RUNTIME_CONFIG}\"\n}\n\nfunction install_snapshotter() {\n    echo \"install nydus snapshotter artifacts\"\n    find \"${SNAPSHOTTER_ARTIFACTS_DIR}${NYDUS_BINARY_DIR}\" -type f -exec install -Dm 755 -t \"${NYDUS_BINARY_DIR}\" \"{}\"  \\;\n    find \"${SNAPSHOTTER_ARTIFACTS_DIR}${NYDUS_CONFIG_DIR}\" -type f -exec install -Dm 644 -t \"${NYDUS_CONFIG_DIR}\" \"{}\"  \\;\n    install -D -m 644 \"${SNAPSHOTTER_ARTIFACTS_DIR}${SNAPSHOTTER_SCRYPT_DIR}/snapshotter.sh\" \"${SNAPSHOTTER_SCRYPT_DIR}/snapshotter.sh\"\n    if [ \"${ENABLE_SYSTEMD_SERVICE}\" == \"true\" ]; then\n        install -D -m 644 \"${SNAPSHOTTER_ARTIFACTS_DIR}${SNAPSHOTTER_SERVICE}\" \"${SNAPSHOTTER_SERVICE}\"\n    fi\n    if [ \"${ENABLE_CONFIG_FROM_VOLUME}\" == \"true\" ]; then\n        find \"/etc/nydus-snapshotter\" -type f -exec install -Dm 644 -t \"${NYDUS_CONFIG_DIR}\" \"{}\"  \\;\n    fi\n}\n\nfunction deploy_snapshotter() {\n    echo \"deploying snapshotter\"\n    install_snapshotter\n\n    COMMANDLINE=\"${SNAPSHOTTER_BINARY}\"\n    fs_driver_handler\n    configure_snapshotter\n    if [ \"${ENABLE_SYSTEMD_SERVICE}\" == \"true\" ]; then\n        echo \"running snapshotter as systemd service\"\n        sed -i \"s|^ExecStart=.*$|ExecStart=$COMMANDLINE|\" \"${SNAPSHOTTER_SERVICE}\"\n        nsenter -t 1 -m systemctl daemon-reload\n        nsenter -t 1 -m systemctl enable nydus-snapshotter.service\n        wait_service_active 30 5 nydus-snapshotter\n    else\n        echo \"running snapshotter as standalone process\"\n        ${COMMANDLINE} &\n    fi\n    wait_service_active 30 5 ${CONTAINER_RUNTIME}\n\n}\n\nfunction remove_images() {\n    local SNAPSHOTTER=\"nydus\"\n    local NAMESPACE=\"k8s.io\"\n    local ctr_args=\"nsenter -t 1 -m ctr\"\n\n    if [[ \" k3s k3s-agent rke2-agent rke2-server \" =~ \" ${CONTAINER_RUNTIME} \" ]]; then\n        ctr_args+=\" --address /run/k3s/containerd/containerd.sock\"\n    fi\n    ctr_args+=\" --namespace $NAMESPACE\"\n\n    # List all snapshots for nydus snapshotter\n    local SNAPSHOTS=$($ctr_args snapshot --snapshotter $SNAPSHOTTER ls | awk 'NR>1 {print $1}')\n    echo \"Images associated with snapshotter $SNAPSHOTTER:\"\n\n    # Loop through each snapshot and find associated contents\n    for SNAPSHOT in $SNAPSHOTS; do\n        local CONTENTS=$($ctr_args content ls | grep $SNAPSHOT | awk '{print $1}')\n        echo \"Snapshot: $SNAPSHOT, Contents: $CONTENTS\"\n        if [ -z \"$CONTENTS\" ]; then\n            continue\n        fi\n        # Loop through each content and find associated digests of images\n        for CONTENT in $CONTENTS; do\n            local DIGESTS=$($ctr_args image ls | grep $CONTENT | awk '{print $3}')\n            echo \"Content: $CONTENT, Digests: $DIGESTS\"\n            if [ -z \"$DIGESTS\" ]; then\n                continue\n            fi\n            # Loop through each digest and find associated image references\n            for DIGEST in $DIGESTS; do\n                local IMAGES=$($ctr_args image ls | grep $DIGEST | awk '{print $1}')\n                echo \"Digest: $DIGEST, Images: $IMAGES\"\n                if [ -z \"$IMAGES\" ]; then\n                    continue\n                fi\n                for IMAGE in $IMAGES; do\n                    # Delete the image\n                    $ctr_args images rm $IMAGE > /dev/null 2>&1 || true\n                    echo \"Image $IMAGE removed\"\n                done\n            done\n            # Delete the content\n            $ctr_args content rm $CONTENT > /dev/null 2>&1 || true\n            echo \"content $CONTENT removed\"\n        done\n        # Delete the snapshot\n        $ctr_args snapshot --snapshotter $SNAPSHOTTER rm $SNAPSHOT > /dev/null 2>&1 || true\n        echo \"snapshot $SNAPSHOT removed\"\n    done\n    echo \"INFO: Images removed\"\n}\n\nfunction cleanup_snapshotter() {\n    echo \"cleaning up snapshotter\"\n\n    pid=$(ps -ef | grep containerd-nydus-grpc | grep -v grep | awk '{print $1}' || true)\n    if [ ! -z \"$pid\" ]; then\n        remove_images\n    fi\n    echo \"Recover containerd config\"\n    cat \"$CONTAINER_RUNTIME_CONFIG\".bak.nydus >\"$CONTAINER_RUNTIME_CONFIG\"\n    if [ \"${ENABLE_SYSTEMD_SERVICE}\" == \"true\" ]; then\n        nsenter -t 1 -m systemctl stop nydus-snapshotter.service\n        nsenter -t 1 -m systemctl disable --now nydus-snapshotter.service\n        rm -f \"${SNAPSHOTTER_SERVICE}\" || true\n    else\n        kill -9 $pid || true\n    fi\n    wait_service_active 30 5 ${CONTAINER_RUNTIME}\n    echo \"Removing nydus-snapshotter artifacts from host\"\n    rm -f \"${NYDUS_BINARY_DIR}\"/nydus*\n    rm -rf \"${NYDUS_CONFIG_DIR}\"/*\n    rm -rf \"${SNAPSHOTTER_SCRYPT_DIR}\"/*\n    rm -rf \"${NYDUS_LIB_DIR}\"/*\n    echo \"cleaned up snapshotter\"\n}\n\nfunction get_container_runtime() {\n    local runtime=$(kubectl get node ${NODE_NAME} -o jsonpath='{.status.nodeInfo.containerRuntimeVersion}')\n    if [ \"$?\" -ne 0 ]; then\n        die \"\\\"$NODE_NAME\\\" is an invalid node name\"\n    fi\n\n    if echo \"$runtime\" | grep -qE 'containerd.*-k3s'; then\n        if nsenter -t 1 -m systemctl is-active --quiet rke2-agent; then\n            echo \"rke2-agent\"\n        elif nsenter -t 1 -m systemctl is-active --quiet rke2-server; then\n            echo \"rke2-server\"\n        elif nsenter -t 1 -m systemctl is-active --quiet k3s-agent; then\n            echo \"k3s-agent\"\n        else\n            echo \"k3s\"\n        fi\n    elif nsenter -t 1 -m systemctl is-active --quiet k0scontroller; then\n        echo \"k0s-controller\"\n    elif nsenter -t 1 -m systemctl is-active --quiet k0sworker; then\n        echo \"k0s-worker\"\n    else\n        echo \"$runtime\" | awk -F '[:]' '{print $1}'\n    fi\n}\n\nfunction main() {\n    # script requires that user is root\n    euid=$(id -u)\n    if [[ $euid -ne 0 ]]; then\n        die \"This script must be run as root\"\n    fi\n\n    CONTAINER_RUNTIME=$(get_container_runtime)\n    if [[ \" k3s k3s-agent rke2-agent rke2-server \" =~ \" ${CONTAINER_RUNTIME} \" ]]; then\n        CONTAINER_RUNTIME_CONFIG_TMPL=\"${CONTAINER_RUNTIME_CONFIG}.tmpl\"\n        if [ ! -f \"${CONTAINER_RUNTIME_CONFIG_TMPL}\" ]; then\n            cp \"${CONTAINER_RUNTIME_CONFIG}\" \"${CONTAINER_RUNTIME_CONFIG_TMPL}\"\n        fi\n\n        CONTAINER_RUNTIME_CONFIG=\"${CONTAINER_RUNTIME_CONFIG_TMPL}\"\n    elif [ \"${CONTAINER_RUNTIME}\" == \"containerd\" ]; then\n        if [ ! -f \"${CONTAINER_RUNTIME_CONFIG}\" ]; then\n            mkdir -p $(dirname ${CONTAINER_RUNTIME_CONFIG}) || true\n            if [ -x $(command -v ${CONTAINER_RUNTIME}) ]; then\n                ${CONTAINER_RUNTIME} config default > ${CONTAINER_RUNTIME_CONFIG}\n            else\n                die \"Not able to find an executable ${CONTAINER_RUNTIME} binary to create the default config\"\n            fi\n        fi\n    else\n        die \"${CONTAINER_RUNTIME} is a unsupported containe runtime\"\n    fi\n\n    action=${1:-}\n    if [ -z \"$action\" ]; then\n        print_usage\n        die \"invalid arguments\"\n    fi\n\n    case \"$action\" in\n    deploy)\n        deploy_snapshotter\n        ;;\n    cleanup)\n        cleanup_snapshotter\n        ;;\n    *)\n        die \"invalid arguments\"\n        print_usage\n        ;;\n    esac\n\n    sleep infinity\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "pkg/auth/cri.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/containerd/containerd/v2/defaults\"\n\t\"github.com/containerd/containerd/v2/pkg/dialer\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/stargz-snapshotter/service/keychain/cri\"\n\t\"github.com/containerd/stargz-snapshotter/service/resolver\"\n\t\"github.com/pkg/errors\"\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/backoff\"\n\t\"google.golang.org/grpc/credentials/insecure\"\n\truntime \"k8s.io/cri-api/pkg/apis/runtime/v1\"\n)\n\nconst DefaultImageServiceAddress = \"/run/containerd/containerd.sock\"\n\n// TODO: embed in CRIProvider\n// Should be concurrency safe\nvar credentials []resolver.Credential = make([]resolver.Credential, 0, 8)\n\n// CRIProvider retrieves credentials from CRI image pull requests.\ntype CRIProvider struct{}\n\n// NewCRIProvider creates a new CRI-based auth provider.\nfunc NewCRIProvider() *CRIProvider {\n\treturn &CRIProvider{}\n}\n\nfunc (p *CRIProvider) String() string {\n\treturn \"cri\"\n}\n\nfunc (p *CRIProvider) GetCredentials(req *AuthRequest) (*PassKeyChain, error) {\n\tif len(credentials) == 0 {\n\t\treturn nil, errors.New(\"no Credentials parsers\")\n\t}\n\n\tif req == nil || req.Ref == \"\" {\n\t\treturn nil, errors.New(\"ref not found in request\")\n\t}\n\n\trefSpec, host, err := parseReference(req.Ref)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"parse reference %s\", req.Ref)\n\t}\n\n\tvar u, s string\n\tvar keychain *PassKeyChain\n\n\tfor _, cred := range credentials {\n\t\tif username, secret, err := cred(host, refSpec); err != nil {\n\t\t\treturn nil, err\n\t\t} else if username != \"\" || secret != \"\" {\n\t\t\tu = username\n\t\t\ts = secret\n\n\t\t\tkeychain = &PassKeyChain{\n\t\t\t\tUsername: u,\n\t\t\t\tPassword: s,\n\t\t\t}\n\n\t\t\treturn keychain, nil\n\t\t}\n\t}\n\n\treturn nil, fmt.Errorf(\"no credentials found for host: %s\", host)\n}\n\n// newCRIConn creates a gRPC connection to the CRI service.\n// This function is borrowed from stargz\nfunc newCRIConn(criAddr string) (*grpc.ClientConn, error) {\n\t// TODO: make gRPC options configurable from config.toml\n\tbackoffConfig := backoff.DefaultConfig\n\tbackoffConfig.MaxDelay = 3 * time.Second\n\tconnParams := grpc.ConnectParams{\n\t\tBackoff: backoffConfig,\n\t}\n\tgopts := []grpc.DialOption{\n\t\tgrpc.WithTransportCredentials(insecure.NewCredentials()),\n\t\tgrpc.WithConnectParams(connParams),\n\t\tgrpc.WithContextDialer(dialer.ContextDialer),\n\t\tgrpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(defaults.DefaultMaxRecvMsgSize)),\n\t\tgrpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(defaults.DefaultMaxSendMsgSize)),\n\t}\n\treturn grpc.NewClient(dialer.DialAddress(criAddr), gopts...)\n}\n\n// AddImageProxy sets up a CRI image proxy that intercepts credentials.\n// This should be called once at startup to enable CRI credential capture.\n// from stargz-snapshotter/cmd/containerd-stargz-grpc/main.go#main\nfunc AddImageProxy(ctx context.Context, rpc *grpc.Server, imageServiceAddress string) {\n\tcriAddr := DefaultImageServiceAddress\n\tif imageServiceAddress != \"\" {\n\t\tcriAddr = imageServiceAddress\n\t}\n\n\tcriCred, criServer := cri.NewCRIKeychain(ctx, func() (runtime.ImageServiceClient, error) {\n\t\tconn, err := newCRIConn(criAddr)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\treturn runtime.NewImageServiceClient(conn), nil\n\t})\n\n\truntime.RegisterImageServiceServer(rpc, criServer)\n\n\tcredentials = append(credentials, criCred)\n\n\tlog.G(ctx).WithField(\"target-image-service\", criAddr).Info(\"setup image proxy keychain\")\n}\n"
  },
  {
    "path": "pkg/auth/cri_test.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"context\"\n\t\"net\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/containerd/containerd/v2/pkg/dialer\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/credentials/insecure\"\n\truntime \"k8s.io/cri-api/pkg/apis/runtime/v1\"\n)\n\ntype MockImageService struct {\n\truntime.UnimplementedImageServiceServer\n}\n\nfunc (*MockImageService) PullImage(_ context.Context, _ *runtime.PullImageRequest) (*runtime.PullImageResponse, error) {\n\treturn &runtime.PullImageResponse{}, nil\n}\n\nfunc TestFromImagePull(t *testing.T) {\n\tvar err error\n\tassertions := assert.New(t)\n\n\tctx := context.TODO()\n\td := t.TempDir()\n\n\ttagImage := \"docker.io/library/busybox:latest\"\n\n\t// should return nil if no proxy\n\tkc, err := NewCRIProvider().GetCredentials(&AuthRequest{Ref: tagImage})\n\tassertions.Nil(kc)\n\tassertions.Error(err)\n\n\t// Mocking the end CRI request consumer.\n\tmockRPC := grpc.NewServer()\n\tmockSocket := filepath.Join(d, \"mock.sock\")\n\tlistenMock, err := net.Listen(\"unix\", mockSocket)\n\tassertions.NoError(err)\n\n\t// Mocking the end CRI request consumer.\n\tserver := &MockImageService{}\n\truntime.RegisterImageServiceServer(mockRPC, server)\n\n\tgo func() {\n\t\terr := mockRPC.Serve(listenMock)\n\t\tassertions.NoError(err)\n\t}()\n\tdefer mockRPC.Stop()\n\n\t// The server of CRI image service proxy.\n\tproxyRPC := grpc.NewServer()\n\tproxySocket := filepath.Join(d, \"proxy.sock\")\n\tlistenProxy, err := net.Listen(\"unix\", proxySocket)\n\tassertions.NoError(err)\n\tAddImageProxy(ctx, proxyRPC, mockSocket)\n\tgo func() {\n\t\terr := proxyRPC.Serve(listenProxy)\n\t\tassertions.NoError(err)\n\t}()\n\tdefer proxyRPC.Stop()\n\n\t// should return empty kc before pulling\n\tkc, err = NewCRIProvider().GetCredentials(&AuthRequest{Ref: tagImage})\n\tassertions.Nil(kc)\n\tassertions.Error(err)\n\n\tgopts := []grpc.DialOption{\n\t\tgrpc.WithTransportCredentials(insecure.NewCredentials()),\n\t\tgrpc.WithContextDialer(dialer.ContextDialer),\n\t}\n\n\tconn, err := grpc.NewClient(dialer.DialAddress(proxySocket), gopts...)\n\tassertions.NoError(err)\n\tcriClient := runtime.NewImageServiceClient(conn)\n\n\t_, err = criClient.PullImage(ctx, &runtime.PullImageRequest{\n\t\tImage: &runtime.ImageSpec{\n\t\t\tImage: tagImage,\n\t\t},\n\t\tAuth: &runtime.AuthConfig{\n\t\t\tUsername: \"test\",\n\t\t\tPassword: \"passwd\",\n\t\t},\n\t})\n\tassertions.NoError(err)\n\n\t// get correct kc after pulling\n\tkc, err = NewCRIProvider().GetCredentials(&AuthRequest{Ref: tagImage})\n\tassertions.Equal(\"test\", kc.Username)\n\tassertions.Equal(\"passwd\", kc.Password)\n\tassertions.NoError(err)\n\n\t// get empty kc with wrong tag\n\tkc, err = NewCRIProvider().GetCredentials(&AuthRequest{Ref: \"docker.io/library/busybox:another\"})\n\tassertions.Nil(kc)\n\tassertions.Error(err)\n\n\timage2 := \"ghcr.io/busybox:latest\"\n\n\t_, err = criClient.PullImage(ctx, &runtime.PullImageRequest{\n\t\tImage: &runtime.ImageSpec{\n\t\t\tImage: image2,\n\t\t},\n\t\tAuth: &runtime.AuthConfig{\n\t\t\tUsername: \"test_1\",\n\t\t\tPassword: \"passwd_1\",\n\t\t},\n\t})\n\tassertions.NoError(err)\n\n\t// get correct kc after pulling\n\tkc, err = NewCRIProvider().GetCredentials(&AuthRequest{Ref: image2})\n\tassertions.NoError(err)\n\tassertions.Equal(kc.Username, \"test_1\")\n\tassertions.Equal(kc.Password, \"passwd_1\")\n\n\t// should work with digest\n\tdigestImage := \"docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa\"\n\t_, err = criClient.PullImage(ctx, &runtime.PullImageRequest{\n\t\tImage: &runtime.ImageSpec{\n\t\t\tImage: digestImage,\n\t\t},\n\t\tAuth: &runtime.AuthConfig{\n\t\t\tUsername: \"digest\",\n\t\t\tPassword: \"dpwd\",\n\t\t},\n\t})\n\tassertions.NoError(err)\n\n\t// get correct kc after pulling\n\tkc, err = NewCRIProvider().GetCredentials(&AuthRequest{Ref: digestImage})\n\tassertions.NoError(err)\n\tassertions.Equal(\"digest\", kc.Username)\n\tassertions.Equal(\"dpwd\", kc.Password)\n}\n"
  },
  {
    "path": "pkg/auth/docker.go",
    "content": "/*\n * Copyright (c) 2021. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\tdockerconfig \"github.com/docker/cli/cli/config\"\n\t\"github.com/docker/cli/cli/config/configfile\"\n\t\"github.com/pkg/errors\"\n)\n\nconst (\n\tdockerHost          = \"https://index.docker.io/v1/\"\n\tconvertedDockerHost = \"registry-1.docker.io\"\n)\n\n// DockerProvider retrieves credentials from Docker's config.json.\ntype DockerProvider struct {\n\tdockerConfig *configfile.ConfigFile\n}\n\n// NewDockerProvider creates a new Docker config-based auth provider.\nfunc NewDockerProvider() *DockerProvider {\n\treturn &DockerProvider{\n\t\tdockerConfig: dockerconfig.LoadDefaultConfigFile(os.Stderr),\n\t}\n}\n\n// CanRenew implements RenewableProvider. Docker credentials can be\n// refreshed by re-reading the config file. Works well with docker credential helpers.\nfunc (p *DockerProvider) CanRenew() bool { return true }\n\nfunc (p *DockerProvider) String() string {\n\treturn \"docker\"\n}\n\n// GetCredentials retrieves credentials from Docker's config.json.\n// Returns nil if no credentials are found for the registry.\nfunc (p *DockerProvider) GetCredentials(req *AuthRequest) (*PassKeyChain, error) {\n\tif req == nil || req.Ref == \"\" {\n\t\treturn nil, errors.New(\"ref not found in request\")\n\t}\n\n\t_, host, err := parseReference(req.Ref)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"parse reference %s\", req.Ref)\n\t}\n\n\t// The host of docker hub image will be converted to `registry-1.docker.io` in:\n\t// github.com/containerd/containerd/remotes/docker/registry.go\n\t// But we need use the key `https://index.docker.io/v1/` to find auth from docker config.\n\tif host == convertedDockerHost {\n\t\thost = dockerHost\n\t}\n\n\tauthConfig, err := p.dockerConfig.GetAuthConfig(host)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"no auth from docker config for host %s\", host)\n\t}\n\n\t// Do not return partially empty auth. It makes caller life easier.\n\tif len(authConfig.Username) == 0 || len(authConfig.Password) == 0 {\n\t\treturn nil, fmt.Errorf(\"auth config not complete for host: %s\", host)\n\t}\n\n\treturn &PassKeyChain{\n\t\tUsername: authConfig.Username,\n\t\tPassword: authConfig.Password,\n\t}, nil\n}\n"
  },
  {
    "path": "pkg/auth/docker_test.go",
    "content": "/*\n * Copyright (c) 2021. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nconst (\n\ttestConfigFmt = `\n{\n        \"auths\": {\n                \"%s\": {\n                        \"auth\": \"%s\"\n                },\n                \"%s\": {\n                        \"auth\": \"%s\"\n                }\n        }\n}\n`\n\tdockerUser = \"dockeruserfoobar\"\n\tdockerPass = \"dockerpassfoobar\"\n\textraHost  = \"reg.docker.alibaba-cloud.com\"\n\textraUser  = \"extrauserfoobar\"\n\textraPass  = \"extrapassfoobar\"\n\n\tconfigFile = \"config.json\"\n)\n\nvar oldDockerConfig = os.Getenv(\"DOCKER_CONFIG\")\n\nfunc setupDockerConfig() (string, error) {\n\tdir, err := os.MkdirTemp(\"\", \"testdocker-\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tos.Setenv(\"DOCKER_CONFIG\", dir)\n\n\terr = os.WriteFile(filepath.Join(dir, configFile),\n\t\t[]byte(fmt.Sprintf(testConfigFmt, dockerHost, base64.StdEncoding.EncodeToString([]byte(dockerUser+\":\"+dockerPass)),\n\t\t\textraHost, base64.StdEncoding.EncodeToString([]byte(extraUser+\":\"+extraPass)))),\n\t\t0600)\n\tif err != nil {\n\t\tos.RemoveAll(dir)\n\t\treturn \"\", err\n\t}\n\n\treturn dir, nil\n}\n\nfunc TestDockerCred(t *testing.T) {\n\tassert := assert.New(t)\n\n\tdir, err := setupDockerConfig()\n\tassert.Nil(err)\n\tdefer func() {\n\t\tos.RemoveAll(dir)\n\t\tos.Setenv(\"DOCKER_CONFIG\", oldDockerConfig)\n\t}()\n\n\t// Empty host should get empty auth\n\tauth, err := NewDockerProvider().GetCredentials(&AuthRequest{Ref: \"\"})\n\tassert.Nil(auth)\n\tassert.Error(err)\n\n\t// Unmatching host should get empty auth\n\tauth, err = NewDockerProvider().GetCredentials(&AuthRequest{Ref: \"foo\"})\n\tassert.Nil(auth)\n\tassert.Error(err)\n\n\tauth, err = NewDockerProvider().GetCredentials(&AuthRequest{Ref: convertedDockerHost + \"/foo:bar\"})\n\tassert.NotNil(auth)\n\tassert.NoError(err)\n\tassert.Equal(auth.Username, dockerUser)\n\tassert.Equal(auth.Password, dockerPass)\n\n\tauth, err = NewDockerProvider().GetCredentials(&AuthRequest{Ref: extraHost + \"/foo:bar\"})\n\tassert.NotNil(auth)\n\tassert.NoError(err)\n\tassert.Equal(auth.Username, extraUser)\n\tassert.Equal(auth.Password, extraPass)\n}\n"
  },
  {
    "path": "pkg/auth/keychain.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"encoding/base64\"\n\tstderrors \"errors\"\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/google/go-containerregistry/pkg/authn\"\n\t\"github.com/pkg/errors\"\n)\n\nconst (\n\tsep = \":\"\n)\n\nvar (\n\temptyPassKeyChain = PassKeyChain{}\n)\n\n// PassKeyChain is user/password based key chain\ntype PassKeyChain struct {\n\tUsername string\n\tPassword string\n}\n\nfunc FromBase64(str string) (PassKeyChain, error) {\n\tdecoded, err := base64.StdEncoding.DecodeString(str)\n\tif err != nil {\n\t\treturn emptyPassKeyChain, err\n\t}\n\tpair := strings.Split(string(decoded), sep)\n\tif len(pair) != 2 {\n\t\treturn emptyPassKeyChain, errors.New(\"invalid registry auth token\")\n\t}\n\treturn PassKeyChain{\n\t\tUsername: pair[0],\n\t\tPassword: pair[1],\n\t}, nil\n}\n\nfunc (kc PassKeyChain) ToBase64() string {\n\tif kc.Username == \"\" && kc.Password == \"\" {\n\t\treturn \"\"\n\t}\n\treturn base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf(\"%s:%s\", kc.Username, kc.Password)))\n}\n\n// TokenBase check if PassKeyChain is token based, when username is empty and password is not empty\n// then password is registry token\nfunc (kc PassKeyChain) TokenBase() bool {\n\treturn kc.Username == \"\" && kc.Password != \"\"\n}\n\n// renewableProviders returns the ordered list of providers used exclusively\n// by the renewal goroutine. CRI and Labels are excluded: CRI caches\n// credentials globally and would keep returning them at renewal time,\n// preventing the renewable providers from being reached; Labels are only\n// available at pull time via snapshot labels and are not accessible during\n// renewal. It is a variable so tests can substitute a different builder.\nvar renewableProviders = func() []AuthProvider {\n\tproviders := []AuthProvider{NewDockerProvider()}\n\tif kubeletProvider != nil {\n\t\tproviders = append(providers, kubeletProvider)\n\t}\n\treturn append(providers, NewKubeSecretProvider())\n}\n\n// buildProviders returns the full ordered list of auth providers.\n// Priority: labels > CRI > docker > kubelet > kubesecret.\n// It is a variable so tests can substitute a different builder.\nvar buildProviders = func() []AuthProvider {\n\treturn append([]AuthProvider{NewLabelsProvider(), NewCRIProvider()}, renewableProviders()...)\n}\n\n// GetRegistryKeyChain retrieves image pull credentials from the first provider\n// that returns a result, checked in priority order:\n// 1. credential renewal store (if enabled)\n// 2. username and secrets labels\n// 3. cri request\n// 4. docker config\n// 5. kubelet credential helpers\n// 6. k8s docker config secret\n//\n// When a renewable provider returns credentials and the renewal store is\n// enabled, the credentials are cached for periodic renewal.\nfunc GetRegistryKeyChain(ref string, labels map[string]string) *PassKeyChain {\n\treturn getRegistryKeyChainFromProviders(ref, labels, buildProviders())\n}\n\n// getRegistryKeyChainFromProviders is the testable core of GetRegistryKeyChain.\nfunc getRegistryKeyChainFromProviders(ref string, labels map[string]string, providers []AuthProvider) *PassKeyChain {\n\tlogger := log.L.WithField(\"ref\", ref)\n\n\tauthReq := &AuthRequest{Ref: ref, Labels: labels}\n\t// Serve from the renewal store if available.\n\tif renewalStore != nil {\n\t\tif kc := renewalStore.Get(ref); kc != nil {\n\t\t\tlogger.Debug(\"serving credentials from renewal store\")\n\t\t\treturn kc\n\t\t}\n\t\t// If not available, request credentials valid until the next renewal tick.\n\t\tauthReq.ValidUntil = time.Now().Add(renewalStore.renewInterval)\n\t}\n\treturn fetchFromProviders(authReq, providers)\n}\n\n// fetchFromProviders walks providers in order and returns credentials from the\n// first one that succeeds. If the winning provider is renewable and the renewal\n// store is active, the credentials are cached for periodic renewal.\nfunc fetchFromProviders(req *AuthRequest, providers []AuthProvider) *PassKeyChain {\n\tlogger := log.L.WithField(\"ref\", req.Ref)\n\n\tvar errs []error\n\tfor _, provider := range providers {\n\t\tlogger.Debugf(\"Trying to get credentials from %s\", provider)\n\t\tkc, err := provider.GetCredentials(req)\n\t\tif err != nil {\n\t\t\terrs = append(errs, errors.Wrapf(err, \"get credentials from %T\", provider))\n\t\t}\n\t\tif kc != nil {\n\t\t\tlogger.Infof(\"Got credentials from provider %s\", provider)\n\t\t\t// Cache in the renewal store when the provider supports renewal.\n\t\t\tif renewalStore != nil {\n\t\t\t\tif rp, ok := provider.(RenewableProvider); ok && rp.CanRenew() {\n\t\t\t\t\trenewalStore.Add(req.Ref, kc)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn kc\n\t\t}\n\t}\n\n\tif len(errs) > 0 {\n\t\tlogger.WithError(stderrors.Join(errs...)).Warn(\"Could not get registry credentials.\")\n\t}\n\treturn nil\n}\n\nfunc GetKeyChainByRef(ref string, labels map[string]string) (*PassKeyChain, error) {\n\tkeychain := GetRegistryKeyChain(ref, labels)\n\n\treturn keychain, nil\n}\n\nfunc (kc PassKeyChain) Resolve(_ authn.Resource) (authn.Authenticator, error) {\n\treturn authn.FromConfig(kc.toAuthConfig()), nil\n}\n\n// toAuthConfig convert PassKeyChain to authn.AuthConfig when kc is token based,\n// RegistryToken is preferred to\nfunc (kc PassKeyChain) toAuthConfig() authn.AuthConfig {\n\tif kc.TokenBase() {\n\t\treturn authn.AuthConfig{\n\t\t\tRegistryToken: kc.Password,\n\t\t}\n\t}\n\treturn authn.AuthConfig{\n\t\tUsername: kc.Username,\n\t\tPassword: kc.Password,\n\t}\n}\n"
  },
  {
    "path": "pkg/auth/kubelet.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"maps\"\n\t\"net\"\n\t\"net/url\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/pkg/errors\"\n\tkubeletconfigv1 \"k8s.io/kubelet/config/v1\"\n\tcredentialproviderv1 \"k8s.io/kubelet/pkg/apis/credentialprovider/v1\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nconst (\n\tpluginExecTimeout = 1 * time.Minute\n\t// globalCacheKey is the key used for caching credentials that are not specific to a registry or image.\n\t// Angle brackets are used to avoid conflicts with actual image or registry names.\n\tglobalCacheKey = \"<global>\"\n)\n\nvar (\n\tkubeletProvider   *KubeletProvider\n\tkubeletProviderMu sync.Mutex\n)\n\n// KubeletProvider retrieves credentials using Kubernetes credential provider plugins.\ntype KubeletProvider struct {\n\tplugins []*kubeletconfigv1.CredentialProvider\n\tbinDir  string\n\tmu      sync.RWMutex\n\tcache   map[string]*kubeletCredential // cache key (image or registry or global) -> cached credential\n}\n\n// kubeletCredential pairs a PassKeyChain with its provider-reported expiry.\ntype kubeletCredential struct {\n\tkeychains map[string]*PassKeyChain\n\texpiresAt time.Time // zero means no cache (always re-exec plugin)\n}\n\n// InitKubeletProvider initializes the global kubelet credential provider.\n// This should be called once at startup if kubelet credential providers are enabled.\nfunc InitKubeletProvider(configPath, binDir string) error {\n\tkubeletProviderMu.Lock()\n\tdefer kubeletProviderMu.Unlock()\n\n\tif kubeletProvider != nil {\n\t\treturn nil\n\t}\n\n\tprovider, err := NewKubeletProvider(configPath, binDir)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to create kubelet provider\")\n\t}\n\n\tkubeletProvider = provider\n\tlog.L.Info(\"kubelet credential provider initialized\")\n\treturn nil\n}\n\n// NewKubeletProvider creates a new kubelet credential helpers-based auth provider.\nfunc NewKubeletProvider(configPath, binDir string) (*KubeletProvider, error) {\n\tif configPath == \"\" {\n\t\treturn nil, errors.New(\"config path cannot be empty\")\n\t}\n\n\tif binDir == \"\" {\n\t\treturn nil, errors.New(\"bin directory cannot be empty\")\n\t}\n\n\t// Load configuration\n\tdata, err := os.ReadFile(configPath)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to read config file %s\", configPath)\n\t}\n\n\tvar config kubeletconfigv1.CredentialProviderConfig\n\t// Using the yaml library from sigs.k8s.io/yaml because it supports both YAML and JSON\n\t// and the type CredentialProvider only has json markups which are used by this lib's Unmarshal\n\tif err := yaml.Unmarshal(data, &config); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to parse credential provider config\")\n\t}\n\n\tif len(config.Providers) == 0 {\n\t\treturn nil, errors.New(\"at least one provider is required\")\n\t}\n\n\tprovider := &KubeletProvider{\n\t\tplugins: make([]*kubeletconfigv1.CredentialProvider, 0, len(config.Providers)),\n\t\tbinDir:  binDir,\n\t\tcache:   make(map[string]*kubeletCredential),\n\t}\n\n\t// Validate and register credential providers\n\t// Heavily inspired by kubelet's validateCredentialProviderConfig function\n\tcredProviderNames := make(map[string]struct{})\n\tfor i := range config.Providers {\n\t\tif err := validateCredentialProvider(&config.Providers[i]); err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"failed to validate credential provider %s\", config.Providers[i].Name)\n\t\t}\n\n\t\t// Check for duplicate provider names\n\t\tif _, ok := credProviderNames[config.Providers[i].Name]; ok {\n\t\t\treturn nil, fmt.Errorf(\"duplicate provider name: %s\", config.Providers[i].Name)\n\t\t}\n\t\tcredProviderNames[config.Providers[i].Name] = struct{}{}\n\t\tprovider.plugins = append(provider.plugins, &config.Providers[i])\n\t\tlog.L.WithField(\"name\", config.Providers[i].Name).Info(\"registered kubelet credential provider plugin\")\n\t}\n\n\treturn provider, nil\n}\n\n// validateCredentialProvider validates a single credential provider configuration.\nfunc validateCredentialProvider(p *kubeletconfigv1.CredentialProvider) error {\n\t// Validate provider name\n\tif p.Name == \"\" {\n\t\treturn fmt.Errorf(\"provider name is required\")\n\t}\n\n\t// Provider name must not contain path separators or special characters\n\tif strings.ContainsAny(p.Name, \" /\\\\\") || p.Name == \".\" || p.Name == \"..\" {\n\t\treturn fmt.Errorf(\"invalid provider name %q: cannot contain spaces, path separators, or be '.' or '..'\", p.Name)\n\t}\n\n\t// Validate API version\n\tif p.APIVersion == \"\" {\n\t\treturn fmt.Errorf(\"provider %s: apiVersion is required\", p.Name)\n\t}\n\n\t// Only support v1 for now\n\tif p.APIVersion != \"credentialprovider.kubelet.k8s.io/v1\" {\n\t\treturn fmt.Errorf(\"provider %s: unsupported apiVersion %q (only v1 is supported)\", p.Name, p.APIVersion)\n\t}\n\n\t// Validate match images\n\tif len(p.MatchImages) == 0 {\n\t\treturn fmt.Errorf(\"provider %s: at least one matchImage is required\", p.Name)\n\t}\n\n\tif slices.Contains(p.MatchImages, \"\") {\n\t\treturn fmt.Errorf(\"provider %s: empty matchImage pattern\", p.Name)\n\t}\n\n\t// Validate cache duration\n\tif p.DefaultCacheDuration == nil {\n\t\treturn fmt.Errorf(\"provider %s: defaultCacheDuration is required\", p.Name)\n\t}\n\n\tif p.DefaultCacheDuration.Duration < 0 {\n\t\treturn fmt.Errorf(\"provider %s: defaultCacheDuration must be >= 0\", p.Name)\n\t}\n\n\t// Validate environment variables\n\tenvNames := make(map[string]struct{})\n\tfor _, env := range p.Env {\n\t\tif env.Name == \"\" {\n\t\t\treturn fmt.Errorf(\"provider %s: environment variable name cannot be empty\", p.Name)\n\t\t}\n\t\tif _, ok := envNames[env.Name]; ok {\n\t\t\treturn fmt.Errorf(\"provider %s: duplicate environment variable name: %s\", p.Name, env.Name)\n\t\t}\n\t\tenvNames[env.Name] = struct{}{}\n\t}\n\n\treturn nil\n}\n\n// CanRenew implements RenewableProvider. Kubelet credentials can be\n// refreshed by re-executing the credential provider plugins.\nfunc (p *KubeletProvider) CanRenew() bool { return true }\n\nfunc (p *KubeletProvider) String() string {\n\treturn \"kubelet\"\n}\n\n// GetCredentials retrieves credentials using kubelet credential provider plugins.\n// It first checks the cache using the same cacheKeyType-based lookup as the\n// kubelet (image -> registry -> global). On a cache miss it executes all\n// matching plugins, stores results keyed by cacheKeyType, and returns the most\n// specific match for the requested ref.\nfunc (p *KubeletProvider) GetCredentials(req *AuthRequest) (*PassKeyChain, error) {\n\tif req == nil || req.Ref == \"\" {\n\t\treturn nil, errors.New(\"ref not found in request\")\n\t}\n\n\t// Normalize the reference to handle short refs like \"nginx:latest\" -> \"docker.io/library/nginx:latest\"\n\trefSpec, _, err := parseReference(req.Ref)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to parse image reference\")\n\t}\n\n\timage := refSpec.String()\n\n\t// Evict expired before adding new ones to bound the map size\n\tp.evictExpired()\n\n\t// Fast path: serve from cache when a valid-long-enough credential exists.\n\t// Lookup order follows the kubelet: image key, registry key, global key.\n\tcred := p.getCachedCredential(image, req.ValidUntil)\n\tif cred != nil {\n\t\tif kc := bestKeychainMatch(cred.keychains, image); kc != nil {\n\t\t\tlog.L.WithField(\"ref\", req.Ref).Debug(\"serving kubelet credentials from cache\")\n\t\t\treturn kc, nil\n\t\t}\n\t}\n\n\t// Slow path: execute matching plugins\n\tallKeychains := make(map[string]*PassKeyChain)\n\tfor _, plugin := range p.plugins {\n\t\tif !isImageAllowed(plugin, image) {\n\t\t\tcontinue\n\t\t}\n\n\t\t// The spec mentions that:\n\t\t// \"If one of the strings matches the requested image from the kubelet, the plugin will be invoked and given a chance to provide credentials\"\n\t\t// So each matching plugin should have a chance to fetch credentials\n\t\t// TODO: parallelize?\n\t\tresp, err := p.execPlugin(context.Background(), plugin, image)\n\t\tif err != nil {\n\t\t\tlog.L.WithError(err).WithFields(map[string]any{\"plugin\": plugin.Name, \"ref\": req.Ref}).Warn(\"failed to execute credential provider plugin\")\n\t\t\tcontinue\n\t\t}\n\n\t\tif resp.Auth == nil {\n\t\t\t// Spec: A plugin should set this field (Auth) to null if no valid credentials can be returned for the requested image.\n\t\t\tcontinue\n\t\t}\n\n\t\tcacheKey := computeCacheKey(resp.CacheKeyType, image)\n\t\tif cacheKey == \"\" {\n\t\t\tlog.L.WithFields(map[string]any{\n\t\t\t\t\"plugin\":       plugin.Name,\n\t\t\t\t\"cacheKeyType\": resp.CacheKeyType,\n\t\t\t}).Warn(\"credential provider plugin returned invalid cacheKeyType\")\n\t\t\tcontinue\n\t\t}\n\n\t\tkeychains := make(map[string]*PassKeyChain, len(resp.Auth))\n\t\tfor registryGlob, authConfig := range resp.Auth {\n\t\t\t// First plugin wins for overlapping auth keys, matching the kubelet spec:\n\t\t\t// \"If providers return overlapping auth keys, the value from the provider\n\t\t\t// earlier in this list is used.\"\n\t\t\tif _, exists := allKeychains[registryGlob]; exists {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tkc := &PassKeyChain{\n\t\t\t\tUsername: authConfig.Username,\n\t\t\t\tPassword: authConfig.Password,\n\t\t\t}\n\t\t\tkeychains[registryGlob] = kc\n\t\t\tallKeychains[registryGlob] = kc\n\t\t}\n\n\t\tvar expiresAt time.Time\n\t\tif d := resolveCacheDuration(resp, plugin); d > 0 {\n\t\t\texpiresAt = time.Now().Add(d)\n\t\t}\n\n\t\t// Only cache when the plugin provides a TTL.\n\t\t// A zero duration means no caching (plugin will be re-executed on the next request).\n\t\tif !expiresAt.IsZero() {\n\t\t\tlog.L.WithFields(map[string]any{\n\t\t\t\t\"cacheKeyType\": resp.CacheKeyType,\n\t\t\t\t\"cacheKey\":     cacheKey,\n\t\t\t\t\"duration\":     time.Until(expiresAt).Round(time.Second),\n\t\t\t\t\"registries\":   slices.Collect(maps.Keys(keychains)),\n\t\t\t}).Debug(\"caching kubelet credential provider response\")\n\n\t\t\tp.mu.Lock()\n\t\t\tp.cache[cacheKey] = &kubeletCredential{\n\t\t\t\tkeychains: keychains,\n\t\t\t\texpiresAt: expiresAt,\n\t\t\t}\n\t\t\tp.mu.Unlock()\n\t\t}\n\t}\n\n\tif len(allKeychains) == 0 {\n\t\treturn nil, errors.New(\"no credentials found\")\n\t}\n\n\tkc := bestKeychainMatch(allKeychains, image)\n\tif kc == nil {\n\t\treturn nil, errors.New(\"no matching registries found\")\n\t}\n\treturn kc, nil\n}\n\n// evictExpired removes all expired entries from p.cache.\nfunc (p *KubeletProvider) evictExpired() {\n\tp.mu.Lock()\n\tdefer p.mu.Unlock()\n\tnow := time.Now()\n\tfor key, cred := range p.cache {\n\t\tif cred.expiresAt.IsZero() || now.After(cred.expiresAt) {\n\t\t\tdelete(p.cache, key)\n\t\t}\n\t}\n}\n\n// getCachedCredential looks up a cached credential for the given image using the\n// same lookup order as the kubelet: image key, registry key, then global key.\n// Returns nil when no valid, non-expired match exists that satisfies validUntil.\nfunc (p *KubeletProvider) getCachedCredential(image string, validUntil time.Time) *kubeletCredential {\n\tp.mu.RLock()\n\tdefer p.mu.RUnlock()\n\n\tnow := time.Now()\n\tfor _, key := range []string{image, parseRegistry(image), globalCacheKey} {\n\t\tcred, ok := p.cache[key]\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tif cred.expiresAt.IsZero() || now.After(cred.expiresAt) {\n\t\t\tcontinue\n\t\t}\n\t\tif !validUntil.IsZero() && !cred.expiresAt.After(validUntil) {\n\t\t\tcontinue\n\t\t}\n\t\treturn cred\n\t}\n\treturn nil\n}\n\n// bestKeychainMatch returns the most specific PassKeyChain whose registry glob\n// matches image, using reverse-alphabetical order (longer/more specific paths first).\nfunc bestKeychainMatch(keychains map[string]*PassKeyChain, image string) *PassKeyChain {\n\tvar matching []string\n\tfor registry := range keychains {\n\t\tif matched, err := urlsMatchStr(registry, image); err == nil && matched {\n\t\t\tmatching = append(matching, registry)\n\t\t} else if err != nil {\n\t\t\tlog.L.WithError(err).\n\t\t\t\tWithField(\"registry\", registry).\n\t\t\t\tWithField(\"image\", image).\n\t\t\t\tWarn(\"registry pattern does not match image\")\n\t\t}\n\t}\n\tif len(matching) == 0 {\n\t\treturn nil\n\t}\n\t// Sort in reverse alphabetical order: longer/more specific paths sort first.\n\t// For example, \"gcr.io/etcd-development\" matches before \"gcr.io\".\n\tsort.Sort(sort.Reverse(sort.StringSlice(matching)))\n\treturn keychains[matching[0]]\n}\n\n// computeCacheKey determines the cache key for a plugin response based on the\n// cacheKeyType field, following the same logic as the kubelet.\n// Inspired from https://github.com/kubernetes/kubernetes/blob/v1.35.0/pkg/credentialprovider/plugin/plugin.go#L545\nfunc computeCacheKey(cacheKeyType credentialproviderv1.PluginCacheKeyType, image string) string {\n\tswitch cacheKeyType {\n\tcase credentialproviderv1.ImagePluginCacheKeyType:\n\t\treturn image\n\tcase credentialproviderv1.RegistryPluginCacheKeyType:\n\t\treturn parseRegistry(image)\n\tcase credentialproviderv1.GlobalPluginCacheKeyType:\n\t\treturn globalCacheKey\n\tdefault:\n\t\treturn \"\"\n\t}\n}\n\n// parseRegistry extracts the registry (host and port) from an image string.\n// Ported: https://github.com/kubernetes/kubernetes/blob/v1.35.0/pkg/credentialprovider/plugin/plugin.go#L592\nfunc parseRegistry(image string) string {\n\timageParts := strings.Split(image, \"/\")\n\treturn imageParts[0]\n}\n\n// resolveCacheDuration picks the effective TTL from a plugin response:\n// the per-response CacheDuration takes precedence if it is positive,\n// otherwise the plugin's DefaultCacheDuration is used.\nfunc resolveCacheDuration(resp *credentialproviderv1.CredentialProviderResponse, plugin *kubeletconfigv1.CredentialProvider) time.Duration {\n\tif resp.CacheDuration != nil && resp.CacheDuration.Duration >= 0 {\n\t\treturn resp.CacheDuration.Duration\n\t}\n\treturn plugin.DefaultCacheDuration.Duration\n}\n\n// isImageAllowed returns true if the image matches against the list of allowed matches by the plugin.\n// Inspired from https://github.com/kubernetes/kubernetes/blob/v1.35.0/pkg/credentialprovider/plugin/plugin.go#L603\nfunc isImageAllowed(plugin *kubeletconfigv1.CredentialProvider, image string) bool {\n\tfor _, matchImage := range plugin.MatchImages {\n\t\tmatched, err := urlsMatchStr(matchImage, image)\n\t\tif err != nil {\n\t\t\tlog.L.WithError(err).\n\t\t\t\tWithField(\"plugin\", plugin.Name).\n\t\t\t\tWithField(\"matchImage\", matchImage).\n\t\t\t\tWarn(\"invalid matchImage pattern in credential provider config\")\n\t\t\tcontinue\n\t\t}\n\t\tif matched {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// execPlugin executes the credential provider plugin binary.\nfunc (p *KubeletProvider) execPlugin(ctx context.Context, plugin *kubeletconfigv1.CredentialProvider, image string) (*credentialproviderv1.CredentialProviderResponse, error) {\n\trequest := &credentialproviderv1.CredentialProviderRequest{\n\t\tImage: image,\n\t}\n\trequest.APIVersion = plugin.APIVersion\n\trequest.Kind = \"CredentialProviderRequest\"\n\n\t// Encode request\n\trequestJSON, err := json.Marshal(request)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to marshal request\")\n\t}\n\n\t// Create command with timeout\n\tctx, cancel := context.WithTimeout(ctx, pluginExecTimeout)\n\tdefer cancel()\n\n\t// Inherit environment from snapshotter\n\tenv := os.Environ()\n\tfor _, e := range plugin.Env {\n\t\tenv = append(env, fmt.Sprintf(\"%s=%s\", e.Name, e.Value))\n\t}\n\n\tcmd := exec.CommandContext(ctx, filepath.Join(p.binDir, plugin.Name), plugin.Args...)\n\tcmd.Env = env\n\n\tstdout := &bytes.Buffer{}\n\tstderr := &bytes.Buffer{}\n\tstdin := bytes.NewBuffer(requestJSON)\n\tcmd.Stdout, cmd.Stderr, cmd.Stdin = stdout, stderr, stdin\n\n\t// Execute\n\terr = cmd.Run()\n\tif ctx.Err() != nil {\n\t\treturn nil, errors.Wrap(ctx.Err(), \"error execing credential provider plugin\")\n\t}\n\tif err != nil {\n\t\tstderrStr := stderr.String()\n\t\treturn nil, errors.Wrapf(err, \"error execing credential provider plugin, stderr: %s\", stderrStr)\n\t}\n\n\t// Decode response\n\tvar response credentialproviderv1.CredentialProviderResponse\n\tif err := json.Unmarshal(stdout.Bytes(), &response); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to decode plugin response\")\n\t}\n\n\tif response.APIVersion != request.APIVersion {\n\t\treturn nil, fmt.Errorf(\"plugin returned API version %s, expected %s\",\n\t\t\tresponse.APIVersion, request.APIVersion)\n\t}\n\n\treturn &response, nil\n}\n\n/*\n#####\t\t\t\t\t\t\t\tPORTED FROM KUBERNETES\t\t\t\t\t\t\t\t#####\n\nThe following functions are ported from k8s.io/kubernetes/pkg/credentialprovider/keyring.go\nSince they are in `k8s.io/kubernetes`, we can't import them directly.\n*/\n\n// parseSchemelessURL parses a schemeless url and returns a url.URL\n// url.Parse require a scheme, but ours don't have schemes.  Adding a\n// scheme to make url.Parse happy, then clear out the resulting scheme.\n// Ported: https://github.com/kubernetes/kubernetes/blob/v1.35.0/pkg/credentialprovider/keyring.go#L220\nfunc parseSchemelessURL(schemelessURL string) (*url.URL, error) {\n\tparsed, err := url.Parse(\"https://\" + schemelessURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t// clear out the resulting scheme\n\tparsed.Scheme = \"\"\n\treturn parsed, nil\n}\n\n// splitURL splits the host name into parts, as well as the port\n// Ported: https://github.com/kubernetes/kubernetes/blob/v1.35.0/pkg/credentialprovider/keyring.go#L231\nfunc splitURL(url *url.URL) (parts []string, port string) {\n\thost, port, err := net.SplitHostPort(url.Host)\n\tif err != nil {\n\t\t// could not parse port\n\t\thost, port = url.Host, \"\"\n\t}\n\treturn strings.Split(host, \".\"), port\n}\n\n// urlsMatchStr is wrapper for urlsMatch, operating on strings instead of URLs.\n// Ported: https://github.com/kubernetes/kubernetes/blob/v1.35.0/pkg/credentialprovider/keyring.go#L241\nfunc urlsMatchStr(glob string, target string) (bool, error) {\n\tglobURL, err := parseSchemelessURL(glob)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\ttargetURL, err := parseSchemelessURL(target)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\treturn urlsMatch(globURL, targetURL)\n}\n\n// urlsMatch checks whether the given target url matches the glob url, which may have\n// glob wild cards in the host name.\n//\n// Examples:\n//\n//\tglobURL=*.docker.io, targetURL=blah.docker.io => match\n//\tglobURL=*.docker.io, targetURL=not.right.io   => no match\n//\n// Note that we don't support wildcards in ports and paths yet.\n// Ported: https://github.com/kubernetes/kubernetes/blob/v1.35.0/pkg/credentialprovider/keyring.go#L262\nfunc urlsMatch(globURL *url.URL, targetURL *url.URL) (bool, error) {\n\tglobURLParts, globPort := splitURL(globURL)\n\ttargetURLParts, targetPort := splitURL(targetURL)\n\tif globPort != targetPort {\n\t\t// port doesn't match\n\t\treturn false, nil\n\t}\n\tif len(globURLParts) != len(targetURLParts) {\n\t\t// host name does not have the same number of parts\n\t\treturn false, nil\n\t}\n\tif !strings.HasPrefix(targetURL.Path, globURL.Path) {\n\t\t// the path of the credential must be a prefix\n\t\treturn false, nil\n\t}\n\tfor k, globURLPart := range globURLParts {\n\t\ttargetURLPart := targetURLParts[k]\n\t\tmatched, err := filepath.Match(globURLPart, targetURLPart)\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\tif !matched {\n\t\t\t// glob mismatch for some part\n\t\t\treturn false, nil\n\t\t}\n\t}\n\t// everything matches\n\treturn true, nil\n}\n\n/*\n#####\t\t\t\t\t\tEND OF PORTED FROM KUBERNETES\t\t\t\t\t\t#####\n*/\n"
  },
  {
    "path": "pkg/auth/kubelet_test.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\tkubeletconfigv1 \"k8s.io/kubelet/config/v1\"\n\tcredentialproviderv1 \"k8s.io/kubelet/pkg/apis/credentialprovider/v1\"\n\t\"sigs.k8s.io/yaml\"\n)\n\nconst (\n\ttestUser = \"test-user\"\n\ttestPass = \"test-pass\"\n)\n\ntype credentialMap map[string]struct{ username, password string }\n\n// setupKubeletProvider creates a temporary directory with mock credential provider\n// plugins and configuration file for testing.\nfunc setupKubeletProvider(t *testing.T) (configPath, binDir string) {\n\tt.Helper()\n\n\t// Create temporary directories\n\ttmpDir := t.TempDir()\n\n\tbinDir = filepath.Join(tmpDir, \"bin\")\n\terr := os.Mkdir(binDir, 0755)\n\trequire.NoError(t, err)\n\n\tconfigPath = filepath.Join(tmpDir, \"credential-config.yaml\")\n\n\treturn configPath, binDir\n}\n\n// buildAuthSection builds a JSON auth map for a mock plugin response.\nfunc buildAuthSection(registries credentialMap) string {\n\tif len(registries) == 0 {\n\t\treturn \"null\"\n\t}\n\tauth := \"{\"\n\tfirst := true\n\tfor registry, creds := range registries {\n\t\tif !first {\n\t\t\tauth += \",\"\n\t\t}\n\t\tauth += fmt.Sprintf(`\"%s\":{\"username\":\"%s\",\"password\":\"%s\"}`,\n\t\t\tregistry, creds.username, creds.password)\n\t\tfirst = false\n\t}\n\treturn auth + \"}\"\n}\n\n// createMockPlugin creates a mock credential provider plugin that returns\n// credentials based on the input image. If registries is empty, return null auth.\n// Uses a 10m cacheDuration so results are cached by default.\nfunc createMockPlugin(t *testing.T, binDir, pluginName string, registries credentialMap) {\n\tt.Helper()\n\tcreateMockPluginWithTTL(t, binDir, pluginName, registries, \"10m\")\n}\n\n// createMockPluginWithTTL is like createMockPlugin but lets the caller control\n// the cacheDuration field in the response (e.g. \"0s\" to disable caching).\nfunc createMockPluginWithTTL(t *testing.T, binDir, pluginName string, registries credentialMap, cacheDuration string) {\n\tt.Helper()\n\tcreateMockPluginFull(t, binDir, pluginName, registries, cacheDuration, \"Image\")\n}\n\n// createMockPluginFull creates a mock plugin with full control over cacheDuration\n// and cacheKeyType fields in the response.\nfunc createMockPluginFull(t *testing.T, binDir, pluginName string, registries credentialMap, cacheDuration, cacheKeyType string) {\n\tt.Helper()\n\n\tscript := fmt.Sprintf(`#!/bin/bash\ncat > /dev/null\ncat <<'EOF'\n{\"kind\":\"CredentialProviderResponse\",\"apiVersion\":\"credentialprovider.kubelet.k8s.io/v1\",\"cacheKeyType\":%q,\"cacheDuration\":%q,\"auth\":%s}\nEOF\n`, cacheKeyType, cacheDuration, buildAuthSection(registries))\n\n\terr := os.WriteFile(filepath.Join(binDir, pluginName), []byte(script), 0755)\n\trequire.NoError(t, err)\n}\n\n// createMockCredentialProvider creates a CredentialProvider with the given parameters.\n// Uses 10m as the default cache duration.\nfunc createMockCredentialProvider(name string, matchImages []string) kubeletconfigv1.CredentialProvider {\n\treturn createMockCredentialProviderWithTTL(name, matchImages, 10*time.Minute)\n}\n\n// createMockCredentialProviderWithTTL is like createMockCredentialProvider but\n// lets the caller control the DefaultCacheDuration.\nfunc createMockCredentialProviderWithTTL(name string, matchImages []string, defaultTTL time.Duration) kubeletconfigv1.CredentialProvider {\n\treturn kubeletconfigv1.CredentialProvider{\n\t\tName:                 name,\n\t\tAPIVersion:           \"credentialprovider.kubelet.k8s.io/v1\",\n\t\tDefaultCacheDuration: &metav1.Duration{Duration: defaultTTL},\n\t\tMatchImages:          matchImages,\n\t}\n}\n\n// createMockProviderConfig creates a credential provider configuration file.\nfunc createMockProviderConfig(t *testing.T, configPath string, providers []kubeletconfigv1.CredentialProvider) {\n\tt.Helper()\n\n\tconfig := kubeletconfigv1.CredentialProviderConfig{\n\t\tTypeMeta: metav1.TypeMeta{\n\t\t\tAPIVersion: \"kubelet.config.k8s.io/v1\",\n\t\t\tKind:       \"CredentialProviderConfig\",\n\t\t},\n\t\tProviders: providers,\n\t}\n\n\tdata, err := yaml.Marshal(config)\n\trequire.NoError(t, err)\n\n\terr = os.WriteFile(configPath, data, 0644)\n\trequire.NoError(t, err)\n}\n\n// setupMockProvider creates a complete mock plugin + config for testing.\nfunc setupMockProvider(t *testing.T, binDir, pluginName, configPath string, registries credentialMap, matchImages []string) {\n\tt.Helper()\n\tcreateMockPlugin(t, binDir, pluginName, registries)\n\tcreateMockProviderConfig(t, configPath, []kubeletconfigv1.CredentialProvider{\n\t\tcreateMockCredentialProvider(pluginName, matchImages),\n\t})\n}\n\nfunc TestNewKubeletProvider(t *testing.T) {\n\tconfigPath, binDir := setupKubeletProvider(t)\n\n\ttests := []struct {\n\t\tname        string\n\t\tsetup       func(t *testing.T) (configPath, binDir string)\n\t\twantErr     bool\n\t\terrContains string\n\t\tvalidate    func(t *testing.T, provider *KubeletProvider)\n\t}{\n\t\t{\n\t\t\tname: \"successful initialization\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\tsetupMockProvider(t, binDir, \"test-plugin\", configPath,\n\t\t\t\t\tcredentialMap{\"registry.example.com\": {testUser, testPass}},\n\t\t\t\t\t[]string{\"*.example.com\"})\n\t\t\t\treturn configPath, binDir\n\t\t\t},\n\t\t\tvalidate: func(t *testing.T, provider *KubeletProvider) {\n\t\t\t\tassert.Len(t, provider.plugins, 1)\n\t\t\t\tassert.Equal(t, \"test-plugin\", provider.plugins[0].Name)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"empty config path\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\treturn \"\", binDir\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"config path cannot be empty\",\n\t\t},\n\t\t{\n\t\t\tname: \"empty bin directory\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\treturn configPath, \"\"\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"bin directory cannot be empty\",\n\t\t},\n\t\t{\n\t\t\tname: \"nonexistent config file\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\treturn \"/nonexistent/config.yaml\", binDir\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid config format\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\tinvalidConfigPath := filepath.Join(binDir, \"invalid.yaml\")\n\t\t\t\terr := os.WriteFile(invalidConfigPath, []byte(\"invalid: yaml: content: [\"), 0644)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn invalidConfigPath, binDir\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t\t{\n\t\t\tname: \"no providers in config\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\temptyConfigPath := filepath.Join(binDir, \"empty.yaml\")\n\t\t\t\terr := os.WriteFile(emptyConfigPath, []byte(`apiVersion: kubelet.config.k8s.io/v1\nkind: CredentialProviderConfig\nproviders: []\n`), 0644)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn emptyConfigPath, binDir\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"at least one provider is required\",\n\t\t},\n\t\t{\n\t\t\tname: \"duplicate provider names\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\tcreateMockPlugin(t, binDir, \"duplicate-plugin\", credentialMap{\"registry.example.com\": {testUser, testPass}})\n\t\t\t\tdupConfigPath := filepath.Join(binDir, \"duplicate.yaml\")\n\t\t\t\tcreateMockProviderConfig(t, dupConfigPath, []kubeletconfigv1.CredentialProvider{\n\t\t\t\t\tcreateMockCredentialProvider(\"duplicate-plugin\", []string{\"*.example.com\"}),\n\t\t\t\t\tcreateMockCredentialProvider(\"duplicate-plugin\", []string{\"*.docker.io\"}),\n\t\t\t\t})\n\t\t\t\treturn dupConfigPath, binDir\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"duplicate provider name\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tconfigPath, binDir := tt.setup(t)\n\t\t\tprovider, err := NewKubeletProvider(configPath, binDir)\n\n\t\t\tif tt.wantErr {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\tassert.Nil(t, provider)\n\t\t\t\tif tt.errContains != \"\" {\n\t\t\t\t\tassert.Contains(t, err.Error(), tt.errContains)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.NotNil(t, provider)\n\t\t\tif tt.validate != nil {\n\t\t\t\ttt.validate(t, provider)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestValidateCredentialProvider(t *testing.T) {\n\ttests := []struct {\n\t\tname        string\n\t\tsetup       func() *kubeletconfigv1.CredentialProvider\n\t\twantErr     bool\n\t\terrContains string\n\t}{\n\t\t{\n\t\t\tname: \"valid provider\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"empty provider name\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.Name = \"\"\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"provider name is required\",\n\t\t},\n\t\t{\n\t\t\tname: \"invalid provider name with path separator\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.Name = \"invalid/name\"\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"cannot contain spaces, path separators\",\n\t\t},\n\t\t{\n\t\t\tname: \"provider name with space\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.Name = \"invalid name\"\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"cannot contain spaces, path separators\",\n\t\t},\n\t\t{\n\t\t\tname: \"provider name is dot\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.Name = \".\"\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"cannot contain spaces, path separators\",\n\t\t},\n\t\t{\n\t\t\tname: \"empty API version\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.APIVersion = \"\"\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"apiVersion is required\",\n\t\t},\n\t\t{\n\t\t\tname: \"unsupported API version\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.APIVersion = \"credentialprovider.kubelet.k8s.io/v2\"\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"unsupported apiVersion\",\n\t\t},\n\t\t{\n\t\t\tname: \"no match images\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.MatchImages = []string{}\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"at least one matchImage is required\",\n\t\t},\n\t\t{\n\t\t\tname: \"empty match image pattern\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.MatchImages = []string{\"valid.com\", \"\"}\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"empty matchImage pattern\",\n\t\t},\n\t\t{\n\t\t\tname: \"nil cache duration\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.DefaultCacheDuration = nil\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"defaultCacheDuration is required\",\n\t\t},\n\t\t{\n\t\t\tname: \"negative cache duration\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tduration := metav1.Duration{Duration: -1 * time.Minute}\n\t\t\t\tprovider.DefaultCacheDuration = &duration\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"defaultCacheDuration must be >= 0\",\n\t\t},\n\t\t{\n\t\t\tname: \"empty environment variable name\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.Env = []kubeletconfigv1.ExecEnvVar{\n\t\t\t\t\t{Name: \"\", Value: \"value1\"},\n\t\t\t\t}\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"environment variable name cannot be empty\",\n\t\t},\n\t\t{\n\t\t\tname: \"duplicate environment variable names\",\n\t\t\tsetup: func() *kubeletconfigv1.CredentialProvider {\n\t\t\t\tprovider := createMockCredentialProvider(\"valid-plugin\", []string{\"*.example.com\"})\n\t\t\t\tprovider.Env = []kubeletconfigv1.ExecEnvVar{\n\t\t\t\t\t{Name: \"VAR1\", Value: \"value1\"},\n\t\t\t\t\t{Name: \"VAR1\", Value: \"value2\"},\n\t\t\t\t}\n\t\t\t\treturn &provider\n\t\t\t},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"duplicate environment variable name\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tprovider := tt.setup()\n\t\t\terr := validateCredentialProvider(provider)\n\n\t\t\tif tt.wantErr {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\tif tt.errContains != \"\" {\n\t\t\t\t\tassert.Contains(t, err.Error(), tt.errContains)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tassert.NoError(t, err)\n\t\t})\n\t}\n}\n\nfunc TestKubeletProviderGetCredentials(t *testing.T) {\n\t// Save and restore the global kubeletProvider\n\toldProvider := kubeletProvider\n\tdefer func() { kubeletProvider = oldProvider }()\n\n\tconfigPath, binDir := setupKubeletProvider(t)\n\n\ttests := []struct {\n\t\tname         string\n\t\tsetup        func(t *testing.T) *KubeletProvider\n\t\trequest      *AuthRequest\n\t\twantErr      bool\n\t\terrContains  string\n\t\twantUsername string\n\t\twantPassword string\n\t\twantNil      bool\n\t}{\n\t\t{\n\t\t\tname: \"nil request\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\tsetupMockProvider(t, binDir, \"test-plugin\", configPath,\n\t\t\t\t\tcredentialMap{\"registry.example.com\": {testUser, testPass}},\n\t\t\t\t\t[]string{\"*.example.com\"})\n\t\t\t\tprovider, err := NewKubeletProvider(configPath, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:     nil,\n\t\t\twantErr:     true,\n\t\t\terrContains: \"ref not found\",\n\t\t},\n\t\t{\n\t\t\tname: \"empty ref\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\tcfg := filepath.Join(binDir, \"config2.yaml\")\n\t\t\t\tsetupMockProvider(t, binDir, \"test-plugin-2\", cfg,\n\t\t\t\t\tcredentialMap{\"registry.example.com\": {testUser, testPass}},\n\t\t\t\t\t[]string{\"*.example.com\"})\n\t\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:     &AuthRequest{Ref: \"\"},\n\t\t\twantErr:     true,\n\t\t\terrContains: \"ref not found\",\n\t\t},\n\t\t{\n\t\t\tname: \"successful credential retrieval\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\tcfg := filepath.Join(binDir, \"success-config.yaml\")\n\t\t\t\tsetupMockProvider(t, binDir, \"success-plugin\", cfg,\n\t\t\t\t\tcredentialMap{\"registry.example.com\": {testUser, testPass}},\n\t\t\t\t\t[]string{\"*.example.com\"})\n\t\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:      &AuthRequest{Ref: \"registry.example.com/image:tag\"},\n\t\t\twantUsername: testUser,\n\t\t\twantPassword: testPass,\n\t\t},\n\t\t{\n\t\t\tname: \"no matching plugin\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\tcfg := filepath.Join(binDir, \"nomatch-config.yaml\")\n\t\t\t\tsetupMockProvider(t, binDir, \"nomatch-plugin\", cfg,\n\t\t\t\t\tcredentialMap{\"registry.docker.io\": {testUser, testPass}},\n\t\t\t\t\t[]string{\"*.docker.io\"})\n\t\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:     &AuthRequest{Ref: \"example.com/image:tag\"},\n\t\t\twantNil:     true,\n\t\t\twantErr:     true,\n\t\t\terrContains: \"no credentials found\",\n\t\t},\n\t\t{\n\t\t\tname: \"plugin returns no auth\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\tcfg := filepath.Join(binDir, \"noauth-config.yaml\")\n\t\t\t\tsetupMockProvider(t, binDir, \"noauth-plugin\", cfg, credentialMap{\"registry.docker.io\": {}}, []string{\"*.example.com\"})\n\t\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:     &AuthRequest{Ref: \"registry.example.com/image:tag\"},\n\t\t\twantNil:     true,\n\t\t\twantErr:     true,\n\t\t\terrContains: \"no matching registries found\",\n\t\t},\n\t\t{\n\t\t\t// Per the kubelet spec: \"If providers return overlapping auth keys,\n\t\t\t// the value from the provider earlier in this list is used.\"\n\t\t\tname: \"multiple plugins credentials collected - first plugin wins\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\tcreateMockPlugin(t, binDir, \"first-plugin\", credentialMap{\"registry.example.com\": {\"first-user\", \"first-pass\"}})\n\t\t\t\tcreateMockPlugin(t, binDir, \"second-plugin\", credentialMap{\"registry.example.com\": {\"second-user\", \"second-pass\"}})\n\t\t\t\tcfg := filepath.Join(binDir, \"multi-config.yaml\")\n\t\t\t\tcreateMockProviderConfig(t, cfg, []kubeletconfigv1.CredentialProvider{\n\t\t\t\t\tcreateMockCredentialProvider(\"first-plugin\", []string{\"*.example.com\"}),\n\t\t\t\t\tcreateMockCredentialProvider(\"second-plugin\", []string{\"*.example.com\"}),\n\t\t\t\t})\n\t\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:      &AuthRequest{Ref: \"registry.example.com/image:tag\"},\n\t\t\twantUsername: \"first-user\",\n\t\t\twantPassword: \"first-pass\",\n\t\t},\n\t\t{\n\t\t\tname: \"most specific registry path wins - specific over general\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\tcfg := filepath.Join(binDir, \"specificity-config.yaml\")\n\t\t\t\tsetupMockProvider(t, binDir, \"specificity-plugin\", cfg,\n\t\t\t\t\tcredentialMap{\n\t\t\t\t\t\t\"gcr.io\":                    {\"general-user\", \"general-pass\"},\n\t\t\t\t\t\t\"gcr.io/etcd-development\":   {\"specific-user\", \"specific-pass\"},\n\t\t\t\t\t\t\"gcr.io/kubernetes-release\": {\"k8s-user\", \"k8s-pass\"},\n\t\t\t\t\t},\n\t\t\t\t\t[]string{\"gcr.io\", \"gcr.io/*\"})\n\t\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:      &AuthRequest{Ref: \"gcr.io/etcd-development/etcd:v3.5.0\"},\n\t\t\twantUsername: \"specific-user\",\n\t\t\twantPassword: \"specific-pass\",\n\t\t},\n\t\t{\n\t\t\tname: \"most specific registry path wins - deeper path preferred\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\tcfg := filepath.Join(binDir, \"deep-path-config.yaml\")\n\t\t\t\tsetupMockProvider(t, binDir, \"deep-path-plugin\", cfg,\n\t\t\t\t\tcredentialMap{\n\t\t\t\t\t\t\"registry.example.com\":          {\"level1-user\", \"level1-pass\"},\n\t\t\t\t\t\t\"registry.example.com/org\":      {\"level2-user\", \"level2-pass\"},\n\t\t\t\t\t\t\"registry.example.com/org/team\": {\"level3-user\", \"level3-pass\"},\n\t\t\t\t\t},\n\t\t\t\t\t[]string{\"registry.example.com\"})\n\t\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:      &AuthRequest{Ref: \"registry.example.com/org/team/app:latest\"},\n\t\t\twantUsername: \"level3-user\",\n\t\t\twantPassword: \"level3-pass\",\n\t\t},\n\t\t{\n\t\t\tname: \"alphabetical sorting ensures consistent specificity\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\tcfg := filepath.Join(binDir, \"alpha-config.yaml\")\n\t\t\t\tsetupMockProvider(t, binDir, \"alpha-plugin\", cfg,\n\t\t\t\t\tcredentialMap{\n\t\t\t\t\t\t\"registry.example.com\":         {\"root-user\", \"root-pass\"},\n\t\t\t\t\t\t\"registry.example.com/aaa\":     {\"aaa-user\", \"aaa-pass\"},\n\t\t\t\t\t\t\"registry.example.com/aaa/bbb\": {\"nested-user\", \"nested-pass\"},\n\t\t\t\t\t},\n\t\t\t\t\t[]string{\"registry.example.com\"})\n\t\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:      &AuthRequest{Ref: \"registry.example.com/aaa/bbb/image:tag\"},\n\t\t\twantUsername: \"nested-user\",\n\t\t\twantPassword: \"nested-pass\",\n\t\t},\n\t\t{\n\t\t\tname: \"only first plugin matches - verifies no loop variable pointer bug\",\n\t\t\tsetup: func(t *testing.T) *KubeletProvider {\n\t\t\t\t// Create two plugins with different matchImages and credentials\n\t\t\t\tcreateMockPlugin(t, binDir, \"first-match-plugin\", credentialMap{\"registry.first.com\": {\"first-user\", \"first-pass\"}})\n\t\t\t\tcreateMockPlugin(t, binDir, \"second-no-match-plugin\", credentialMap{\"registry.second.com\": {\"second-user\", \"second-pass\"}})\n\t\t\t\tcfg := filepath.Join(binDir, \"first-match-config.yaml\")\n\t\t\t\tcreateMockProviderConfig(t, cfg, []kubeletconfigv1.CredentialProvider{\n\t\t\t\t\tcreateMockCredentialProvider(\"first-match-plugin\", []string{\"*.first.com\"}),\n\t\t\t\t\tcreateMockCredentialProvider(\"second-no-match-plugin\", []string{\"*.second.com\"}),\n\t\t\t\t})\n\t\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\treturn provider\n\t\t\t},\n\t\t\trequest:      &AuthRequest{Ref: \"registry.first.com/image:tag\"},\n\t\t\twantUsername: \"first-user\",\n\t\t\twantPassword: \"first-pass\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tprovider := tt.setup(t)\n\t\t\tkubeletProvider = provider\n\n\t\t\tkc, err := provider.GetCredentials(tt.request)\n\n\t\t\tif tt.wantErr {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\tassert.Nil(t, kc)\n\t\t\t\tif tt.errContains != \"\" {\n\t\t\t\t\tassert.Contains(t, err.Error(), tt.errContains)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\trequire.NoError(t, err)\n\t\t\tif tt.wantNil {\n\t\t\t\tassert.Nil(t, kc)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\trequire.NotNil(t, kc)\n\t\t\tassert.Equal(t, tt.wantUsername, kc.Username)\n\t\t\tassert.Equal(t, tt.wantPassword, kc.Password)\n\t\t})\n\t}\n}\n\nfunc TestInitKubeletProvider(t *testing.T) {\n\t// Save and restore the global kubeletProvider\n\toldProvider := kubeletProvider\n\tdefer func() { kubeletProvider = oldProvider }()\n\n\tconfigPath, binDir := setupKubeletProvider(t)\n\n\ttests := []struct {\n\t\tname        string\n\t\tsetup       func(t *testing.T) (configPath, binDir string)\n\t\twantErr     bool\n\t\terrContains string\n\t\tvalidate    func(t *testing.T)\n\t}{\n\t\t{\n\t\t\tname: \"successful initialization\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\tkubeletProvider = nil\n\t\t\t\tsetupMockProvider(t, binDir, \"init-plugin\", configPath,\n\t\t\t\t\tcredentialMap{\"registry.example.com\": {testUser, testPass}},\n\t\t\t\t\t[]string{\"*.example.com\"})\n\t\t\t\treturn configPath, binDir\n\t\t\t},\n\t\t\tvalidate: func(t *testing.T) {\n\t\t\t\tassert.NotNil(t, kubeletProvider)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"idempotent initialization\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\t// Provider already initialized from previous test\n\t\t\t\treturn configPath, binDir\n\t\t\t},\n\t\t\twantErr: false,\n\t\t\tvalidate: func(t *testing.T) {\n\t\t\t\tassert.NotNil(t, kubeletProvider)\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"initialization with invalid config\",\n\t\t\tsetup: func(t *testing.T) (string, string) {\n\t\t\t\tkubeletProvider = nil\n\t\t\t\treturn \"/nonexistent/config.yaml\", binDir\n\t\t\t},\n\t\t\twantErr: true,\n\t\t\tvalidate: func(t *testing.T) {\n\t\t\t\tassert.Nil(t, kubeletProvider)\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tconfigPath, binDir := tt.setup(t)\n\t\t\terr := InitKubeletProvider(configPath, binDir)\n\n\t\t\tif tt.wantErr {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\tif tt.errContains != \"\" {\n\t\t\t\t\tassert.Contains(t, err.Error(), tt.errContains)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trequire.NoError(t, err)\n\t\t\t}\n\n\t\t\tif tt.validate != nil {\n\t\t\t\ttt.validate(t)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestURLsMatch(t *testing.T) {\n\ttests := []struct {\n\t\tname      string\n\t\tglobURL   string\n\t\ttargetURL string\n\t\twantMatch bool\n\t\twantError bool\n\t}{\n\t\t{\n\t\t\tname:      \"exact match\",\n\t\t\tglobURL:   \"example.com\",\n\t\t\ttargetURL: \"example.com\",\n\t\t\twantMatch: true,\n\t\t},\n\t\t{\n\t\t\tname:      \"wildcard subdomain match\",\n\t\t\tglobURL:   \"*.docker.io\",\n\t\t\ttargetURL: \"registry.docker.io\",\n\t\t\twantMatch: true,\n\t\t},\n\t\t{\n\t\t\tname:      \"wildcard subdomain no match\",\n\t\t\tglobURL:   \"*.docker.io\",\n\t\t\ttargetURL: \"example.com\",\n\t\t\twantMatch: false,\n\t\t},\n\t\t{\n\t\t\tname:      \"port mismatch\",\n\t\t\tglobURL:   \"example.com:443\",\n\t\t\ttargetURL: \"example.com:8080\",\n\t\t\twantMatch: false,\n\t\t},\n\t\t{\n\t\t\tname:      \"port match\",\n\t\t\tglobURL:   \"example.com:443\",\n\t\t\ttargetURL: \"example.com:443\",\n\t\t\twantMatch: true,\n\t\t},\n\t\t{\n\t\t\tname:      \"path prefix match\",\n\t\t\tglobURL:   \"example.com/prefix\",\n\t\t\ttargetURL: \"example.com/prefix/image\",\n\t\t\twantMatch: true,\n\t\t},\n\t\t{\n\t\t\tname:      \"path prefix no match\",\n\t\t\tglobURL:   \"example.com/prefix\",\n\t\t\ttargetURL: \"example.com/other\",\n\t\t\twantMatch: false,\n\t\t},\n\t\t{\n\t\t\tname:      \"different number of parts\",\n\t\t\tglobURL:   \"*.example.com\",\n\t\t\ttargetURL: \"example.com\",\n\t\t\twantMatch: false,\n\t\t},\n\t\t{\n\t\t\tname:      \"malformed glob URL with invalid escape\",\n\t\t\tglobURL:   \"example.com%\",\n\t\t\ttargetURL: \"example.com\",\n\t\t\twantMatch: false,\n\t\t\twantError: true,\n\t\t},\n\t\t{\n\t\t\tname:      \"malformed target URL with invalid escape\",\n\t\t\tglobURL:   \"example.com\",\n\t\t\ttargetURL: \"example.com%\",\n\t\t\twantMatch: false,\n\t\t\twantError: true,\n\t\t},\n\t\t{\n\t\t\tname:      \"invalid glob pattern unclosed bracket\",\n\t\t\tglobURL:   \"[.example.com\",\n\t\t\ttargetURL: \"x.example.com\",\n\t\t\twantMatch: false,\n\t\t\twantError: true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tmatched, err := urlsMatchStr(tt.globURL, tt.targetURL)\n\t\t\tif tt.wantError {\n\t\t\t\tassert.Error(t, err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\trequire.NoError(t, err)\n\t\t\tassert.Equal(t, tt.wantMatch, matched)\n\t\t})\n\t}\n}\n\n// --- evictExpired ---\n\nfunc TestKubeletProviderEvictExpired(t *testing.T) {\n\tnow := time.Now()\n\tprovider := &KubeletProvider{\n\t\tcache: map[string]*kubeletCredential{\n\t\t\t\"valid.com\":   {keychains: map[string]*PassKeyChain{\"valid.com\": {}}, expiresAt: now.Add(10 * time.Minute)},\n\t\t\t\"expired.com\": {keychains: map[string]*PassKeyChain{\"expired.com\": {}}, expiresAt: now.Add(-1 * time.Minute)},\n\t\t\t\"zero.com\":    {keychains: map[string]*PassKeyChain{\"zero.com\": {}}, expiresAt: time.Time{}},\n\t\t},\n\t}\n\n\tprovider.evictExpired()\n\n\tassert.Len(t, provider.cache, 1)\n\tassert.Contains(t, provider.cache, \"valid.com\")\n\tassert.NotContains(t, provider.cache, \"expired.com\")\n\tassert.NotContains(t, provider.cache, \"zero.com\")\n}\n\n// TestKubeletProviderValidUntil verifies that ValidUntil causes the provider to\n// bypass a cached credential that won't survive until the requested time, while\n// still serving from cache when the cached credential is valid long enough.\nfunc TestKubeletProviderValidUntil(t *testing.T) {\n\t_, binDir := setupKubeletProvider(t)\n\n\tpluginName := \"valid-until-plugin\"\n\tcfgPath := filepath.Join(binDir, \"valid-until-config.yaml\")\n\tpluginPath := filepath.Join(binDir, pluginName)\n\n\t// Plugin returns a 10-minute TTL; cached expiresAt ≈ now+10m.\n\tcreateMockPluginWithTTL(t, binDir, pluginName,\n\t\tcredentialMap{\"registry.example.com\": {testUser, testPass}}, \"10m\")\n\tcreateMockProviderConfig(t, cfgPath, []kubeletconfigv1.CredentialProvider{\n\t\tcreateMockCredentialProvider(pluginName, []string{\"registry.example.com\"}),\n\t})\n\n\tprovider, err := NewKubeletProvider(cfgPath, binDir)\n\trequire.NoError(t, err)\n\n\tref := \"registry.example.com/image:tag\"\n\n\t// First call: executes the plugin and caches the result (expiresAt ≈ now+10m).\n\tkc, err := provider.GetCredentials(&AuthRequest{Ref: ref})\n\trequire.NoError(t, err)\n\trequire.NotNil(t, kc)\n\tassert.Equal(t, testUser, kc.Username)\n\n\t// Remove the plugin binary; any re-execution attempt will now fail.\n\trequire.NoError(t, os.Remove(pluginPath))\n\n\t// ValidUntil within the cached TTL (now+5m < expiresAt ≈ now+10m): cache hit.\n\tkc2, err := provider.GetCredentials(&AuthRequest{Ref: ref, ValidUntil: time.Now().Add(5 * time.Minute)})\n\trequire.NoError(t, err, \"credential is valid long enough; expected cache hit\")\n\trequire.NotNil(t, kc2)\n\tassert.Equal(t, testUser, kc2.Username)\n\n\t// ValidUntil beyond the cached TTL (now+20m > expiresAt ≈ now+10m): cache\n\t// bypassed, re-exec attempted → fails because the binary is gone.\n\t_, err = provider.GetCredentials(&AuthRequest{Ref: ref, ValidUntil: time.Now().Add(20 * time.Minute)})\n\trequire.Error(t, err, \"cached credential won't last long enough; expected plugin re-exec and failure\")\n\n\t// Cache is still intact (failed re-exec didn't evict it): zero ValidUntil succeeds.\n\tkc3, err := provider.GetCredentials(&AuthRequest{Ref: ref})\n\trequire.NoError(t, err, \"cache should be unaffected by the failed re-exec attempt\")\n\trequire.NotNil(t, kc3)\n\tassert.Equal(t, testUser, kc3.Username)\n}\n\n// TestKubeletProviderRegistryCache verifies caching behaviour by removing the\n// plugin binary after the first successful call. The second call either\n// succeeds (cache hit) or fails (no cache), proving whether the result was\n// stored.\nfunc TestKubeletProviderRegistryCache(t *testing.T) {\n\ttests := []struct {\n\t\tname             string\n\t\tpluginName       string\n\t\tcfgName          string\n\t\tresponseTTL      string        // cacheDuration field in the plugin response\n\t\tdefaultTTL       time.Duration // DefaultCacheDuration in the provider config\n\t\twantCachedOnNext bool          // whether second call should succeed from cache\n\t}{\n\t\t{\n\t\t\tname:             \"positive TTL caches result\",\n\t\t\tpluginName:       \"cache-hit-plugin\",\n\t\t\tcfgName:          \"cache-hit-config.yaml\",\n\t\t\tresponseTTL:      \"10m\",\n\t\t\tdefaultTTL:       10 * time.Minute,\n\t\t\twantCachedOnNext: true,\n\t\t},\n\t\t{\n\t\t\tname:             \"zero TTL does not cache\",\n\t\t\tpluginName:       \"zero-ttl-plugin\",\n\t\t\tcfgName:          \"zero-ttl-config.yaml\",\n\t\t\tresponseTTL:      \"0s\",\n\t\t\tdefaultTTL:       0,\n\t\t\twantCachedOnNext: false,\n\t\t},\n\t\t{\n\t\t\tname:             \"response zero TTL overrides non-zero default\",\n\t\t\tpluginName:       \"override-ttl-plugin\",\n\t\t\tcfgName:          \"override-ttl-config.yaml\",\n\t\t\tresponseTTL:      \"0s\",\n\t\t\tdefaultTTL:       10 * time.Minute,\n\t\t\twantCachedOnNext: false,\n\t\t},\n\t\t{\n\t\t\tname:             \"response negative TTL uses default TTL\",\n\t\t\tpluginName:       \"negative-ttl-plugin\",\n\t\t\tcfgName:          \"negative-ttl-config.yaml\",\n\t\t\tresponseTTL:      \"-1s\",\n\t\t\tdefaultTTL:       10 * time.Minute,\n\t\t\twantCachedOnNext: true,\n\t\t},\n\t}\n\n\t_, binDir := setupKubeletProvider(t)\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tpluginPath := filepath.Join(binDir, tt.pluginName)\n\t\t\tcfg := filepath.Join(binDir, tt.cfgName)\n\n\t\t\tcreateMockPluginWithTTL(t, binDir, tt.pluginName,\n\t\t\t\tcredentialMap{\"registry.example.com\": {testUser, testPass}}, tt.responseTTL)\n\t\t\tcreateMockProviderConfig(t, cfg, []kubeletconfigv1.CredentialProvider{\n\t\t\t\tcreateMockCredentialProviderWithTTL(tt.pluginName, []string{\"registry.example.com\"}, tt.defaultTTL),\n\t\t\t})\n\n\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\trequire.NoError(t, err)\n\n\t\t\t// First call: executes the plugin.\n\t\t\tkc, err := provider.GetCredentials(&AuthRequest{Ref: \"registry.example.com/image:tag\"})\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.NotNil(t, kc)\n\t\t\tassert.Equal(t, testUser, kc.Username)\n\n\t\t\t// Remove the plugin so any subsequent exec attempt fails.\n\t\t\trequire.NoError(t, os.Remove(pluginPath))\n\n\t\t\t// Second call: served from cache (hit) or re-executes the gone plugin (miss).\n\t\t\tkc2, err := provider.GetCredentials(&AuthRequest{Ref: \"registry.example.com/image:tag\"})\n\t\t\tif tt.wantCachedOnNext {\n\t\t\t\trequire.NoError(t, err, \"expected cache hit; plugin binary is gone\")\n\t\t\t\trequire.NotNil(t, kc2)\n\t\t\t\tassert.Equal(t, testUser, kc2.Username)\n\t\t\t} else {\n\t\t\t\trequire.Error(t, err, \"expected miss: result should not have been cached\")\n\t\t\t}\n\t\t})\n\t}\n}\n\n// TestKubeletProviderCacheKeyType verifies that the cache key is determined by\n// the cacheKeyType field in the plugin response, following the kubelet behavior.\nfunc TestKubeletProviderCacheKeyType(t *testing.T) {\n\t_, binDir := setupKubeletProvider(t)\n\n\ttests := []struct {\n\t\tname         string\n\t\tcacheKeyType string\n\t\t// firstRef is the image used for the first call (populates the cache).\n\t\tfirstRef string\n\t\t// secondRef is the image used for the second call (after plugin removal).\n\t\t// Must share the same registry or be anything for Global.\n\t\tsecondRef string\n\t\t// wantCacheHit indicates whether the second call should succeed from cache.\n\t\twantCacheHit bool\n\t}{\n\t\t{\n\t\t\tname:         \"Image: same image hits cache\",\n\t\t\tcacheKeyType: \"Image\",\n\t\t\tfirstRef:     \"registry.example.com/image:tag\",\n\t\t\tsecondRef:    \"registry.example.com/image:tag\",\n\t\t\twantCacheHit: true,\n\t\t},\n\t\t{\n\t\t\tname:         \"Image: different image misses cache\",\n\t\t\tcacheKeyType: \"Image\",\n\t\t\tfirstRef:     \"registry.example.com/image-a:tag\",\n\t\t\tsecondRef:    \"registry.example.com/image-b:tag\",\n\t\t\twantCacheHit: false,\n\t\t},\n\t\t{\n\t\t\tname:         \"Registry: same registry different image hits cache\",\n\t\t\tcacheKeyType: \"Registry\",\n\t\t\tfirstRef:     \"registry.example.com/image-a:tag\",\n\t\t\tsecondRef:    \"registry.example.com/image-b:tag\",\n\t\t\twantCacheHit: true,\n\t\t},\n\t\t{\n\t\t\tname:         \"Registry: different registry misses cache\",\n\t\t\tcacheKeyType: \"Registry\",\n\t\t\tfirstRef:     \"registry.example.com/image:tag\",\n\t\t\tsecondRef:    \"other.example.com/image:tag\",\n\t\t\twantCacheHit: false,\n\t\t},\n\t\t{\n\t\t\tname:         \"Global: any image hits cache\",\n\t\t\tcacheKeyType: \"Global\",\n\t\t\tfirstRef:     \"registry.example.com/image:tag\",\n\t\t\tsecondRef:    \"other.example.com/different:tag\",\n\t\t\twantCacheHit: true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tpluginName := \"ckt-\" + strings.ReplaceAll(strings.ToLower(tt.name[:10]), \" \", \"-\")\n\t\t\tcfgName := pluginName + \"-config.yaml\"\n\n\t\t\tcreateMockPluginFull(t, binDir, pluginName,\n\t\t\t\tcredentialMap{\n\t\t\t\t\t\"registry.example.com\": {testUser, testPass},\n\t\t\t\t\t\"other.example.com\":    {testUser, testPass},\n\t\t\t\t}, \"10m\", tt.cacheKeyType)\n\t\t\tcfg := filepath.Join(binDir, cfgName)\n\t\t\tcreateMockProviderConfig(t, cfg, []kubeletconfigv1.CredentialProvider{\n\t\t\t\tcreateMockCredentialProviderWithTTL(pluginName,\n\t\t\t\t\t[]string{\"*.example.com\"}, 10*time.Minute),\n\t\t\t})\n\n\t\t\tprovider, err := NewKubeletProvider(cfg, binDir)\n\t\t\trequire.NoError(t, err)\n\n\t\t\t// First call: execute the plugin and populate the cache.\n\t\t\tkc, err := provider.GetCredentials(&AuthRequest{Ref: tt.firstRef})\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.NotNil(t, kc)\n\n\t\t\t// Remove the plugin binary so any re-exec attempt fails.\n\t\t\trequire.NoError(t, os.Remove(filepath.Join(binDir, pluginName)))\n\n\t\t\t// Second call: should hit or miss the cache depending on cacheKeyType.\n\t\t\tkc2, err := provider.GetCredentials(&AuthRequest{Ref: tt.secondRef})\n\t\t\tif tt.wantCacheHit {\n\t\t\t\trequire.NoError(t, err, \"expected cache hit\")\n\t\t\t\trequire.NotNil(t, kc2)\n\t\t\t\tassert.Equal(t, testUser, kc2.Username)\n\t\t\t} else {\n\t\t\t\trequire.Error(t, err, \"expected cache miss\")\n\t\t\t}\n\t\t})\n\t}\n}\n\n// --- computeCacheKey ---\n\nfunc TestComputeCacheKey(t *testing.T) {\n\ttests := []struct {\n\t\tname         string\n\t\tcacheKeyType credentialproviderv1.PluginCacheKeyType\n\t\timage        string\n\t\twant         string\n\t}{\n\t\t{\n\t\t\tname:         \"Image returns full image\",\n\t\t\tcacheKeyType: credentialproviderv1.ImagePluginCacheKeyType,\n\t\t\timage:        \"registry.example.com/org/app:latest\",\n\t\t\twant:         \"registry.example.com/org/app:latest\",\n\t\t},\n\t\t{\n\t\t\tname:         \"Registry returns host only\",\n\t\t\tcacheKeyType: credentialproviderv1.RegistryPluginCacheKeyType,\n\t\t\timage:        \"registry.example.com/org/app:latest\",\n\t\t\twant:         \"registry.example.com\",\n\t\t},\n\t\t{\n\t\t\tname:         \"Global returns global key\",\n\t\t\tcacheKeyType: credentialproviderv1.GlobalPluginCacheKeyType,\n\t\t\timage:        \"registry.example.com/org/app:latest\",\n\t\t\twant:         \"<global>\",\n\t\t},\n\t\t{\n\t\t\tname:         \"unknown returns empty\",\n\t\t\tcacheKeyType: \"Unknown\",\n\t\t\timage:        \"registry.example.com/org/app:latest\",\n\t\t\twant:         \"\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot := computeCacheKey(tt.cacheKeyType, tt.image)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n\n// --- parseRegistry ---\n\nfunc TestParseRegistry(t *testing.T) {\n\ttests := []struct {\n\t\timage string\n\t\twant  string\n\t}{\n\t\t{\"registry.example.com/org/app:latest\", \"registry.example.com\"},\n\t\t{\"localhost:5000/myimage\", \"localhost:5000\"},\n\t\t{\"docker.io/library/nginx:latest\", \"docker.io\"},\n\t\t{\"singlepart\", \"singlepart\"},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.image, func(t *testing.T) {\n\t\t\tassert.Equal(t, tt.want, parseRegistry(tt.image))\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/auth/kubesecret.go",
    "content": "package auth\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"sync\"\n\n\t\"github.com/docker/cli/cli/config/configfile\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/sirupsen/logrus\"\n\tcorev1 \"k8s.io/api/core/v1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/watch\"\n\t\"k8s.io/client-go/kubernetes\"\n\t\"k8s.io/client-go/tools/cache\"\n\t\"k8s.io/client-go/tools/clientcmd\"\n)\n\nvar (\n\t// TODO: embed in KubeSecretProvider\n\tkubeSecretListener *KubeSecretListener\n\tconfigMu           sync.Mutex\n)\n\n// KubeSecretProvider implements AuthProvider for Kubernetes secrets.\ntype KubeSecretProvider struct{}\n\n// NewKubeSecretProvider creates a new Kubernetes secret-based auth provider.\nfunc NewKubeSecretProvider() *KubeSecretProvider {\n\treturn &KubeSecretProvider{}\n}\n\n// CanRenew implements RenewableProvider. KubeSecret credentials can be\n// refreshed because the underlying informer watches for secret changes.\nfunc (p *KubeSecretProvider) CanRenew() bool { return true }\n\nfunc (p *KubeSecretProvider) String() string {\n\treturn \"kubesecret\"\n}\n\n// GetCredentials retrieves credentials from Kubernetes secrets.\n// Returns nil if no credentials are found or the listener is not initialized.\nfunc (p *KubeSecretProvider) GetCredentials(req *AuthRequest) (*PassKeyChain, error) {\n\tif kubeSecretListener == nil {\n\t\treturn nil, errors.New(\"no secret listener initialized\")\n\t}\n\n\tif req == nil || req.Ref == \"\" {\n\t\treturn nil, errors.New(\"ref not found in request\")\n\t}\n\n\t_, host, err := parseReference(req.Ref)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"parse reference %s\", req.Ref)\n\t}\n\n\tpassKey := kubeSecretListener.GetCredentialsStore(host)\n\tif passKey == nil {\n\t\treturn nil, fmt.Errorf(\"no kube secret credentials found for host: %s\", host)\n\t}\n\n\treturn passKey, nil\n}\n\ntype KubeSecretListener struct {\n\tdockerConfigs map[string]*configfile.ConfigFile\n\tinformer      cache.SharedIndexInformer\n}\n\nfunc InitKubeSecretListener(ctx context.Context, kubeconfigPath string) error {\n\tconfigMu.Lock()\n\tdefer configMu.Unlock()\n\tif kubeSecretListener != nil {\n\t\treturn nil\n\t}\n\tkubeSecretListener = &KubeSecretListener{\n\t\tdockerConfigs: make(map[string]*configfile.ConfigFile),\n\t}\n\n\tif kubeconfigPath != \"\" {\n\t\t_, err := os.Stat(kubeconfigPath)\n\t\tif err != nil && !os.IsNotExist(err) {\n\t\t\tlogrus.WithError(err).Warningf(\"kubeconfig does not exist, kubeconfigPath %s\", kubeconfigPath)\n\t\t\treturn err\n\t\t} else if err != nil {\n\t\t\tlogrus.WithError(err).Warningf(\"failed to detect kubeconfig existence, kubeconfigPath %s\", kubeconfigPath)\n\t\t\treturn err\n\t\t}\n\t}\n\tloadingRule := clientcmd.NewDefaultClientConfigLoadingRules()\n\tloadingRule.ExplicitPath = kubeconfigPath\n\tclientConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(\n\t\tloadingRule,\n\t\t&clientcmd.ConfigOverrides{},\n\t).ClientConfig()\n\tif err != nil {\n\t\tlogrus.WithError(err).Warningf(\"failed to load kubeconfig\")\n\t\treturn err\n\t}\n\tclientset, err := kubernetes.NewForConfig(clientConfig)\n\tif err != nil {\n\t\tlogrus.WithError(err).Warningf(\"failed to create kubernetes client\")\n\t\treturn err\n\t}\n\tif err := kubeSecretListener.SyncKubeSecrets(ctx, clientset); err != nil {\n\t\tlogrus.WithError(err).Warningf(\"failed to sync secrets\")\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (kubelistener *KubeSecretListener) addDockerConfig(key string, obj interface{}) error {\n\tdata, ok := obj.(*corev1.Secret).Data[corev1.DockerConfigJsonKey]\n\tif !ok {\n\t\treturn fmt.Errorf(\"failed to get data from new object\")\n\t}\n\tdockerConfig := configfile.ConfigFile{}\n\tif err := dockerConfig.LoadFromReader(bytes.NewReader(data)); err != nil {\n\t\treturn errors.Wrap(err, \"failed to load docker config json from secret\")\n\t}\n\tconfigMu.Lock()\n\tkubelistener.dockerConfigs[key] = &dockerConfig\n\tconfigMu.Unlock()\n\treturn nil\n}\n\nfunc (kubelistener *KubeSecretListener) deleteDockerConfig(key string) {\n\tconfigMu.Lock()\n\tdelete(kubelistener.dockerConfigs, key)\n\tconfigMu.Unlock()\n}\n\nfunc (kubelistener *KubeSecretListener) SyncKubeSecrets(ctx context.Context, clientset *kubernetes.Clientset) error {\n\tif kubelistener.informer != nil {\n\t\treturn nil\n\t}\n\tinformer := cache.NewSharedIndexInformer(\n\t\t&cache.ListWatch{\n\t\t\tListFunc: func(options metav1.ListOptions) (runtime.Object, error) {\n\t\t\t\toptions.FieldSelector = \"type=\" + string(corev1.SecretTypeDockerConfigJson)\n\t\t\t\treturn clientset.CoreV1().Secrets(metav1.NamespaceAll).List(context.Background(), options)\n\t\t\t},\n\t\t\tWatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {\n\t\t\t\toptions.FieldSelector = \"type=\" + string(corev1.SecretTypeDockerConfigJson)\n\t\t\t\treturn clientset.CoreV1().Secrets(metav1.NamespaceAll).Watch(context.Background(), options)\n\t\t\t}},\n\t\t&corev1.Secret{},\n\t\t0,\n\t\tcache.Indexers{},\n\t)\n\tkubelistener.informer = informer\n\t_, err := kubelistener.informer.AddEventHandler(cache.ResourceEventHandlerFuncs{\n\t\tAddFunc: func(obj interface{}) {\n\t\t\tkey, err := cache.MetaNamespaceKeyFunc(obj)\n\t\t\tif err != nil {\n\t\t\t\tlogrus.WithError(err).Errorf(\"failed to get key for secret from cache\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err := kubelistener.addDockerConfig(key, obj); err != nil {\n\t\t\t\tlogrus.WithError(err).Errorf(\"failed to add a new dockerconfigjson\")\n\t\t\t\treturn\n\t\t\t}\n\t\t},\n\t\tUpdateFunc: func(_, newObj interface{}) {\n\t\t\tkey, err := cache.MetaNamespaceKeyFunc(newObj)\n\t\t\tif err != nil {\n\t\t\t\tlogrus.WithError(err).Errorf(\"failed to get key for secret from cache\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err := kubelistener.addDockerConfig(key, newObj); err != nil {\n\t\t\t\tlogrus.WithError(err).Errorf(\"failed to add a new dockerconfigjson\")\n\t\t\t\treturn\n\t\t\t}\n\t\t},\n\t\tDeleteFunc: func(obj interface{}) {\n\t\t\tkey, err := cache.MetaNamespaceKeyFunc(obj)\n\t\t\tif err != nil {\n\t\t\t\tlogrus.WithError(err).Errorf(\"failed to get key for secret from cache\")\n\t\t\t}\n\t\t\tkubelistener.deleteDockerConfig(key)\n\t\t}},\n\t)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"add event handler to informer\")\n\t}\n\tgo kubelistener.informer.Run(ctx.Done())\n\tif !cache.WaitForCacheSync(ctx.Done(), informer.HasSynced) {\n\t\treturn fmt.Errorf(\"timed out for syncing cache\")\n\t}\n\treturn nil\n}\n\nfunc (kubelistener *KubeSecretListener) GetCredentialsStore(host string) *PassKeyChain {\n\tconfigMu.Lock()\n\tdefer configMu.Unlock()\n\tfor _, dockerConfig := range kubelistener.dockerConfigs {\n\t\t// Find the auth for the host.\n\t\tauthConfig, err := dockerConfig.GetAuthConfig(host)\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif len(authConfig.Username) != 0 && len(authConfig.Password) != 0 {\n\t\t\treturn &PassKeyChain{\n\t\t\t\tUsername: authConfig.Username,\n\t\t\t\tPassword: authConfig.Password,\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/auth/kubesecret_test.go",
    "content": "package auth\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\tcorev1 \"k8s.io/api/core/v1\"\n)\n\nconst (\n\ttestDockerConfigJSONFmt = `\n{\n\t\"auths\": {\n\t\t\"%s\": {\n\t\t\t\"username\": \"%s\",\n\t\t\t\"password\": \"%s\",\n\t\t\t\"email\": \"%s\",\n\t\t\t\"auth\": \"%s\"\n\t\t}\n\t}\n}\n`\n\tdockerConfigKey = \"testKey\"\n\tregistryUser    = \"dockeruserfoobar\"\n\tregistryPass    = \"dockerpassfoobar\"\n\tregistryEmail   = \"test@alibaba.com\"\n)\n\nfunc TestGetCredentialsStore(t *testing.T) {\n\tassert := assert.New(t)\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\t// Host may not has kubeconfig, so ignore the error and continue the test\n\t_ = InitKubeSecretListener(ctx, \"\")\n\tassert.NotNil(kubeSecretListener)\n\n\tvar obj interface{} = &corev1.Secret{\n\t\tData: map[string][]byte{\n\t\t\tcorev1.DockerConfigJsonKey: []byte(fmt.Sprintf(testDockerConfigJSONFmt, extraHost, registryUser,\n\t\t\t\tregistryPass, registryEmail, base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf(\"%s:%s\", registryUser, registryPass))))),\n\t\t},\n\t}\n\terr := kubeSecretListener.addDockerConfig(dockerConfigKey, obj)\n\tassert.Nil(err)\n\n\tauth, err := NewKubeSecretProvider().GetCredentials(&AuthRequest{Ref: extraHost + \"/foo:bar\"})\n\tassert.NoError(err)\n\tassert.Equal(auth.Username, registryUser)\n\tassert.Equal(auth.Password, registryPass)\n\n\tauth = kubeSecretListener.GetCredentialsStore(extraHost)\n\tassert.Equal(auth.Username, registryUser)\n\tassert.Equal(auth.Password, registryPass)\n\t_, ok := kubeSecretListener.dockerConfigs[dockerConfigKey]\n\tassert.Equal(ok, true)\n\tkubeSecretListener.deleteDockerConfig(dockerConfigKey)\n\t_, ok = kubeSecretListener.dockerConfigs[dockerConfigKey]\n\tassert.Equal(ok, false)\n\n\tauth = kubeSecretListener.GetCredentialsStore(extraHost)\n\tassert.Nil(auth)\n}\n"
  },
  {
    "path": "pkg/auth/labels.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/pkg/errors\"\n)\n\n// LabelsProvider retrieves credentials from snapshot labels.\ntype LabelsProvider struct{}\n\n// NewLabelsProvider creates a new labels-based auth provider.\nfunc NewLabelsProvider() *LabelsProvider {\n\treturn &LabelsProvider{}\n}\n\nfunc (p *LabelsProvider) String() string {\n\treturn \"labels\"\n}\n\n// GetCredentials retrieves credentials from snapshot labels.\n// Returns nil if labels don't contain valid credentials.\nfunc (p *LabelsProvider) GetCredentials(req *AuthRequest) (*PassKeyChain, error) {\n\tif req.Labels == nil {\n\t\treturn nil, errors.New(\"labels not found in request\")\n\t}\n\n\tu, found := req.Labels[label.NydusImagePullUsername]\n\tif !found || u == \"\" {\n\t\treturn nil, errors.New(\"username label not found\")\n\t}\n\n\tpass, found := req.Labels[label.NydusImagePullSecret]\n\tif !found || pass == \"\" {\n\t\treturn nil, errors.New(\"password label not found\")\n\t}\n\n\treturn &PassKeyChain{\n\t\tUsername: u,\n\t\tPassword: pass,\n\t}, nil\n}\n"
  },
  {
    "path": "pkg/auth/labels_test.go",
    "content": "/*\n * Copyright (c) 2020. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n)\n\nfunc TestFromLabels(t *testing.T) {\n\tlabels := map[string]string{\n\t\tlabel.NydusImagePullUsername: \"mock\",\n\t\tlabel.NydusImagePullSecret:   \"mock\",\n\t}\n\tkc, err := NewLabelsProvider().GetCredentials(&AuthRequest{Labels: labels})\n\tassert.NoError(t, err)\n\tassert.Equal(t, kc.Username, \"mock\")\n\tassert.Equal(t, kc.Password, \"mock\")\n\tassert.Equal(t, \"bW9jazptb2Nr\", kc.ToBase64())\n\n\tkc1, err := FromBase64(\"bW9jazptb2Nr\")\n\tassert.Nil(t, err)\n\tassert.Equal(t, kc1.Username, \"mock\")\n\tassert.Equal(t, kc1.Password, \"mock\")\n\n\tlabels = map[string]string{}\n\tkc, err = NewLabelsProvider().GetCredentials(&AuthRequest{Labels: labels})\n\tassert.Nil(t, kc)\n\tassert.Error(t, err)\n\n\tlabels = map[string]string{\n\t\tlabel.NydusImagePullSecret: \"mock\",\n\t}\n\tkc, err = NewLabelsProvider().GetCredentials(&AuthRequest{Labels: labels})\n\tassert.Nil(t, kc)\n\tassert.Error(t, err)\n}\n"
  },
  {
    "path": "pkg/auth/provider.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"time\"\n\n\t\"github.com/containerd/containerd/v2/pkg/reference\"\n\tdistribution \"github.com/distribution/reference\"\n\t\"github.com/pkg/errors\"\n)\n\n// AuthRequest contains parameters for retrieving registry credentials.\ntype AuthRequest struct {\n\t// Ref is the full image reference (e.g., \"docker.io/library/nginx:latest\")\n\tRef string\n\t// Labels are snapshot labels that may contain credentials\n\tLabels map[string]string\n\t// ValidUntil, when non-zero, instructs providers to return a credential\n\t// that remains valid at least until this time. Providers that do not\n\t// have a notion of expiration will ignore this..\n\tValidUntil time.Time\n}\n\n// AuthProvider manage how credentials are retrieved for different sources\ntype AuthProvider interface {\n\t// GetCredentials retrieves credentials for the given request.\n\t// Returns nil if no credentials are available.\n\tGetCredentials(req *AuthRequest) (*PassKeyChain, error)\n\tString() string\n}\n\n// RenewableProvider extends AuthProvider with credential renewal capability.\n// Providers that can refresh credentials implement this interface.\ntype RenewableProvider interface {\n\tAuthProvider\n\t// CanRenew reports whether this provider can renew credentials.\n\tCanRenew() bool\n}\n\n// parseReference returns the reference.Spec and host for the given reference\nfunc parseReference(ref string) (refSpec reference.Spec, host string, err error) {\n\tnamedRef, err := distribution.ParseDockerRef(ref)\n\tif err != nil {\n\t\treturn reference.Spec{}, \"\", errors.Wrap(err, \"parse docker reference\")\n\t}\n\n\trefSpec, err = reference.Parse(namedRef.String())\n\tif err != nil {\n\t\treturn reference.Spec{}, \"\", errors.Wrap(err, \"parse image reference\")\n\t}\n\n\thost = distribution.Domain(namedRef)\n\tif host == \"\" {\n\t\treturn reference.Spec{}, \"\", errors.New(\"host not found in ref\")\n\t}\n\n\treturn refSpec, host, nil\n}\n"
  },
  {
    "path": "pkg/auth/renewal.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/data\"\n)\n\n// renewalStore is the global credential store. It is nil when credential\n// renewal is disabled (the default).\nvar renewalStore *credentialStore\n\n// InitCredentialStore creates the global credential store without starting\n// any background goroutine. The caller is responsible for driving renewal\n// (e.g., from snapshot/renewal.go).\nfunc InitCredentialStore(interval time.Duration) {\n\trenewalStore = newCredentialStore(interval)\n}\n\n// GetStoredCredential returns the cached keychain for ref from the global\n// store, or nil if not present or the store is not initialized.\nfunc GetStoredCredential(ref string) *PassKeyChain {\n\tif renewalStore == nil {\n\t\treturn nil\n\t}\n\treturn renewalStore.Get(ref)\n}\n\n// RenewCredential fetches fresh credentials for ref from the renewable\n// provider list and caches them in the global store. Returns the keychain\n// on success or nil on failure. Emits renewal metrics.\nfunc RenewCredential(ref string) *PassKeyChain {\n\tkc := fetchFromProviders(\n\t\t&AuthRequest{Ref: ref, ValidUntil: time.Now().Add(renewalStore.renewInterval)},\n\t\trenewableProviders(),\n\t)\n\tif kc != nil {\n\t\tdata.CredentialRenewals.WithLabelValues(ref, \"success\").Inc()\n\t} else {\n\t\tlog.L.WithField(\"ref\", ref).Warn(\"credential renewal returned no credentials from any provider\")\n\t\tdata.CredentialRenewals.WithLabelValues(ref, \"failure\").Inc()\n\t}\n\treturn kc\n}\n\n// EvictStaleCredentials removes store entries whose ref is not present in\n// liveRefs. Entries added recently (within interval/2) are kept to avoid\n// racing with a concurrent image pull: GetRegistryKeyChain adds the ref to\n// the store on the first layer fetch, but the RAFS entry is only created\n// later when the mount completes. Evicting here would cause redundant\n// provider lookups for every remaining layer fetch in the pull.\nfunc EvictStaleCredentials(liveRefs map[string]struct{}) {\n\tif renewalStore == nil {\n\t\treturn\n\t}\n\tgrace := renewalStore.renewInterval / 2\n\tfor _, entry := range renewalStore.Entries() {\n\t\tif _, live := liveRefs[entry.ref]; !live && time.Since(entry.renewedAt) >= grace {\n\t\t\trenewalStore.Remove(entry.ref)\n\t\t}\n\t}\n}\n\n// --- credentialEntry ---\n\n// credentialEntry holds a cached credential and the time it was last\n// successfully renewed.\ntype credentialEntry struct {\n\tref       string\n\tkeychain  *PassKeyChain\n\trenewedAt time.Time\n}\n\n// --- credentialStore ---\n\n// credentialStore is a concurrency-safe in-memory store for renewable\n// credentials keyed by image ref.\ntype credentialStore struct {\n\tmu            sync.RWMutex\n\tentries       map[string]*credentialEntry\n\trenewInterval time.Duration\n}\n\nfunc newCredentialStore(renewInterval time.Duration) *credentialStore {\n\treturn &credentialStore{\n\t\tentries:       make(map[string]*credentialEntry),\n\t\trenewInterval: renewInterval,\n\t}\n}\n\n// Add inserts or updates a credential entry for the given ref.\nfunc (s *credentialStore) Add(ref string, kc *PassKeyChain) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tlog.L.WithField(\"ref\", ref).Debug(\"adding credential entry to store\")\n\ts.entries[ref] = &credentialEntry{\n\t\tref:       ref,\n\t\tkeychain:  kc,\n\t\trenewedAt: time.Now(),\n\t}\n\tdata.CredentialStoreEntries.WithLabelValues(ref).Set(1)\n}\n\n// Get returns the cached keychain for ref, or nil if not present.\nfunc (s *credentialStore) Get(ref string) *PassKeyChain {\n\ts.mu.RLock()\n\tdefer s.mu.RUnlock()\n\n\tentry, ok := s.entries[ref]\n\tif !ok {\n\t\treturn nil\n\t}\n\treturn entry.keychain\n}\n\n// Remove deletes the entry for the given ref.\nfunc (s *credentialStore) Remove(ref string) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tlog.L.WithField(\"ref\", ref).Debug(\"removing credential entry from store\")\n\tdelete(s.entries, ref)\n\tdata.CredentialStoreEntries.DeleteLabelValues(ref)\n\tdata.CredentialRenewals.DeleteLabelValues(ref, \"success\")\n\tdata.CredentialRenewals.DeleteLabelValues(ref, \"failure\")\n}\n\n// Entries returns a snapshot of all current entries.\nfunc (s *credentialStore) Entries() []credentialEntry {\n\ts.mu.RLock()\n\tdefer s.mu.RUnlock()\n\n\tresult := make([]credentialEntry, 0, len(s.entries))\n\tfor _, e := range s.entries {\n\t\tresult = append(result, *e)\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "pkg/auth/renewal_test.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage auth\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\n// --- test helpers ---\n\n// mockProvider implements RenewableProvider.\ntype mockProvider struct {\n\tcreds *PassKeyChain\n\terr   error\n}\n\nfunc (m *mockProvider) GetCredentials(_ *AuthRequest) (*PassKeyChain, error) {\n\treturn m.creds, m.err\n}\n\nfunc (m *mockProvider) CanRenew() bool { return true }\n\nfunc (m *mockProvider) String() string { return \"mockProvider\" }\n\n// mockNonRenewableProvider implements AuthProvider but NOT RenewableProvider.\ntype mockNonRenewableProvider struct {\n\tcreds *PassKeyChain\n\terr   error\n}\n\nfunc (m *mockNonRenewableProvider) GetCredentials(_ *AuthRequest) (*PassKeyChain, error) {\n\treturn m.creds, m.err\n}\n\nfunc (m *mockNonRenewableProvider) String() string { return \"mockNonRenewableProvider\" }\n\n// trackingProvider counts calls and returns evolving credentials.\ntype trackingProvider struct {\n\tcalls    atomic.Int32\n\tfailNext atomic.Bool\n\tnilNext  atomic.Bool\n}\n\nfunc (p *trackingProvider) GetCredentials(_ *AuthRequest) (*PassKeyChain, error) {\n\tn := p.calls.Add(1)\n\tif p.failNext.Load() {\n\t\treturn nil, fmt.Errorf(\"simulated failure\")\n\t}\n\tif p.nilNext.Load() {\n\t\treturn nil, fmt.Errorf(\"no credentials available\")\n\t}\n\treturn &PassKeyChain{\n\t\tUsername: fmt.Sprintf(\"user-v%d\", n),\n\t\tPassword: fmt.Sprintf(\"pass-v%d\", n),\n\t}, nil\n}\n\nfunc (p *trackingProvider) CanRenew() bool { return true }\n\nfunc (p *trackingProvider) String() string { return \"trackingProvider\" }\n\n// --- RenewableProvider type assertion ---\n\nfunc TestRenewableProviderTypeAssertion(t *testing.T) {\n\ttests := []struct {\n\t\tname      string\n\t\tprovider  AuthProvider\n\t\trenewable bool\n\t}{\n\t\t{\"LabelsProvider is not renewable\", NewLabelsProvider(), false},\n\t\t{\"CRIProvider is not renewable\", NewCRIProvider(), false},\n\t\t{\"DockerProvider is renewable\", NewDockerProvider(), true},\n\t\t{\"KubeSecretProvider is renewable\", NewKubeSecretProvider(), true},\n\t\t{\"KubeletProvider is renewable\", &KubeletProvider{}, true},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\trp, ok := tt.provider.(RenewableProvider)\n\t\t\tif tt.renewable {\n\t\t\t\tassert.True(t, ok, \"expected provider to implement RenewableProvider\")\n\t\t\t\tassert.True(t, rp.CanRenew(), \"expected CanRenew() to return true\")\n\t\t\t} else {\n\t\t\t\tassert.False(t, ok, \"expected provider to NOT implement RenewableProvider\")\n\t\t\t}\n\t\t})\n\t}\n}\n\n// --- credentialStore ---\n\nfunc TestCredentialStoreGet(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\tref     string\n\t\twantNil bool\n\t}{\n\t\t{\n\t\t\tname:    \"returns nil for missing ref\",\n\t\t\tref:     \"nonexistent\",\n\t\t\twantNil: true,\n\t\t},\n\t\t{\n\t\t\tname: \"returns keychain for present ref\",\n\t\t\tref:  \"ref\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tstore := newCredentialStore(5 * time.Minute)\n\t\t\tstore.Add(\"ref\", &PassKeyChain{Username: \"user\", Password: \"pass\"})\n\n\t\t\tgot := store.Get(tt.ref)\n\t\t\tif tt.wantNil {\n\t\t\t\tassert.Nil(t, got)\n\t\t\t} else {\n\t\t\t\trequire.NotNil(t, got)\n\t\t\t\tassert.Equal(t, \"user\", got.Username)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestCredentialStoreRemove(t *testing.T) {\n\ttests := []struct {\n\t\tname  string\n\t\tsetup func(s *credentialStore)\n\t\tref   string\n\t}{\n\t\t{\n\t\t\tname: \"removes existing entry\",\n\t\t\tsetup: func(s *credentialStore) {\n\t\t\t\ts.Add(\"ref\", &PassKeyChain{Username: \"user\", Password: \"pass\"})\n\t\t\t},\n\t\t\tref: \"ref\",\n\t\t},\n\t\t{\n\t\t\tname:  \"no-op for nonexistent ref\",\n\t\t\tsetup: func(_ *credentialStore) {},\n\t\t\tref:   \"nonexistent\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tstore := newCredentialStore(5 * time.Minute)\n\t\t\ttt.setup(store)\n\t\t\tstore.Remove(tt.ref)\n\t\t\tassert.Nil(t, store.Get(tt.ref))\n\t\t})\n\t}\n}\n\nfunc TestCredentialStoreAdd_Upsert(t *testing.T) {\n\tstore := newCredentialStore(5 * time.Minute)\n\n\tstore.Add(\"ref\", &PassKeyChain{Username: \"old\", Password: \"old\"})\n\tgot := store.Get(\"ref\")\n\trequire.NotNil(t, got)\n\tassert.Equal(t, \"old\", got.Username)\n\n\tstore.Add(\"ref\", &PassKeyChain{Username: \"new\", Password: \"new\"})\n\tgot = store.Get(\"ref\")\n\trequire.NotNil(t, got)\n\tassert.Equal(t, \"new\", got.Username)\n}\n\nfunc TestCredentialStoreEntries(t *testing.T) {\n\tstore := newCredentialStore(5 * time.Minute)\n\n\tstore.Add(\"ref1\", &PassKeyChain{Username: \"u1\", Password: \"p1\"})\n\tstore.Add(\"ref2\", &PassKeyChain{Username: \"u2\", Password: \"p2\"})\n\n\tassert.Len(t, store.Entries(), 2)\n}\n\nfunc TestCredentialStoreConcurrency(t *testing.T) {\n\tstore := newCredentialStore(5 * time.Minute)\n\n\tvar wg sync.WaitGroup\n\tfor i := range 100 {\n\t\twg.Add(1)\n\t\tgo func(i int) {\n\t\t\tdefer wg.Done()\n\t\t\tstore.Add(\"ref\", &PassKeyChain{Username: \"user\", Password: \"pass\"})\n\t\t\tstore.Get(\"ref\")\n\t\t\tstore.Entries()\n\t\t\tif i%2 == 0 {\n\t\t\t\tstore.Remove(\"ref\")\n\t\t\t}\n\t\t}(i)\n\t}\n\twg.Wait()\n}\n\n// --- RenewCredential ---\n\nfunc TestRenewCredential(t *testing.T) {\n\tconst ref = \"docker.io/library/nginx:latest\"\n\n\ttests := []struct {\n\t\tname     string\n\t\tprovider *trackingProvider\n\t\twantUser string\n\t\twantCall int32\n\t\twantNil  bool\n\t}{\n\t\t{\n\t\t\tname:     \"updates store on success\",\n\t\t\tprovider: &trackingProvider{},\n\t\t\twantUser: \"user-v1\",\n\t\t\twantCall: 1,\n\t\t},\n\t\t{\n\t\t\tname: \"returns nil on failure\",\n\t\t\tprovider: func() *trackingProvider {\n\t\t\t\tp := &trackingProvider{}\n\t\t\t\tp.failNext.Store(true)\n\t\t\t\treturn p\n\t\t\t}(),\n\t\t\twantCall: 1,\n\t\t\twantNil:  true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\toldRenewable := renewableProviders\n\t\t\toldStore := renewalStore\n\t\t\tdefer func() {\n\t\t\t\trenewableProviders = oldRenewable\n\t\t\t\trenewalStore = oldStore\n\t\t\t}()\n\t\t\trenewableProviders = func() []AuthProvider { return []AuthProvider{tt.provider} }\n\t\t\trenewalStore = newCredentialStore(5 * time.Minute)\n\n\t\t\tgot := RenewCredential(ref)\n\n\t\t\tassert.Equal(t, tt.wantCall, tt.provider.calls.Load())\n\t\t\tif tt.wantNil {\n\t\t\t\tassert.Nil(t, got)\n\t\t\t} else {\n\t\t\t\trequire.NotNil(t, got)\n\t\t\t\tassert.Equal(t, tt.wantUser, got.Username)\n\t\t\t}\n\t\t})\n\t}\n}\n\n// --- EvictStaleCredentials ---\n\nfunc TestEvictStaleCredentials(t *testing.T) {\n\ttests := []struct {\n\t\tname     string\n\t\tstored   []string\n\t\tlive     map[string]struct{}\n\t\twantRefs []string\n\t}{\n\t\t{\n\t\t\tname:     \"evicts refs not in live set\",\n\t\t\tstored:   []string{\"ref-a\", \"ref-b\", \"ref-c\"},\n\t\t\tlive:     map[string]struct{}{\"ref-a\": {}, \"ref-c\": {}},\n\t\t\twantRefs: []string{\"ref-a\", \"ref-c\"},\n\t\t},\n\t\t{\n\t\t\tname:     \"evicts all when live set is empty\",\n\t\t\tstored:   []string{\"ref-a\", \"ref-b\"},\n\t\t\tlive:     map[string]struct{}{},\n\t\t\twantRefs: nil,\n\t\t},\n\t\t{\n\t\t\tname:     \"keeps all when all are live\",\n\t\t\tstored:   []string{\"ref-a\", \"ref-b\"},\n\t\t\tlive:     map[string]struct{}{\"ref-a\": {}, \"ref-b\": {}},\n\t\t\twantRefs: []string{\"ref-a\", \"ref-b\"},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\toldStore := renewalStore\n\t\t\tdefer func() { renewalStore = oldStore }()\n\n\t\t\t// Use a tiny interval so grace period (interval/2) is effectively zero.\n\t\t\trenewalStore = newCredentialStore(time.Millisecond)\n\t\t\tfor _, ref := range tt.stored {\n\t\t\t\trenewalStore.Add(ref, &PassKeyChain{Username: \"u\", Password: \"p\"})\n\t\t\t}\n\t\t\ttime.Sleep(time.Millisecond)\n\n\t\t\tEvictStaleCredentials(tt.live)\n\n\t\t\tentries := renewalStore.Entries()\n\t\t\tgotRefs := make([]string, 0, len(entries))\n\t\t\tfor _, e := range entries {\n\t\t\t\tgotRefs = append(gotRefs, e.ref)\n\t\t\t}\n\t\t\tassert.ElementsMatch(t, tt.wantRefs, gotRefs)\n\t\t})\n\t}\n}\n\nfunc TestEvictStaleCredentials_GracePeriod(t *testing.T) {\n\toldStore := renewalStore\n\tdefer func() { renewalStore = oldStore }()\n\n\t// Grace period is interval/2 = 2.5 minutes. A freshly added entry\n\t// should survive eviction even when not in the live set.\n\trenewalStore = newCredentialStore(5 * time.Minute)\n\trenewalStore.Add(\"recent-ref\", &PassKeyChain{Username: \"u\", Password: \"p\"})\n\n\tEvictStaleCredentials(map[string]struct{}{})\n\n\tassert.NotNil(t, renewalStore.Get(\"recent-ref\"), \"entry within grace period should not be evicted\")\n}\n\nfunc TestGetStoredCredential(t *testing.T) {\n\ttests := []struct {\n\t\tname      string\n\t\tinitStore bool\n\t\taddEntry  bool\n\t\twantNil   bool\n\t}{\n\t\t{\n\t\t\tname:      \"returns keychain when present\",\n\t\t\tinitStore: true,\n\t\t\taddEntry:  true,\n\t\t},\n\t\t{\n\t\t\tname:      \"returns nil when not present\",\n\t\t\tinitStore: true,\n\t\t\twantNil:   true,\n\t\t},\n\t\t{\n\t\t\tname:    \"returns nil when store is nil\",\n\t\t\twantNil: true,\n\t\t},\n\t}\n\n\tconst ref = \"docker.io/library/nginx:latest\"\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\toldStore := renewalStore\n\t\t\tdefer func() { renewalStore = oldStore }()\n\n\t\t\tif tt.initStore {\n\t\t\t\trenewalStore = newCredentialStore(5 * time.Minute)\n\t\t\t\tif tt.addEntry {\n\t\t\t\t\trenewalStore.Add(ref, &PassKeyChain{Username: \"user\", Password: \"pass\"})\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trenewalStore = nil\n\t\t\t}\n\n\t\t\tgot := GetStoredCredential(ref)\n\t\t\tif tt.wantNil {\n\t\t\t\tassert.Nil(t, got)\n\t\t\t} else {\n\t\t\t\trequire.NotNil(t, got)\n\t\t\t\tassert.Equal(t, \"user\", got.Username)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestEvictStaleCredentials_NilStore(t *testing.T) {\n\toldStore := renewalStore\n\tdefer func() { renewalStore = oldStore }()\n\trenewalStore = nil\n\n\t// Should not panic.\n\tEvictStaleCredentials(map[string]struct{}{\"ref\": {}})\n}\n\n// --- getRegistryKeyChainFromProviders ---\n\nfunc TestGetRegistryKeyChainFromProviders(t *testing.T) {\n\ttests := []struct {\n\t\tname         string\n\t\tstoreEnabled bool\n\t\tcached       *PassKeyChain\n\t\tproviders    []AuthProvider\n\t\twantUser     string\n\t\twantStored   bool\n\t}{\n\t\t{\n\t\t\tname:         \"serves from store when cached\",\n\t\t\tstoreEnabled: true,\n\t\t\tcached:       &PassKeyChain{Username: \"cached\", Password: \"cached-pass\"},\n\t\t\tproviders:    []AuthProvider{&mockNonRenewableProvider{creds: &PassKeyChain{Username: \"fresh\", Password: \"fresh\"}}},\n\t\t\twantUser:     \"cached\",\n\t\t\twantStored:   true,\n\t\t},\n\t\t{\n\t\t\tname:         \"falls through on store miss\",\n\t\t\tstoreEnabled: true,\n\t\t\tproviders:    []AuthProvider{&mockProvider{creds: &PassKeyChain{Username: \"fresh\", Password: \"fresh\"}}},\n\t\t\twantUser:     \"fresh\",\n\t\t\twantStored:   true,\n\t\t},\n\t\t{\n\t\t\tname:         \"stores renewable provider creds\",\n\t\t\tstoreEnabled: true,\n\t\t\tproviders:    []AuthProvider{&mockProvider{creds: &PassKeyChain{Username: \"user\", Password: \"pass\"}}},\n\t\t\twantUser:     \"user\",\n\t\t\twantStored:   true,\n\t\t},\n\t\t{\n\t\t\tname:         \"does not store non-renewable provider creds\",\n\t\t\tstoreEnabled: true,\n\t\t\tproviders:    []AuthProvider{&mockNonRenewableProvider{creds: &PassKeyChain{Username: \"user\", Password: \"pass\"}}},\n\t\t\twantUser:     \"user\",\n\t\t\twantStored:   false,\n\t\t},\n\t\t{\n\t\t\tname:      \"works when store is nil\",\n\t\t\tproviders: []AuthProvider{&mockProvider{creds: &PassKeyChain{Username: \"user\", Password: \"pass\"}}},\n\t\t\twantUser:  \"user\",\n\t\t},\n\t}\n\n\tconst ref = \"docker.io/library/nginx:latest\"\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\toldStore := renewalStore\n\t\t\tdefer func() { renewalStore = oldStore }()\n\n\t\t\tif tt.storeEnabled {\n\t\t\t\trenewalStore = newCredentialStore(5 * time.Minute)\n\t\t\t\tif tt.cached != nil {\n\t\t\t\t\trenewalStore.Add(ref, tt.cached)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trenewalStore = nil\n\t\t\t}\n\n\t\t\tgot := getRegistryKeyChainFromProviders(ref, nil, tt.providers)\n\t\t\trequire.NotNil(t, got)\n\t\t\tassert.Equal(t, tt.wantUser, got.Username)\n\n\t\t\tif tt.storeEnabled {\n\t\t\t\tstored := renewalStore.Get(ref)\n\t\t\t\tif tt.wantStored {\n\t\t\t\t\tassert.NotNil(t, stored)\n\t\t\t\t} else {\n\t\t\t\t\tassert.Nil(t, stored)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/backend/backend.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage backend\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\nconst (\n\tBackendTypeOSS     = \"oss\"\n\tBackendTypeS3      = \"s3\"\n\tBackendTypeLocalFS = \"localfs\"\n)\n\nvar (\n\t// We always use multipart upload for backend, and limit the\n\t// multipart chunk size to 500MB by default.\n\tMultipartChunkSize int64 = 500 * 1024 * 1024\n)\n\n// Backend uploads blobs generated by nydus-image builder to a backend storage.\ntype Backend interface {\n\t// Push pushes specified blob file to remote storage backend.\n\tPush(ctx context.Context, cs content.Store, desc ocispec.Descriptor) error\n\t// Check checks whether a blob exists in remote storage backend,\n\t// blob exists -> return (blobPath, nil)\n\t// blob not exists -> return (\"\", err)\n\tCheck(blobDigest digest.Digest) (string, error)\n\t// Type returns backend type name.\n\tType() string\n}\n\n// Nydus driver majorly works for registry backend, which means blob is stored in\n// registry as per OCI distribution specification. But nydus can also make OSS or\n// other storage services as backend storage. Pass config as byte slice here because\n// we haven't find a way to represent all backend config at the same time.\nfunc NewBackend(_type string, config []byte, forcePush bool) (Backend, error) {\n\tswitch _type {\n\tcase BackendTypeOSS:\n\t\treturn newOSSBackend(config, forcePush)\n\tcase BackendTypeS3:\n\t\treturn newS3Backend(config, forcePush)\n\tcase BackendTypeLocalFS:\n\t\treturn newLocalFSBackend(config, forcePush)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported backend type %s\", _type)\n\t}\n}\n"
  },
  {
    "path": "pkg/backend/localfs.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage backend\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n)\n\ntype LocalFSBackend struct {\n\tdir       string\n\tforcePush bool\n}\n\nfunc newLocalFSBackend(rawConfig []byte, forcePush bool) (*LocalFSBackend, error) {\n\tvar configMap map[string]string\n\tif err := json.Unmarshal(rawConfig, &configMap); err != nil {\n\t\treturn nil, errors.Wrap(err, \"parse LocalFS storage backend configuration\")\n\t}\n\n\tdir, ok := configMap[\"dir\"]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"no `dir` option is specified\")\n\t}\n\n\treturn &LocalFSBackend{\n\t\tdir:       dir,\n\t\tforcePush: forcePush,\n\t}, nil\n}\n\nfunc (b *LocalFSBackend) dstPath(blobID string) string {\n\treturn path.Join(b.dir, blobID)\n}\n\nfunc (b *LocalFSBackend) Push(ctx context.Context, cs content.Store, desc ocispec.Descriptor) error {\n\tif _, err := b.Check(desc.Digest); err == nil && !b.forcePush {\n\t\treturn nil\n\t}\n\n\tif err := os.MkdirAll(b.dir, 0755); err != nil {\n\t\treturn errors.Wrap(err, \"create directory in localfs backend\")\n\t}\n\n\tra, err := cs.ReaderAt(ctx, desc)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"get reader from content store\")\n\t}\n\tdefer ra.Close()\n\n\tblobID := desc.Digest.Hex()\n\tdstPath := b.dstPath(blobID)\n\n\tdstFile, err := os.Create(dstPath)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"create destination file: %s\", dstPath)\n\t}\n\tdefer dstFile.Close()\n\n\tsr := io.NewSectionReader(ra, 0, ra.Size())\n\tif _, err := io.Copy(dstFile, sr); err != nil {\n\t\treturn errors.Wrapf(err, \"copy blob to %s\", dstPath)\n\t}\n\n\treturn nil\n}\n\nfunc (b *LocalFSBackend) Check(blobDigest digest.Digest) (string, error) {\n\tdstPath := b.dstPath(blobDigest.Hex())\n\n\tinfo, err := os.Stat(dstPath)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn \"\", errdefs.ErrNotFound\n\t\t}\n\t\treturn \"\", err\n\t}\n\n\tif !info.IsDir() {\n\t\treturn dstPath, nil\n\t}\n\n\treturn \"\", errdefs.ErrNotFound\n}\n\nfunc (b *LocalFSBackend) Type() string {\n\treturn BackendTypeLocalFS\n}\n"
  },
  {
    "path": "pkg/backend/oss.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage backend\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"time\"\n\n\t\"github.com/aliyun/aliyun-oss-go-sdk/oss\"\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x/sync/errgroup\"\n)\n\ntype OSSBackend struct {\n\t// OSS storage does not support directory. Therefore add a prefix to each object\n\t// to make it a path-like object.\n\tobjectPrefix string\n\tbucket       *oss.Bucket\n\tforcePush    bool\n}\n\nfunc newOSSBackend(rawConfig []byte, forcePush bool) (*OSSBackend, error) {\n\tvar configMap map[string]string\n\tif err := json.Unmarshal(rawConfig, &configMap); err != nil {\n\t\treturn nil, errors.Wrap(err, \"Parse OSS storage backend configuration\")\n\t}\n\n\tendpoint, ok1 := configMap[\"endpoint\"]\n\tbucketName, ok2 := configMap[\"bucket_name\"]\n\n\t// Below fields are not mandatory.\n\taccessKeyID := configMap[\"access_key_id\"]\n\taccessKeySecret := configMap[\"access_key_secret\"]\n\tobjectPrefix := configMap[\"object_prefix\"]\n\n\tif !ok1 || !ok2 {\n\t\treturn nil, fmt.Errorf(\"no endpoint or bucket is specified\")\n\t}\n\n\tclient, err := oss.New(endpoint, accessKeyID, accessKeySecret)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"Create client\")\n\t}\n\n\tbucket, err := client.Bucket(bucketName)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"Create bucket\")\n\t}\n\n\treturn &OSSBackend{\n\t\tobjectPrefix: objectPrefix,\n\t\tbucket:       bucket,\n\t\tforcePush:    forcePush,\n\t}, nil\n}\n\n// Ported from https://github.com/aliyun/aliyun-oss-go-sdk/blob/v2.2.6/oss/utils.go#L259\nfunc splitFileByPartSize(blobSize, chunkSize int64) ([]oss.FileChunk, error) {\n\tif chunkSize <= 0 {\n\t\treturn nil, errors.New(\"invalid chunk size\")\n\t}\n\n\tvar chunkN = blobSize / chunkSize\n\tif chunkN >= 10000 {\n\t\treturn nil, errors.New(\"too many parts, please increase chunk size\")\n\t}\n\n\tvar chunks []oss.FileChunk\n\tvar chunk = oss.FileChunk{}\n\tfor i := int64(0); i < chunkN; i++ {\n\t\tchunk.Number = int(i + 1)\n\t\tchunk.Offset = i * chunkSize\n\t\tchunk.Size = chunkSize\n\t\tchunks = append(chunks, chunk)\n\t}\n\n\tif blobSize%chunkSize > 0 {\n\t\tchunk.Number = len(chunks) + 1\n\t\tchunk.Offset = int64(len(chunks)) * chunkSize\n\t\tchunk.Size = blobSize % chunkSize\n\t\tchunks = append(chunks, chunk)\n\t}\n\n\treturn chunks, nil\n}\n\n// Upload nydus blob to oss storage backend.\nfunc (b *OSSBackend) push(ctx context.Context, cs content.Store, desc ocispec.Descriptor) error {\n\tblobID := desc.Digest.Hex()\n\tblobObjectKey := b.objectPrefix + blobID\n\n\tra, err := cs.ReaderAt(ctx, desc)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"get reader for compression blob %q\", desc.Digest)\n\t}\n\tdefer ra.Close()\n\n\tif exist, err := b.bucket.IsObjectExist(blobObjectKey); err != nil {\n\t\treturn errors.Wrap(err, \"check object existence\")\n\t} else if exist && !b.forcePush {\n\t\treturn nil\n\t}\n\n\tchunks, err := splitFileByPartSize(ra.Size(), MultipartChunkSize)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"split blob by part num\")\n\t}\n\n\timur, err := b.bucket.InitiateMultipartUpload(blobObjectKey)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"initiate multipart upload\")\n\t}\n\tpartsChan := make(chan oss.UploadPart, len(chunks))\n\n\tg := new(errgroup.Group)\n\tfor _, chunk := range chunks {\n\t\tck := chunk\n\t\tg.Go(func() error {\n\t\t\tp, err := b.bucket.UploadPart(imur, io.NewSectionReader(ra, ck.Offset, ck.Size), ck.Size, ck.Number)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"upload part\")\n\t\t\t}\n\t\t\tpartsChan <- p\n\t\t\treturn nil\n\t\t})\n\t}\n\n\tif err := g.Wait(); err != nil {\n\t\t_ = b.bucket.AbortMultipartUpload(imur)\n\t\tclose(partsChan)\n\t\treturn errors.Wrap(err, \"upload parts\")\n\t}\n\tclose(partsChan)\n\n\tparts := make([]oss.UploadPart, 0, 16)\n\tfor p := range partsChan {\n\t\tparts = append(parts, p)\n\t}\n\n\t_, err = b.bucket.CompleteMultipartUpload(imur, parts)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"complete multipart upload\")\n\t}\n\n\treturn nil\n}\n\nfunc (b *OSSBackend) Push(ctx context.Context, cs content.Store, desc ocispec.Descriptor) error {\n\tbackoff := time.Second\n\tfor {\n\t\terr := b.push(ctx, cs, desc)\n\t\tif err != nil {\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn err\n\t\t\tdefault:\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil\n\t\t}\n\t\tif backoff >= 8*time.Second {\n\t\t\treturn err\n\t\t}\n\t\ttime.Sleep(backoff)\n\t\tbackoff *= 2\n\t}\n}\n\nfunc (b *OSSBackend) Check(blobDigest digest.Digest) (string, error) {\n\tblobID := blobDigest.Hex()\n\tblobObjectKey := b.objectPrefix + blobID\n\tif exist, err := b.bucket.IsObjectExist(blobObjectKey); err != nil {\n\t\treturn \"\", err\n\t} else if exist {\n\t\treturn blobID, nil\n\t}\n\treturn \"\", errdefs.ErrNotFound\n}\n\nfunc (b *OSSBackend) Type() string {\n\treturn BackendTypeOSS\n}\n"
  },
  {
    "path": "pkg/backend/s3.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage backend\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\n\t\"github.com/aws/aws-sdk-go-v2/aws\"\n\tawshttp \"github.com/aws/aws-sdk-go-v2/aws/transport/http\"\n\tawscfg \"github.com/aws/aws-sdk-go-v2/config\"\n\t\"github.com/aws/aws-sdk-go-v2/credentials\"\n\t\"github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager\"\n\ttmtypes \"github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager/types\"\n\t\"github.com/aws/aws-sdk-go-v2/service/s3\"\n\t\"github.com/aws/aws-sdk-go-v2/service/s3/types\"\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n)\n\ntype S3Backend struct {\n\t// objectPrefix is the path prefix of the uploaded object.\n\t// For example, if the blobID which should be uploaded is \"abc\",\n\t// and the objectPrefix is \"path/to/my-registry/\", then the object key will be\n\t// \"path/to/my-registry/abc\".\n\tobjectPrefix       string\n\tbucketName         string\n\tendpointWithScheme string\n\tregion             string\n\taccessKeySecret    string\n\taccessKeyID        string\n\tforcePush          bool\n\tchecksumAlgorithm  types.ChecksumAlgorithm\n}\n\ntype S3Config struct {\n\tAccessKeyID       string  `json:\"access_key_id,omitempty\"`\n\tAccessKeySecret   string  `json:\"access_key_secret,omitempty\"`\n\tEndpoint          string  `json:\"endpoint,omitempty\"`\n\tScheme            string  `json:\"scheme,omitempty\"`\n\tBucketName        string  `json:\"bucket_name,omitempty\"`\n\tRegion            string  `json:\"region,omitempty\"`\n\tObjectPrefix      string  `json:\"object_prefix,omitempty\"`\n\tChecksumAlgorithm *string `json:\"checksum_algorithm,omitempty\"`\n}\n\nfunc newS3Backend(rawConfig []byte, forcePush bool) (*S3Backend, error) {\n\tcfg := &S3Config{}\n\tif err := json.Unmarshal(rawConfig, cfg); err != nil {\n\t\treturn nil, errors.Wrap(err, \"parse S3 storage backend configuration\")\n\t}\n\tif cfg.Endpoint == \"\" {\n\t\tcfg.Endpoint = \"s3.amazonaws.com\"\n\t}\n\tif cfg.Scheme == \"\" {\n\t\tcfg.Scheme = \"https\"\n\t}\n\tendpointWithScheme := fmt.Sprintf(\"%s://%s\", cfg.Scheme, cfg.Endpoint)\n\n\tif cfg.BucketName == \"\" || cfg.Region == \"\" {\n\t\treturn nil, fmt.Errorf(\"invalid S3 configuration: missing 'bucket_name' or 'region'\")\n\t}\n\n\tvar checksumAlgorithm types.ChecksumAlgorithm\n\tif cfg.ChecksumAlgorithm == nil {\n\t\t// Default to CRC32 checksum\n\t\tchecksumAlgorithm = types.ChecksumAlgorithmCrc32\n\t} else if *cfg.ChecksumAlgorithm != \"\" {\n\t\tfor _, algorithm := range checksumAlgorithm.Values() {\n\t\t\tif string(algorithm) == *cfg.ChecksumAlgorithm {\n\t\t\t\tchecksumAlgorithm = algorithm\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif checksumAlgorithm == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"invalid checksum algorithm: %s, supported algorithms: %v\", *cfg.ChecksumAlgorithm, checksumAlgorithm.Values())\n\t\t}\n\t}\n\n\treturn &S3Backend{\n\t\tobjectPrefix:       cfg.ObjectPrefix,\n\t\tbucketName:         cfg.BucketName,\n\t\tregion:             cfg.Region,\n\t\tendpointWithScheme: endpointWithScheme,\n\t\taccessKeySecret:    cfg.AccessKeySecret,\n\t\taccessKeyID:        cfg.AccessKeyID,\n\t\tforcePush:          forcePush,\n\t\tchecksumAlgorithm:  checksumAlgorithm,\n\t}, nil\n}\n\nfunc (b *S3Backend) client() (*s3.Client, error) {\n\ts3AWSConfig, err := awscfg.LoadDefaultConfig(context.TODO())\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"load default AWS config\")\n\t}\n\n\tclient := s3.NewFromConfig(s3AWSConfig, func(o *s3.Options) {\n\t\to.BaseEndpoint = &b.endpointWithScheme\n\t\to.Region = b.region\n\t\to.UsePathStyle = true\n\t\tif len(b.accessKeySecret) > 0 && len(b.accessKeyID) > 0 {\n\t\t\to.Credentials = credentials.NewStaticCredentialsProvider(b.accessKeyID, b.accessKeySecret, \"\")\n\t\t}\n\t\to.UsePathStyle = true\n\t})\n\treturn client, nil\n}\n\nfunc (b *S3Backend) existObject(ctx context.Context, objectKey string) (bool, error) {\n\tclient, err := b.client()\n\tif err != nil {\n\t\treturn false, errors.Wrap(err, \"failed to create s3 client\")\n\t}\n\t_, err = client.HeadObject(ctx, &s3.HeadObjectInput{\n\t\tBucket: &b.bucketName,\n\t\tKey:    &objectKey,\n\t})\n\tif err != nil {\n\t\tvar responseError *awshttp.ResponseError\n\t\tif errors.As(err, &responseError) && responseError.HTTPStatusCode() == http.StatusNotFound {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn false, err\n\t}\n\treturn true, nil\n}\n\nfunc (b *S3Backend) Push(ctx context.Context, cs content.Store, desc ocispec.Descriptor) error {\n\tblobID := desc.Digest.Hex()\n\tblobObjectKey := b.objectPrefix + blobID\n\n\tif exist, err := b.existObject(ctx, blobObjectKey); err != nil {\n\t\treturn errors.Wrap(err, \"check object existence\")\n\t} else if exist && !b.forcePush {\n\t\treturn nil\n\t}\n\n\tra, err := cs.ReaderAt(ctx, desc)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"get reader from content store\")\n\t}\n\tdefer ra.Close()\n\treader := content.NewReader(ra)\n\n\tclient, err := b.client()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to create s3 client\")\n\t}\n\n\ttm := transfermanager.New(client, func(o *transfermanager.Options) {\n\t\to.PartSizeBytes = MultipartChunkSize\n\t})\n\tif _, err := tm.UploadObject(ctx, &transfermanager.UploadObjectInput{\n\t\tBucket:            aws.String(b.bucketName),\n\t\tKey:               aws.String(blobObjectKey),\n\t\tBody:              reader,\n\t\tChecksumAlgorithm: tmtypes.ChecksumAlgorithm(b.checksumAlgorithm),\n\t}); err != nil {\n\t\treturn errors.Wrap(err, \"push blob to s3 backend\")\n\t}\n\n\treturn nil\n}\n\nfunc (b *S3Backend) Check(blobDigest digest.Digest) (string, error) {\n\tblobID := blobDigest.Hex()\n\tobjectKey := b.objectPrefix + blobDigest.Hex()\n\tif exist, err := b.existObject(context.Background(), objectKey); err != nil {\n\t\treturn \"\", err\n\t} else if exist {\n\t\treturn blobID, nil\n\t}\n\treturn \"\", errdefs.ErrNotFound\n}\n\nfunc (b *S3Backend) Type() string {\n\treturn BackendTypeS3\n}\n"
  },
  {
    "path": "pkg/backend/s3_test.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage backend\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/aws/aws-sdk-go-v2/service/s3/types\"\n)\n\nfunc Test_newS3Backend(t *testing.T) {\n\ttype args struct {\n\t\trawConfig []byte\n\t}\n\n\ttests := []struct {\n\t\tname    string\n\t\targs    args\n\t\twant    *S3Backend\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"test1, no error\",\n\t\t\targs: args{\n\t\t\t\trawConfig: []byte(`{\n\t\t\t\t\t\"endpoint\": \"localhost:9000\",\n\t\t\t\t\t\"scheme\": \"http\",\n\t\t\t\t\t\"bucket_name\": \"nydus\",\n\t\t\t\t\t\"region\": \"us-east-1\",\n\t\t\t\t\t\"object_prefix\": \"path/to/my-registry/\",\n\t\t\t\t\t\"access_key_id\": \"minio\",\n\t\t\t\t\t\"access_key_secret\": \"minio123\"\n\t\t\t\t}`),\n\t\t\t},\n\t\t\twant: &S3Backend{\n\t\t\t\tobjectPrefix:       \"path/to/my-registry/\",\n\t\t\t\tbucketName:         \"nydus\",\n\t\t\t\tendpointWithScheme: \"http://localhost:9000\",\n\t\t\t\tregion:             \"us-east-1\",\n\t\t\t\taccessKeySecret:    \"minio123\",\n\t\t\t\taccessKeyID:        \"minio\",\n\t\t\t\tchecksumAlgorithm:  types.ChecksumAlgorithmCrc32,\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"test2, set checksum algorithm\",\n\t\t\targs: args{\n\t\t\t\trawConfig: []byte(`{\n\t\t\t\t\t\"endpoint\": \"localhost:9000\",\n\t\t\t\t\t\"scheme\": \"http\",\n\t\t\t\t\t\"bucket_name\": \"nydus\",\n\t\t\t\t\t\"region\": \"us-east-1\",\n\t\t\t\t\t\"object_prefix\": \"path/to/my-registry/\",\n\t\t\t\t\t\"access_key_id\": \"minio\",\n\t\t\t\t\t\"access_key_secret\": \"minio123\",\n\t\t\t\t\t\"checksum_algorithm\": \"SHA256\"\n\t\t\t\t}`),\n\t\t\t},\n\t\t\twant: &S3Backend{\n\t\t\t\tobjectPrefix:       \"path/to/my-registry/\",\n\t\t\t\tbucketName:         \"nydus\",\n\t\t\t\tendpointWithScheme: \"http://localhost:9000\",\n\t\t\t\tregion:             \"us-east-1\",\n\t\t\t\taccessKeySecret:    \"minio123\",\n\t\t\t\taccessKeyID:        \"minio\",\n\t\t\t\tchecksumAlgorithm:  types.ChecksumAlgorithmSha256,\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot, err := newS3Backend(tt.args.rawConfig, false)\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"newS3Backend() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"newS3Backend() = %+#v\\nwant %+#v\\n\\n\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/cache/manager.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage cache\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"path\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/containerd/v2/core/snapshots\"\n\t\"github.com/containerd/continuity/fs\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/store\"\n)\n\nconst (\n\timageDiskFileSuffix = \".image.disk\"\n\tlayerDiskFileSuffix = \".layer.disk\"\n\tchunkMapFileSuffix  = \".chunk_map\"\n\tmetaFileSuffix      = \".blob.meta\"\n\t// Blob cache is suffixed after nydus v2.1\n\tdataFileSuffix = \".blob.data\"\n)\n\n// Disk cache manager for fusedev.\ntype Manager struct {\n\tcacheDir string\n\tperiod   time.Duration\n\teventCh  chan struct{}\n}\n\ntype Opt struct {\n\tDisabled bool\n\tCacheDir string\n\tPeriod   time.Duration\n\tDatabase *store.Database\n}\n\nfunc NewManager(opt Opt) (*Manager, error) {\n\t// Ensure cache directory exists\n\tif err := os.MkdirAll(opt.CacheDir, 0755); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to create cache dir %s\", opt.CacheDir)\n\t}\n\n\teventCh := make(chan struct{})\n\tm := &Manager{\n\t\tcacheDir: opt.CacheDir,\n\t\tperiod:   opt.Period,\n\t\teventCh:  eventCh,\n\t}\n\n\treturn m, nil\n}\n\nfunc (m *Manager) CacheDir() string {\n\treturn m.cacheDir\n}\n\n// Report each blob disk usage\n// TODO: For fscache cache files, the cache files are managed by nydusd and Linux kernel\n// We don't know how it manages cache files. A method to address this is to query nydusd.\n// So we can't report cache usage in the case of fscache now\nfunc (m *Manager) CacheUsage(ctx context.Context, blobID string) (snapshots.Usage, error) {\n\tvar usage snapshots.Usage\n\n\tblobCachePath := path.Join(m.cacheDir, blobID)\n\tblobChunkMap := path.Join(m.cacheDir, blobID+chunkMapFileSuffix)\n\t// For backward compatibility\n\tblobCacheSuffixedPath := path.Join(m.cacheDir, blobID+dataFileSuffix)\n\tblobChunkMapSuffixedPath := path.Join(m.cacheDir, blobID+dataFileSuffix+chunkMapFileSuffix)\n\tblobMeta := path.Join(m.cacheDir, blobID+metaFileSuffix)\n\timageDisk := path.Join(m.cacheDir, blobID+imageDiskFileSuffix)\n\tlayerDisk := path.Join(m.cacheDir, blobID+layerDiskFileSuffix)\n\n\tstuffs := []string{blobCachePath, blobChunkMap, blobCacheSuffixedPath, blobChunkMapSuffixedPath, blobMeta, imageDisk, layerDisk}\n\n\tfor _, f := range stuffs {\n\t\tdu, err := fs.DiskUsage(ctx, f)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\t\tlog.L.Debugf(\"Cache %s does not exist\", f)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn snapshots.Usage{}, err\n\t\t}\n\t\tusage.Add(snapshots.Usage(du))\n\t}\n\n\treturn usage, nil\n}\n\nfunc (m *Manager) RemoveBlobCache(blobID string) error {\n\tblobCachePath := path.Join(m.cacheDir, blobID)\n\tblobChunkMap := path.Join(m.cacheDir, blobID+chunkMapFileSuffix)\n\tblobCacheSuffixedPath := path.Join(m.cacheDir, blobID+dataFileSuffix)\n\tblobChunkMapSuffixedPath := path.Join(m.cacheDir, blobID+dataFileSuffix+chunkMapFileSuffix)\n\tblobMeta := path.Join(m.cacheDir, blobID+metaFileSuffix)\n\timageDisk := path.Join(m.cacheDir, blobID+imageDiskFileSuffix)\n\tlayerDisk := path.Join(m.cacheDir, blobID+layerDiskFileSuffix)\n\n\t// NOTE: Delete chunk bitmap file before data blob\n\tstuffs := []string{blobChunkMap, blobChunkMapSuffixedPath, blobMeta, blobCachePath, blobCacheSuffixedPath, imageDisk, layerDisk}\n\n\tfor _, f := range stuffs {\n\t\terr := os.Remove(f)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\t\tlog.L.Debugf(\"file %s doest not exist.\", f)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// extractBlobIDFromFilename extracts the blob ID from a cache filename\n// Cache files can have formats like:\n// - <blobID>\n// - <blobID>.blob.data\n// - <blobID>.chunk_map\n// - <blobID>.blob.meta\n// - <blobID>.image.disk\n// - <blobID>.layer.disk\nfunc ExtractBlobIDFromFilename(filename string) string {\n\t// Remove known suffixes\n\tsuffixes := []string{\n\t\tdataFileSuffix,\n\t\tdataFileSuffix + chunkMapFileSuffix,\n\t\tchunkMapFileSuffix,\n\t\tmetaFileSuffix,\n\t\timageDiskFileSuffix,\n\t\tlayerDiskFileSuffix,\n\t}\n\n\tfor _, suffix := range suffixes {\n\t\tif strings.HasSuffix(filename, suffix) {\n\t\t\treturn strings.TrimSuffix(filename, suffix)\n\t\t}\n\t}\n\n\t// If no suffix matches, assume it's already a blob ID\n\treturn filename\n}\n"
  },
  {
    "path": "pkg/cache/manager_test.go",
    "content": "/*\n * Copyright (c) 2025. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage cache\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestExtractBlobIDFromFilename(t *testing.T) {\n\ttests := map[string]struct {\n\t\tfilename string\n\t\texpected string\n\t}{\n\t\t\"plain blob ID\": {\n\t\t\tfilename: \"abc123def456\",\n\t\t\texpected: \"abc123def456\",\n\t\t},\n\t\t\"blob with .blob.data suffix\": {\n\t\t\tfilename: \"abc123def456.blob.data\",\n\t\t\texpected: \"abc123def456\",\n\t\t},\n\t\t\"blob with .chunk_map suffix\": {\n\t\t\tfilename: \"abc123def456.chunk_map\",\n\t\t\texpected: \"abc123def456\",\n\t\t},\n\t\t\"blob with .blob.meta suffix\": {\n\t\t\tfilename: \"abc123def456.blob.meta\",\n\t\t\texpected: \"abc123def456\",\n\t\t},\n\t\t\"blob with .image.disk suffix\": {\n\t\t\tfilename: \"abc123def456.image.disk\",\n\t\t\texpected: \"abc123def456\",\n\t\t},\n\t\t\"blob with .layer.disk suffix\": {\n\t\t\tfilename: \"abc123def456.layer.disk\",\n\t\t\texpected: \"abc123def456\",\n\t\t},\n\t\t\"blob with combined .blob.data.chunk_map suffix\": {\n\t\t\tfilename: \"abc123def456.blob.data.chunk_map\",\n\t\t\texpected: \"abc123def456\",\n\t\t},\n\t\t\"real sha256 hash\": {\n\t\t\tfilename: \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\n\t\t\texpected: \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\n\t\t},\n\t\t\"real sha256 hash with .blob.data\": {\n\t\t\tfilename: \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.blob.data\",\n\t\t\texpected: \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\n\t\t},\n\t\t\"real sha256 hash with .chunk_map\": {\n\t\t\tfilename: \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.chunk_map\",\n\t\t\texpected: \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\n\t\t},\n\t\t\"real sha256 hash with .blob.data.chunk_map\": {\n\t\t\tfilename: \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.blob.data.chunk_map\",\n\t\t\texpected: \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\",\n\t\t},\n\t\t\"empty filename\": {\n\t\t\tfilename: \"\",\n\t\t\texpected: \"\",\n\t\t},\n\t\t\"filename with unknown suffix\": {\n\t\t\tfilename: \"abc123def456.unknown\",\n\t\t\texpected: \"abc123def456.unknown\",\n\t\t},\n\t\t\"filename with multiple dots but no known suffix\": {\n\t\t\tfilename: \"abc.def.ghi\",\n\t\t\texpected: \"abc.def.ghi\",\n\t\t},\n\t\t\".blob.data.chunk_map is matched before .blob.data or .chunk_map\": {\n\t\t\tfilename: \"test.blob.data.chunk_map\",\n\t\t\texpected: \"test\",\n\t\t},\n\t}\n\n\tfor name, tc := range tests {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tresult := ExtractBlobIDFromFilename(tc.filename)\n\t\t\tassert.Equal(t, tc.expected, result)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/cgroup/cgroup.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage cgroup\n\nimport (\n\t\"errors\"\n\n\t\"github.com/containerd/cgroups/v3\"\n\tv1 \"github.com/containerd/nydus-snapshotter/pkg/cgroup/v1\"\n\tv2 \"github.com/containerd/nydus-snapshotter/pkg/cgroup/v2\"\n)\n\nconst (\n\tdefaultSlice = \"system.slice\"\n)\n\nvar (\n\tErrCgroupNotSupported = errors.New(\"cgroups: cgroup not supported\")\n)\n\ntype Config struct {\n\tMemoryLimitInBytes int64\n}\n\ntype DaemonCgroup interface {\n\t// Delete the current cgroup.\n\tDelete() error\n\t// Add a process to current cgroup.\n\tAddProc(pid int) error\n}\n\nfunc createCgroup(name string, config Config) (DaemonCgroup, error) {\n\tif cgroups.Mode() == cgroups.Unified {\n\t\treturn v2.NewCgroup(defaultSlice, name, config.MemoryLimitInBytes)\n\t}\n\n\treturn v1.NewCgroup(defaultSlice, name, config.MemoryLimitInBytes)\n}\n\nfunc supported() bool {\n\treturn cgroups.Mode() != cgroups.Unavailable\n}\n\nfunc displayMode() string {\n\tswitch cgroups.Mode() {\n\tcase cgroups.Legacy:\n\t\treturn \"legacy\"\n\tcase cgroups.Hybrid:\n\t\treturn \"hybrid\"\n\tcase cgroups.Unified:\n\t\treturn \"unified\"\n\tcase cgroups.Unavailable:\n\t\treturn \"unavailable\"\n\tdefault:\n\t\treturn \"unknown\"\n\t}\n}\n"
  },
  {
    "path": "pkg/cgroup/manager.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage cgroup\n\nimport (\n\t\"github.com/containerd/log\"\n)\n\ntype Manager struct {\n\tname   string\n\tconfig Config\n\tcgroup DaemonCgroup\n}\n\ntype Opt struct {\n\tName   string\n\tConfig Config\n}\n\nfunc NewManager(opt Opt) (*Manager, error) {\n\tif !supported() {\n\t\tlog.L.Warn(\"cgroup is not supported\")\n\t\treturn nil, ErrCgroupNotSupported\n\t}\n\n\tlog.L.Infof(\"cgroup mode: %s\", displayMode())\n\tcg, err := createCgroup(opt.Name, opt.Config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &Manager{\n\t\tname:   opt.Name,\n\t\tconfig: opt.Config,\n\t\tcgroup: cg,\n\t}, nil\n}\n\n// Please make sure the *Manager is not null.\nfunc (m *Manager) AddProc(pid int) error {\n\treturn m.cgroup.AddProc(pid)\n}\n\n// Please make sure the *Manager is not null.\nfunc (m *Manager) Delete() error {\n\treturn m.cgroup.Delete()\n}\n"
  },
  {
    "path": "pkg/cgroup/v1/v1.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage v1\n\nimport (\n\t\"github.com/containerd/cgroups/v3/cgroup1\"\n\t\"github.com/containerd/log\"\n\t\"github.com/opencontainers/runtime-spec/specs-go\"\n\t\"github.com/pkg/errors\"\n)\n\ntype Cgroup struct {\n\tcontroller cgroup1.Cgroup\n}\n\nfunc generateHierarchy() cgroup1.Hierarchy {\n\treturn cgroup1.SingleSubsystem(cgroup1.Default, cgroup1.Memory)\n}\n\nfunc NewCgroup(slice, name string, memoryLimitInBytes int64) (Cgroup, error) {\n\thierarchy := generateHierarchy()\n\tspecResources := &specs.LinuxResources{\n\t\tMemory: &specs.LinuxMemory{\n\t\t\tLimit: &memoryLimitInBytes,\n\t\t},\n\t}\n\n\tcontroller, err := cgroup1.Load(cgroup1.Slice(slice, name), cgroup1.WithHiearchy(hierarchy))\n\tif err != nil && err != cgroup1.ErrCgroupDeleted {\n\t\treturn Cgroup{}, err\n\t}\n\n\tif controller != nil {\n\t\tprocesses, err := controller.Processes(cgroup1.Memory, true)\n\t\tif err != nil {\n\t\t\treturn Cgroup{}, err\n\t\t}\n\t\tif len(processes) > 0 {\n\t\t\tlog.L.Infof(\"target cgroup is existed with processes %v\", processes)\n\t\t\tif err := controller.Update(specResources); err != nil {\n\t\t\t\treturn Cgroup{}, err\n\t\t\t}\n\t\t\treturn Cgroup{\n\t\t\t\tcontroller: controller,\n\t\t\t}, nil\n\t\t}\n\t\tif err := controller.Delete(); err != nil {\n\t\t\treturn Cgroup{}, err\n\t\t}\n\t}\n\n\tcontroller, err = cgroup1.New(cgroup1.Slice(slice, name), specResources, cgroup1.WithHiearchy(hierarchy))\n\tif err != nil {\n\t\treturn Cgroup{}, errors.Wrapf(err, \"create cgroup\")\n\t}\n\tlog.L.Infof(\"create cgroup (v1) successful, state: %v\", controller.State())\n\n\treturn Cgroup{\n\t\tcontroller: controller,\n\t}, nil\n}\n\nfunc (cg Cgroup) Delete() error {\n\tprocesses, err := cg.controller.Processes(cgroup1.Memory, true)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(processes) > 0 {\n\t\tlog.L.Infof(\"skip destroy cgroup because of running daemon %v\", processes)\n\t\treturn nil\n\t}\n\treturn cg.controller.Delete()\n}\nfunc (cg Cgroup) AddProc(pid int) error {\n\terr := cg.controller.AddProc(uint64(pid), cgroup1.Memory)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.L.Infof(\"add process %d to daemon cgroup successful\", pid)\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/cgroup/v2/v2.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage v2\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/containerd/cgroups/v3/cgroup2\"\n\t\"github.com/containerd/log\"\n\t\"golang.org/x/exp/slices\"\n)\n\nconst (\n\tdefaultRoot = \"/sys/fs/cgroup\"\n)\n\nvar (\n\tErrRootMemorySubtreeControllerDisabled = errors.New(\"cgroups v2: root subtree controller for memory is disabled\")\n)\n\ntype Cgroup struct {\n\tmanager *cgroup2.Manager\n}\n\nfunc readSubtreeControllers(dir string) ([]string, error) {\n\tb, err := os.ReadFile(filepath.Join(dir, \"cgroup.subtree_control\"))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn strings.Fields(string(b)), nil\n}\n\nfunc NewCgroup(slice, name string, memoryLimitInBytes int64) (Cgroup, error) {\n\tresources := &cgroup2.Resources{\n\t\tMemory: &cgroup2.Memory{},\n\t}\n\tif memoryLimitInBytes > -1 {\n\t\tresources = &cgroup2.Resources{\n\t\t\tMemory: &cgroup2.Memory{\n\t\t\t\tMax: &memoryLimitInBytes,\n\t\t\t},\n\t\t}\n\t}\n\n\trootSubtreeControllers, err := readSubtreeControllers(defaultRoot)\n\tif err != nil {\n\t\treturn Cgroup{}, err\n\t}\n\tlog.L.Infof(\"root subtree controllers: %s\", rootSubtreeControllers)\n\n\tif !slices.Contains(rootSubtreeControllers, \"memory\") {\n\t\treturn Cgroup{}, ErrRootMemorySubtreeControllerDisabled\n\t}\n\n\tm, err := cgroup2.NewManager(defaultRoot, fmt.Sprintf(\"/%s/%s\", slice, name), resources)\n\tif err != nil {\n\t\treturn Cgroup{}, err\n\t}\n\n\tcontrollers, err := m.Controllers()\n\tif err != nil {\n\t\treturn Cgroup{}, err\n\t}\n\tlog.L.Infof(\"create cgroup (v2) successful, controllers: %v\", controllers)\n\n\treturn Cgroup{\n\t\tmanager: m,\n\t}, nil\n}\n\nfunc (cg Cgroup) Delete() error {\n\tif cg.manager != nil {\n\t\treturn cg.manager.Delete()\n\t}\n\treturn nil\n}\nfunc (cg Cgroup) AddProc(pid int) error {\n\tif cg.manager != nil {\n\t\terr := cg.manager.AddProc(uint64(pid))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlog.L.Infof(\"add process %d to daemon cgroup successful\", pid)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/converter/constant.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage converter\n\nconst (\n\tManifestOSFeatureNydus    = \"nydus.remoteimage.v1\"\n\tManifestConfigNydus       = \"application/vnd.nydus.image.config.v1+json\"\n\tManifestArtifactTypeNydus = \"application/vnd.nydus.image.manifest.v1+json\"\n\tMediaTypeNydusBlob        = \"application/vnd.oci.image.layer.nydus.blob.v1\"\n\tBootstrapFileNameInLayer  = \"image/image.boot\"\n\n\tManifestNydusCache = \"containerd.io/snapshot/nydus-cache\"\n\n\tLayerAnnotationFSVersion          = \"containerd.io/snapshot/nydus-fs-version\"\n\tLayerAnnotationNydusBlob          = \"containerd.io/snapshot/nydus-blob\"\n\tLayerAnnotationNydusBlobDigest    = \"containerd.io/snapshot/nydus-blob-digest\"\n\tLayerAnnotationNydusBlobSize      = \"containerd.io/snapshot/nydus-blob-size\"\n\tLayerAnnotationNydusBootstrap     = \"containerd.io/snapshot/nydus-bootstrap\"\n\tLayerAnnotationNydusSourceChainID = \"containerd.io/snapshot/nydus-source-chainid\"\n\tLayerAnnotationNydusEncryptedBlob = \"containerd.io/snapshot/nydus-encrypted-blob\"\n\tLayerAnnotationNydusSourceDigest  = \"containerd.io/snapshot/nydus-source-digest\"\n\tLayerAnnotationNydusTargetDigest  = \"containerd.io/snapshot/nydus-target-digest\"\n\n\tLayerAnnotationNydusReferenceBlobIDs = \"containerd.io/snapshot/nydus-reference-blob-ids\"\n\n\tLayerAnnotationUncompressed = \"containerd.io/uncompressed\"\n)\n"
  },
  {
    "path": "pkg/converter/convert_unix.go",
    "content": "//go:build !windows\n// +build !windows\n\n/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage converter\n\nimport (\n\t\"archive/tar\"\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"context\"\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\t\"syscall\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/containerd/v2/core/images/converter\"\n\t\"github.com/containerd/containerd/v2/pkg/archive\"\n\t\"github.com/containerd/containerd/v2/pkg/archive/compression\"\n\t\"github.com/containerd/containerd/v2/pkg/labels\"\n\t\"github.com/containerd/containerd/v2/plugins/content/local\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/fifo\"\n\t\"github.com/klauspost/compress/zstd\"\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/opencontainers/image-spec/identity\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/sirupsen/logrus\"\n\t\"golang.org/x/sync/errgroup\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/converter/tool\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n)\n\nconst EntryBlob = \"image.blob\"\nconst EntryBootstrap = \"image.boot\"\nconst EntryBlobMeta = \"blob.meta\"\nconst EntryBlobMetaHeader = \"blob.meta.header\"\nconst EntryTOC = \"rafs.blob.toc\"\n\nconst envNydusBuilder = \"NYDUS_BUILDER\"\nconst envNydusWorkDir = \"NYDUS_WORKDIR\"\n\nconst configGCLabelKey = \"containerd.io/gc.ref.content.config\"\n\nvar bufPool = sync.Pool{\n\tNew: func() interface{} {\n\t\tbuffer := make([]byte, 1<<20)\n\t\treturn &buffer\n\t},\n}\n\nfunc getBuilder(specifiedPath string) string {\n\tif specifiedPath != \"\" {\n\t\treturn specifiedPath\n\t}\n\n\tbuilderPath := os.Getenv(envNydusBuilder)\n\tif builderPath != \"\" {\n\t\treturn builderPath\n\t}\n\n\treturn \"nydus-image\"\n}\n\nfunc ensureWorkDir(specifiedBasePath string) (string, error) {\n\tvar baseWorkDir string\n\n\tif specifiedBasePath != \"\" {\n\t\tbaseWorkDir = specifiedBasePath\n\t} else {\n\t\tbaseWorkDir = os.Getenv(envNydusWorkDir)\n\t}\n\tif baseWorkDir == \"\" {\n\t\tbaseWorkDir = os.TempDir()\n\t}\n\n\tif err := os.MkdirAll(baseWorkDir, 0750); err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"create base directory %s\", baseWorkDir)\n\t}\n\n\tworkDirPath, err := os.MkdirTemp(baseWorkDir, \"nydus-converter-\")\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"create work directory\")\n\t}\n\n\treturn workDirPath, nil\n}\n\n// Unpack a OCI formatted tar stream into a directory.\nfunc unpackOciTar(ctx context.Context, dst string, reader io.Reader) error {\n\tds, err := compression.DecompressStream(reader)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"unpack stream\")\n\t}\n\tdefer ds.Close()\n\n\tif _, err := archive.Apply(\n\t\tctx,\n\t\tdst,\n\t\tds,\n\t\tarchive.WithConvertWhiteout(func(_ *tar.Header, _ string) (bool, error) {\n\t\t\t// Keep to extract all whiteout files.\n\t\t\treturn true, nil\n\t\t}),\n\t); err != nil {\n\t\treturn errors.Wrap(err, \"apply with convert whiteout\")\n\t}\n\n\t// Read any trailing data for some tar formats, in case the\n\t// PipeWriter of opposite side gets stuck.\n\tif _, err := io.Copy(io.Discard, ds); err != nil {\n\t\treturn errors.Wrap(err, \"trailing data after applying archive\")\n\t}\n\n\treturn nil\n}\n\n// unpackNydusBlob unpacks a Nydus formatted tar stream into a directory.\n// unpackBlob indicates whether to unpack blob data.\nfunc unpackNydusBlob(bootDst, blobDst string, ra content.ReaderAt, unpackBlob bool) error {\n\tboot, err := os.OpenFile(bootDst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0640)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"write to bootstrap %s\", bootDst)\n\t}\n\tdefer boot.Close()\n\n\tif _, err = UnpackEntry(ra, EntryBootstrap, boot); err != nil {\n\t\treturn errors.Wrap(err, \"unpack bootstrap from nydus\")\n\t}\n\n\tif unpackBlob {\n\t\tblob, err := os.OpenFile(blobDst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0640)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"write to blob %s\", blobDst)\n\t\t}\n\t\tdefer blob.Close()\n\n\t\tif _, err = UnpackEntry(ra, EntryBlob, blob); err != nil {\n\t\t\tif errors.Is(err, ErrNotFound) {\n\t\t\t\t// The nydus layer may contain only bootstrap and no blob\n\t\t\t\t// data, which should be ignored.\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn errors.Wrap(err, \"unpack blob from nydus\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc seekFileByTarHeader(ra content.ReaderAt, targetName string, maxSize *int64, handle func(io.Reader, *tar.Header) error) error {\n\tconst headerSize = 512\n\n\tif headerSize > ra.Size() {\n\t\treturn fmt.Errorf(\"invalid nydus tar size %d\", ra.Size())\n\t}\n\n\tcur := ra.Size() - headerSize\n\treader := newSeekReader(ra)\n\n\t// Seek from tail to head of nydus formatted tar stream to find\n\t// target data.\n\tfor {\n\t\t// Try to seek the part of tar header.\n\t\t_, err := reader.Seek(cur, io.SeekStart)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"seek %d for nydus tar header\", cur)\n\t\t}\n\n\t\t// Parse tar header.\n\t\ttr := tar.NewReader(reader)\n\t\thdr, err := tr.Next()\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"parse nydus tar header\")\n\t\t}\n\n\t\tif cur < hdr.Size {\n\t\t\treturn fmt.Errorf(\"invalid nydus tar data, name %s, size %d\", hdr.Name, hdr.Size)\n\t\t}\n\n\t\tif hdr.Name == targetName {\n\t\t\tif maxSize != nil && hdr.Size > *maxSize {\n\t\t\t\treturn fmt.Errorf(\"invalid nydus tar size %d\", ra.Size())\n\t\t\t}\n\n\t\t\t// Try to seek the part of tar data.\n\t\t\t_, err = reader.Seek(cur-hdr.Size, io.SeekStart)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"seek target data offset\")\n\t\t\t}\n\t\t\tdataReader := io.NewSectionReader(reader, cur-hdr.Size, hdr.Size)\n\n\t\t\tif err := handle(dataReader, hdr); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"handle target data\")\n\t\t\t}\n\n\t\t\treturn nil\n\t\t}\n\n\t\tcur = cur - hdr.Size - headerSize\n\t\tif cur < 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn errors.Wrapf(ErrNotFound, \"can't find target %s by seeking tar\", targetName)\n}\n\nfunc seekFileByTOC(ra content.ReaderAt, targetName string, handle func(io.Reader, *tar.Header) error) (*TOCEntry, error) {\n\tentrySize := 128\n\tmaxSize := int64(1 << 20)\n\tvar tocEntry *TOCEntry\n\n\terr := seekFileByTarHeader(ra, EntryTOC, &maxSize, func(tocEntryDataReader io.Reader, _ *tar.Header) error {\n\t\tentryData, err := io.ReadAll(tocEntryDataReader)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"read toc entries\")\n\t\t}\n\t\tif len(entryData)%entrySize != 0 {\n\t\t\treturn fmt.Errorf(\"invalid entries length %d\", len(entryData))\n\t\t}\n\n\t\tcount := len(entryData) / entrySize\n\t\tfor i := 0; i < count; i++ {\n\t\t\tvar entry TOCEntry\n\t\t\tr := bytes.NewReader(entryData[i*entrySize : i*entrySize+entrySize])\n\t\t\tif err := binary.Read(r, binary.LittleEndian, &entry); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"read toc entries\")\n\t\t\t}\n\t\t\tif entry.GetName() == targetName {\n\t\t\t\tcompressor, err := entry.GetCompressor()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn errors.Wrap(err, \"get compressor of entry\")\n\t\t\t\t}\n\t\t\t\tcompressedOffset := int64(entry.GetCompressedOffset())\n\t\t\t\tcompressedSize := int64(entry.GetCompressedSize())\n\t\t\t\tsr := io.NewSectionReader(ra, compressedOffset, compressedSize)\n\n\t\t\t\tvar rd io.Reader\n\t\t\t\tswitch compressor {\n\t\t\t\tcase CompressorZstd:\n\t\t\t\t\tdecoder, err := zstd.NewReader(sr)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn errors.Wrap(err, \"seek to target data offset\")\n\t\t\t\t\t}\n\t\t\t\t\tdefer decoder.Close()\n\t\t\t\t\trd = decoder\n\t\t\t\tcase CompressorNone:\n\t\t\t\t\trd = sr\n\t\t\t\tdefault:\n\t\t\t\t\treturn fmt.Errorf(\"unsupported compressor %x\", compressor)\n\t\t\t\t}\n\n\t\t\t\tif err := handle(rd, nil); err != nil {\n\t\t\t\t\treturn errors.Wrap(err, \"handle target entry data\")\n\t\t\t\t}\n\n\t\t\t\ttocEntry = &entry\n\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\n\t\treturn errors.Wrapf(ErrNotFound, \"can't find target %s by seeking TOC\", targetName)\n\t})\n\n\treturn tocEntry, err\n}\n\n// Unpack the file from nydus formatted tar stream.\n// The nydus formatted tar stream is a tar-like structure that arranges the\n// data as follows:\n//\n// `data | tar_header | ... | data | tar_header | [toc_entry | ... | toc_entry | tar_header]`\nfunc UnpackEntry(ra content.ReaderAt, targetName string, target io.Writer) (*TOCEntry, error) {\n\thandle := func(dataReader io.Reader, _ *tar.Header) error {\n\t\t// Copy data to provided target writer.\n\t\tif _, err := io.Copy(target, dataReader); err != nil {\n\t\t\treturn errors.Wrap(err, \"copy target data to reader\")\n\t\t}\n\n\t\treturn nil\n\t}\n\n\treturn seekFile(ra, targetName, handle)\n}\n\nfunc seekFile(ra content.ReaderAt, targetName string, handle func(io.Reader, *tar.Header) error) (*TOCEntry, error) {\n\t// Try seek target data by TOC.\n\tentry, err := seekFileByTOC(ra, targetName, handle)\n\tif err != nil {\n\t\tif !errors.Is(err, ErrNotFound) {\n\t\t\treturn nil, errors.Wrap(err, \"seek file by TOC\")\n\t\t}\n\t} else {\n\t\treturn entry, nil\n\t}\n\n\t// Seek target data by tar header, ensure compatible with old rafs blob format.\n\treturn nil, seekFileByTarHeader(ra, targetName, nil, handle)\n}\n\n// Pack converts an OCI tar stream to nydus formatted stream with a tar-like\n// structure that arranges the data as follows:\n//\n// `data | tar_header | data | tar_header | [toc_entry | ... | toc_entry | tar_header]`\n//\n// The caller should write OCI tar stream into the returned `io.WriteCloser`,\n// then the Pack method will write the nydus formatted stream to `dest`\n// provided by the caller.\n//\n// Important: the caller must check `io.WriteCloser.Close() == nil` to ensure\n// the conversion workflow is finished.\nfunc Pack(ctx context.Context, dest io.Writer, opt PackOption) (io.WriteCloser, error) {\n\tif opt.FsVersion == \"\" {\n\t\topt.FsVersion = \"6\"\n\t}\n\n\tbuilderPath := getBuilder(opt.BuilderPath)\n\n\trequiredFeatures := tool.NewFeatures(tool.FeatureTar2Rafs)\n\tif opt.BatchSize != \"\" && opt.BatchSize != \"0\" {\n\t\trequiredFeatures.Add(tool.FeatureBatchSize)\n\t}\n\tif opt.Encrypt {\n\t\trequiredFeatures.Add(tool.FeatureEncrypt)\n\t}\n\n\tdetectedFeatures, err := tool.DetectFeatures(builderPath, requiredFeatures, tool.GetHelp)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\topt.features = detectedFeatures\n\n\tif opt.OCIRef {\n\t\tif opt.FsVersion == \"6\" {\n\t\t\treturn packFromTar(ctx, dest, opt)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"oci ref can only be supported by fs version 6\")\n\t}\n\n\tif opt.features.Contains(tool.FeatureBatchSize) && opt.FsVersion != \"6\" {\n\t\treturn nil, fmt.Errorf(\"'--batch-size' can only be supported by fs version 6\")\n\t}\n\n\tif opt.features.Contains(tool.FeatureTar2Rafs) {\n\t\treturn packFromTar(ctx, dest, opt)\n\t}\n\n\treturn packFromDirectory(ctx, dest, opt, builderPath)\n}\n\nfunc packFromDirectory(ctx context.Context, dest io.Writer, opt PackOption, builderPath string) (io.WriteCloser, error) {\n\tworkDir, err := ensureWorkDir(opt.WorkDir)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"ensure work directory\")\n\t}\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tos.RemoveAll(workDir)\n\t\t}\n\t}()\n\n\tsourceDir := filepath.Join(workDir, \"source\")\n\tif err := os.MkdirAll(sourceDir, 0755); err != nil {\n\t\treturn nil, errors.Wrap(err, \"create source directory\")\n\t}\n\n\tpr, pw := io.Pipe()\n\n\tunpackDone := make(chan bool, 1)\n\tgo func() {\n\t\tif err := unpackOciTar(ctx, sourceDir, pr); err != nil {\n\t\t\tpr.CloseWithError(errors.Wrapf(err, \"unpack to %s\", sourceDir))\n\t\t\tclose(unpackDone)\n\t\t\treturn\n\t\t}\n\t\tunpackDone <- true\n\t}()\n\n\twc := newWriteCloser(pw, func() error {\n\t\tdefer os.RemoveAll(workDir)\n\n\t\t// Because PipeWriter#Close is called does not mean that the PipeReader\n\t\t// has finished reading all the data, and unpack may not be complete yet,\n\t\t// so we need to wait for that here.\n\t\t<-unpackDone\n\n\t\tblobPath := filepath.Join(workDir, \"blob\")\n\t\tblobFifo, err := fifo.OpenFifo(ctx, blobPath, syscall.O_CREAT|syscall.O_RDONLY|syscall.O_NONBLOCK, 0640)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"create fifo file\")\n\t\t}\n\t\tdefer blobFifo.Close()\n\n\t\tgo func() {\n\t\t\terr := tool.Pack(tool.PackOption{\n\t\t\t\tBuilderPath: builderPath,\n\n\t\t\t\tBlobPath:         blobPath,\n\t\t\t\tFsVersion:        opt.FsVersion,\n\t\t\t\tSourcePath:       sourceDir,\n\t\t\t\tChunkDictPath:    opt.ChunkDictPath,\n\t\t\t\tPrefetchPatterns: opt.PrefetchPatterns,\n\t\t\t\tAlignedChunk:     opt.AlignedChunk,\n\t\t\t\tChunkSize:        opt.ChunkSize,\n\t\t\t\tBatchSize:        opt.BatchSize,\n\t\t\t\tCompressor:       opt.Compressor,\n\t\t\t\tTimeout:          opt.Timeout,\n\t\t\t\tEncrypt:          opt.Encrypt,\n\n\t\t\t\tFeatures: opt.features,\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\tpw.CloseWithError(errors.Wrapf(err, \"convert blob for %s\", sourceDir))\n\t\t\t\tblobFifo.Close()\n\t\t\t}\n\t\t}()\n\n\t\tbuffer := bufPool.Get().(*[]byte)\n\t\tdefer bufPool.Put(buffer)\n\t\tif _, err := io.CopyBuffer(dest, blobFifo, *buffer); err != nil {\n\t\t\treturn errors.Wrap(err, \"pack nydus tar\")\n\t\t}\n\n\t\treturn nil\n\t})\n\n\treturn wc, nil\n}\n\nfunc packFromTar(ctx context.Context, dest io.Writer, opt PackOption) (io.WriteCloser, error) {\n\tworkDir, err := ensureWorkDir(opt.WorkDir)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"ensure work directory\")\n\t}\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tos.RemoveAll(workDir)\n\t\t}\n\t}()\n\n\trafsBlobPath := filepath.Join(workDir, \"blob.rafs\")\n\trafsBlobFifo, err := fifo.OpenFifo(ctx, rafsBlobPath, syscall.O_CREAT|syscall.O_RDONLY|syscall.O_NONBLOCK, 0640)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"create fifo file\")\n\t}\n\n\ttarBlobPath := filepath.Join(workDir, \"blob.targz\")\n\ttarBlobFifo, err := fifo.OpenFifo(ctx, tarBlobPath, syscall.O_CREAT|syscall.O_WRONLY|syscall.O_NONBLOCK, 0640)\n\tif err != nil {\n\t\tdefer rafsBlobFifo.Close()\n\t\treturn nil, errors.Wrapf(err, \"create fifo file\")\n\t}\n\n\tpr, pw := io.Pipe()\n\teg := errgroup.Group{}\n\n\twc := newWriteCloser(pw, func() error {\n\t\tdefer os.RemoveAll(workDir)\n\t\tif err := eg.Wait(); err != nil {\n\t\t\treturn errors.Wrapf(err, \"convert nydus ref\")\n\t\t}\n\t\treturn nil\n\t})\n\n\teg.Go(func() error {\n\t\tdefer tarBlobFifo.Close()\n\t\tbuffer := bufPool.Get().(*[]byte)\n\t\tdefer bufPool.Put(buffer)\n\t\tif _, err := io.CopyBuffer(tarBlobFifo, pr, *buffer); err != nil {\n\t\t\treturn errors.Wrapf(err, \"copy targz to fifo\")\n\t\t}\n\t\treturn nil\n\t})\n\n\teg.Go(func() error {\n\t\tdefer rafsBlobFifo.Close()\n\t\tbuffer := bufPool.Get().(*[]byte)\n\t\tdefer bufPool.Put(buffer)\n\t\tif _, err := io.CopyBuffer(dest, rafsBlobFifo, *buffer); err != nil {\n\t\t\treturn errors.Wrapf(err, \"copy blob meta fifo to nydus blob\")\n\t\t}\n\t\treturn nil\n\t})\n\n\teg.Go(func() error {\n\t\tvar err error\n\t\tif opt.OCIRef {\n\t\t\terr = tool.Pack(tool.PackOption{\n\t\t\t\tBuilderPath: getBuilder(opt.BuilderPath),\n\n\t\t\t\tOCIRef:     opt.OCIRef,\n\t\t\t\tBlobPath:   rafsBlobPath,\n\t\t\t\tSourcePath: tarBlobPath,\n\t\t\t\tTimeout:    opt.Timeout,\n\n\t\t\t\tFeatures: opt.features,\n\t\t\t})\n\t\t} else {\n\t\t\terr = tool.Pack(tool.PackOption{\n\t\t\t\tBuilderPath: getBuilder(opt.BuilderPath),\n\n\t\t\t\tBlobPath:         rafsBlobPath,\n\t\t\t\tFsVersion:        opt.FsVersion,\n\t\t\t\tSourcePath:       tarBlobPath,\n\t\t\t\tChunkDictPath:    opt.ChunkDictPath,\n\t\t\t\tPrefetchPatterns: opt.PrefetchPatterns,\n\t\t\t\tAlignedChunk:     opt.AlignedChunk,\n\t\t\t\tChunkSize:        opt.ChunkSize,\n\t\t\t\tBatchSize:        opt.BatchSize,\n\t\t\t\tCompressor:       opt.Compressor,\n\t\t\t\tTimeout:          opt.Timeout,\n\t\t\t\tEncrypt:          opt.Encrypt,\n\n\t\t\t\tFeatures: opt.features,\n\t\t\t})\n\t\t}\n\t\tif err != nil {\n\t\t\t// Without handling the returned error because we just only\n\t\t\t// focus on the command exit status in `tool.Pack`.\n\t\t\t_ = wc.Close()\n\t\t}\n\t\treturn errors.Wrapf(err, \"call builder\")\n\t})\n\n\treturn wc, nil\n}\n\nfunc calcBlobTOCDigest(ra content.ReaderAt) (*digest.Digest, error) {\n\tmaxSize := int64(1 << 20)\n\tdigester := digest.Canonical.Digester()\n\tif err := seekFileByTarHeader(ra, EntryTOC, &maxSize, func(tocData io.Reader, _ *tar.Header) error {\n\t\tif _, err := io.Copy(digester.Hash(), tocData); err != nil {\n\t\t\treturn errors.Wrap(err, \"calc toc data and header digest\")\n\t\t}\n\t\treturn nil\n\t}); err != nil {\n\t\treturn nil, err\n\t}\n\ttocDigest := digester.Digest()\n\treturn &tocDigest, nil\n}\n\n// Merge multiple nydus bootstraps (from each layer of image) to a final\n// bootstrap. And due to the possibility of enabling the `ChunkDictPath`\n// option causes the data deduplication, it will return the actual blob\n// digests referenced by the bootstrap.\nfunc Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption) ([]digest.Digest, error) {\n\tworkDir, err := ensureWorkDir(opt.WorkDir)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"ensure work directory\")\n\t}\n\tdefer os.RemoveAll(workDir)\n\n\tgetLayerPath := func(layerIdx int, suffix string) string {\n\t\tif layerIdx < 0 || layerIdx >= len(layers) {\n\t\t\treturn \"\"\n\t\t}\n\n\t\tdigestHex := layers[layerIdx].Digest.Hex()\n\t\tif suffix == \"\" && layers[layerIdx].OriginalDigest != nil {\n\t\t\tdigestHex = layers[layerIdx].OriginalDigest.Hex()\n\t\t}\n\t\treturn filepath.Join(workDir, digestHex+suffix)\n\t}\n\n\tunpackLayerEntry := func(layerIdx int, entryName string, filePath string) error {\n\t\tif layerIdx < 0 || layerIdx >= len(layers) {\n\t\t\treturn errors.Errorf(\"layer index %d out of bounds\", layerIdx)\n\t\t}\n\n\t\tfile, err := os.Create(filePath)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"create %s file\", entryName)\n\t\t}\n\t\tdefer file.Close()\n\n\t\tif _, err := UnpackEntry(layers[layerIdx].ReaderAt, entryName, file); err != nil {\n\t\t\treturn errors.Wrapf(err, \"unpack %s\", entryName)\n\t\t}\n\t\treturn nil\n\t}\n\n\teg, _ := errgroup.WithContext(ctx)\n\tsourceBootstrapPaths := []string{}\n\trafsBlobDigests := []string{}\n\trafsBlobSizes := []int64{}\n\trafsBlobTOCDigests := []string{}\n\tfor idx := range layers {\n\t\tsourceBootstrapPaths = append(sourceBootstrapPaths, getLayerPath(idx, \"\"))\n\t\tif layers[idx].OriginalDigest != nil {\n\t\t\trafsBlobTOCDigest, err := calcBlobTOCDigest(layers[idx].ReaderAt)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrapf(err, \"calc blob toc digest for layer %s\", layers[idx].Digest)\n\t\t\t}\n\t\t\trafsBlobTOCDigests = append(rafsBlobTOCDigests, rafsBlobTOCDigest.Hex())\n\t\t\trafsBlobDigests = append(rafsBlobDigests, layers[idx].Digest.Hex())\n\t\t\trafsBlobSizes = append(rafsBlobSizes, layers[idx].ReaderAt.Size())\n\t\t}\n\n\t\teg.Go(func(idx int) func() error {\n\t\t\treturn func() error {\n\t\t\t\t// Use the hex hash string of whole tar blob as the bootstrap name.\n\t\t\t\tif err := unpackLayerEntry(idx, EntryBootstrap, getLayerPath(idx, \"\")); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\tif opt.FsVersion == \"6\" {\n\t\t\t\t\tif err := unpackLayerEntry(idx, EntryBlobMeta, getLayerPath(idx, \".blob.meta\")); err != nil {\n\t\t\t\t\t\tlogrus.Warnf(\"Failed to extract blob.meta.header for layer %d: %v\\n\", idx, err)\n\t\t\t\t\t}\n\n\t\t\t\t\tif err := unpackLayerEntry(idx, EntryBlobMetaHeader, getLayerPath(idx, \".blob.meta.header\")); err != nil {\n\t\t\t\t\t\tlogrus.Warnf(\"Failed to extract blob.meta.header for layer %d: %v\\n\", idx, err)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}(idx))\n\t}\n\n\tif err := eg.Wait(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"unpack all bootstraps\")\n\t}\n\n\ttargetBootstrapPath := filepath.Join(workDir, \"bootstrap\")\n\n\tblobDigests, err := tool.Merge(tool.MergeOption{\n\t\tBuilderPath: getBuilder(opt.BuilderPath),\n\n\t\tSourceBootstrapPaths: sourceBootstrapPaths,\n\t\tRafsBlobDigests:      rafsBlobDigests,\n\t\tRafsBlobSizes:        rafsBlobSizes,\n\t\tRafsBlobTOCDigests:   rafsBlobTOCDigests,\n\n\t\tTargetBootstrapPath: targetBootstrapPath,\n\t\tChunkDictPath:       opt.ChunkDictPath,\n\t\tParentBootstrapPath: opt.ParentBootstrapPath,\n\t\tPrefetchPatterns:    opt.PrefetchPatterns,\n\t\tOutputJSONPath:      filepath.Join(workDir, \"merge-output.json\"),\n\t\tTimeout:             opt.Timeout,\n\t})\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"merge bootstrap\")\n\t}\n\n\tbootstrapRa, err := local.OpenReader(targetBootstrapPath)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"open bootstrap reader\")\n\t}\n\tdefer bootstrapRa.Close()\n\n\tfiles := []File{\n\t\t{\n\t\t\tName:   EntryBootstrap,\n\t\t\tReader: content.NewReader(bootstrapRa),\n\t\t\tSize:   bootstrapRa.Size(),\n\t\t},\n\t}\n\n\tif opt.FsVersion == \"6\" {\n\t\tmetaRas := make([]io.Closer, 0, len(layers)*2)\n\t\tdefer func() {\n\t\t\tfor _, closer := range metaRas {\n\t\t\t\tcloser.Close()\n\t\t\t}\n\t\t}()\n\n\t\tfor idx := range layers {\n\t\t\tdigestHex := layers[idx].Digest.Hex()\n\t\t\tblobMetaPath := getLayerPath(idx, \".blob.meta\")\n\t\t\tblobMetaHeaderPath := getLayerPath(idx, \".blob.meta.header\")\n\n\t\t\tmetaContent, err := os.ReadFile(blobMetaPath)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"read blob.meta\")\n\t\t\t}\n\n\t\t\theaderContent, err := os.ReadFile(blobMetaHeaderPath)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"read blob.meta.header\")\n\t\t\t}\n\t\t\tuncompressedSize := len(metaContent)\n\t\t\talignedUncompressedSize := (uncompressedSize + 4095) &^ 4095\n\t\t\ttotalSize := alignedUncompressedSize + len(headerContent)\n\n\t\t\tif totalSize == 0 {\n\t\t\t\tlogrus.Warnf(\"blob data for layer %s is empty, skipped\\n\", digestHex)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tassembledFileName := fmt.Sprintf(\"%s.blob.meta\", digestHex)\n\t\t\tassembledFilePath := filepath.Join(workDir, assembledFileName)\n\n\t\t\twriteMetaFile := func() error {\n\t\t\t\tf, err := os.Create(assembledFilePath)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tdefer f.Close()\n\n\t\t\t\tif _, err := f.Write(metaContent); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\tif padding := alignedUncompressedSize - uncompressedSize; padding > 0 {\n\t\t\t\t\tif _, err := f.Write(make([]byte, padding)); err != nil {\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif _, err := f.Write(headerContent); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\n\t\t\t\treturn f.Sync()\n\t\t\t}\n\n\t\t\tif err := writeMetaFile(); err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"write blob meta file\")\n\t\t\t}\n\n\t\t\tassembledRa, err := local.OpenReader(assembledFilePath)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"open blob meta file\")\n\t\t\t}\n\n\t\t\tmetaRas = append(metaRas, assembledRa)\n\n\t\t\tfiles = append(files, File{\n\t\t\t\tName:   assembledFileName,\n\t\t\t\tReader: content.NewReader(assembledRa),\n\t\t\t\tSize:   int64(totalSize),\n\t\t\t})\n\t\t}\n\t}\n\n\tfiles = append(files, opt.AppendFiles...)\n\tvar rc io.ReadCloser\n\n\tif opt.WithTar {\n\t\trc = packToTar(files, false)\n\t} else {\n\t\trc, err = os.Open(targetBootstrapPath)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"open targe bootstrap\")\n\t\t}\n\t}\n\tdefer rc.Close()\n\n\tbuffer := bufPool.Get().(*[]byte)\n\tdefer bufPool.Put(buffer)\n\tif _, err = io.CopyBuffer(dest, rc, *buffer); err != nil {\n\t\treturn nil, errors.Wrap(err, \"copy merged bootstrap\")\n\t}\n\treturn blobDigests, nil\n}\n\n// Unpack converts a nydus blob layer to OCI formatted tar stream.\nfunc Unpack(ctx context.Context, ra content.ReaderAt, dest io.Writer, opt UnpackOption) error {\n\tworkDir, err := ensureWorkDir(opt.WorkDir)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"ensure work directory\")\n\t}\n\tdefer os.RemoveAll(workDir)\n\n\tbootPath, blobPath := filepath.Join(workDir, EntryBootstrap), filepath.Join(workDir, EntryBlob)\n\tif err = unpackNydusBlob(bootPath, blobPath, ra, !opt.Stream); err != nil {\n\t\treturn errors.Wrap(err, \"unpack nydus tar\")\n\t}\n\n\ttarPath := filepath.Join(workDir, \"oci.tar\")\n\tblobFifo, err := fifo.OpenFifo(ctx, tarPath, syscall.O_CREAT|syscall.O_RDONLY|syscall.O_NONBLOCK, 0640)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"create fifo file\")\n\t}\n\tdefer blobFifo.Close()\n\n\tunpackOpt := tool.UnpackOption{\n\t\tBuilderPath:   getBuilder(opt.BuilderPath),\n\t\tBootstrapPath: bootPath,\n\t\tBlobPath:      blobPath,\n\t\tTarPath:       tarPath,\n\t\tTimeout:       opt.Timeout,\n\t}\n\n\tif opt.Stream {\n\t\tproxy, err := setupContentStoreProxy(opt.WorkDir, ra)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"new content store proxy\")\n\t\t}\n\t\tdefer func() { _ = proxy.close() }()\n\n\t\t// generate backend config file\n\t\tbackendConfigStr := fmt.Sprintf(`{\"version\":2,\"backend\":{\"type\":\"http-proxy\",\"http-proxy\":{\"addr\":\"%s\"}}}`, proxy.socketPath)\n\t\tbackendConfigPath := filepath.Join(workDir, \"backend-config.json\")\n\t\tif err := os.WriteFile(backendConfigPath, []byte(backendConfigStr), 0640); err != nil {\n\t\t\treturn errors.Wrap(err, \"write backend config\")\n\t\t}\n\t\tunpackOpt.BlobPath = \"\"\n\t\tunpackOpt.BackendConfigPath = backendConfigPath\n\t}\n\n\tunpackErrChan := make(chan error)\n\tgo func() {\n\t\tdefer close(unpackErrChan)\n\t\terr := tool.Unpack(unpackOpt)\n\t\tif err != nil {\n\t\t\tblobFifo.Close()\n\t\t\tunpackErrChan <- err\n\t\t}\n\t}()\n\n\tbuffer := bufPool.Get().(*[]byte)\n\tdefer bufPool.Put(buffer)\n\tif _, err := io.CopyBuffer(dest, blobFifo, *buffer); err != nil {\n\t\tif unpackErr := <-unpackErrChan; unpackErr != nil {\n\t\t\treturn errors.Wrap(unpackErr, \"unpack\")\n\t\t}\n\t\treturn errors.Wrap(err, \"copy oci tar\")\n\t}\n\n\treturn nil\n}\n\n// IsNydusBlobAndExists returns true when the specified digest of content exists in\n// the content store and it's nydus blob format.\nfunc IsNydusBlobAndExists(ctx context.Context, cs content.Store, desc ocispec.Descriptor) bool {\n\t_, err := cs.Info(ctx, desc.Digest)\n\tif err != nil {\n\t\treturn false\n\t}\n\n\treturn IsNydusBlob(desc)\n}\n\n// IsNydusBlob returns true when the specified descriptor is nydus blob layer.\nfunc IsNydusBlob(desc ocispec.Descriptor) bool {\n\tif desc.Annotations == nil {\n\t\treturn false\n\t}\n\n\t_, hasAnno := desc.Annotations[LayerAnnotationNydusBlob]\n\treturn hasAnno\n}\n\n// IsNydusBootstrap returns true when the specified descriptor is nydus bootstrap layer.\nfunc IsNydusBootstrap(desc ocispec.Descriptor) bool {\n\tif desc.Annotations == nil {\n\t\treturn false\n\t}\n\n\t_, hasAnno := desc.Annotations[LayerAnnotationNydusBootstrap]\n\treturn hasAnno\n}\n\n// isNydusImage checks if the last layer is nydus bootstrap,\n// so that we can ensure it is a nydus image.\nfunc isNydusImage(manifest *ocispec.Manifest) bool {\n\tlayers := manifest.Layers\n\tif len(layers) != 0 {\n\t\tdesc := layers[len(layers)-1]\n\t\tif IsNydusBootstrap(desc) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// makeBlobDesc returns a ocispec.Descriptor by the given information.\nfunc makeBlobDesc(ctx context.Context, cs content.Store, opt PackOption, sourceDigest, targetDigest digest.Digest) (*ocispec.Descriptor, error) {\n\ttargetInfo, err := cs.Info(ctx, targetDigest)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get target blob info %s\", targetDigest)\n\t}\n\tif targetInfo.Labels == nil {\n\t\ttargetInfo.Labels = map[string]string{}\n\t}\n\t// Write a diff id label of layer in content store for simplifying\n\t// diff id calculation to speed up the conversion.\n\t// See: https://github.com/containerd/containerd/blob/e4fefea5544d259177abb85b64e428702ac49c97/images/diffid.go#L49\n\ttargetInfo.Labels[labels.LabelUncompressed] = targetDigest.String()\n\t_, err = cs.Update(ctx, targetInfo)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"update layer label\")\n\t}\n\n\ttargetDesc := ocispec.Descriptor{\n\t\tDigest:    targetDigest,\n\t\tSize:      targetInfo.Size,\n\t\tMediaType: MediaTypeNydusBlob,\n\t\tAnnotations: map[string]string{\n\t\t\t// Use `containerd.io/uncompressed` to generate DiffID of\n\t\t\t// layer defined in OCI spec.\n\t\t\tLayerAnnotationUncompressed: targetDigest.String(),\n\t\t\tLayerAnnotationNydusBlob:    \"true\",\n\t\t},\n\t}\n\n\tif opt.OCIRef {\n\t\ttargetDesc.Annotations[label.NydusRefLayer] = sourceDigest.String()\n\t}\n\n\tif opt.Encrypt {\n\t\ttargetDesc.Annotations[LayerAnnotationNydusEncryptedBlob] = \"true\"\n\t}\n\n\treturn &targetDesc, nil\n}\n\n// LayerConvertFunc returns a function which converts an OCI image layer to\n// a nydus blob layer, and set the media type to \"application/vnd.oci.image.layer.nydus.blob.v1\".\nfunc LayerConvertFunc(opt PackOption) converter.ConvertFunc {\n\treturn func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {\n\t\tif ctx.Err() != nil {\n\t\t\t// The context is already cancelled, no need to proceed.\n\t\t\treturn nil, ctx.Err()\n\t\t}\n\t\tif !images.IsLayerType(desc.MediaType) {\n\t\t\treturn nil, nil\n\t\t}\n\n\t\t// Skip the conversion of nydus layer.\n\t\tif IsNydusBlob(desc) || IsNydusBootstrap(desc) {\n\t\t\treturn nil, nil\n\t\t}\n\n\t\t// Use remote cache to avoid unnecessary conversion\n\t\tinfo, err := cs.Info(ctx, desc.Digest)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"get blob info %s\", desc.Digest)\n\t\t}\n\t\tif targetDigest := digest.Digest(info.Labels[LayerAnnotationNydusTargetDigest]); targetDigest.Validate() == nil {\n\t\t\treturn makeBlobDesc(ctx, cs, opt, desc.Digest, targetDigest)\n\t\t}\n\n\t\tra, err := cs.ReaderAt(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"get source blob reader\")\n\t\t}\n\t\tdefer ra.Close()\n\t\trdr := io.NewSectionReader(ra, 0, ra.Size())\n\n\t\tref := fmt.Sprintf(\"convert-nydus-from-%s\", desc.Digest)\n\t\tdst, err := content.OpenWriter(ctx, cs, content.WithRef(ref))\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"open blob writer\")\n\t\t}\n\t\tdefer dst.Close()\n\n\t\tvar tr io.ReadCloser\n\t\tif opt.OCIRef {\n\t\t\ttr = io.NopCloser(rdr)\n\t\t} else {\n\t\t\ttr, err = compression.DecompressStream(rdr)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"decompress blob stream\")\n\t\t\t}\n\t\t}\n\n\t\tdigester := digest.SHA256.Digester()\n\t\tpr, pw := io.Pipe()\n\t\ttw, err := Pack(ctx, io.MultiWriter(pw, digester.Hash()), opt)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"pack tar to nydus\")\n\t\t}\n\n\t\tcopyBufferDone := make(chan error, 1)\n\t\tgo func() {\n\t\t\tbuffer := bufPool.Get().(*[]byte)\n\t\t\tdefer bufPool.Put(buffer)\n\t\t\t_, err := io.CopyBuffer(tw, tr, *buffer)\n\t\t\tcopyBufferDone <- err\n\t\t}()\n\n\t\tgo func() {\n\t\t\tdefer pw.Close()\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\t// The context was cancelled!\n\t\t\t\t// Close the pipe with the context's error to signal\n\t\t\t\t// the reader to stop.\n\t\t\t\tpw.CloseWithError(ctx.Err())\n\t\t\t\treturn\n\t\t\tcase err := <-copyBufferDone:\n\t\t\t\tif err != nil {\n\t\t\t\t\tpw.CloseWithError(err)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tif err := tr.Close(); err != nil {\n\t\t\t\tpw.CloseWithError(err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif err := tw.Close(); err != nil {\n\t\t\t\tpw.CloseWithError(err)\n\t\t\t\treturn\n\t\t\t}\n\t\t}()\n\n\t\tif err := content.Copy(ctx, dst, pr, 0, \"\"); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"copy nydus blob to content store\")\n\t\t}\n\n\t\tblobDigest := digester.Digest()\n\t\tnewDesc, err := makeBlobDesc(ctx, cs, opt, desc.Digest, blobDigest)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif opt.Backend != nil {\n\t\t\tif err := opt.Backend.Push(ctx, cs, *newDesc); err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"push to storage backend\")\n\t\t\t}\n\t\t}\n\n\t\treturn newDesc, nil\n\t}\n}\n\n// ConvertHookFunc returns a function which will be used as a callback\n// called for each blob after conversion is done. The function only hooks\n// the index conversion and the manifest conversion.\nfunc ConvertHookFunc(opt MergeOption) converter.ConvertHookFunc {\n\treturn func(ctx context.Context, cs content.Store, orgDesc ocispec.Descriptor, newDesc *ocispec.Descriptor) (*ocispec.Descriptor, error) {\n\t\t// If the previous conversion did not occur, the `newDesc` may be nil.\n\t\tif newDesc == nil {\n\t\t\treturn &orgDesc, nil\n\t\t}\n\t\tswitch {\n\t\tcase images.IsIndexType(newDesc.MediaType):\n\t\t\treturn convertIndex(ctx, cs, newDesc)\n\t\tcase images.IsManifestType(newDesc.MediaType):\n\t\t\treturn convertManifest(ctx, cs, orgDesc, newDesc, opt)\n\t\tdefault:\n\t\t\treturn newDesc, nil\n\t\t}\n\t}\n}\n\n// convertIndex modifies the original index converting it to manifest directly if it contains only one manifest.\nfunc convertIndex(ctx context.Context, cs content.Store, newDesc *ocispec.Descriptor) (*ocispec.Descriptor, error) {\n\tvar index ocispec.Index\n\t_, err := readJSON(ctx, cs, &index, *newDesc)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"read index json\")\n\t}\n\n\t// If the converted manifest list contains only one manifest,\n\t// convert it directly to manifest.\n\tif len(index.Manifests) == 1 {\n\t\treturn &index.Manifests[0], nil\n\t}\n\treturn newDesc, nil\n}\n\n// convertManifest merges all the nydus blob layers into a\n// nydus bootstrap layer, update the image config,\n// and modify the image manifest.\nfunc convertManifest(ctx context.Context, cs content.Store, oldDesc ocispec.Descriptor, newDesc *ocispec.Descriptor, opt MergeOption) (*ocispec.Descriptor, error) {\n\tvar manifest ocispec.Manifest\n\tmanifestDesc := *newDesc\n\tmanifestLabels, err := readJSON(ctx, cs, &manifest, manifestDesc)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"read manifest json\")\n\t}\n\n\tif isNydusImage(&manifest) {\n\t\treturn &manifestDesc, nil\n\t}\n\n\t// This option needs to be enabled for image scenario.\n\topt.WithTar = true\n\n\t// If the original image is already an OCI type, we should forcibly set the\n\t// bootstrap layer to the OCI type.\n\tif !opt.OCI && oldDesc.MediaType == ocispec.MediaTypeImageManifest {\n\t\topt.OCI = true\n\t}\n\n\t// Append bootstrap layer to manifest, encrypt bootstrap layer if needed.\n\tbootstrapDesc, blobDescs, err := MergeLayers(ctx, cs, manifest.Layers, opt)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"merge nydus layers\")\n\t}\n\tif opt.Backend != nil {\n\t\t// Only append nydus bootstrap layer into manifest, and do not put nydus\n\t\t// blob layer into manifest if blob storage backend is specified.\n\t\tmanifest.Layers = []ocispec.Descriptor{*bootstrapDesc}\n\t} else {\n\t\tfor idx, blobDesc := range blobDescs {\n\t\t\tblobGCLabelKey := fmt.Sprintf(\"containerd.io/gc.ref.content.l.%d\", idx)\n\t\t\tmanifestLabels[blobGCLabelKey] = blobDesc.Digest.String()\n\t\t}\n\t\t// Affected by chunk dict, the blob list referenced by final bootstrap\n\t\t// are from different layers, part of them are from original layers, part\n\t\t// from chunk dict bootstrap, so we need to rewrite manifest's layers here.\n\t\tblobDescs := append(blobDescs, *bootstrapDesc)\n\t\tmanifest.Layers = blobDescs\n\t}\n\n\t// Update the gc label of bootstrap layer\n\tbootstrapGCLabelKey := fmt.Sprintf(\"containerd.io/gc.ref.content.l.%d\", len(manifest.Layers)-1)\n\tmanifestLabels[bootstrapGCLabelKey] = bootstrapDesc.Digest.String()\n\n\t// Rewrite diff ids and remove useless annotation.\n\tvar config ocispec.Image\n\tconfigLabels, err := readJSON(ctx, cs, &config, manifest.Config)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"read image config\")\n\t}\n\tbootstrapHistory := ocispec.History{\n\t\tCreatedBy: \"Nydus Converter\",\n\t\tComment:   \"Nydus Bootstrap Layer\",\n\t}\n\tif opt.Backend != nil {\n\t\tconfig.RootFS.DiffIDs = []digest.Digest{digest.Digest(bootstrapDesc.Annotations[LayerAnnotationUncompressed])}\n\t\tconfig.History = []ocispec.History{bootstrapHistory}\n\t} else {\n\t\tconfig.RootFS.DiffIDs = make([]digest.Digest, 0, len(manifest.Layers))\n\t\tfor i, layer := range manifest.Layers {\n\t\t\tconfig.RootFS.DiffIDs = append(config.RootFS.DiffIDs, digest.Digest(layer.Annotations[LayerAnnotationUncompressed]))\n\t\t\t// Remove useless annotation.\n\t\t\tdelete(manifest.Layers[i].Annotations, LayerAnnotationUncompressed)\n\t\t}\n\t\t// Append history item for bootstrap layer, to ensure the history consistency.\n\t\t// See https://github.com/distribution/distribution/blob/e5d5810851d1f17a5070e9b6f940d8af98ea3c29/manifest/schema1/config_builder.go#L136\n\t\tconfig.History = append(config.History, bootstrapHistory)\n\t}\n\t// Update image config in content store.\n\tnewConfigDesc, err := writeJSON(ctx, cs, config, manifest.Config, configLabels)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"write image config\")\n\t}\n\t// When manifests are merged, we need to put a special value for the config mediaType.\n\t// This values must be one that containerd doesn't understand to ensure it doesn't try tu pull the nydus image\n\t// but use the OCI one instead. And then if the nydus-snapshotter is used, it can pull the nydus image instead.\n\tif opt.MergeManifest {\n\t\tnewConfigDesc.MediaType = ManifestConfigNydus\n\t}\n\tmanifest.Config = *newConfigDesc\n\t// Update the config gc label\n\tmanifestLabels[configGCLabelKey] = newConfigDesc.Digest.String()\n\n\tif opt.WithReferrer {\n\t\t// Associate a reference to the original OCI manifest.\n\t\t// See the `subject` field description in\n\t\t// https://github.com/opencontainers/image-spec/blob/main/manifest.md#image-manifest-property-descriptions\n\t\tmanifest.Subject = &oldDesc\n\t\t// Remove the platform field as it is not supported by certain registries like ECR.\n\t\tmanifest.Subject.Platform = nil\n\t}\n\n\t// Update image manifest in content store.\n\tnewManifestDesc, err := writeJSON(ctx, cs, manifest, manifestDesc, manifestLabels)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"write manifest\")\n\t}\n\n\treturn newManifestDesc, nil\n}\n\n// mergeManifestBlobDigests combines the per-layer nydus blob tar digests with any\n// additional blobs from the nydus-image merge output that are not already covered.\n//\n// nydusBlobDigests contains one entry per OCI source layer in layer order, including\n// metadata-only layers (e.g. symlink-only layers) whose blob tars have no chunk data.\n// originalBlobDigests comes from the nydus-image merge output blob table, which omits\n// metadata-only layers but may include chunk-dict blobs not present in nydusBlobDigests.\n//\n// The result preserves the OCI layer order from nydusBlobDigests and appends any\n// dict-only blobs from originalBlobDigests at the end.\nfunc mergeManifestBlobDigests(nydusBlobDigests, originalBlobDigests []digest.Digest) []digest.Digest {\n\tnydusSet := make(map[digest.Digest]struct{}, len(nydusBlobDigests))\n\tfor _, d := range nydusBlobDigests {\n\t\tnydusSet[d] = struct{}{}\n\t}\n\tresult := append([]digest.Digest{}, nydusBlobDigests...)\n\tfor _, d := range originalBlobDigests {\n\t\tif _, ok := nydusSet[d]; !ok {\n\t\t\tresult = append(result, d)\n\t\t}\n\t}\n\treturn result\n}\n\n// MergeLayers merges a list of nydus blob layer into a nydus bootstrap layer.\n// The media type of the nydus bootstrap layer is \"application/vnd.oci.image.layer.v1.tar+gzip\".\nfunc MergeLayers(ctx context.Context, cs content.Store, descs []ocispec.Descriptor, opt MergeOption) (*ocispec.Descriptor, []ocispec.Descriptor, error) {\n\t// Extracts nydus bootstrap from nydus format for each layer.\n\tlayers := []Layer{}\n\n\tvar chainID digest.Digest\n\tnydusBlobDigests := []digest.Digest{}\n\tfor _, nydusBlobDesc := range descs {\n\t\tra, err := cs.ReaderAt(ctx, nydusBlobDesc)\n\t\tif err != nil {\n\t\t\treturn nil, nil, errors.Wrapf(err, \"get reader for blob %q\", nydusBlobDesc.Digest)\n\t\t}\n\t\tdefer ra.Close()\n\t\tvar originalDigest *digest.Digest\n\t\tif opt.OCIRef {\n\t\t\tdigestStr := nydusBlobDesc.Annotations[label.NydusRefLayer]\n\t\t\t_originalDigest, err := digest.Parse(digestStr)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, errors.Wrapf(err, \"invalid label %s=%s\", label.NydusRefLayer, digestStr)\n\t\t\t}\n\t\t\toriginalDigest = &_originalDigest\n\t\t}\n\t\tlayers = append(layers, Layer{\n\t\t\tDigest:         nydusBlobDesc.Digest,\n\t\t\tOriginalDigest: originalDigest,\n\t\t\tReaderAt:       ra,\n\t\t})\n\t\tif chainID == \"\" {\n\t\t\tchainID = identity.ChainID([]digest.Digest{nydusBlobDesc.Digest})\n\t\t} else {\n\t\t\tchainID = identity.ChainID([]digest.Digest{chainID, nydusBlobDesc.Digest})\n\t\t}\n\t\tnydusBlobDigests = append(nydusBlobDigests, nydusBlobDesc.Digest)\n\t}\n\n\t// Merge all nydus bootstraps into a final nydus bootstrap.\n\tpr, pw := io.Pipe()\n\toriginalBlobDigestChan := make(chan []digest.Digest, 1)\n\tgo func() {\n\t\tdefer pw.Close()\n\t\toriginalBlobDigests, err := Merge(ctx, layers, pw, opt)\n\t\tif err != nil {\n\t\t\tpw.CloseWithError(errors.Wrapf(err, \"merge nydus bootstrap\"))\n\t\t}\n\t\toriginalBlobDigestChan <- originalBlobDigests\n\t}()\n\n\t// Compress final nydus bootstrap to tar.gz and write into content store.\n\tcw, err := content.OpenWriter(ctx, cs, content.WithRef(\"nydus-merge-\"+chainID.String()))\n\tif err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"open content store writer\")\n\t}\n\tdefer cw.Close()\n\n\tgw := gzip.NewWriter(cw)\n\tuncompressedDgst := digest.SHA256.Digester()\n\tcompressed := io.MultiWriter(gw, uncompressedDgst.Hash())\n\tbuffer := bufPool.Get().(*[]byte)\n\tdefer bufPool.Put(buffer)\n\tif _, err := io.CopyBuffer(compressed, pr, *buffer); err != nil {\n\t\treturn nil, nil, errors.Wrapf(err, \"copy bootstrap targz into content store\")\n\t}\n\tif err := gw.Close(); err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"close gzip writer\")\n\t}\n\n\tcompressedDgst := cw.Digest()\n\tif err := cw.Commit(ctx, 0, compressedDgst, content.WithLabels(map[string]string{\n\t\tLayerAnnotationUncompressed: uncompressedDgst.Digest().String(),\n\t})); err != nil {\n\t\tif !errdefs.IsAlreadyExists(err) {\n\t\t\treturn nil, nil, errors.Wrap(err, \"commit to content store\")\n\t\t}\n\t}\n\tif err := cw.Close(); err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"close content store writer\")\n\t}\n\n\tbootstrapInfo, err := cs.Info(ctx, compressedDgst)\n\tif err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"get info from content store\")\n\t}\n\n\toriginalBlobDigests := <-originalBlobDigestChan\n\tblobDescs := []ocispec.Descriptor{}\n\n\tvar blobDigests []digest.Digest\n\tif opt.OCIRef {\n\t\tblobDigests = nydusBlobDigests\n\t} else {\n\t\tblobDigests = mergeManifestBlobDigests(nydusBlobDigests, originalBlobDigests)\n\t}\n\n\tfor idx, blobDigest := range blobDigests {\n\t\tblobInfo, err := cs.Info(ctx, blobDigest)\n\t\tif err != nil {\n\t\t\treturn nil, nil, errors.Wrap(err, \"get info from content store\")\n\t\t}\n\t\tblobDesc := ocispec.Descriptor{\n\t\t\tDigest:    blobDigest,\n\t\t\tSize:      blobInfo.Size,\n\t\t\tMediaType: MediaTypeNydusBlob,\n\t\t\tAnnotations: map[string]string{\n\t\t\t\tLayerAnnotationUncompressed: blobDigest.String(),\n\t\t\t\tLayerAnnotationNydusBlob:    \"true\",\n\t\t\t},\n\t\t}\n\t\tif opt.OCIRef {\n\t\t\tblobDesc.Annotations[label.NydusRefLayer] = layers[idx].OriginalDigest.String()\n\t\t}\n\n\t\tif opt.Encrypt != nil {\n\t\t\tblobDesc.Annotations[LayerAnnotationNydusEncryptedBlob] = \"true\"\n\t\t}\n\n\t\tblobDescs = append(blobDescs, blobDesc)\n\t}\n\n\tif opt.FsVersion == \"\" {\n\t\topt.FsVersion = \"6\"\n\t}\n\tmediaType := images.MediaTypeDockerSchema2LayerGzip\n\tif opt.OCI {\n\t\tmediaType = ocispec.MediaTypeImageLayerGzip\n\t}\n\n\tbootstrapDesc := ocispec.Descriptor{\n\t\tDigest:    compressedDgst,\n\t\tSize:      bootstrapInfo.Size,\n\t\tMediaType: mediaType,\n\t\tAnnotations: map[string]string{\n\t\t\tLayerAnnotationUncompressed: uncompressedDgst.Digest().String(),\n\t\t\tLayerAnnotationFSVersion:    opt.FsVersion,\n\t\t\t// Use this annotation to identify nydus bootstrap layer.\n\t\t\tLayerAnnotationNydusBootstrap: \"true\",\n\t\t},\n\t}\n\n\tif opt.Encrypt != nil {\n\t\t// Encrypt the Nydus bootstrap layer.\n\t\tbootstrapDesc, err = opt.Encrypt(ctx, cs, bootstrapDesc)\n\t\tif err != nil {\n\t\t\treturn nil, nil, errors.Wrap(err, \"encrypt bootstrap layer\")\n\t\t}\n\t}\n\treturn &bootstrapDesc, blobDescs, nil\n}\n"
  },
  {
    "path": "pkg/converter/convert_windows.go",
    "content": "//go:build windows\n// +build windows\n\n/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage converter\n\nimport (\n\t\"context\"\n\t\"io\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images/converter\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\nfunc Pack(ctx context.Context, dest io.Writer, opt PackOption) (io.WriteCloser, error) {\n\tpanic(\"not implemented\")\n}\n\nfunc Merge(ctx context.Context, layers []Layer, dest io.Writer, opt MergeOption) ([]digest.Digest, error) {\n\tpanic(\"not implemented\")\n}\n\nfunc Unpack(ctx context.Context, ra content.ReaderAt, dest io.Writer, opt UnpackOption) error {\n\tpanic(\"not implemented\")\n}\n\nfunc IsNydusBlobAndExists(ctx context.Context, cs content.Store, desc ocispec.Descriptor) bool {\n\tpanic(\"not implemented\")\n}\n\nfunc IsNydusBlob(desc ocispec.Descriptor) bool {\n\tpanic(\"not implemented\")\n}\n\nfunc IsNydusBootstrap(desc ocispec.Descriptor) bool {\n\tpanic(\"not implemented\")\n}\n\nfunc LayerConvertFunc(opt PackOption) converter.ConvertFunc {\n\tpanic(\"not implemented\")\n}\n\nfunc ConvertHookFunc(opt MergeOption) converter.ConvertHookFunc {\n\tpanic(\"not implemented\")\n}\n\nfunc MergeLayers(ctx context.Context, cs content.Store, descs []ocispec.Descriptor, opt MergeOption) (*ocispec.Descriptor, []ocispec.Descriptor, error) {\n\tpanic(\"not implemented\")\n}\n"
  },
  {
    "path": "pkg/converter/cs_proxy_unix.go",
    "content": "//go:build !windows\n// +build !windows\n\n/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage converter\n\nimport (\n\t\"archive/tar\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/sirupsen/logrus\"\n)\n\ntype contentStoreProxy struct {\n\tsocketPath string\n\tserver     *http.Server\n}\n\nfunc setupContentStoreProxy(workDir string, ra content.ReaderAt) (*contentStoreProxy, error) {\n\tsockP, err := os.CreateTemp(workDir, \"nydus-cs-proxy-*.sock\")\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"create unix socket file\")\n\t}\n\tif err := os.Remove(sockP.Name()); err != nil {\n\t\treturn nil, err\n\t}\n\tlistener, err := net.Listen(\"unix\", sockP.Name())\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"listen unix socket when setup content store proxy\")\n\t}\n\n\tserver := &http.Server{\n\t\tHandler: contentProxyHandler(ra),\n\t}\n\n\tgo func() {\n\t\tif err := server.Serve(listener); err != nil && err != http.ErrServerClosed {\n\t\t\tlogrus.WithError(err).Warn(\"serve content store proxy\")\n\t\t}\n\t}()\n\n\treturn &contentStoreProxy{\n\t\tsocketPath: sockP.Name(),\n\t\tserver:     server,\n\t}, nil\n}\n\nfunc (p *contentStoreProxy) close() error {\n\tdefer os.Remove(p.socketPath)\n\tif err := p.server.Shutdown(context.Background()); err != nil {\n\t\treturn errors.Wrap(err, \"shutdown content store proxy\")\n\t}\n\treturn nil\n}\n\nfunc parseRangeHeader(rangeStr string, totalLen int64) (start, wantedLen int64, err error) {\n\trangeList := strings.Split(rangeStr, \"-\")\n\tstart, err = strconv.ParseInt(rangeList[0], 10, 64)\n\tif err != nil {\n\t\terr = errors.Wrap(err, \"parse range header\")\n\t\treturn\n\t}\n\tif len(rangeList) == 2 {\n\t\tvar end int64\n\t\tend, err = strconv.ParseInt(rangeList[1], 10, 64)\n\t\tif err != nil {\n\t\t\terr = errors.Wrap(err, \"parse range header\")\n\t\t\treturn\n\t\t}\n\t\twantedLen = end - start + 1\n\t} else {\n\t\twantedLen = totalLen - start\n\t}\n\tif start < 0 || start >= totalLen || wantedLen <= 0 {\n\t\terr = fmt.Errorf(\"invalid range header: %s\", rangeStr)\n\t\treturn\n\t}\n\treturn\n}\n\nfunc contentProxyHandler(ra content.ReaderAt) http.Handler {\n\tvar (\n\t\tdataReader io.Reader\n\t\tcurPos     int64\n\n\t\ttarHeader *tar.Header\n\t\ttotalLen  int64\n\t)\n\tresetReader := func() {\n\t\t// TODO: Handle error?\n\t\t_, _ = seekFile(ra, EntryBlob, func(reader io.Reader, hdr *tar.Header) error {\n\t\t\tdataReader, tarHeader = reader, hdr\n\t\t\treturn nil\n\t\t})\n\t\tcurPos = 0\n\t}\n\n\tresetReader()\n\tif tarHeader != nil {\n\t\ttotalLen = tarHeader.Size\n\t} else {\n\t\ttotalLen = ra.Size()\n\t}\n\thandler := func(w http.ResponseWriter, r *http.Request) {\n\t\tswitch r.Method {\n\t\tcase http.MethodHead:\n\t\t\t{\n\t\t\t\tw.Header().Set(\"Content-Length\", strconv.FormatInt(totalLen, 10))\n\t\t\t\tw.Header().Set(\"Content-Type\", \"application/octet-stream\")\n\t\t\t\treturn\n\t\t\t}\n\t\tcase http.MethodGet:\n\t\t\t{\n\t\t\t\tstart, wantedLen, err := parseRangeHeader(strings.TrimPrefix(r.Header.Get(\"Range\"), \"bytes=\"), totalLen)\n\t\t\t\tif err != nil {\n\t\t\t\t\tw.WriteHeader(http.StatusBadRequest)\n\t\t\t\t\t// TODO: Handle error?\n\t\t\t\t\t_, _ = w.Write([]byte(err.Error()))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// we need to make sure that the dataReader is at the right position\n\t\t\t\tif start < curPos {\n\t\t\t\t\tresetReader()\n\t\t\t\t}\n\t\t\t\tif start > curPos {\n\t\t\t\t\t_, err = io.CopyN(io.Discard, dataReader, start-curPos)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\t\t\t\t// TODO: Handle error?\n\t\t\t\t\t\t_, _ = w.Write([]byte(err.Error()))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tcurPos = start\n\t\t\t\t}\n\t\t\t\t// then, the curPos must be equal to start\n\n\t\t\t\treadLen, err := io.CopyN(w, dataReader, wantedLen)\n\t\t\t\tif err != nil && !errors.Is(err, io.EOF) {\n\t\t\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\t\t\t// TODO: Handle error?\n\t\t\t\t\t_, _ = w.Write([]byte(err.Error()))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcurPos += readLen\n\t\t\t\tw.Header().Set(\"Content-Length\", strconv.FormatInt(readLen, 10))\n\t\t\t\tw.Header().Set(\"Content-Range\", fmt.Sprintf(\"bytes %d-%d/%d\", start, start+readLen-1, totalLen))\n\t\t\t\tw.Header().Set(\"Content-Type\", \"application/octet-stream\")\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\treturn http.HandlerFunc(handler)\n}\n"
  },
  {
    "path": "pkg/converter/merge_unix_test.go",
    "content": "//go:build !windows\n// +build !windows\n\n/*\n * Copyright (c) 2024. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage converter\n\nimport (\n\t\"testing\"\n\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\n// d returns a synthetic digest for testing by repeating a hex character.\nfunc d(c byte) digest.Digest {\n\treturn digest.NewDigestFromEncoded(digest.SHA256, string(repeat(c, 64)))\n}\n\nfunc repeat(c byte, n int) []byte {\n\tb := make([]byte, n)\n\tfor i := range b {\n\t\tb[i] = c\n\t}\n\treturn b\n}\n\n// TestMergeManifestBlobDigests verifies the blob digest selection logic used when\n// building the nydus manifest layer list.\nfunc TestMergeManifestBlobDigests(t *testing.T) {\n\tD0 := d('0')\n\tD1 := d('1')\n\tD2 := d('2')\n\tD3 := d('3') // metadata-only layer (symlink-only, 0-byte blob data)\n\tDICT := d('d')\n\n\ttests := []struct {\n\t\tname                string\n\t\tnydusBlobDigests    []digest.Digest\n\t\toriginalBlobDigests []digest.Digest\n\t\texpected            []digest.Digest\n\t}{\n\t\t{\n\t\t\t// A metadata-only layer (e.g. symlink-only OCI layer) produces an empty\n\t\t\t// blob inside nydus-image merge, so it is absent from originalBlobDigests.\n\t\t\t// mergeManifestBlobDigests must preserve it from nydusBlobDigests so that\n\t\t\t// reverse conversion (nydus→OCI) reproduces the correct number of layers.\n\t\t\tname:                \"metadata-only layer preserved from nydusBlobDigests\",\n\t\t\tnydusBlobDigests:    []digest.Digest{D0, D1, D2, D3},\n\t\t\toriginalBlobDigests: []digest.Digest{D2, D0, D1}, // BFS order, D3 missing\n\t\t\texpected:            []digest.Digest{D0, D1, D2, D3},\n\t\t},\n\t\t{\n\t\t\t// When a chunk-dict is used, nydus-image merge adds the dict blob to its\n\t\t\t// output blob table. That dict blob is not a regular OCI layer, so it does\n\t\t\t// not appear in nydusBlobDigests and must be appended at the end.\n\t\t\tname:                \"chunk-dict blob appended after layer blobs\",\n\t\t\tnydusBlobDigests:    []digest.Digest{D0, D1, D2, D3},\n\t\t\toriginalBlobDigests: []digest.Digest{D0, D1, D2, DICT},\n\t\t\texpected:            []digest.Digest{D0, D1, D2, D3, DICT},\n\t\t},\n\t\t{\n\t\t\t// When chunk-dict is used and layers are also reordered by BFS, both the\n\t\t\t// OCI layer order must be preserved and the dict blob must be appended.\n\t\t\tname:                \"chunk-dict blob appended when originalBlobDigests uses BFS order\",\n\t\t\tnydusBlobDigests:    []digest.Digest{D0, D1, D2, D3},\n\t\t\toriginalBlobDigests: []digest.Digest{D2, D0, D1, DICT}, // BFS order + dict, D3 missing\n\t\t\texpected:            []digest.Digest{D0, D1, D2, D3, DICT},\n\t\t},\n\t\t{\n\t\t\t// When all layers have chunk data, originalBlobDigests covers all of\n\t\t\t// nydusBlobDigests (possibly in different BFS order). The result must equal\n\t\t\t// nydusBlobDigests in OCI layer order without duplicates.\n\t\t\tname:                \"all layers have data, OCI order preserved\",\n\t\t\tnydusBlobDigests:    []digest.Digest{D0, D1, D2},\n\t\t\toriginalBlobDigests: []digest.Digest{D2, D0, D1}, // BFS order\n\t\t\texpected:            []digest.Digest{D0, D1, D2},\n\t\t},\n\t\t{\n\t\t\tname:                \"empty inputs produce empty result\",\n\t\t\tnydusBlobDigests:    []digest.Digest{},\n\t\t\toriginalBlobDigests: []digest.Digest{},\n\t\t\texpected:            []digest.Digest{},\n\t\t},\n\t\t{\n\t\t\tname:                \"single metadata-only layer\",\n\t\t\tnydusBlobDigests:    []digest.Digest{D0},\n\t\t\toriginalBlobDigests: []digest.Digest{},\n\t\t\texpected:            []digest.Digest{D0},\n\t\t},\n\t\t{\n\t\t\t// Multiple chunk-dict blobs (edge case; not typical but must not be dropped).\n\t\t\tname:                \"multiple chunk-dict blobs appended\",\n\t\t\tnydusBlobDigests:    []digest.Digest{D0, D1},\n\t\t\toriginalBlobDigests: []digest.Digest{D0, D1, D2, D3},\n\t\t\texpected:            []digest.Digest{D0, D1, D2, D3},\n\t\t},\n\t}\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tgot := mergeManifestBlobDigests(tc.nydusBlobDigests, tc.originalBlobDigests)\n\t\t\tassert.Equal(t, tc.expected, got)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/converter/reconvert_unix.go",
    "content": "//go:build !windows\n// +build !windows\n\n/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage converter\n\nimport (\n\t\"compress/gzip\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/containerd/v2/core/images/converter\"\n\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/platforms\"\n\t\"github.com/klauspost/compress/zstd\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/sirupsen/logrus\"\n)\n\n// DefaultIndexConvertFunc wraps containerd's converter to handle Nydus blob reconversion.\n//\n// Problem: Containerd's convertManifest calls images.GetDiffID() which attempts to\n// decompress layers. Nydus blobs use a custom format and fail with \"magic number mismatch\".\n//\n// Solution: Wrap content store with a proxy that adds containerd.io/uncompressed label\n// for Nydus blobs. This makes GetDiffID take the fast path and skip decompression.\nfunc DefaultIndexConvertFunc(layerConvertFunc converter.ConvertFunc, docker2oci bool, platformMC platforms.MatchComparer) converter.ConvertFunc {\n\thooks := converter.ConvertHooks{\n\t\tPostConvertHook: ReconvertHookFunc(),\n\t}\n\n\tfn := converter.IndexConvertFuncWithHook(layerConvertFunc, docker2oci, platformMC, hooks)\n\n\treturn func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {\n\t\tlogrus.Debugf(\"DefaultIndexConvertFunc called for desc mediaType=%s digest=%s\", desc.MediaType, desc.Digest.String())\n\n\t\tnydusBlobs := collectNydusBlobDigests(ctx, cs, desc)\n\t\tif len(nydusBlobs) == 0 {\n\t\t\treturn fn(ctx, cs, desc)\n\t\t}\n\n\t\tws := &wrappedStore{\n\t\t\tStore:      cs,\n\t\t\tnydusBlobs: nydusBlobs,\n\t\t}\n\t\treturn fn(ctx, ws, desc)\n\t}\n}\n\n// This is used to identify which blobs need the uncompressed label workaround.\nfunc collectNydusBlobDigests(ctx context.Context, cs content.Store, desc ocispec.Descriptor) map[digest.Digest]bool {\n\tnydusBlobs := make(map[digest.Digest]bool)\n\n\tif images.IsIndexType(desc.MediaType) {\n\t\tvar index ocispec.Index\n\t\tif _, err := readJSON(ctx, cs, &index, desc); err != nil {\n\t\t\tlogrus.WithError(err).Warn(\"failed to read index\")\n\t\t\treturn nydusBlobs\n\t\t}\n\t\tfor _, m := range index.Manifests {\n\t\t\tif images.IsManifestType(m.MediaType) {\n\t\t\t\tcollectFromManifest(ctx, cs, m, nydusBlobs)\n\t\t\t}\n\t\t}\n\t} else if images.IsManifestType(desc.MediaType) {\n\t\tcollectFromManifest(ctx, cs, desc, nydusBlobs)\n\t}\n\n\tlogrus.Debugf(\"Collected %d Nydus blob digests\", len(nydusBlobs))\n\treturn nydusBlobs\n}\n\nfunc collectFromManifest(ctx context.Context, cs content.Store, desc ocispec.Descriptor, nydusBlobs map[digest.Digest]bool) {\n\tvar manifest ocispec.Manifest\n\tif _, err := readJSON(ctx, cs, &manifest, desc); err != nil {\n\t\tlogrus.WithError(err).Warnf(\"failed to read manifest %s\", desc.Digest)\n\t\treturn\n\t}\n\n\tfor _, l := range manifest.Layers {\n\t\tif IsNydusBlob(l) {\n\t\t\tlogrus.Debugf(\"Found Nydus blob: %s (mediaType=%s)\", l.Digest, l.MediaType)\n\t\t\tnydusBlobs[l.Digest] = true\n\t\t}\n\t}\n}\n\n// wrappedStore wraps the content store to add containerd.io/uncompressed labels\n// for Nydus blobs. This makes images.GetDiffID skip decompression and return\n// the digest directly.\ntype wrappedStore struct {\n\tcontent.Store\n\tnydusBlobs map[digest.Digest]bool // Set of Nydus blob digests\n}\n\nfunc (s *wrappedStore) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {\n\tinfo, err := s.Store.Info(ctx, dgst)\n\tif err != nil {\n\t\treturn info, err\n\t}\n\n\t// If this is a Nydus blob, add the uncompressed label\n\tif s.nydusBlobs[dgst] {\n\t\tif info.Labels == nil {\n\t\t\tinfo.Labels = make(map[string]string)\n\t\t}\n\t\t// Use the blob's own digest as the \"uncompressed\" digest\n\t\t// This makes GetDiffID return the blob digest directly\n\t\tinfo.Labels[\"containerd.io/uncompressed\"] = dgst.String()\n\t\tlogrus.Debugf(\"Added uncompressed label for Nydus blob: %s\", dgst)\n\t}\n\n\treturn info, nil\n}\n\nfunc ReconvertHookFunc() converter.ConvertHookFunc {\n\treturn func(ctx context.Context, cs content.Store, _ ocispec.Descriptor, newDesc *ocispec.Descriptor) (*ocispec.Descriptor, error) {\n\t\tif newDesc == nil {\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tif !images.IsManifestType(newDesc.MediaType) {\n\t\t\treturn newDesc, nil\n\t\t}\n\n\t\tvar manifest ocispec.Manifest\n\t\tlabels, err := readJSON(ctx, cs, &manifest, *newDesc)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"read manifest\")\n\t\t}\n\n\t\tvar layersToKeep []ocispec.Descriptor\n\t\tbootstrapIndex := -1\n\n\t\t// 1. Filter Layers: Remove Nydus Bootstrap Layer\n\t\tfor i, l := range manifest.Layers {\n\t\t\tif IsNydusBootstrap(l) {\n\t\t\t\tbootstrapIndex = i\n\t\t\t\t// Clean GC labels for the removed layer\n\t\t\t\tconverter.ClearGCLabels(labels, l.Digest)\n\t\t\t} else {\n\t\t\t\tlayersToKeep = append(layersToKeep, l)\n\t\t\t}\n\t\t}\n\n\t\tmanifest.Layers = layersToKeep\n\n\t\t// 2. Read and Update Config\n\t\tvar config ocispec.Image\n\t\tconfigLabels, err := readJSON(ctx, cs, &config, manifest.Config)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"read image config\")\n\t\t}\n\n\t\t// 2.1 Remove corresponding DiffID\n\t\tif bootstrapIndex != -1 && len(config.RootFS.DiffIDs) > bootstrapIndex {\n\t\t\tconfig.RootFS.DiffIDs = append(config.RootFS.DiffIDs[:bootstrapIndex], config.RootFS.DiffIDs[bootstrapIndex+1:]...)\n\t\t}\n\n\t\t// 2.2 Clean History\n\t\tvar newHistory []ocispec.History\n\t\tfor _, h := range config.History {\n\t\t\t// Remove Nydus Bootstrap History\n\t\t\tif h.Comment == \"Nydus Bootstrap Layer\" && h.CreatedBy == \"Nydus Converter\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tnewHistory = append(newHistory, h)\n\t\t}\n\t\tconfig.History = newHistory\n\n\t\t// 3. Write back Config\n\t\tnewConfigDesc, err := writeJSON(ctx, cs, config, manifest.Config, configLabels)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"write image config\")\n\t\t}\n\t\tmanifest.Config = *newConfigDesc\n\t\t// Update Manifest GC label for config\n\t\tlabels[\"containerd.io/gc.ref.content.config\"] = newConfigDesc.Digest.String()\n\n\t\t// 4. Write back Manifest\n\t\treturn writeJSON(ctx, cs, manifest, *newDesc, labels)\n\t}\n}\n\nfunc LayerReconvertFunc(opt UnpackOption) converter.ConvertFunc {\n\treturn func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {\n\t\tlogrus.Debugf(\"Reconvert layer: mediaType=%s digest=%s, anno=%v\", desc.MediaType, desc.Digest.String(), desc.Annotations)\n\t\tif !images.IsLayerType(desc.MediaType) {\n\t\t\treturn nil, nil\n\t\t}\n\n\t\t// Skip the nydus bootstrap layer.\n\t\tif IsNydusBootstrap(desc) {\n\t\t\tlogrus.Debugf(\"skip nydus bootstrap layer %s\", desc.Digest.String())\n\t\t\treturn &desc, nil\n\t\t}\n\n\t\tra, err := cs.ReaderAt(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"get reader\")\n\t\t}\n\t\tdefer ra.Close()\n\n\t\tref := fmt.Sprintf(\"convert-oci-from-%s\", desc.Digest)\n\t\tcw, err := content.OpenWriter(ctx, cs, content.WithRef(ref))\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"open blob writer\")\n\t\t}\n\t\tdefer cw.Close()\n\n\t\tvar gw io.WriteCloser\n\t\tvar mediaType string\n\t\tcompressor := opt.Compressor\n\t\tif compressor == \"\" {\n\t\t\tcompressor = \"gzip\"\n\t\t}\n\t\tswitch compressor {\n\t\tcase \"gzip\":\n\t\t\tgw = gzip.NewWriter(cw)\n\t\t\tmediaType = ocispec.MediaTypeImageLayerGzip\n\t\tcase \"zstd\":\n\t\t\tgw, err = zstd.NewWriter(cw)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"create zstd writer\")\n\t\t\t}\n\t\t\tmediaType = ocispec.MediaTypeImageLayerZstd\n\t\tcase \"uncompressed\":\n\t\t\tgw = cw\n\t\t\tmediaType = ocispec.MediaTypeImageLayer\n\t\tdefault:\n\t\t\treturn nil, errors.Errorf(\"unsupported compressor type: %s (support: gzip, zstd, uncompressed)\", opt.Compressor)\n\t\t}\n\n\t\tuncompressedDgster := digest.SHA256.Digester()\n\t\tpr, pw := io.Pipe()\n\n\t\t// Unpack nydus blob to pipe writer in background\n\t\tgo func() {\n\t\t\tdefer pw.Close()\n\t\t\tif err := Unpack(ctx, ra, pw, opt); err != nil {\n\t\t\t\tpw.CloseWithError(errors.Wrap(err, \"unpack nydus to tar\"))\n\t\t\t}\n\t\t}()\n\n\t\t// Stream data from pipe reader to compressed writer and digester\n\t\tcompressed := io.MultiWriter(gw, uncompressedDgster.Hash())\n\t\tbuffer := bufPool.Get().(*[]byte)\n\t\tdefer bufPool.Put(buffer)\n\t\tif _, err = io.CopyBuffer(compressed, pr, *buffer); err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"copy to compressed writer\")\n\t\t}\n\n\t\t// Close compressor writer if different from content writer\n\t\tif gw != cw {\n\t\t\tif err = gw.Close(); err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"close compressor writer\")\n\t\t\t}\n\t\t}\n\n\t\tuncompressedDigest := uncompressedDgster.Digest()\n\t\tcompressedDgst := cw.Digest()\n\t\tif err = cw.Commit(ctx, 0, compressedDgst, content.WithLabels(map[string]string{\n\t\t\tLayerAnnotationUncompressed: uncompressedDigest.String(),\n\t\t})); err != nil {\n\t\t\tif !errdefs.IsAlreadyExists(err) {\n\t\t\t\treturn nil, errors.Wrap(err, \"commit to content store\")\n\t\t\t}\n\t\t}\n\t\tif err = cw.Close(); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"close content store writer\")\n\t\t}\n\n\t\tnewDesc, err := makeOCIBlobDesc(ctx, cs, uncompressedDigest, compressedDgst, mediaType)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif opt.Backend != nil {\n\t\t\tif err := opt.Backend.Push(ctx, cs, *newDesc); err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"push to storage backend\")\n\t\t\t}\n\t\t}\n\t\treturn newDesc, nil\n\t}\n}\n\nfunc makeOCIBlobDesc(ctx context.Context, cs content.Store, uncompressedDigest, targetDigest digest.Digest, mediaType string) (*ocispec.Descriptor, error) {\n\ttargetInfo, err := cs.Info(ctx, targetDigest)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get target blob info %s\", targetDigest)\n\t}\n\tif targetInfo.Labels == nil {\n\t\ttargetInfo.Labels = map[string]string{}\n\t}\n\n\ttargetDesc := ocispec.Descriptor{\n\t\tDigest:    targetDigest,\n\t\tSize:      targetInfo.Size,\n\t\tMediaType: mediaType,\n\t\tAnnotations: map[string]string{\n\t\t\t// Use `containerd.io/uncompressed` to generate DiffID of\n\t\t\t// layer defined in OCI spec.\n\t\t\tLayerAnnotationUncompressed: uncompressedDigest.String(),\n\t\t},\n\t}\n\n\treturn &targetDesc, nil\n}\n"
  },
  {
    "path": "pkg/converter/reconvert_unix_test.go",
    "content": "//go:build !windows\n// +build !windows\n\n/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage converter\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\n// mockContentStore implements content.Store interface for testing\ntype mockContentStore struct {\n\tcontent.Store\n\tinfos map[digest.Digest]content.Info\n\tblobs map[digest.Digest][]byte\n}\n\nfunc newMockContentStore() *mockContentStore {\n\treturn &mockContentStore{\n\t\tinfos: make(map[digest.Digest]content.Info),\n\t\tblobs: make(map[digest.Digest][]byte),\n\t}\n}\n\nfunc (m *mockContentStore) Info(_ context.Context, dgst digest.Digest) (content.Info, error) {\n\tif info, ok := m.infos[dgst]; ok {\n\t\treturn info, nil\n\t}\n\treturn content.Info{}, ErrNotFound\n}\n\nfunc (m *mockContentStore) addBlob(dgst digest.Digest, data []byte, labels map[string]string) {\n\tm.infos[dgst] = content.Info{\n\t\tDigest: dgst,\n\t\tSize:   int64(len(data)),\n\t\tLabels: labels,\n\t}\n\tm.blobs[dgst] = data\n}\n\nfunc (m *mockContentStore) ReaderAt(_ context.Context, desc ocispec.Descriptor) (content.ReaderAt, error) {\n\tif data, ok := m.blobs[desc.Digest]; ok {\n\t\treturn &mockReaderAt{data: data}, nil\n\t}\n\treturn nil, ErrNotFound\n}\n\ntype mockReaderAt struct {\n\tdata []byte\n}\n\nfunc (r *mockReaderAt) ReadAt(p []byte, off int64) (n int, err error) {\n\tif off >= int64(len(r.data)) {\n\t\treturn 0, ErrNotFound\n\t}\n\tn = copy(p, r.data[off:])\n\treturn n, nil\n}\n\nfunc (r *mockReaderAt) Size() int64 {\n\treturn int64(len(r.data))\n}\n\nfunc (r *mockReaderAt) Close() error {\n\treturn nil\n}\n\nfunc TestCollectNydusBlobDigests(t *testing.T) {\n\tctx := context.Background()\n\n\t// Create test digests\n\tnydusBlob1 := digest.FromString(\"nydus-blob-1\")\n\tnydusBlob2 := digest.FromString(\"nydus-blob-2\")\n\tregularBlob := digest.FromString(\"regular-blob\")\n\tmanifestDigest := digest.FromString(\"manifest\")\n\tindexDigest := digest.FromString(\"index\")\n\n\t// Test cases\n\ttests := []struct {\n\t\tname          string\n\t\tsetupStore    func(*mockContentStore)\n\t\tdesc          ocispec.Descriptor\n\t\texpectedBlobs map[digest.Digest]bool\n\t\texpectedCount int\n\t}{\n\t\t{\n\t\t\tname: \"manifest with nydus blobs\",\n\t\t\tsetupStore: func(cs *mockContentStore) {\n\t\t\t\tmanifest := ocispec.Manifest{\n\t\t\t\t\tLayers: []ocispec.Descriptor{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: MediaTypeNydusBlob,\n\t\t\t\t\t\t\tDigest:    nydusBlob1,\n\t\t\t\t\t\t\tAnnotations: map[string]string{\n\t\t\t\t\t\t\t\tLayerAnnotationNydusBlob: \"true\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: ocispec.MediaTypeImageLayerGzip,\n\t\t\t\t\t\t\tDigest:    regularBlob,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tdata, _ := json.Marshal(manifest)\n\t\t\t\tcs.addBlob(manifestDigest, data, nil)\n\t\t\t},\n\t\t\tdesc: ocispec.Descriptor{\n\t\t\t\tMediaType: ocispec.MediaTypeImageManifest,\n\t\t\t\tDigest:    manifestDigest,\n\t\t\t},\n\t\t\texpectedCount: 1,\n\t\t},\n\t\t{\n\t\t\tname: \"index with multiple manifests\",\n\t\t\tsetupStore: func(cs *mockContentStore) {\n\t\t\t\t// Create two manifests\n\t\t\t\tmanifest1 := ocispec.Manifest{\n\t\t\t\t\tLayers: []ocispec.Descriptor{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: MediaTypeNydusBlob,\n\t\t\t\t\t\t\tDigest:    nydusBlob1,\n\t\t\t\t\t\t\tAnnotations: map[string]string{\n\t\t\t\t\t\t\t\tLayerAnnotationNydusBlob: \"true\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tmanifest1Data, _ := json.Marshal(manifest1)\n\t\t\t\tmanifest1Digest := digest.FromBytes(manifest1Data)\n\t\t\t\tcs.addBlob(manifest1Digest, manifest1Data, nil)\n\n\t\t\t\tmanifest2 := ocispec.Manifest{\n\t\t\t\t\tLayers: []ocispec.Descriptor{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: MediaTypeNydusBlob,\n\t\t\t\t\t\t\tDigest:    nydusBlob2,\n\t\t\t\t\t\t\tAnnotations: map[string]string{\n\t\t\t\t\t\t\t\tLayerAnnotationNydusBlob: \"true\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tmanifest2Data, _ := json.Marshal(manifest2)\n\t\t\t\tmanifest2Digest := digest.FromBytes(manifest2Data)\n\t\t\t\tcs.addBlob(manifest2Digest, manifest2Data, nil)\n\n\t\t\t\t// Create index\n\t\t\t\tindex := ocispec.Index{\n\t\t\t\t\tManifests: []ocispec.Descriptor{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: ocispec.MediaTypeImageManifest,\n\t\t\t\t\t\t\tDigest:    manifest1Digest,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: ocispec.MediaTypeImageManifest,\n\t\t\t\t\t\t\tDigest:    manifest2Digest,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tindexData, _ := json.Marshal(index)\n\t\t\t\tcs.addBlob(indexDigest, indexData, nil)\n\t\t\t},\n\t\t\tdesc: ocispec.Descriptor{\n\t\t\t\tMediaType: ocispec.MediaTypeImageIndex,\n\t\t\t\tDigest:    indexDigest,\n\t\t\t},\n\t\t\texpectedCount: 2,\n\t\t},\n\t\t{\n\t\t\tname: \"manifest with no nydus blobs\",\n\t\t\tsetupStore: func(cs *mockContentStore) {\n\t\t\t\tmanifest := ocispec.Manifest{\n\t\t\t\t\tLayers: []ocispec.Descriptor{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: ocispec.MediaTypeImageLayerGzip,\n\t\t\t\t\t\t\tDigest:    regularBlob,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tdata, _ := json.Marshal(manifest)\n\t\t\t\tcs.addBlob(manifestDigest, data, nil)\n\t\t\t},\n\t\t\tdesc: ocispec.Descriptor{\n\t\t\t\tMediaType: ocispec.MediaTypeImageManifest,\n\t\t\t\tDigest:    manifestDigest,\n\t\t\t},\n\t\t\texpectedCount: 0,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid descriptor type\",\n\t\t\tsetupStore: func(_ *mockContentStore) {\n\t\t\t\t// No setup needed\n\t\t\t},\n\t\t\tdesc: ocispec.Descriptor{\n\t\t\t\tMediaType: ocispec.MediaTypeImageConfig,\n\t\t\t\tDigest:    digest.FromString(\"config\"),\n\t\t\t},\n\t\t\texpectedCount: 0,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tcs := newMockContentStore()\n\t\t\ttt.setupStore(cs)\n\n\t\t\tblobs := collectNydusBlobDigests(ctx, cs, tt.desc)\n\t\t\tassert.Equal(t, tt.expectedCount, len(blobs))\n\t\t})\n\t}\n}\n\nfunc TestCollectFromManifest(t *testing.T) {\n\tctx := context.Background()\n\n\tnydusBlob1 := digest.FromString(\"nydus-blob-1\")\n\tnydusBlob2 := digest.FromString(\"nydus-blob-2\")\n\tbootstrapBlob := digest.FromString(\"bootstrap-blob\")\n\tregularBlob := digest.FromString(\"regular-blob\")\n\tmanifestDigest := digest.FromString(\"manifest\")\n\n\ttests := []struct {\n\t\tname          string\n\t\tsetupManifest func() (ocispec.Manifest, []byte)\n\t\texpectedCount int\n\t\texpectedBlobs []digest.Digest\n\t}{\n\t\t{\n\t\t\tname: \"manifest with multiple nydus blobs and bootstrap\",\n\t\t\tsetupManifest: func() (ocispec.Manifest, []byte) {\n\t\t\t\tmanifest := ocispec.Manifest{\n\t\t\t\t\tLayers: []ocispec.Descriptor{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: MediaTypeNydusBlob,\n\t\t\t\t\t\t\tDigest:    nydusBlob1,\n\t\t\t\t\t\t\tAnnotations: map[string]string{\n\t\t\t\t\t\t\t\tLayerAnnotationNydusBlob: \"true\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: MediaTypeNydusBlob,\n\t\t\t\t\t\t\tDigest:    nydusBlob2,\n\t\t\t\t\t\t\tAnnotations: map[string]string{\n\t\t\t\t\t\t\t\tLayerAnnotationNydusBlob: \"true\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: ocispec.MediaTypeImageLayer,\n\t\t\t\t\t\t\tDigest:    bootstrapBlob,\n\t\t\t\t\t\t\tAnnotations: map[string]string{\n\t\t\t\t\t\t\t\tLayerAnnotationNydusBootstrap: \"true\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: ocispec.MediaTypeImageLayerGzip,\n\t\t\t\t\t\t\tDigest:    regularBlob,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tdata, _ := json.Marshal(manifest)\n\t\t\t\treturn manifest, data\n\t\t\t},\n\t\t\texpectedCount: 2,\n\t\t\texpectedBlobs: []digest.Digest{nydusBlob1, nydusBlob2},\n\t\t},\n\t\t{\n\t\t\tname: \"manifest with only regular layers\",\n\t\t\tsetupManifest: func() (ocispec.Manifest, []byte) {\n\t\t\t\tmanifest := ocispec.Manifest{\n\t\t\t\t\tLayers: []ocispec.Descriptor{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: ocispec.MediaTypeImageLayerGzip,\n\t\t\t\t\t\t\tDigest:    regularBlob,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t\tdata, _ := json.Marshal(manifest)\n\t\t\t\treturn manifest, data\n\t\t\t},\n\t\t\texpectedCount: 0,\n\t\t\texpectedBlobs: []digest.Digest{},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tcs := newMockContentStore()\n\t\t\t_, manifestData := tt.setupManifest()\n\t\t\tcs.addBlob(manifestDigest, manifestData, nil)\n\n\t\t\tnydusBlobs := make(map[digest.Digest]bool)\n\t\t\tdesc := ocispec.Descriptor{\n\t\t\t\tMediaType: ocispec.MediaTypeImageManifest,\n\t\t\t\tDigest:    manifestDigest,\n\t\t\t}\n\n\t\t\tcollectFromManifest(ctx, cs, desc, nydusBlobs)\n\n\t\t\tassert.Equal(t, tt.expectedCount, len(nydusBlobs))\n\t\t\tfor _, expectedBlob := range tt.expectedBlobs {\n\t\t\t\tassert.True(t, nydusBlobs[expectedBlob], \"expected blob %s not found\", expectedBlob)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestWrappedStore_Info(t *testing.T) {\n\tctx := context.Background()\n\n\tnydusBlob := digest.FromString(\"nydus-blob\")\n\tregularBlob := digest.FromString(\"regular-blob\")\n\n\ttests := []struct {\n\t\tname             string\n\t\tdigest           digest.Digest\n\t\tisNydusBlob      bool\n\t\texistingLabels   map[string]string\n\t\tshouldAddLabel   bool\n\t\texpectedLabelVal string\n\t}{\n\t\t{\n\t\t\tname:             \"nydus blob without existing labels\",\n\t\t\tdigest:           nydusBlob,\n\t\t\tisNydusBlob:      true,\n\t\t\texistingLabels:   nil,\n\t\t\tshouldAddLabel:   true,\n\t\t\texpectedLabelVal: nydusBlob.String(),\n\t\t},\n\t\t{\n\t\t\tname:        \"nydus blob with existing labels\",\n\t\t\tdigest:      nydusBlob,\n\t\t\tisNydusBlob: true,\n\t\t\texistingLabels: map[string]string{\n\t\t\t\t\"other.label\": \"value\",\n\t\t\t},\n\t\t\tshouldAddLabel:   true,\n\t\t\texpectedLabelVal: nydusBlob.String(),\n\t\t},\n\t\t{\n\t\t\tname:        \"regular blob\",\n\t\t\tdigest:      regularBlob,\n\t\t\tisNydusBlob: false,\n\t\t\texistingLabels: map[string]string{\n\t\t\t\t\"other.label\": \"value\",\n\t\t\t},\n\t\t\tshouldAddLabel:   false,\n\t\t\texpectedLabelVal: \"\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tcs := newMockContentStore()\n\t\t\tcs.addBlob(tt.digest, []byte(\"test data\"), tt.existingLabels)\n\n\t\t\tnydusBlobs := make(map[digest.Digest]bool)\n\t\t\tif tt.isNydusBlob {\n\t\t\t\tnydusBlobs[tt.digest] = true\n\t\t\t}\n\n\t\t\tws := &wrappedStore{\n\t\t\t\tStore:      cs,\n\t\t\t\tnydusBlobs: nydusBlobs,\n\t\t\t}\n\n\t\t\tinfo, err := ws.Info(ctx, tt.digest)\n\t\t\trequire.NoError(t, err)\n\t\t\tassert.Equal(t, tt.digest, info.Digest)\n\n\t\t\tif tt.shouldAddLabel {\n\t\t\t\tassert.NotNil(t, info.Labels)\n\t\t\t\tassert.Equal(t, tt.expectedLabelVal, info.Labels[\"containerd.io/uncompressed\"])\n\t\t\t} else if info.Labels != nil {\n\t\t\t\tassert.Empty(t, info.Labels[\"containerd.io/uncompressed\"])\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestWrappedStore_Info_Error(t *testing.T) {\n\tctx := context.Background()\n\tcs := newMockContentStore()\n\tws := &wrappedStore{\n\t\tStore:      cs,\n\t\tnydusBlobs: make(map[digest.Digest]bool),\n\t}\n\n\tnonExistentDigest := digest.FromString(\"non-existent\")\n\t_, err := ws.Info(ctx, nonExistentDigest)\n\tassert.Error(t, err)\n\tassert.Equal(t, ErrNotFound, err)\n}\n\nfunc TestMakeOCIBlobDesc(t *testing.T) {\n\tctx := context.Background()\n\n\tuncompressedDigest := digest.FromString(\"uncompressed-data\")\n\ttargetDigest := digest.FromString(\"compressed-data\")\n\n\ttests := []struct {\n\t\tname              string\n\t\tuncompressedDgst  digest.Digest\n\t\ttargetDgst        digest.Digest\n\t\tmediaType         string\n\t\texistingLabels    map[string]string\n\t\texpectedMediaType string\n\t\tshouldFail        bool\n\t}{\n\t\t{\n\t\t\tname:              \"gzip layer\",\n\t\t\tuncompressedDgst:  uncompressedDigest,\n\t\t\ttargetDgst:        targetDigest,\n\t\t\tmediaType:         ocispec.MediaTypeImageLayerGzip,\n\t\t\texistingLabels:    nil,\n\t\t\texpectedMediaType: ocispec.MediaTypeImageLayerGzip,\n\t\t\tshouldFail:        false,\n\t\t},\n\t\t{\n\t\t\tname:              \"zstd layer\",\n\t\t\tuncompressedDgst:  uncompressedDigest,\n\t\t\ttargetDgst:        targetDigest,\n\t\t\tmediaType:         ocispec.MediaTypeImageLayerZstd,\n\t\t\texistingLabels:    nil,\n\t\t\texpectedMediaType: ocispec.MediaTypeImageLayerZstd,\n\t\t\tshouldFail:        false,\n\t\t},\n\t\t{\n\t\t\tname:              \"uncompressed layer\",\n\t\t\tuncompressedDgst:  uncompressedDigest,\n\t\t\ttargetDgst:        targetDigest,\n\t\t\tmediaType:         ocispec.MediaTypeImageLayer,\n\t\t\texistingLabels:    nil,\n\t\t\texpectedMediaType: ocispec.MediaTypeImageLayer,\n\t\t\tshouldFail:        false,\n\t\t},\n\t\t{\n\t\t\tname:             \"non-existent target\",\n\t\t\tuncompressedDgst: uncompressedDigest,\n\t\t\ttargetDgst:       digest.FromString(\"non-existent\"),\n\t\t\tmediaType:        ocispec.MediaTypeImageLayerGzip,\n\t\t\tshouldFail:       true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tcs := newMockContentStore()\n\n\t\t\tif !tt.shouldFail {\n\t\t\t\tcs.addBlob(tt.targetDgst, []byte(\"compressed data\"), tt.existingLabels)\n\t\t\t}\n\n\t\t\tdesc, err := makeOCIBlobDesc(ctx, cs, tt.uncompressedDgst, tt.targetDgst, tt.mediaType)\n\n\t\t\tif tt.shouldFail {\n\t\t\t\tassert.Error(t, err)\n\t\t\t\tassert.Nil(t, desc)\n\t\t\t} else {\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\trequire.NotNil(t, desc)\n\t\t\t\tassert.Equal(t, tt.targetDgst, desc.Digest)\n\t\t\t\tassert.Equal(t, tt.expectedMediaType, desc.MediaType)\n\t\t\t\tassert.Equal(t, int64(len(\"compressed data\")), desc.Size)\n\t\t\t\tassert.NotNil(t, desc.Annotations)\n\t\t\t\tassert.Equal(t, tt.uncompressedDgst.String(), desc.Annotations[LayerAnnotationUncompressed])\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestReconvertHookFunc_NilDescriptor(t *testing.T) {\n\tctx := context.Background()\n\tcs := newMockContentStore()\n\n\thook := ReconvertHookFunc()\n\tresult, err := hook(ctx, cs, ocispec.Descriptor{}, nil)\n\n\tassert.NoError(t, err)\n\tassert.Nil(t, result)\n}\n\nfunc TestReconvertHookFunc_NonManifestType(t *testing.T) {\n\tctx := context.Background()\n\tcs := newMockContentStore()\n\n\tdesc := ocispec.Descriptor{\n\t\tMediaType: ocispec.MediaTypeImageConfig,\n\t\tDigest:    digest.FromString(\"config\"),\n\t}\n\n\thook := ReconvertHookFunc()\n\tresult, err := hook(ctx, cs, ocispec.Descriptor{}, &desc)\n\n\tassert.NoError(t, err)\n\tassert.Equal(t, &desc, result)\n}\n"
  },
  {
    "path": "pkg/converter/tool/builder.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage tool\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/sirupsen/logrus\"\n)\n\nvar logger = logrus.WithField(\"module\", \"builder\")\n\nfunc isSignalKilled(err error) bool {\n\treturn strings.Contains(err.Error(), \"signal: killed\")\n}\n\ntype PackOption struct {\n\tBuilderPath string\n\n\tBootstrapPath    string\n\tBlobPath         string\n\tFsVersion        string\n\tSourcePath       string\n\tChunkDictPath    string\n\tPrefetchPatterns string\n\tCompressor       string\n\tOCIRef           bool\n\tAlignedChunk     bool\n\tChunkSize        string\n\tBatchSize        string\n\tEncrypt          bool\n\tTimeout          *time.Duration\n\n\tFeatures Features\n}\n\ntype MergeOption struct {\n\tBuilderPath string\n\n\tSourceBootstrapPaths []string\n\tRafsBlobDigests      []string\n\tRafsBlobTOCDigests   []string\n\tRafsBlobSizes        []int64\n\n\tTargetBootstrapPath string\n\tChunkDictPath       string\n\tParentBootstrapPath string\n\tPrefetchPatterns    string\n\tOutputJSONPath      string\n\tTimeout             *time.Duration\n}\n\ntype UnpackOption struct {\n\tBuilderPath       string\n\tBootstrapPath     string\n\tBlobPath          string\n\tBackendConfigPath string\n\tTarPath           string\n\tTimeout           *time.Duration\n}\n\ntype outputJSON struct {\n\tBlobs []string\n}\n\nfunc buildPackArgs(option PackOption) []string {\n\tif option.FsVersion == \"\" {\n\t\toption.FsVersion = \"6\"\n\t}\n\n\targs := []string{\n\t\t\"create\",\n\t\t\"--log-level\",\n\t\t\"warn\",\n\t\t\"--prefetch-policy\",\n\t\t\"fs\",\n\t\t\"--blob\",\n\t\toption.BlobPath,\n\t\t\"--whiteout-spec\",\n\t\t\"none\",\n\t\t\"--fs-version\",\n\t\toption.FsVersion,\n\t}\n\n\tif option.Features.Contains(FeatureTar2Rafs) {\n\t\targs = append(\n\t\t\targs,\n\t\t\t\"--type\",\n\t\t\t\"tar-rafs\",\n\t\t\t\"--blob-inline-meta\",\n\t\t)\n\t\tif option.FsVersion == \"6\" {\n\t\t\targs = append(\n\t\t\t\targs,\n\t\t\t\t\"--features\",\n\t\t\t\t\"blob-toc\",\n\t\t\t)\n\t\t}\n\t} else {\n\t\targs = append(\n\t\t\targs,\n\t\t\t\"--source-type\",\n\t\t\t\"directory\",\n\t\t\t// Sames with `--blob-inline-meta`, it's used for compatibility\n\t\t\t// with the old nydus-image builder.\n\t\t\t\"--inline-bootstrap\",\n\t\t)\n\t}\n\n\tif option.ChunkDictPath != \"\" {\n\t\targs = append(args, \"--chunk-dict\", fmt.Sprintf(\"bootstrap=%s\", option.ChunkDictPath))\n\t}\n\tif option.PrefetchPatterns == \"\" {\n\t\toption.PrefetchPatterns = \"/\"\n\t}\n\tif option.Compressor != \"\" {\n\t\targs = append(args, \"--compressor\", option.Compressor)\n\t}\n\tif option.AlignedChunk {\n\t\targs = append(args, \"--aligned-chunk\")\n\t}\n\tif option.ChunkSize != \"\" {\n\t\targs = append(args, \"--chunk-size\", option.ChunkSize)\n\t}\n\tif option.Features.Contains(FeatureBatchSize) {\n\t\targs = append(args, \"--batch-size\", option.BatchSize)\n\t}\n\tif option.Encrypt {\n\t\targs = append(args, \"--encrypt\")\n\t}\n\targs = append(args, option.SourcePath)\n\n\treturn args\n}\n\nfunc Pack(option PackOption) error {\n\tif option.OCIRef {\n\t\treturn packRef(option)\n\t}\n\n\tctx := context.Background()\n\tvar cancel context.CancelFunc\n\tif option.Timeout != nil {\n\t\tctx, cancel = context.WithTimeout(ctx, *option.Timeout)\n\t\tdefer cancel()\n\t}\n\n\targs := buildPackArgs(option)\n\tlogrus.Debugf(\"\\tCommand: %s %s\", option.BuilderPath, strings.Join(args, \" \"))\n\n\tcmd := exec.CommandContext(ctx, option.BuilderPath, args...)\n\tcmd.Stdout = logger.Writer()\n\tcmd.Stderr = logger.Writer()\n\tcmd.Stdin = strings.NewReader(option.PrefetchPatterns)\n\n\tif err := cmd.Run(); err != nil {\n\t\tif isSignalKilled(err) && option.Timeout != nil {\n\t\t\tlogrus.WithError(err).Errorf(\"fail to run %v %+v, possibly due to timeout %v\", option.BuilderPath, args, *option.Timeout)\n\t\t} else {\n\t\t\tlogrus.WithError(err).Errorf(\"fail to run %v %+v\", option.BuilderPath, args)\n\t\t}\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc packRef(option PackOption) error {\n\targs := []string{\n\t\t\"create\",\n\t\t\"--log-level\",\n\t\t\"warn\",\n\t\t\"--type\",\n\t\t\"targz-ref\",\n\t\t\"--blob-inline-meta\",\n\t\t\"--features\",\n\t\t\"blob-toc\",\n\t\t\"--blob\",\n\t\toption.BlobPath,\n\t}\n\targs = append(args, option.SourcePath)\n\n\tctx := context.Background()\n\tvar cancel context.CancelFunc\n\tif option.Timeout != nil {\n\t\tctx, cancel = context.WithTimeout(ctx, *option.Timeout)\n\t\tdefer cancel()\n\t}\n\n\tlogrus.Debugf(\"\\tCommand: %s %s\", option.BuilderPath, strings.Join(args, \" \"))\n\n\tcmd := exec.CommandContext(ctx, option.BuilderPath, args...)\n\tcmd.Stdout = logger.Writer()\n\tcmd.Stderr = logger.Writer()\n\n\tif err := cmd.Run(); err != nil {\n\t\tif isSignalKilled(err) && option.Timeout != nil {\n\t\t\tlogrus.WithError(err).Errorf(\"fail to run %v %+v, possibly due to timeout %v\", option.BuilderPath, args, *option.Timeout)\n\t\t} else {\n\t\t\tlogrus.WithError(err).Errorf(\"fail to run %v %+v\", option.BuilderPath, args)\n\t\t}\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc Merge(option MergeOption) ([]digest.Digest, error) {\n\targs := []string{\n\t\t\"merge\",\n\t\t\"--log-level\",\n\t\t\"warn\",\n\t\t\"--prefetch-policy\",\n\t\t\"fs\",\n\t\t\"--output-json\",\n\t\toption.OutputJSONPath,\n\t\t\"--bootstrap\",\n\t\toption.TargetBootstrapPath,\n\t}\n\tif option.ChunkDictPath != \"\" {\n\t\targs = append(args, \"--chunk-dict\", fmt.Sprintf(\"bootstrap=%s\", option.ChunkDictPath))\n\t}\n\tif option.ParentBootstrapPath != \"\" {\n\t\targs = append(args, \"--parent-bootstrap\", option.ParentBootstrapPath)\n\t}\n\tif option.PrefetchPatterns == \"\" {\n\t\toption.PrefetchPatterns = \"/\"\n\t}\n\targs = append(args, option.SourceBootstrapPaths...)\n\tif len(option.RafsBlobDigests) > 0 {\n\t\targs = append(args, \"--blob-digests\", strings.Join(option.RafsBlobDigests, \",\"))\n\t}\n\tif len(option.RafsBlobTOCDigests) > 0 {\n\t\targs = append(args, \"--blob-toc-digests\", strings.Join(option.RafsBlobTOCDigests, \",\"))\n\t}\n\tif len(option.RafsBlobSizes) > 0 {\n\t\tsizes := []string{}\n\t\tfor _, size := range option.RafsBlobSizes {\n\t\t\tsizes = append(sizes, fmt.Sprintf(\"%d\", size))\n\t\t}\n\t\targs = append(args, \"--blob-sizes\", strings.Join(sizes, \",\"))\n\t}\n\n\tctx := context.Background()\n\tvar cancel context.CancelFunc\n\tif option.Timeout != nil {\n\t\tctx, cancel = context.WithTimeout(ctx, *option.Timeout)\n\t\tdefer cancel()\n\t}\n\tlogrus.Debugf(\"\\tCommand: %s %s\", option.BuilderPath, strings.Join(args, \" \"))\n\n\tcmd := exec.CommandContext(ctx, option.BuilderPath, args...)\n\tcmd.Stdout = logger.Writer()\n\tcmd.Stderr = logger.Writer()\n\tcmd.Stdin = strings.NewReader(option.PrefetchPatterns)\n\n\tif err := cmd.Run(); err != nil {\n\t\tif isSignalKilled(err) && option.Timeout != nil {\n\t\t\tlogrus.WithError(err).Errorf(\"fail to run %v %+v, possibly due to timeout %v\", option.BuilderPath, args, *option.Timeout)\n\t\t} else {\n\t\t\tlogrus.WithError(err).Errorf(\"fail to run %v %+v\", option.BuilderPath, args)\n\t\t}\n\t\treturn nil, errors.Wrap(err, \"run merge command\")\n\t}\n\n\toutputBytes, err := os.ReadFile(option.OutputJSONPath)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"read file %s\", option.OutputJSONPath)\n\t}\n\tvar output outputJSON\n\terr = json.Unmarshal(outputBytes, &output)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"unmarshal output json file %s\", option.OutputJSONPath)\n\t}\n\n\tblobDigests := []digest.Digest{}\n\tfor _, blobID := range output.Blobs {\n\t\tblobDigests = append(blobDigests, digest.NewDigestFromHex(string(digest.SHA256), blobID))\n\t}\n\n\treturn blobDigests, nil\n}\n\nfunc Unpack(option UnpackOption) error {\n\targs := []string{\n\t\t\"unpack\",\n\t\t\"--log-level\",\n\t\t\"warn\",\n\t\t\"--bootstrap\",\n\t\toption.BootstrapPath,\n\t\t\"--output\",\n\t\toption.TarPath,\n\t}\n\n\tif option.BackendConfigPath != \"\" {\n\t\tconfigBytes, err := os.ReadFile(option.BackendConfigPath)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"fail to read backend config file %s\", option.BackendConfigPath)\n\t\t}\n\n\t\tvar config map[string]interface{}\n\t\tif err := json.Unmarshal(configBytes, &config); err != nil {\n\t\t\treturn errors.Wrapf(err, \"fail to unmarshal backend config file %s\", option.BackendConfigPath)\n\t\t}\n\n\t\tbackendConfigType, ok := config[\"backend\"].(map[string]interface{})[\"type\"]\n\t\tif !ok {\n\t\t\treturn errors.New(\"backend config file should contain a valid backend type\")\n\t\t}\n\n\t\tbackendConfig, ok := config[\"backend\"].(map[string]interface{})[backendConfigType.(string)]\n\t\tif !ok {\n\t\t\treturn errors.New(\"failed to get backend config with type \" + backendConfigType.(string))\n\t\t}\n\n\t\tbackendConfigBytes, err := json.Marshal(backendConfig)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"fail to marshal backend config %v\", backendConfig)\n\t\t}\n\n\t\targs = append(args, \"--backend-type\", backendConfigType.(string))\n\t\targs = append(args, \"--backend-config\", string(backendConfigBytes))\n\t} else if option.BlobPath != \"\" {\n\t\targs = append(args, \"--blob\", option.BlobPath)\n\t}\n\n\tctx := context.Background()\n\tvar cancel context.CancelFunc\n\tif option.Timeout != nil {\n\t\tctx, cancel = context.WithTimeout(ctx, *option.Timeout)\n\t\tdefer cancel()\n\t}\n\n\tlogrus.Debugf(\"\\tCommand: %s %s\", option.BuilderPath, strings.Join(args, \" \"))\n\n\tcmd := exec.CommandContext(ctx, option.BuilderPath, args...)\n\tcmd.Stdout = logger.Writer()\n\tcmd.Stderr = logger.Writer()\n\n\tif err := cmd.Run(); err != nil {\n\t\tif isSignalKilled(err) && option.Timeout != nil {\n\t\t\tlogrus.WithError(err).Errorf(\"fail to run %v %+v, possibly due to timeout %v\", option.BuilderPath, args, *option.Timeout)\n\t\t} else {\n\t\t\tlogrus.WithError(err).Errorf(\"fail to run %v %+v\", option.BuilderPath, args)\n\t\t}\n\t\treturn err\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/converter/tool/feature.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage tool\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/sirupsen/logrus\"\n)\n\ntype Feature string\ntype Features map[Feature]struct{}\n\nconst envNydusDisableTar2Rafs string = \"NYDUS_DISABLE_TAR2RAFS\"\n\nconst (\n\t// The option `--type tar-rafs` enables converting OCI tar blob\n\t// stream into nydus blob directly, the tar2rafs eliminates the\n\t// need to decompress it to a local directory first, thus greatly\n\t// accelerating the pack process.\n\tFeatureTar2Rafs Feature = \"--type tar-rafs\"\n\t// The option `--batch-size` enables merging multiple small chunks\n\t// into a big batch chunk, which can reduce the the size of the image\n\t// and accelerate the runtime file loading.\n\tFeatureBatchSize Feature = \"--batch-size\"\n\t// The option `--encrypt` enables converting directories, tar files\n\t// or OCI images into encrypted nydus blob.\n\tFeatureEncrypt Feature = \"--encrypt\"\n)\n\nvar requiredFeatures Features\nvar detectedFeatures Features\nvar detectFeaturesOnce sync.Once\nvar disableTar2Rafs = os.Getenv(envNydusDisableTar2Rafs) != \"\"\n\nfunc NewFeatures(items ...Feature) Features {\n\tfeatures := Features{}\n\tfeatures.Add(items...)\n\treturn features\n}\n\nfunc (features *Features) Add(items ...Feature) {\n\tfor _, item := range items {\n\t\t(*features)[item] = struct{}{}\n\t}\n}\n\nfunc (features *Features) Remove(items ...Feature) {\n\tfor _, item := range items {\n\t\tdelete(*features, item)\n\t}\n}\n\nfunc (features *Features) Contains(feature Feature) bool {\n\t_, ok := (*features)[feature]\n\treturn ok\n}\n\nfunc (features *Features) Equals(other Features) bool {\n\tif len(*features) != len(other) {\n\t\treturn false\n\t}\n\n\tfor f := range *features {\n\t\tif !other.Contains(f) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n// GetHelp returns the help message of `nydus-image create`.\nfunc GetHelp(builder string) []byte {\n\tcmd := exec.CommandContext(context.Background(), builder, \"create\", \"-h\")\n\toutput, err := cmd.Output()\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\treturn output\n}\n\n// detectFeature returns true if the feature is detected in the help message.\nfunc detectFeature(msg []byte, feature Feature) bool {\n\tif feature == \"\" {\n\t\treturn false\n\t}\n\n\tif strings.Contains(string(msg), string(feature)) {\n\t\treturn true\n\t}\n\n\tif parts := strings.Split(string(feature), \" \"); len(parts) == 2 {\n\t\t// Check each part of the feature.\n\t\t// e.g., \"--type tar-rafs\" -> [\"--type\", \"tar-rafs\"]\n\t\tif strings.Contains(string(msg), parts[0]) && strings.Contains(string(msg), parts[1]) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n// DetectFeatures returns supported feature list from required feature list.\n// The supported feature list is detected from the help message of `nydus-image create`.\nfunc DetectFeatures(builder string, required Features, getHelp func(string) []byte) (Features, error) {\n\tdetectFeaturesOnce.Do(func() {\n\t\trequiredFeatures = required\n\t\tdetectedFeatures = Features{}\n\n\t\thelpMsg := getHelp(builder)\n\n\t\tfor feature := range required {\n\t\t\t// The feature is supported by current version of nydus-image.\n\t\t\tsupported := detectFeature(helpMsg, feature)\n\t\t\tif supported {\n\t\t\t\t// It is an experimental feature, so we still provide an env\n\t\t\t\t// variable to allow users to disable it.\n\t\t\t\tif feature == FeatureTar2Rafs && disableTar2Rafs {\n\t\t\t\t\tlogrus.Warnf(\"the feature '%s' is disabled by env '%s'\", FeatureTar2Rafs, envNydusDisableTar2Rafs)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tdetectedFeatures.Add(feature)\n\t\t\t} else {\n\t\t\t\tlogrus.Warnf(\"the feature '%s' is ignored, it requires higher version of nydus-image\", feature)\n\t\t\t}\n\t\t}\n\t})\n\n\t// Return Error if required features changed in different calls.\n\tif !requiredFeatures.Equals(required) {\n\t\treturn nil, fmt.Errorf(\"features changed: %v -> %v\", requiredFeatures, required)\n\t}\n\n\treturn detectedFeatures, nil\n}\n"
  },
  {
    "path": "pkg/converter/tool/feature_test.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage tool\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestFeature(t *testing.T) {\n\ttestsAdd := []struct {\n\t\tname     string\n\t\tfeatures Features\n\t\titems    []Feature\n\t\texpect   Features\n\t}{\n\t\t{\n\t\t\tname:     \"should successfully add items\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}},\n\t\t\titems:    []Feature{FeatureTar2Rafs},\n\t\t\texpect:   Features{FeatureTar2Rafs: {}, FeatureBatchSize: {}},\n\t\t},\n\t\t{\n\t\t\tname:     \"should add nothing if duplicated\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}},\n\t\t\titems:    []Feature{FeatureBatchSize},\n\t\t\texpect:   Features{FeatureBatchSize: {}},\n\t\t},\n\t\t{\n\t\t\tname:     \"add should accept nil\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}},\n\t\t\titems:    nil,\n\t\t\texpect:   Features{FeatureBatchSize: {}},\n\t\t},\n\t}\n\tfor _, tt := range testsAdd {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\ttt.features.Add(tt.items...)\n\t\t\trequire.Equal(t, tt.expect, tt.features)\n\t\t})\n\t}\n\n\ttestsNew := []struct {\n\t\tname   string\n\t\titems  []Feature\n\t\texpect Features\n\t}{\n\t\t{\n\t\t\tname:   \"should successfully new Features\",\n\t\t\titems:  []Feature{FeatureTar2Rafs, FeatureBatchSize},\n\t\t\texpect: Features{FeatureTar2Rafs: {}, FeatureBatchSize: {}},\n\t\t},\n\t\t{\n\t\t\tname:   \"should duplicate same items\",\n\t\t\titems:  []Feature{FeatureBatchSize, FeatureBatchSize},\n\t\t\texpect: Features{FeatureBatchSize: {}},\n\t\t},\n\t\t{\n\t\t\tname:   \"New should accept nil\",\n\t\t\titems:  nil,\n\t\t\texpect: Features{},\n\t\t},\n\t}\n\tfor _, tt := range testsNew {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tfeatures := NewFeatures(tt.items...)\n\t\t\trequire.Equal(t, tt.expect, features)\n\t\t})\n\t}\n\n\ttestsRemove := []struct {\n\t\tname     string\n\t\tfeatures Features\n\t\titems    []Feature\n\t\texpect   Features\n\t}{\n\t\t{\n\t\t\tname:     \"should successfully remove items\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}, FeatureTar2Rafs: {}},\n\t\t\titems:    []Feature{FeatureTar2Rafs},\n\t\t\texpect:   Features{FeatureBatchSize: {}},\n\t\t},\n\t\t{\n\t\t\tname:     \"should remove item iff exists\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}},\n\t\t\titems:    []Feature{FeatureBatchSize, FeatureTar2Rafs},\n\t\t\texpect:   Features{},\n\t\t},\n\t\t{\n\t\t\tname:     \"Remove should accept nil\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}},\n\t\t\titems:    nil,\n\t\t\texpect:   Features{FeatureBatchSize: {}},\n\t\t},\n\t}\n\tfor _, tt := range testsRemove {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\ttt.features.Remove(tt.items...)\n\t\t\trequire.Equal(t, tt.expect, tt.features)\n\t\t})\n\t}\n\n\ttestsContains := []struct {\n\t\tname     string\n\t\tfeatures Features\n\t\titem     Feature\n\t\texpect   bool\n\t}{\n\t\t{\n\t\t\tname:     \"should return contains\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}, FeatureTar2Rafs: {}},\n\t\t\titem:     FeatureTar2Rafs,\n\t\t\texpect:   true,\n\t\t},\n\t\t{\n\t\t\tname:     \"should return not contains\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}},\n\t\t\titem:     FeatureTar2Rafs,\n\t\t\texpect:   false,\n\t\t},\n\t\t{\n\t\t\tname:     \"Contains should accept empty string\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}},\n\t\t\titem:     \"\",\n\t\t\texpect:   false,\n\t\t},\n\t}\n\tfor _, tt := range testsContains {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\trequire.Equal(t, tt.expect, tt.features.Contains(tt.item))\n\t\t})\n\t}\n\n\ttestsEquals := []struct {\n\t\tname     string\n\t\tfeatures Features\n\t\tother    Features\n\t\texpect   bool\n\t}{\n\t\t{\n\t\t\tname:     \"should successfully check equality\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}, FeatureTar2Rafs: {}},\n\t\t\tother:    Features{FeatureBatchSize: {}, FeatureTar2Rafs: {}},\n\t\t\texpect:   true,\n\t\t},\n\t\t{\n\t\t\tname:     \"should successfully check inequality with different length\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}, FeatureTar2Rafs: {}},\n\t\t\tother:    Features{FeatureBatchSize: {}},\n\t\t\texpect:   false,\n\t\t},\n\t\t{\n\t\t\tname:     \"should successfully check inequality with different items\",\n\t\t\tfeatures: Features{FeatureTar2Rafs: {}},\n\t\t\tother:    Features{FeatureBatchSize: {}},\n\t\t\texpect:   false,\n\t\t},\n\t\t{\n\t\t\tname:     \"should ignore order\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}, FeatureTar2Rafs: {}},\n\t\t\tother:    Features{FeatureTar2Rafs: {}, FeatureBatchSize: {}},\n\t\t\texpect:   true,\n\t\t},\n\t\t{\n\t\t\tname:     \"Equals should accept nil\",\n\t\t\tfeatures: Features{FeatureBatchSize: {}},\n\t\t\tother:    nil,\n\t\t\texpect:   false,\n\t\t},\n\t}\n\tfor _, tt := range testsEquals {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\trequire.Equal(t, tt.expect, tt.features.Equals(tt.other))\n\t\t})\n\t}\n}\n\nfunc TestDetectFeature(t *testing.T) {\n\ttests := []struct {\n\t\tname    string\n\t\tfeature Feature\n\t\thelpMsg []byte\n\t\texpect  bool\n\t}{\n\t\t{\n\t\t\tname:    \"'--type tar-rafs' is supported in v2.2.0-239-gf5c08fcf\",\n\t\t\tfeature: FeatureTar2Rafs,\n\t\t\texpect:  true,\n\t\t\thelpMsg: []byte(`\n\t\t\tCreate RAFS filesystems from directories, tar files or OCI images\n\n\t\t\tUsage: nydus-image create [OPTIONS] <SOURCE>\n\t\t\t\n\t\t\tArguments:\n\t\t\t  <SOURCE>  source from which to build the RAFS filesystem\n\t\t\t\n\t\t\tOptions:\n\t\t\t  -L, --log-file <log-file>\n\t\t\t\t\t  Log file path\n\t\t\t  -t, --type <type>\n\t\t\t\t\t  Conversion type: [default: dir-rafs] [possible values: directory, dir-rafs, estargz-rafs, estargz-ref, estargztoc-ref, tar-rafs, tar-tarfs, targz-rafs, targz-ref, stargz_index]\n\t\t\t  -B, --bootstrap <bootstrap>\n\t\t\t\t\t  File path to save the generated RAFS metadata blob\n\t\t\t  -l, --log-level <log-level>\n\t\t\t\t\t  Log level: [default: info] [possible values: trace, debug, info, warn, error]\n\t\t\t  -D, --blob-dir <blob-dir>\n\t\t\t\t\t  Directory path to save generated RAFS metadata and data blobs\n\t\t\t  -b, --blob <blob>\n\t\t\t\t\t  File path to save the generated RAFS data blob\n\t\t\t\t  --blob-inline-meta\n\t\t\t\t\t  Inline RAFS metadata and blob metadata into the data blob\n\t\t\t\t  --blob-id <blob-id>\n\t\t\t\t\t  OSS object id for the generated RAFS data blob\n\t\t\t\t  --blob-data-size <blob-data-size>\n\t\t\t\t\t  Set data blob size for 'estargztoc-ref' conversion\n\t\t\t\t  --chunk-size <chunk-size>\n\t\t\t\t\t  Set the size of data chunks, must be power of two and between 0x1000-0x1000000:\n\t\t\t\t  --batch-size <batch-size>\n\t\t\t\t\t  Set the batch size to merge small chunks, must be power of two, between 0x1000-0x1000000 or be zero: [default: 0]\n\t\t\t\t  --compressor <compressor>\n\t\t\t\t\t  Algorithm to compress data chunks: [default: zstd] [possible values: none, lz4_block, zstd]\n\t\t\t\t  --digester <digester>\n\t\t\t\t\t  Algorithm to digest data chunks: [default: blake3] [possible values: blake3, sha256]\n\t\t\t  -C, --config <config>\n\t\t\t\t\t  Configuration file for storage backend, cache and RAFS FUSE filesystem.\n\t\t\t  -v, --fs-version <fs-version>\n\t\t\t\t\t  Set RAFS format version number: [default: 6] [possible values: 5, 6]\n\t\t\t\t  --features <features>\n\t\t\t\t\t  Enable/disable features [possible values: blob-toc]\n\t\t\t\t  --chunk-dict <chunk-dict>\n\t\t\t\t\t  File path of chunk dictionary for data deduplication\n\t\t\t\t  --parent-bootstrap <parent-bootstrap>\n\t\t\t\t\t  File path of the parent/referenced RAFS metadata blob (optional)\n\t\t\t\t  --aligned-chunk\n\t\t\t\t\t  Align uncompressed data chunks to 4K, only for RAFS V5\n\t\t\t\t  --repeatable\n\t\t\t\t\t  Generate reproducible RAFS metadata\n\t\t\t\t  --whiteout-spec <whiteout-spec>\n\t\t\t\t\t  Set the type of whiteout specification: [default: oci] [possible values: oci, overlayfs, none]\n\t\t\t\t  --prefetch-policy <prefetch-policy>\n\t\t\t\t\t  Set data prefetch policy [default: none] [possible values: fs, blob, none]\n\t\t\t  -J, --output-json <output-json>\n\t\t\t\t\t  File path to save operation result in JSON format\n\t\t\t  -h, --help\n\t\t\t\t\t  Print help information\n\t\t\t`),\n\t\t},\n\t\t{\n\t\t\tname:    \"'--batch-size' is supported in v2.2.0-239-gf5c08fcf\",\n\t\t\tfeature: FeatureBatchSize,\n\t\t\texpect:  true,\n\t\t\thelpMsg: []byte(`\n\t\t\tCreate RAFS filesystems from directories, tar files or OCI images\n\n\t\t\tUsage: nydus-image create [OPTIONS] <SOURCE>\n\t\t\t\n\t\t\tArguments:\n\t\t\t  <SOURCE>  source from which to build the RAFS filesystem\n\t\t\t\n\t\t\tOptions:\n\t\t\t  -L, --log-file <log-file>\n\t\t\t\t\t  Log file path\n\t\t\t  -t, --type <type>\n\t\t\t\t\t  Conversion type: [default: dir-rafs] [possible values: directory, dir-rafs, estargz-rafs, estargz-ref, estargztoc-ref, tar-rafs, tar-tarfs, targz-rafs, targz-ref, stargz_index]\n\t\t\t  -B, --bootstrap <bootstrap>\n\t\t\t\t\t  File path to save the generated RAFS metadata blob\n\t\t\t  -l, --log-level <log-level>\n\t\t\t\t\t  Log level: [default: info] [possible values: trace, debug, info, warn, error]\n\t\t\t  -D, --blob-dir <blob-dir>\n\t\t\t\t\t  Directory path to save generated RAFS metadata and data blobs\n\t\t\t  -b, --blob <blob>\n\t\t\t\t\t  File path to save the generated RAFS data blob\n\t\t\t\t  --blob-inline-meta\n\t\t\t\t\t  Inline RAFS metadata and blob metadata into the data blob\n\t\t\t\t  --blob-id <blob-id>\n\t\t\t\t\t  OSS object id for the generated RAFS data blob\n\t\t\t\t  --blob-data-size <blob-data-size>\n\t\t\t\t\t  Set data blob size for 'estargztoc-ref' conversion\n\t\t\t\t  --chunk-size <chunk-size>\n\t\t\t\t\t  Set the size of data chunks, must be power of two and between 0x1000-0x1000000:\n\t\t\t\t  --batch-size <batch-size>\n\t\t\t\t\t  Set the batch size to merge small chunks, must be power of two, between 0x1000-0x1000000 or be zero: [default: 0]\n\t\t\t\t  --compressor <compressor>\n\t\t\t\t\t  Algorithm to compress data chunks: [default: zstd] [possible values: none, lz4_block, zstd]\n\t\t\t\t  --digester <digester>\n\t\t\t\t\t  Algorithm to digest data chunks: [default: blake3] [possible values: blake3, sha256]\n\t\t\t  -C, --config <config>\n\t\t\t\t\t  Configuration file for storage backend, cache and RAFS FUSE filesystem.\n\t\t\t  -v, --fs-version <fs-version>\n\t\t\t\t\t  Set RAFS format version number: [default: 6] [possible values: 5, 6]\n\t\t\t\t  --features <features>\n\t\t\t\t\t  Enable/disable features [possible values: blob-toc]\n\t\t\t\t  --chunk-dict <chunk-dict>\n\t\t\t\t\t  File path of chunk dictionary for data deduplication\n\t\t\t\t  --parent-bootstrap <parent-bootstrap>\n\t\t\t\t\t  File path of the parent/referenced RAFS metadata blob (optional)\n\t\t\t\t  --aligned-chunk\n\t\t\t\t\t  Align uncompressed data chunks to 4K, only for RAFS V5\n\t\t\t\t  --repeatable\n\t\t\t\t\t  Generate reproducible RAFS metadata\n\t\t\t\t  --whiteout-spec <whiteout-spec>\n\t\t\t\t\t  Set the type of whiteout specification: [default: oci] [possible values: oci, overlayfs, none]\n\t\t\t\t  --prefetch-policy <prefetch-policy>\n\t\t\t\t\t  Set data prefetch policy [default: none] [possible values: fs, blob, none]\n\t\t\t  -J, --output-json <output-json>\n\t\t\t\t\t  File path to save operation result in JSON format\n\t\t\t  -h, --help\n\t\t\t\t\t  Print help information\n\t\t\t`),\n\t\t},\n\t\t{\n\t\t\tname:    \"'--batch-size' is not supported in v2.2.0-163-g180f6d2c\",\n\t\t\tfeature: FeatureBatchSize,\n\t\t\texpect:  false,\n\t\t\thelpMsg: []byte(`\n\t\t\tCreate RAFS filesystems from directories, tar files or OCI images\n\n\t\t\tUsage: nydus-image create [OPTIONS] <SOURCE>\n\t\t\t\n\t\t\tArguments:\n\t\t\t  <SOURCE>  source from which to build the RAFS filesystem\n\t\t\t\n\t\t\tOptions:\n\t\t\t  -L, --log-file <log-file>\n\t\t\t\t\t  Log file path\n\t\t\t  -t, --type <type>\n\t\t\t\t\t  Conversion type: [default: dir-rafs] [possible values: directory, dir-rafs, estargz-rafs, estargz-ref, estargztoc-ref, tar-rafs, tar-tarfs, targz-rafs, targz-ref, stargz_index]\n\t\t\t  -B, --bootstrap <bootstrap>\n\t\t\t\t\t  File path to save the generated RAFS metadata blob\n\t\t\t  -l, --log-level <log-level>\n\t\t\t\t\t  Log level: [default: info] [possible values: trace, debug, info, warn, error]\n\t\t\t  -D, --blob-dir <blob-dir>\n\t\t\t\t\t  Directory path to save generated RAFS metadata and data blobs\n\t\t\t  -b, --blob <blob>\n\t\t\t\t\t  File path to save the generated RAFS data blob\n\t\t\t\t  --blob-inline-meta\n\t\t\t\t\t  Inline RAFS metadata and blob metadata into the data blob\n\t\t\t\t  --blob-id <blob-id>\n\t\t\t\t\t  OSS object id for the generated RAFS data blob\n\t\t\t\t  --blob-data-size <blob-data-size>\n\t\t\t\t\t  Set data blob size for 'estargztoc-ref' conversion\n\t\t\t\t  --chunk-size <chunk-size>\n\t\t\t\t\t  Set the size of data chunks, must be power of two and between 0x1000-0x1000000:\n\t\t\t\t  --compressor <compressor>\n\t\t\t\t\t  Algorithm to compress data chunks: [default: zstd] [possible values: none, lz4_block, zstd]\n\t\t\t\t  --digester <digester>\n\t\t\t\t\t  Algorithm to digest data chunks: [default: blake3] [possible values: blake3, sha256]\n\t\t\t  -C, --config <config>\n\t\t\t\t\t  Configuration file for storage backend, cache and RAFS FUSE filesystem.\n\t\t\t  -v, --fs-version <fs-version>\n\t\t\t\t\t  Set RAFS format version number: [default: 6] [possible values: 5, 6]\n\t\t\t\t  --features <features>\n\t\t\t\t\t  Enable/disable features [possible values: blob-toc]\n\t\t\t\t  --chunk-dict <chunk-dict>\n\t\t\t\t\t  File path of chunk dictionary for data deduplication\n\t\t\t\t  --parent-bootstrap <parent-bootstrap>\n\t\t\t\t\t  File path of the parent/referenced RAFS metadata blob (optional)\n\t\t\t\t  --aligned-chunk\n\t\t\t\t\t  Align uncompressed data chunks to 4K, only for RAFS V5\n\t\t\t\t  --repeatable\n\t\t\t\t\t  Generate reproducible RAFS metadata\n\t\t\t\t  --whiteout-spec <whiteout-spec>\n\t\t\t\t\t  Set the type of whiteout specification: [default: oci] [possible values: oci, overlayfs, none]\n\t\t\t\t  --prefetch-policy <prefetch-policy>\n\t\t\t\t\t  Set data prefetch policy [default: none] [possible values: fs, blob, none]\n\t\t\t  -J, --output-json <output-json>\n\t\t\t\t\t  File path to save operation result in JSON format\n\t\t\t  -h, --help\n\t\t\t\t\t  Print help information\n\t\t\t`),\n\t\t},\n\t\t{\n\t\t\tname:    \"'--encrypt' is supported in v2.2.0-261-g22ad0e2c\",\n\t\t\tfeature: FeatureEncrypt,\n\t\t\texpect:  true,\n\t\t\thelpMsg: []byte(`\n\t\t\tCreate RAFS filesystems from directories, tar files or OCI images\n\n\t\t\tUsage: nydus-image create [OPTIONS] <SOURCE>\n\n\t\t\tArguments:\n\t\t\t<SOURCE>  source from which to build the RAFS filesystem\n\n\t\t\tOptions:\n\t\t\t-L, --log-file <log-file>\n\t\t\t\t\tLog file path\n\t\t\t-t, --type <type>\n\t\t\t\t\tConversion type: [default: dir-rafs] [possible values: directory, dir-rafs, estargz-rafs, estargz-ref, estargztoc-ref, tar-rafs, tar-tarfs, targz-rafs, targz-ref, stargz_index]\n\t\t\t-B, --bootstrap <bootstrap>\n\t\t\t\t\tFile path to save the generated RAFS metadata blob\n\t\t\t-l, --log-level <log-level>\n\t\t\t\t\tLog level: [default: info] [possible values: trace, debug, info, warn, error]\n\t\t\t-D, --blob-dir <blob-dir>\n\t\t\t\t\tDirectory path to save generated RAFS metadata and data blobs\n\t\t\t-b, --blob <blob>\n\t\t\t\t\tFile path to save the generated RAFS data blob\n\t\t\t\t--blob-inline-meta\n\t\t\t\t\tInline RAFS metadata and blob metadata into the data blob\n\t\t\t\t--blob-id <blob-id>\n\t\t\t\t\tOSS object id for the generated RAFS data blob\n\t\t\t\t--blob-data-size <blob-data-size>\n\t\t\t\t\tSet data blob size for 'estargztoc-ref' conversion\n\t\t\t\t--chunk-size <chunk-size>\n\t\t\t\t\tSet the size of data chunks, must be power of two and between 0x1000-0x1000000:\n\t\t\t\t--batch-size <batch-size>\n\t\t\t\t\tSet the batch size to merge small chunks, must be power of two, between 0x1000-0x1000000 or be zero: [default: 0]\n\t\t\t\t--compressor <compressor>\n\t\t\t\t\tAlgorithm to compress data chunks: [default: zstd] [possible values: none, lz4_block, zstd]\n\t\t\t\t--digester <digester>\n\t\t\t\t\tAlgorithm to digest data chunks: [default: blake3] [possible values: blake3, sha256]\n\t\t\t-C, --config <config>\n\t\t\t\t\tConfiguration file for storage backend, cache and RAFS FUSE filesystem.\n\t\t\t-v, --fs-version <fs-version>\n\t\t\t\t\tSet RAFS format version number: [default: 6] [possible values: 5, 6]\n\t\t\t\t--features <features>\n\t\t\t\t\tEnable/disable features [possible values: blob-toc]\n\t\t\t\t--chunk-dict <chunk-dict>\n\t\t\t\t\tFile path of chunk dictionary for data deduplication\n\t\t\t\t--parent-bootstrap <parent-bootstrap>\n\t\t\t\t\tFile path of the parent/referenced RAFS metadata blob (optional)\n\t\t\t\t--aligned-chunk\n\t\t\t\t\tAlign uncompressed data chunks to 4K, only for RAFS V5\n\t\t\t\t--repeatable\n\t\t\t\t\tGenerate reproducible RAFS metadata\n\t\t\t\t--whiteout-spec <whiteout-spec>\n\t\t\t\t\tSet the type of whiteout specification: [default: oci] [possible values: oci, overlayfs, none]\n\t\t\t\t--prefetch-policy <prefetch-policy>\n\t\t\t\t\tSet data prefetch policy [default: none] [possible values: fs, blob, none]\n\t\t\t-J, --output-json <output-json>\n\t\t\t\t\tFile path to save operation result in JSON format\n\t\t\t-E, --encrypt\n\t\t\t\t\tEncrypt the generated RAFS metadata and data blobs\n\t\t\t-h, --help\n\t\t\t\t\tPrint help information\n\t\t\t`),\n\t\t},\n\n\t\t{\n\t\t\tname:    \"'--type tar-rafs' is not supported in v2.1.4\",\n\t\t\tfeature: FeatureTar2Rafs,\n\t\t\texpect:  false,\n\t\t\thelpMsg: []byte(`\n\t\t\tnydus-image-create \n\t\t\tCreates a nydus image from source\n\t\t\t\n\t\t\tUSAGE:\n\t\t\t\tnydus-image create [FLAGS] [OPTIONS] <SOURCE>... --blob <blob> --bootstrap <bootstrap> --fs-version <fs-version> --whiteout-spec <whiteout-spec>\n\t\t\t\n\t\t\tFLAGS:\n\t\t\t\t-A, --aligned-chunk       Align data chunks to 4K\n\t\t\t\t\t--disable-check       disable validation of metadata after building\n\t\t\t\t-h, --help                Prints help information\n\t\t\t\t\t--inline-bootstrap    append bootstrap data to blob\n\t\t\t\t-R, --repeatable          generate reproducible nydus image\n\t\t\t\t-V, --version             Prints version information\n\t\t\t\n\t\t\tOPTIONS:\n\t\t\t\t\t--backend-config <backend-config>\n\t\t\t\t\t\t[deprecated!] Blob storage backend config - JSON string, only support localfs for compatibility\n\t\t\t\n\t\t\t\t\t--backend-type <backend-type>\n\t\t\t\t\t\t[deprecated!] Blob storage backend type, only support localfs for compatibility. Try use --blob instead.\n\t\t\t\t\t\t[possible values: localfs]\n\t\t\t\t-b, --blob <blob>                            path to store nydus image's data blob\n\t\t\t\t-D, --blob-dir <blob-dir>                    directory to store nydus image's metadata and data blob\n\t\t\t\t\t--blob-id <blob-id>                      blob id (as object id in backend/oss)\n\t\t\t\t\t--blob-meta <blob-meta>                  path to store nydus blob metadata\n\t\t\t\t\t--blob-offset <blob-offset>\n\t\t\t\t\t\tadd an offset for compressed blob (is only used to put the blob in the tarball) [default: 0]\n\t\t\t\n\t\t\t\t-B, --bootstrap <bootstrap>                  path to store the nydus image's metadata blob\n\t\t\t\t-M, --chunk-dict <chunk-dict>                Specify a chunk dictionary for chunk deduplication\n\t\t\t\t-S, --chunk-size <chunk-size>\n\t\t\t\t\t\tsize of nydus image data chunk, must be power of two and between 0x1000-0x100000: [default: 0x100000]\n\t\t\t\n\t\t\t\t-c, --compressor <compressor>\n\t\t\t\t\t\talgorithm to compress image data blob: [default: lz4_block]  [possible values: none, lz4_block, gzip, zstd]\n\t\t\t\n\t\t\t\t-d, --digester <digester>\n\t\t\t\t\t\talgorithm to digest inodes and data chunks: [default: blake3]  [possible values: blake3, sha256]\n\t\t\t\n\t\t\t\t-v, --fs-version <fs-version>\n\t\t\t\t\t\tversion number of nydus image format: [default: 5]  [possible values: 5, 6]\n\t\t\t\n\t\t\t\t-o, --log-file <log-file>                    Specify log file name\n\t\t\t\t-l, --log-level <log-level>\n\t\t\t\t\t\tSpecify log level: [default: info]  [possible values: trace, debug, info, warn, error]\n\t\t\t\n\t\t\t\t-J, --output-json <output-json>              JSON file output path for result\n\t\t\t\t-p, --parent-bootstrap <parent-bootstrap>    path to parent/referenced image's metadata blob (optional)\n\t\t\t\t-P, --prefetch-policy <prefetch-policy>\n\t\t\t\t\t\tblob data prefetch policy [default: none]  [possible values: fs, blob, none]\n\t\t\t\n\t\t\t\t-t, --source-type <source-type>\n\t\t\t\t\t\ttype of the source: [default: directory]  [possible values: directory, stargz_index]\n\t\t\t\n\t\t\t\t-W, --whiteout-spec <whiteout-spec>\n\t\t\t\t\t\ttype of whiteout specification: [default: oci]  [possible values: oci, overlayfs, none]\n\t\t\t\n\t\t\t\n\t\t\tARGS:\n\t\t\t\t<SOURCE>...    source path to build the nydus image from\n\t\t\t`),\n\t\t},\n\t\t{\n\t\t\tname:    \"'--batch-size' is not supported in v1.1.2\",\n\t\t\tfeature: FeatureBatchSize,\n\t\t\texpect:  false,\n\t\t\thelpMsg: []byte(`\n\t\t\tnydus-image-create \n\t\t\tCreate a nydus format accelerated container image\n\t\t\t\n\t\t\tUSAGE:\n\t\t\t\tnydus-image create [FLAGS] [OPTIONS] <SOURCE> --blob <blob> --bootstrap <bootstrap> --whiteout-spec <whiteout-spec>\n\t\t\t\n\t\t\tFLAGS:\n\t\t\t\t\t--aligned-chunk    Whether to align chunks into blobcache\n\t\t\t\t\t--disable-check    Disable to validate bootstrap file after building\n\t\t\t\t-h, --help             Prints help information\n\t\t\t\t\t--repeatable       Produce environment independent image\n\t\t\t\t-V, --version          Prints version information\n\t\t\t\n\t\t\tOPTIONS:\n\t\t\t\t\t--backend-config <backend-config>\n\t\t\t\t\t\t[deprecated!] Blob storage backend config - JSON string, only support localfs for compatibility\n\t\t\t\n\t\t\t\t\t--backend-type <backend-type>\n\t\t\t\t\t\t[deprecated!] Blob storage backend type, only support localfs for compatibility. Try use --blob instead.\n\t\t\t\t\t\t[possible values: localfs]\n\t\t\t\t\t--blob <blob>                            A path to blob file which stores nydus image data portion\n\t\t\t\t\t--blob-dir <blob-dir>\n\t\t\t\t\t\tA directory where blob files are saved named as their sha256 digest. It's very useful when multiple layers\n\t\t\t\t\t\tare built at the same time.\n\t\t\t\t\t--blob-id <blob-id>                      blob id (as object id in backend/oss)\n\t\t\t\t\t--bootstrap <bootstrap>                  A path to bootstrap file which stores nydus image metadata portion\n\t\t\t\t\t--chunk-dict <chunk-dict>\n\t\t\t\t\t\tspecify a chunk dictionary file in bootstrap/db format for chunk deduplication.\n\t\t\t\n\t\t\t\t\t--compressor <compressor>\n\t\t\t\t\t\thow blob will be compressed: none, lz4_block (default) [default: lz4_block]\n\t\t\t\n\t\t\t\t\t--digester <digester>\n\t\t\t\t\t\thow inode and blob chunk will be digested: blake3 (default), sha256 [default: blake3]\n\t\t\t\n\t\t\t\t\t--log-level <log-level>\n\t\t\t\t\t\tSpecify log level: trace, debug, info, warn, error [default: info]  [possible values: trace, debug, info,\n\t\t\t\t\t\twarn, error]\n\t\t\t\t\t--output-json <output-json>              JSON output path for build result\n\t\t\t\t\t--parent-bootstrap <parent-bootstrap>    bootstrap file path of parent (optional)\n\t\t\t\t\t--prefetch-policy <prefetch-policy>\n\t\t\t\t\t\tPrefetch policy: fs(issued from Fs layer), blob(issued from backend/blob layer), none(no readahead is\n\t\t\t\t\t\tneeded) [default: none]\n\t\t\t\t\t--source-type <source-type>\n\t\t\t\t\t\tsource type [default: directory]  [possible values: directory, stargz_index]\n\t\t\t\n\t\t\t\t\t--whiteout-spec <whiteout-spec>\n\t\t\t\t\t\tdecide which whiteout spec to follow: \"oci\" or \"overlayfs\" [default: oci]  [possible values: oci, overlayfs]\n\t\t\t\n\t\t\t\n\t\t\tARGS:\n\t\t\t\t<SOURCE>    source path\n\t\t\t`),\n\t\t},\n\t\t{\n\t\t\tname:    \"'--type tar-rafs' is not supported in v0.1.0\",\n\t\t\tfeature: FeatureTar2Rafs,\n\t\t\texpect:  false,\n\t\t\thelpMsg: []byte(`\n\t\t\tnydus-image-create \n\t\t\tdump image bootstrap and upload blob to storage backend\n\t\t\t\n\t\t\tUSAGE:\n\t\t\t\tnydus-image create [FLAGS] [OPTIONS] <SOURCE> --bootstrap <bootstrap> --whiteout-spec <whiteout-spec>\n\t\t\t\n\t\t\tFLAGS:\n\t\t\t\t\t--aligned-chunk    Whether to align chunks into blobcache\n\t\t\t\t\t--disable-check    Disable to validate bootstrap file after building\n\t\t\t\t-h, --help             Prints help information\n\t\t\t\t\t--repeatable       Produce environment independent image\n\t\t\t\t-V, --version          Prints version information\n\t\t\t\n\t\t\tOPTIONS:\n\t\t\t\t\t--backend-config <backend-config>              blob storage backend config (JSON string)\n\t\t\t\t\t--backend-config-file <backend-config-file>    blob storage backend config (JSON file)\n\t\t\t\t\t--backend-type <backend-type>                  blob storage backend type (enable blob upload if specified)\n\t\t\t\t\t--blob <blob>                                  blob file path\n\t\t\t\t\t--blob-id <blob-id>                            blob id (as object id in backend)\n\t\t\t\t\t--bootstrap <bootstrap>                        bootstrap file path (required)\n\t\t\t\t\t--compressor <compressor>\n\t\t\t\t\t\thow blob will be compressed: none, lz4_block (default) [default: lz4_block]\n\t\t\t\n\t\t\t\t\t--digester <digester>\n\t\t\t\t\t\thow inode and blob chunk will be digested: blake3 (default), sha256 [default: blake3]\n\t\t\t\n\t\t\t\t\t--log-level <log-level>\n\t\t\t\t\t\tSpecify log level: trace, debug, info, warn, error [default: info]  [possible values: trace, debug, info,\n\t\t\t\t\t\twarn, error]\n\t\t\t\t\t--output-json <output-json>                    JSON output path for build result\n\t\t\t\t\t--parent-bootstrap <parent-bootstrap>          bootstrap file path of parent (optional)\n\t\t\t\t\t--prefetch-policy <prefetch-policy>\n\t\t\t\t\t\tPrefetch policy: fs(issued from Fs layer), blob(issued from backend/blob layer), none(no readahead is\n\t\t\t\t\t\tneeded) [default: none]\n\t\t\t\t\t--source-type <source-type>\n\t\t\t\t\t\tsource type [default: directory]  [possible values: directory, stargz_index]\n\t\t\t\n\t\t\t\t\t--whiteout-spec <whiteout-spec>\n\t\t\t\t\t\tdecide which whiteout spec to follow: \"oci\" or \"overlayfs\" [default: oci]  [possible values: oci, overlayfs]\n\t\t\t\n\t\t\t\n\t\t\tARGS:\n\t\t\t\t<SOURCE>    source path\n\t\t\t`),\n\t\t},\n\t\t{\n\t\t\tname:    \"'--encrypt' is not supported in v2.2.0\",\n\t\t\tfeature: FeatureEncrypt,\n\t\t\texpect:  false,\n\t\t\thelpMsg: []byte(`\n\t\t\tCreate RAFS filesystems from directories, tar files or OCI images\n\n\t\t\tUsage: nydus-image create [OPTIONS] <SOURCE>\n\n\t\t\tArguments:\n\t\t\t<SOURCE>  source from which to build the RAFS filesystem\n\n\t\t\tOptions:\n\t\t\t-L, --log-file <log-file>\n\t\t\t\t\tLog file path\n\t\t\t-t, --type <type>\n\t\t\t\t\tConversion type: [default: dir-rafs] [possible values: directory, dir-rafs, estargz-rafs, estargz-ref, estargztoc-ref, tar-rafs, tar-tarfs, targz-rafs, targz-ref, stargz_index]\n\t\t\t-B, --bootstrap <bootstrap>\n\t\t\t\t\tFile path to save the generated RAFS metadata blob\n\t\t\t-l, --log-level <log-level>\n\t\t\t\t\tLog level: [default: info] [possible values: trace, debug, info, warn, error]\n\t\t\t-D, --blob-dir <blob-dir>\n\t\t\t\t\tDirectory path to save generated RAFS metadata and data blobs\n\t\t\t-b, --blob <blob>\n\t\t\t\t\tFile path to save the generated RAFS data blob\n\t\t\t\t--blob-inline-meta\n\t\t\t\t\tInline RAFS metadata and blob metadata into the data blob\n\t\t\t\t--blob-id <blob-id>\n\t\t\t\t\tOSS object id for the generated RAFS data blob\n\t\t\t\t--blob-data-size <blob-data-size>\n\t\t\t\t\tSet data blob size for 'estargztoc-ref' conversion\n\t\t\t\t--chunk-size <chunk-size>\n\t\t\t\t\tSet the size of data chunks, must be power of two and between 0x1000-0x1000000:\n\t\t\t\t--batch-size <batch-size>\n\t\t\t\t\tSet the batch size to merge small chunks, must be power of two, between 0x1000-0x1000000 or be zero: [default: 0]\n\t\t\t\t--compressor <compressor>\n\t\t\t\t\tAlgorithm to compress data chunks: [default: zstd] [possible values: none, lz4_block, zstd]\n\t\t\t\t--digester <digester>\n\t\t\t\t\tAlgorithm to digest data chunks: [default: blake3] [possible values: blake3, sha256]\n\t\t\t-C, --config <config>\n\t\t\t\t\tConfiguration file for storage backend, cache and RAFS FUSE filesystem.\n\t\t\t-v, --fs-version <fs-version>\n\t\t\t\t\tSet RAFS format version number: [default: 6] [possible values: 5, 6]\n\t\t\t\t--features <features>\n\t\t\t\t\tEnable/disable features [possible values: blob-toc]\n\t\t\t\t--chunk-dict <chunk-dict>\n\t\t\t\t\tFile path of chunk dictionary for data deduplication\n\t\t\t\t--parent-bootstrap <parent-bootstrap>\n\t\t\t\t\tFile path of the parent/referenced RAFS metadata blob (optional)\n\t\t\t\t--aligned-chunk\n\t\t\t\t\tAlign uncompressed data chunks to 4K, only for RAFS V5\n\t\t\t\t--repeatable\n\t\t\t\t\tGenerate reproducible RAFS metadata\n\t\t\t\t--whiteout-spec <whiteout-spec>\n\t\t\t\t\tSet the type of whiteout specification: [default: oci] [possible values: oci, overlayfs, none]\n\t\t\t\t--prefetch-policy <prefetch-policy>\n\t\t\t\t\tSet data prefetch policy [default: none] [possible values: fs, blob, none]\n\t\t\t-J, --output-json <output-json>\n\t\t\t\t\tFile path to save operation result in JSON format\n\t\t\t-h, --help\n\t\t\t\t\tPrint help information\n\t\t\t`),\n\t\t},\n\t\t{\n\t\t\tname:    \"detectFeature should support empty input\",\n\t\t\tfeature: \"\",\n\t\t\texpect:  false,\n\t\t\thelpMsg: []byte(`\n\t\t\tOPTIONS:\n\t\t\t\t\t--type <type>\n\t\t\t\t\t\t[deprecated!] Conversion type.\n\t\t\t\t\t\t[possible values: tar-rafs]\n\t\t\t`),\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\trequire.Equal(t, tt.expect, detectFeature(tt.helpMsg, tt.feature))\n\t\t})\n\t}\n}\n\nfunc TestDetectFeatures(t *testing.T) {\n\ttestsCompare := []struct {\n\t\tname            string\n\t\tresetGlobal     bool\n\t\tdisableTar2Rafs bool\n\t\thelpText        []byte\n\t\trequired        Features\n\t\tdetected        Features\n\t\texpectErr       bool\n\t}{\n\t\t{\n\t\t\tname:            \"should satisfy required features in v2.2.0-239-gf5c08fcf\",\n\t\t\tresetGlobal:     true,\n\t\t\tdisableTar2Rafs: false,\n\t\t\thelpText: []byte(`\n\t\t\tOptions:\n\t\t\t  -t, --type <type>\n\t\t\t\t\t  Conversion type: [default: dir-rafs] [possible values: directory, dir-rafs, estargz-rafs, estargz-ref, estargztoc-ref, tar-rafs, tar-tarfs, targz-rafs, targz-ref, stargz_index]\n\t\t\t\t  --batch-size <batch-size>\n\t\t\t\t\t  Set the batch size to merge small chunks, must be power of two, between 0x1000-0x1000000 or be zero: [default: 0]\n\t\t\t`),\n\t\t\trequired:  Features{FeatureTar2Rafs: {}, FeatureBatchSize: {}},\n\t\t\tdetected:  Features{FeatureTar2Rafs: {}, FeatureBatchSize: {}},\n\t\t\texpectErr: false,\n\t\t},\n\t\t{\n\t\t\tname:            \"should not support '--encrypt', '--batch-size' or '--type tar-rafs' in v2.1.4\",\n\t\t\tresetGlobal:     true,\n\t\t\tdisableTar2Rafs: true,\n\t\t\thelpText: []byte(`\n\t\t\tnydus-image-create \n\t\t\tCreates a nydus image from source\n\t\t\t\n\t\t\tUSAGE:\n\t\t\t\tnydus-image create [FLAGS] [OPTIONS] <SOURCE>... --blob <blob> --bootstrap <bootstrap> --fs-version <fs-version> --whiteout-spec <whiteout-spec>\n\t\t\t\n\t\t\tFLAGS:\n\t\t\t\t-A, --aligned-chunk       Align data chunks to 4K\n\t\t\t\t\t--disable-check       disable validation of metadata after building\n\t\t\t\t-h, --help                Prints help information\n\t\t\t\t\t--inline-bootstrap    append bootstrap data to blob\n\t\t\t\t-R, --repeatable          generate reproducible nydus image\n\t\t\t\t-V, --version             Prints version information\n\t\t\t\n\t\t\tOPTIONS:\n\t\t\t\t\t--backend-config <backend-config>\n\t\t\t\t\t\t[deprecated!] Blob storage backend config - JSON string, only support localfs for compatibility\n\t\t\t\n\t\t\t\t\t--backend-type <backend-type>\n\t\t\t\t\t\t[deprecated!] Blob storage backend type, only support localfs for compatibility. Try use --blob instead.\n\t\t\t\t\t\t[possible values: localfs]\n\t\t\t\t-b, --blob <blob>                            path to store nydus image's data blob\n\t\t\t\t-D, --blob-dir <blob-dir>                    directory to store nydus image's metadata and data blob\n\t\t\t\t\t--blob-id <blob-id>                      blob id (as object id in backend/oss)\n\t\t\t\t\t--blob-meta <blob-meta>                  path to store nydus blob metadata\n\t\t\t\t\t--blob-offset <blob-offset>\n\t\t\t\t\t\tadd an offset for compressed blob (is only used to put the blob in the tarball) [default: 0]\n\t\t\t\n\t\t\t\t-B, --bootstrap <bootstrap>                  path to store the nydus image's metadata blob\n\t\t\t\t-M, --chunk-dict <chunk-dict>                Specify a chunk dictionary for chunk deduplication\n\t\t\t\t-S, --chunk-size <chunk-size>\n\t\t\t\t\t\tsize of nydus image data chunk, must be power of two and between 0x1000-0x100000: [default: 0x100000]\n\t\t\t\n\t\t\t\t-c, --compressor <compressor>\n\t\t\t\t\t\talgorithm to compress image data blob: [default: lz4_block]  [possible values: none, lz4_block, gzip, zstd]\n\t\t\t\n\t\t\t\t-d, --digester <digester>\n\t\t\t\t\t\talgorithm to digest inodes and data chunks: [default: blake3]  [possible values: blake3, sha256]\n\t\t\t\n\t\t\t\t-v, --fs-version <fs-version>\n\t\t\t\t\t\tversion number of nydus image format: [default: 5]  [possible values: 5, 6]\n\t\t\t\n\t\t\t\t-o, --log-file <log-file>                    Specify log file name\n\t\t\t\t-l, --log-level <log-level>\n\t\t\t\t\t\tSpecify log level: [default: info]  [possible values: trace, debug, info, warn, error]\n\t\t\t\n\t\t\t\t-J, --output-json <output-json>              JSON file output path for result\n\t\t\t\t-p, --parent-bootstrap <parent-bootstrap>    path to parent/referenced image's metadata blob (optional)\n\t\t\t\t-P, --prefetch-policy <prefetch-policy>\n\t\t\t\t\t\tblob data prefetch policy [default: none]  [possible values: fs, blob, none]\n\t\t\t\n\t\t\t\t-t, --source-type <source-type>\n\t\t\t\t\t\ttype of the source: [default: directory]  [possible values: directory, stargz_index]\n\t\t\t\n\t\t\t\t-W, --whiteout-spec <whiteout-spec>\n\t\t\t\t\t\ttype of whiteout specification: [default: oci]  [possible values: oci, overlayfs, none]\n\t\t\t\n\t\t\t\n\t\t\tARGS:\n\t\t\t\t<SOURCE>...    source path to build the nydus image from\n\t\t\t`),\n\t\t\trequired:  Features{FeatureTar2Rafs: {}, FeatureBatchSize: {}, FeatureEncrypt: {}},\n\t\t\tdetected:  Features{},\n\t\t\texpectErr: false,\n\t\t},\n\t\t{\n\t\t\tname:            \"should ignore '--type tar-rafs' if disabled\",\n\t\t\tresetGlobal:     true,\n\t\t\tdisableTar2Rafs: true,\n\t\t\thelpText: []byte(`\n\t\t\tOptions:\n\t\t\t  -t, --type <type>\n\t\t\t\t\t  Conversion type: [default: dir-rafs] [possible values: directory, dir-rafs, estargz-rafs, estargz-ref, estargztoc-ref, tar-rafs, tar-tarfs, targz-rafs, targz-ref, stargz_index]\n\t\t\t\t  --batch-size <batch-size>\n\t\t\t\t\t  Set the batch size to merge small chunks, must be power of two, between 0x1000-0x1000000 or be zero: [default: 0]\n\t\t\t`),\n\t\t\trequired:  Features{FeatureTar2Rafs: {}, FeatureBatchSize: {}},\n\t\t\tdetected:  Features{FeatureBatchSize: {}},\n\t\t\texpectErr: false,\n\t\t},\n\t\t{\n\t\t\tname:            \"should return error if required features changed in different calls\",\n\t\t\tresetGlobal:     false,\n\t\t\tdisableTar2Rafs: false,\n\t\t\thelpText:        nil,\n\t\t\trequired:        Features{},\n\t\t\tdetected:        nil,\n\t\t\texpectErr:       true,\n\t\t},\n\t}\n\tfor _, tt := range testsCompare {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif tt.resetGlobal {\n\t\t\t\t// Reset global variables.\n\t\t\t\trequiredFeatures = Features{}\n\t\t\t\tdetectedFeatures = Features{}\n\t\t\t\tdetectFeaturesOnce = sync.Once{}\n\t\t\t\tdisableTar2Rafs = tt.disableTar2Rafs\n\t\t\t}\n\t\t\tdetected, err := DetectFeatures(\"\", tt.required, func(_ string) []byte { return tt.helpText })\n\t\t\trequire.Equal(t, tt.expectErr, err != nil)\n\t\t\trequire.Equal(t, tt.detected, detected)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/converter/types.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage converter\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/converter/tool\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\ntype Compressor = uint32\n\ntype Encrypter = func(context.Context, content.Store, ocispec.Descriptor) (ocispec.Descriptor, error)\n\nconst (\n\tCompressorNone     Compressor = 0x0000_0001\n\tCompressorZstd     Compressor = 0x0000_0002\n\tCompressorLz4Block Compressor = 0x0000_0004\n\tCompressorMask     Compressor = 0x0000_000f\n)\n\nvar (\n\tErrNotFound = errors.New(\"data not found\")\n)\n\ntype Layer struct {\n\t// Digest represents the hash of whole tar blob.\n\tDigest digest.Digest\n\t// Digest represents the original OCI tar(.gz) blob.\n\tOriginalDigest *digest.Digest\n\t// ReaderAt holds the reader of whole tar blob.\n\tReaderAt content.ReaderAt\n}\n\n// Backend uploads blobs generated by nydus-image builder to a backend storage.\ntype Backend interface {\n\t// Push pushes specified blob file to remote storage backend.\n\tPush(ctx context.Context, cs content.Store, desc ocispec.Descriptor) error\n\t// Check checks whether a blob exists in remote storage backend,\n\t// blob exists -> return (blobPath, nil)\n\t// blob not exists -> return (\"\", err)\n\tCheck(blobDigest digest.Digest) (string, error)\n\t// Type returns backend type name.\n\tType() string\n}\n\ntype PackOption struct {\n\t// WorkDir is used as the work directory during layer pack.\n\tWorkDir string\n\t// BuilderPath holds the path of `nydus-image` binary tool.\n\tBuilderPath string\n\t// FsVersion specifies nydus RAFS format version, possible\n\t// values: `5`, `6` (EROFS-compatible), default is `6`.\n\tFsVersion string\n\t// ChunkDictPath holds the bootstrap path of chunk dict image.\n\tChunkDictPath string\n\t// PrefetchPatterns holds file path pattern list want to prefetch.\n\tPrefetchPatterns string\n\t// Compressor specifies nydus blob compression algorithm.\n\tCompressor string\n\t// OCIRef enables converting OCI tar(.gz) blob to nydus referenced blob.\n\tOCIRef bool\n\t// AlignedChunk aligns uncompressed data chunks to 4K, only for RAFS V5.\n\tAlignedChunk bool\n\t// ChunkSize sets the size of data chunks, must be power of two and between 0x1000-0x1000000.\n\tChunkSize string\n\t// BacthSize sets the size of batch data chunks, must be power of two and between 0x1000-0x1000000 or zero.\n\tBatchSize string\n\t// Backend uploads blobs generated by nydus-image builder to a backend storage.\n\tBackend Backend\n\t// Timeout cancels execution once exceed the specified time.\n\tTimeout *time.Duration\n\t// Whether the generated Nydus blobs should be encrypted.\n\tEncrypt bool\n\n\t// Features keeps a feature list supported by newer version of builder,\n\t// It is detected automatically, so don't export it.\n\tfeatures tool.Features\n}\n\ntype MergeOption struct {\n\t// WorkDir is used as the work directory during layer merge.\n\tWorkDir string\n\t// BuilderPath holds the path of `nydus-image` binary tool.\n\tBuilderPath string\n\t// FsVersion specifies nydus RAFS format version, possible\n\t// values: `5`, `6` (EROFS-compatible), default is `6`.\n\tFsVersion string\n\t// ChunkDictPath holds the bootstrap path of chunk dict image.\n\tChunkDictPath string\n\t// ParentBootstrapPath holds the bootstrap path of parent image.\n\tParentBootstrapPath string\n\t// PrefetchPatterns holds file path pattern list want to prefetch.\n\tPrefetchPatterns string\n\t// WithTar puts bootstrap into a tar stream (no gzip).\n\tWithTar bool\n\t// OCI converts docker media types to OCI media types.\n\tOCI bool\n\t// OCIRef enables converting OCI tar(.gz) blob to nydus referenced blob.\n\tOCIRef bool\n\t// WithReferrer associates a reference to the original OCI manifest.\n\t// See the `subject` field description in\n\t// https://github.com/opencontainers/image-spec/blob/main/manifest.md#image-manifest-property-descriptions\n\t//\n\t// With this association, we can track all nydus images associated with\n\t// an OCI image. For example, in Harbor we can cascade to show nydus\n\t// images linked to an OCI image, deleting the OCI image can also delete\n\t// the corresponding nydus images. At runtime, nydus snapshotter can also\n\t// automatically upgrade an OCI image run to nydus image.\n\tWithReferrer bool\n\t// Backend uploads blobs generated by nydus-image builder to a backend storage.\n\tBackend Backend\n\t// Timeout cancels execution once exceed the specified time.\n\tTimeout *time.Duration\n\t// Encrypt encrypts the bootstrap layer if it's specified.\n\tEncrypt Encrypter\n\t// AppendFiles specifies the files that need to be appended to the bootstrap layer.\n\tAppendFiles []File\n\t// MergeManifest indicates that the resulting nydus manifest will be merged with the original\n\t// OCI one into a single index manifest.\n\tMergeManifest bool\n}\n\ntype UnpackOption struct {\n\t// WorkDir is used as the work directory during layer unpack.\n\tWorkDir string\n\t// BuilderPath holds the path of `nydus-image` binary tool.\n\tBuilderPath string\n\t// Timeout cancels execution once exceed the specified time.\n\tTimeout *time.Duration\n\t// Stream enables streaming mode, which doesn't unpack the blob data to disk,\n\t// but setup a http server to serve the blob data.\n\tStream bool\n\t// Compressor specifies oci blob compression algorithm.\n\t// Supported values: \"uncompressed\" (no compression), \"gzip\", \"zstd\".\n\t// Defaults to \"gzip\" if not specified.\n\tCompressor string\n\t// Backend uploads blobs generated by oci-image builder to a backend storage.\n\tBackend Backend\n}\n\ntype TOCEntry struct {\n\t// Feature flags of entry\n\tFlags     uint32\n\tReserved1 uint32\n\t// Name of entry data\n\tName [16]byte\n\t// Sha256 of uncompressed entry data\n\tUncompressedDigest [32]byte\n\t// Offset of compressed entry data\n\tCompressedOffset uint64\n\t// Size of compressed entry data\n\tCompressedSize uint64\n\t// Size of uncompressed entry data\n\tUncompressedSize uint64\n\tReserved2        [44]byte\n}\n\nfunc (entry *TOCEntry) GetCompressor() (Compressor, error) {\n\tswitch entry.Flags & CompressorMask {\n\tcase CompressorNone:\n\t\treturn CompressorNone, nil\n\tcase CompressorZstd:\n\t\treturn CompressorZstd, nil\n\tcase CompressorLz4Block:\n\t\treturn CompressorLz4Block, nil\n\t}\n\treturn 0, fmt.Errorf(\"unsupported compressor, entry flags %x\", entry.Flags)\n}\n\nfunc (entry *TOCEntry) GetName() string {\n\tvar name strings.Builder\n\tname.Grow(16)\n\tfor _, c := range entry.Name {\n\t\tif c == 0 {\n\t\t\tbreak\n\t\t}\n\t\tfmt.Fprintf(&name, \"%c\", c)\n\t}\n\treturn name.String()\n}\n\nfunc (entry *TOCEntry) GetUncompressedDigest() string {\n\treturn fmt.Sprintf(\"%x\", entry.UncompressedDigest)\n}\n\nfunc (entry *TOCEntry) GetCompressedOffset() uint64 {\n\treturn entry.CompressedOffset\n}\n\nfunc (entry *TOCEntry) GetCompressedSize() uint64 {\n\treturn entry.CompressedSize\n}\n\nfunc (entry *TOCEntry) GetUncompressedSize() uint64 {\n\treturn entry.UncompressedSize\n}\n"
  },
  {
    "path": "pkg/converter/utils.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage converter\n\nimport (\n\t\"archive/tar\"\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"path/filepath\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\ntype File struct {\n\tName   string\n\tReader io.Reader\n\tSize   int64\n}\n\ntype writeCloser struct {\n\tclosed bool\n\tio.WriteCloser\n\taction func() error\n}\n\nfunc (c *writeCloser) Close() error {\n\tif c.closed {\n\t\treturn nil\n\t}\n\n\tif err := c.WriteCloser.Close(); err != nil {\n\t\treturn err\n\t}\n\tc.closed = true\n\n\tif err := c.action(); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc newWriteCloser(wc io.WriteCloser, action func() error) *writeCloser {\n\treturn &writeCloser{\n\t\tWriteCloser: wc,\n\t\taction:      action,\n\t}\n}\n\ntype seekReader struct {\n\tio.ReaderAt\n\tpos int64\n}\n\nfunc (ra *seekReader) Read(p []byte) (int, error) {\n\tn, err := ra.ReadAt(p, ra.pos)\n\tra.pos += int64(n)\n\treturn n, err\n}\n\nfunc (ra *seekReader) Seek(offset int64, whence int) (int64, error) {\n\tswitch whence {\n\tcase io.SeekCurrent:\n\t\tra.pos += offset\n\tcase io.SeekStart:\n\t\tra.pos = offset\n\tdefault:\n\t\treturn 0, fmt.Errorf(\"unsupported whence %d\", whence)\n\t}\n\n\treturn ra.pos, nil\n}\n\nfunc newSeekReader(ra io.ReaderAt) *seekReader {\n\treturn &seekReader{\n\t\tReaderAt: ra,\n\t\tpos:      0,\n\t}\n}\n\n// packToTar packs files to .tar(.gz) stream then return reader.\nfunc packToTar(files []File, compress bool) io.ReadCloser {\n\tdirHdr := &tar.Header{\n\t\tName:     \"image\",\n\t\tMode:     0755,\n\t\tTypeflag: tar.TypeDir,\n\t}\n\n\tpr, pw := io.Pipe()\n\n\tgo func() {\n\t\t// Prepare targz writer\n\t\tvar tw *tar.Writer\n\t\tvar gw *gzip.Writer\n\t\tvar err error\n\n\t\tif compress {\n\t\t\tgw = gzip.NewWriter(pw)\n\t\t\ttw = tar.NewWriter(gw)\n\t\t} else {\n\t\t\ttw = tar.NewWriter(pw)\n\t\t}\n\n\t\tdefer func() {\n\t\t\terr1 := tw.Close()\n\t\t\tvar err2 error\n\t\t\tif gw != nil {\n\t\t\t\terr2 = gw.Close()\n\t\t\t}\n\n\t\t\tvar finalErr error\n\n\t\t\t// Return the first error encountered to the other end and ignore others.\n\t\t\tswitch {\n\t\t\tcase err != nil:\n\t\t\t\tfinalErr = err\n\t\t\tcase err1 != nil:\n\t\t\t\tfinalErr = err1\n\t\t\tcase err2 != nil:\n\t\t\t\tfinalErr = err2\n\t\t\t}\n\n\t\t\tpw.CloseWithError(finalErr)\n\t\t}()\n\n\t\t// Write targz stream\n\t\tif err = tw.WriteHeader(dirHdr); err != nil {\n\t\t\treturn\n\t\t}\n\n\t\tfor _, file := range files {\n\t\t\thdr := tar.Header{\n\t\t\t\tName: filepath.Join(\"image\", file.Name),\n\t\t\t\tMode: 0444,\n\t\t\t\tSize: file.Size,\n\t\t\t}\n\t\t\tif err = tw.WriteHeader(&hdr); err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif _, err = io.Copy(tw, file.Reader); err != nil {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}()\n\n\treturn pr\n}\n\n// Copied from containerd/containerd project, copyright The containerd Authors.\n// https://github.com/containerd/containerd/blob/4902059cb554f4f06a8d06a12134c17117809f4e/images/converter/default.go#L385\nfunc readJSON(ctx context.Context, cs content.Store, x interface{}, desc ocispec.Descriptor) (map[string]string, error) {\n\tinfo, err := cs.Info(ctx, desc.Digest)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlabels := info.Labels\n\tif labels == nil {\n\t\tlabels = map[string]string{}\n\t}\n\tb, err := content.ReadBlob(ctx, cs, desc)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := json.Unmarshal(b, x); err != nil {\n\t\treturn nil, err\n\t}\n\treturn labels, nil\n}\n\n// Copied from containerd/containerd project, copyright The containerd Authors.\n// https://github.com/containerd/containerd/blob/4902059cb554f4f06a8d06a12134c17117809f4e/images/converter/default.go#L401\nfunc writeJSON(ctx context.Context, cs content.Store, x interface{}, oldDesc ocispec.Descriptor, labels map[string]string) (*ocispec.Descriptor, error) {\n\tb, err := json.Marshal(x)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdgst := digest.SHA256.FromBytes(b)\n\tref := fmt.Sprintf(\"converter-write-json-%s\", dgst.String())\n\tw, err := content.OpenWriter(ctx, cs, content.WithRef(ref))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := content.Copy(ctx, w, bytes.NewReader(b), int64(len(b)), dgst, content.WithLabels(labels)); err != nil {\n\t\treturn nil, err\n\t}\n\tif err := w.Close(); err != nil {\n\t\treturn nil, err\n\t}\n\tnewDesc := oldDesc\n\tnewDesc.Size = int64(len(b))\n\tnewDesc.Digest = dgst\n\treturn &newDesc, nil\n}\n"
  },
  {
    "path": "pkg/daemon/client.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemon\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/tool\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/retry\"\n)\n\nconst (\n\t// Get information about nydus daemon\n\tendpointDaemonInfo = \"/api/v1/daemon\"\n\t// Mount or umount filesystems.\n\tendpointMount = \"/api/v1/mount\"\n\t// Fetch generic filesystem metrics.\n\tendpointMetrics = \"/api/v1/metrics\"\n\t// Fetch metrics relevant to caches usage.\n\tendpointCacheMetrics = \"/api/v1/metrics/blobcache\"\n\t// Fetch metrics about inflighting operations.\n\tendpointInflightMetrics = \"/api/v1/metrics/inflight\"\n\t// Request nydus daemon to retrieve its runtime states from the supervisor, recovering states for failover.\n\tendpointTakeOver = \"/api/v1/daemon/fuse/takeover\"\n\t// Request nydus daemon to send its runtime states to the supervisor, preparing for failover.\n\tendpointSendFd = \"/api/v1/daemon/fuse/sendfd\"\n\t// Request nydus daemon to start filesystem service.\n\tendpointStart = \"/api/v1/daemon/start\"\n\t// Request nydus daemon to exit\n\tendpointExit = \"/api/v1/daemon/exit\"\n\t// Update daemon configuration at runtime.\n\tendpointConfig = \"/api/v1/config\"\n\n\t// --- V2 API begins\n\t// Add/remove blobs managed by the blob cache manager.\n\tendpointBlobs = \"/api/v2/blobs\"\n\n\tdefaultHTTPClientTimeout = 30 * time.Second\n\n\tjsonContentType = \"application/json\"\n)\n\n// Nydusd HTTP client to query nydusd runtime status, operate file system instances.\n// Control nydusd workflow like failover and upgrade.\ntype NydusdClient interface {\n\tGetDaemonInfo() (*types.DaemonInfo, error)\n\n\tMount(mountpoint, bootstrap, daemonConfig string) error\n\tUmount(mountpoint string) error\n\n\tBindBlob(daemonConfig string) error\n\tUnbindBlob(domainID, blobID string) error\n\n\tGetFsMetrics(sid string) (*types.FsMetrics, error)\n\tGetInflightMetrics() (*types.InflightMetrics, error)\n\tGetCacheMetrics(sid string) (*types.CacheMetrics, error)\n\n\tUpdateConfig(id string, params map[string]string) error\n\n\tTakeOver() error\n\tSendFd() error\n\tStart() error\n\tExit() error\n}\n\n// Nydusd API server http client used to command nydusd's action and\n// query nydusd working status.\ntype nydusdClient struct {\n\thttpClient *http.Client\n}\n\ntype query = url.Values\n\nfunc (c *nydusdClient) url(path string, query query) (url string) {\n\turl = fmt.Sprintf(\"http://unix%s\", path)\n\n\tif len(query) != 0 {\n\t\turl += \"?\" + query.Encode()\n\t}\n\n\treturn\n}\n\n// A simple http client request wrapper with capability to take\n// request body and handle or process http response if result is expected.\nfunc (c *nydusdClient) request(method string, url string,\n\tbody io.Reader, respHandler func(resp *http.Response) error) error {\n\n\treq, err := http.NewRequest(method, url, body)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"construct request %s\", url)\n\t}\n\n\tif body != nil {\n\t\treq.Header.Add(\"Content-Type\", jsonContentType)\n\t}\n\n\tresp, err := c.httpClient.Do(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\tif succeeded(resp) {\n\t\tif respHandler != nil {\n\t\t\tif err = respHandler(resp); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"handle response\")\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\treturn parseErrorMessage(resp)\n}\n\nfunc succeeded(resp *http.Response) bool {\n\treturn resp.StatusCode == http.StatusNoContent || resp.StatusCode == http.StatusOK\n}\n\nfunc decode(resp *http.Response, v any) error {\n\tif err := json.NewDecoder(resp.Body).Decode(&v); err != nil {\n\t\treturn errors.Wrap(err, \"decode response\")\n\t}\n\n\treturn nil\n}\n\n// Parse http response to get the specific error message formatted by nydusd API server.\n// So it will be clear what's wrong in nydusd during processing http requests.\nfunc parseErrorMessage(resp *http.Response) error {\n\tvar errMessage types.ErrorMessage\n\terr := decode(resp, &errMessage)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn errors.Errorf(\"http response: %d, error code: %s, error message: %s\",\n\t\tresp.StatusCode, errMessage.Code, errMessage.Message)\n}\n\nfunc buildTransport(sock string) http.RoundTripper {\n\treturn &http.Transport{\n\t\tMaxIdleConns:          10,\n\t\tIdleConnTimeout:       10 * time.Second,\n\t\tExpectContinueTimeout: 1 * time.Second,\n\t\tDialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {\n\t\t\tdialer := &net.Dialer{\n\t\t\t\tTimeout:   5 * time.Second,\n\t\t\t\tKeepAlive: 5 * time.Second,\n\t\t\t}\n\t\t\treturn dialer.DialContext(ctx, \"unix\", sock)\n\t\t},\n\t}\n}\n\nfunc WaitUntilSocketExisted(sock string, pid int) error {\n\treturn retry.Do(func() (err error) {\n\t\tvar st fs.FileInfo\n\t\tif st, err = os.Stat(sock); err != nil {\n\t\t\treturn\n\t\t}\n\n\t\tif st.Mode()&os.ModeSocket == 0 {\n\t\t\treturn errors.Errorf(\"file %s is not socket file\", sock)\n\t\t}\n\n\t\treturn nil\n\t},\n\t\tretry.Attempts(100), // totally wait for 10 seconds, should be enough\n\t\tretry.LastErrorOnly(true),\n\t\tretry.Delay(100*time.Millisecond),\n\t\tretry.OnlyRetryIf(func(error) bool {\n\t\t\tzombie, err := tool.IsZombieProcess(pid)\n\t\t\tif err != nil {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Stop retry if nydus daemon process is already in Zombie state.\n\t\t\tif zombie {\n\t\t\t\tlog.L.Errorf(\"Process %d has been a zombie\", pid)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn false\n\t\t}),\n\t)\n}\n\nfunc NewNydusClient(sock string) (NydusdClient, error) {\n\ttransport := buildTransport(sock)\n\treturn &nydusdClient{\n\t\thttpClient: &http.Client{\n\t\t\tTimeout:   defaultHTTPClientTimeout,\n\t\t\tTransport: transport,\n\t\t},\n\t}, nil\n}\n\nfunc (c *nydusdClient) GetDaemonInfo() (*types.DaemonInfo, error) {\n\turl := c.url(endpointDaemonInfo, query{})\n\n\tvar info types.DaemonInfo\n\terr := c.request(http.MethodGet, url, nil, func(resp *http.Response) error {\n\t\tif err := decode(resp, &info); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &info, nil\n}\n\nfunc (c *nydusdClient) Mount(mp, bootstrap, mountConfig string) error {\n\tcmd, err := json.Marshal(types.NewMountRequest(bootstrap, mountConfig))\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"construct mount request\")\n\t}\n\n\tquery := query{}\n\tquery.Add(\"mountpoint\", mp)\n\turl := c.url(endpointMount, query)\n\n\treturn c.request(http.MethodPost, url, bytes.NewBuffer(cmd), nil)\n}\n\nfunc (c *nydusdClient) Umount(mp string) error {\n\tquery := query{}\n\tquery.Add(\"mountpoint\", mp)\n\turl := c.url(endpointMount, query)\n\treturn c.request(http.MethodDelete, url, nil, nil)\n}\n\nfunc (c *nydusdClient) BindBlob(daemonConfig string) error {\n\turl := c.url(endpointBlobs, query{})\n\treturn c.request(http.MethodPut, url, bytes.NewBuffer([]byte(daemonConfig)), nil)\n}\n\n// Delete /api/v2/blobs implements different functions according to different parameters\n//  1. domainID , delete all blob entries in the domain.\n//  2. domainID + blobID, delete the blob entry, if the blob is bootstrap\n//     also delete blob entries belong to it.\n//  3. blobID, try to find and cull blob cache files by blobID in all domains.\nfunc (c *nydusdClient) UnbindBlob(domainID, blobID string) error {\n\tquery := query{}\n\tif domainID != \"\" {\n\t\tquery.Add(\"domain_id\", domainID)\n\t\tif domainID != blobID {\n\t\t\tquery.Add(\"blob_id\", blobID)\n\t\t}\n\t} else {\n\t\tquery.Add(\"blob_id\", blobID)\n\t}\n\n\turl := c.url(endpointBlobs, query)\n\n\treturn c.request(http.MethodDelete, url, nil, nil)\n}\n\nfunc (c *nydusdClient) GetFsMetrics(sid string) (*types.FsMetrics, error) {\n\tquery := query{}\n\tif sid != \"\" {\n\t\tquery.Add(\"id\", \"/\"+sid)\n\t}\n\n\turl := c.url(endpointMetrics, query)\n\tvar m types.FsMetrics\n\tif err := c.request(http.MethodGet, url, nil, func(resp *http.Response) error {\n\t\treturn decode(resp, &m)\n\t}); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &m, nil\n}\n\nfunc (c *nydusdClient) GetInflightMetrics() (*types.InflightMetrics, error) {\n\turl := c.url(endpointInflightMetrics, query{})\n\tvar m types.InflightMetrics\n\tif err := c.request(http.MethodGet, url, nil, func(resp *http.Response) error {\n\t\tif resp.StatusCode != http.StatusNoContent {\n\t\t\treturn decode(resp, &m.Values)\n\t\t}\n\t\treturn nil\n\t}); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &m, nil\n}\n\nfunc (c *nydusdClient) GetCacheMetrics(sid string) (*types.CacheMetrics, error) {\n\tquery := query{}\n\tif sid != \"\" {\n\t\tquery.Add(\"id\", \"/\"+sid)\n\t}\n\n\turl := c.url(endpointCacheMetrics, query)\n\tvar m types.CacheMetrics\n\tif err := c.request(http.MethodGet, url, nil, func(resp *http.Response) error {\n\t\treturn decode(resp, &m)\n\t}); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &m, nil\n}\n\nfunc (c *nydusdClient) UpdateConfig(id string, params map[string]string) error {\n\tbody, err := json.Marshal(params)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"marshal config params\")\n\t}\n\n\tq := query{}\n\tq.Add(\"id\", id)\n\turl := c.url(endpointConfig, q)\n\n\treturn c.request(http.MethodPut, url, bytes.NewBuffer(body), nil)\n}\n\nfunc (c *nydusdClient) TakeOver() error {\n\turl := c.url(endpointTakeOver, query{})\n\treturn c.request(http.MethodPut, url, nil, nil)\n}\n\nfunc (c *nydusdClient) SendFd() error {\n\turl := c.url(endpointSendFd, query{})\n\treturn c.request(http.MethodPut, url, nil, nil)\n}\n\nfunc (c *nydusdClient) Start() error {\n\turl := c.url(endpointStart, query{})\n\treturn c.request(http.MethodPut, url, nil, nil)\n}\n\nfunc (c *nydusdClient) Exit() error {\n\turl := c.url(endpointExit, query{})\n\treturn c.request(http.MethodPut, url, nil, nil)\n}\n"
  },
  {
    "path": "pkg/daemon/client_test.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemon\n\nimport (\n\t\"encoding/json\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n)\n\nvar BTI = types.BuildTimeInfo{\n\tPackageVer: \"1.1.0\",\n\tGitCommit:  \"67f4ecc7acee6dd37234e6a697e72ac09d6cc8ba\",\n\tBuildTime:  \"Thu, 28 Jan 2021 14:02:39 +0000\",\n\tProfile:    \"debug\",\n\tRustc:      \"rustc 1.46.0 (04488afe3 2020-08-24)\",\n}\n\nfunc prepareNydusServer(t *testing.T) (string, func()) {\n\tdir, _ := os.MkdirTemp(\"\", \"nydus-snapshotter-test\")\n\tmockSocket := filepath.Join(dir, \"nydusd.sock\")\n\n\t_, err := os.Stat(mockSocket)\n\tif err == nil {\n\t\t_ = os.Remove(mockSocket)\n\t}\n\tts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {\n\t\tw.WriteHeader(200)\n\t\tinfo := types.DaemonInfo{\n\t\t\tID:      \"testid\",\n\t\t\tVersion: BTI,\n\t\t\tState:   \"RUNNING\",\n\t\t}\n\t\tw.Header().Set(\"Content-Type\", \"application/json\")\n\t\tj, _ := json.Marshal(info)\n\t\t_, err := w.Write(j)\n\t\tassert.Nil(t, err)\n\t}))\n\tunixListener, err := net.Listen(\"unix\", mockSocket)\n\trequire.Nil(t, err)\n\tts.Listener = unixListener\n\tts.Start()\n\treturn mockSocket, func() {\n\t\tts.Close()\n\t}\n}\n\nfunc TestNydusClient_CheckStatus(t *testing.T) {\n\tsock, dispose := prepareNydusServer(t)\n\tdefer dispose()\n\tclient, err := NewNydusClient(sock)\n\trequire.Nil(t, err)\n\tinfo, err := client.GetDaemonInfo()\n\trequire.Nil(t, err)\n\tassert.Equal(t, info.DaemonState(), types.DaemonStateRunning)\n\tassert.Equal(t, \"testid\", info.ID)\n\tassert.Equal(t, BTI, info.Version)\n}\n\nfunc TestUpdateConfig(t *testing.T) {\n\ttests := []struct {\n\t\tname       string\n\t\tid         string\n\t\tparams     map[string]string\n\t\tstatusCode int\n\t\trespBody   string\n\t\twantErr    bool\n\t}{\n\t\t{\n\t\t\tname:       \"shared daemon with snapshot ID\",\n\t\t\tid:         \"/snap-1\",\n\t\t\tparams:     map[string]string{\"registry_auth\": \"dXNlcjpwYXNz\"},\n\t\t\tstatusCode: http.StatusNoContent,\n\t\t},\n\t\t{\n\t\t\tname:       \"dedicated daemon with root ID\",\n\t\t\tid:         \"/\",\n\t\t\tparams:     map[string]string{\"registry_auth\": \"dXNlcjpwYXNz\"},\n\t\t\tstatusCode: http.StatusNoContent,\n\t\t},\n\t\t{\n\t\t\tname:       \"server returns error\",\n\t\t\tid:         \"/snap-1\",\n\t\t\tparams:     map[string]string{\"registry_auth\": \"dXNlcjpwYXNz\"},\n\t\t\tstatusCode: http.StatusInternalServerError,\n\t\t\trespBody:   `{\"code\":\"EINVAL\",\"message\":\"invalid config\"}`,\n\t\t\twantErr:    true,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tvar gotID string\n\t\t\tvar gotBody map[string]string\n\n\t\t\tdir := t.TempDir()\n\t\t\tsock := filepath.Join(dir, \"api.sock\")\n\n\t\t\tts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t\t\tassert.Equal(t, http.MethodPut, r.Method)\n\t\t\t\tassert.Equal(t, \"/api/v1/config\", r.URL.Path)\n\n\t\t\t\tgotID = r.URL.Query().Get(\"id\")\n\t\t\t\t_ = json.NewDecoder(r.Body).Decode(&gotBody)\n\n\t\t\t\tif tt.respBody != \"\" {\n\t\t\t\t\tw.Header().Set(\"Content-Type\", \"application/json\")\n\t\t\t\t\tw.WriteHeader(tt.statusCode)\n\t\t\t\t\t_, _ = w.Write([]byte(tt.respBody))\n\t\t\t\t} else {\n\t\t\t\t\tw.WriteHeader(tt.statusCode)\n\t\t\t\t}\n\t\t\t}))\n\n\t\t\tlistener, err := net.Listen(\"unix\", sock)\n\t\t\trequire.NoError(t, err)\n\t\t\tts.Listener = listener\n\t\t\tts.Start()\n\t\t\tdefer ts.Close()\n\n\t\t\tclient, err := NewNydusClient(sock)\n\t\t\trequire.NoError(t, err)\n\n\t\t\terr = client.UpdateConfig(tt.id, tt.params)\n\t\t\tassert.Equal(t, tt.id, gotID)\n\t\t\tassert.Equal(t, tt.params, gotBody)\n\t\t\tif tt.wantErr {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\tassert.Contains(t, err.Error(), \"invalid config\")\n\t\t\t} else {\n\t\t\t\trequire.NoError(t, err)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/daemon/command/command.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage command\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\n\t\"github.com/pkg/errors\"\n)\n\ntype Opt = func(cmd *DaemonCommand)\n\n// Define how to build a command line to start a nydusd daemon\ntype DaemonCommand struct {\n\t// \"singleton\" \"fuse\"\n\tMode string `type:\"subcommand\"`\n\t// \"blobcache\" \"fscache\" \"virtiofs\"\n\tFscacheDriver  string `type:\"param\" name:\"fscache\"`\n\tFscacheThreads string `type:\"param\" name:\"fscache-threads\"`\n\tUpgrade        bool   `type:\"flag\" name:\"upgrade\" default:\"\"`\n\tThreadNum      string `type:\"param\" name:\"thread-num\"`\n\t// `--id` is required by `--supervisor` when starting nydusd\n\tID              string `type:\"param\" name:\"id\"`\n\tConfig          string `type:\"param\" name:\"config\"`\n\tBootstrap       string `type:\"param\" name:\"bootstrap\"`\n\tMountpoint      string `type:\"param\" name:\"mountpoint\"`\n\tAPISock         string `type:\"param\" name:\"apisock\"`\n\tLogLevel        string `type:\"param\" name:\"log-level\"`\n\tLogRotationSize int    `type:\"param\" name:\"log-rotation-size\"`\n\tSupervisor      string `type:\"param\" name:\"supervisor\"`\n\tLogFile         string `type:\"param\" name:\"log-file\"`\n\tPrefetchFiles   string `type:\"param\" name:\"prefetch-files\"`\n\tBackendSource   string `type:\"param\" name:\"backend-source\"`\n\tFailoverPolicy  string `type:\"param\" name:\"failover-policy\"`\n}\n\n// Build exec style command line\nfunc BuildCommand(opts []Opt) ([]string, error) {\n\tvar cmd DaemonCommand\n\tvar subcommand string\n\n\tfor _, o := range opts {\n\t\to(&cmd)\n\t}\n\n\targs := make([]string, 0, 32)\n\tt := reflect.TypeOf(cmd)\n\tv := reflect.ValueOf(cmd)\n\n\tfor i := 0; i < t.NumField(); i++ {\n\t\ttag := t.Field(i).Tag\n\t\targType := tag.Get(\"type\")\n\n\t\tswitch argType {\n\t\tcase \"param\":\n\t\t\t// Zero value will be skipped appending to command line\n\t\t\tif v.Field(i).IsZero() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvalue := v.Field(i).Interface()\n\n\t\t\tpair := []string{fmt.Sprintf(\"--%s\", tag.Get(\"name\")), fmt.Sprintf(\"%v\", value)}\n\t\t\targs = append(args, pair...)\n\t\tcase \"subcommand\":\n\t\t\t// Zero value will be skipped appending to command line\n\t\t\tif v.Field(i).IsZero() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tsubcommand = v.Field(i).String()\n\t\tcase \"flag\":\n\t\t\tkind := v.Field(i).Kind()\n\n\t\t\tif kind != reflect.Bool {\n\t\t\t\treturn nil, errors.Errorf(\"flag must be boolean\")\n\t\t\t}\n\n\t\t\tv := v.Field(i).Bool()\n\n\t\t\tif v {\n\t\t\t\tflag := fmt.Sprintf(\"--%s\", tag.Get(\"name\"))\n\t\t\t\targs = append(args, flag)\n\t\t\t} else {\n\t\t\t\tcontinue\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil, errors.Errorf(\"unknown tag type: %s \", argType)\n\t\t}\n\t}\n\n\tif subcommand != \"\" {\n\t\t// Ensure subcommand is at the first place.\n\t\targs = append([]string{subcommand}, args...)\n\t}\n\n\treturn args, nil\n}\n\nfunc WithMode(m string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.Mode = m\n\t}\n}\n\nfunc WithPrefetchFiles(p string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.PrefetchFiles = p\n\t}\n}\n\nfunc WithFscacheDriver(w string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.FscacheDriver = w\n\t}\n}\n\nfunc WithFscacheThreads(num int) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.FscacheThreads = strconv.Itoa(num)\n\t}\n}\n\nfunc WithThreadNum(num int) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.ThreadNum = strconv.Itoa(num)\n\t}\n}\n\nfunc WithConfig(config string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.Config = config\n\t}\n}\n\nfunc WithBootstrap(b string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.Bootstrap = b\n\t}\n}\n\nfunc WithMountpoint(m string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.Mountpoint = m\n\t}\n}\n\nfunc WithAPISock(api string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.APISock = api\n\t}\n}\n\nfunc WithLogFile(l string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.LogFile = l\n\t}\n}\n\nfunc WithLogLevel(l string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.LogLevel = l\n\t}\n}\n\nfunc WithLogRotationSize(l int) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.LogRotationSize = l\n\t}\n}\n\nfunc WithSupervisor(s string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.Supervisor = s\n\t}\n}\n\nfunc WithID(id string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.ID = id\n\t}\n}\n\nfunc WithUpgrade() Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.Upgrade = true\n\t}\n}\n\nfunc WithBackendSource(source string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.BackendSource = source\n\t}\n}\n\nfunc WithFailoverPolicy(policy string) Opt {\n\treturn func(cmd *DaemonCommand) {\n\t\tcmd.FailoverPolicy = policy\n\t}\n}\n"
  },
  {
    "path": "pkg/daemon/command/command_builder_test.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage command\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestBuildCommand(t *testing.T) {\n\n\tc := []Opt{WithMode(\"singleton\"),\n\t\tWithFscacheDriver(\"fs_cache_dir\"),\n\t\tWithFscacheThreads(4),\n\t\tWithAPISock(\"/dummy/apisock\"),\n\t\tWithUpgrade()}\n\n\targs, err := BuildCommand(c)\n\tassert.Nil(t, err)\n\tactual := strings.Join(args, \" \")\n\tassert.Equal(t, \"singleton --fscache fs_cache_dir --fscache-threads 4 --upgrade --apisock /dummy/apisock\", actual)\n\n\tc1 := []Opt{WithMode(\"singleton\"),\n\t\tWithFscacheDriver(\"fs_cache_dir\"),\n\t\tWithFscacheThreads(4),\n\t\tWithAPISock(\"/dummy/apisock\")}\n\n\targs1, err := BuildCommand(c1)\n\tassert.Nil(t, err)\n\tactual1 := strings.Join(args1, \" \")\n\tassert.Equal(t, \"singleton --fscache fs_cache_dir --fscache-threads 4 --apisock /dummy/apisock\", actual1)\n}\n\n// cpu: Intel(R) Xeon(R) Platinum 8260 CPU @ 2.40GHz\n// BenchmarkBuildCommand-8   \t  394146\t      3084 ns/op\n// BenchmarkXxx-8            \t 3933902\t       281.4 ns/op\n// PASS\nfunc BenchmarkBuildCommand(b *testing.B) {\n\n\tc := []Opt{WithMode(\"singleton\"),\n\t\tWithFscacheDriver(\"fs_cache_dir\"),\n\t\tWithFscacheThreads(4),\n\t\tWithAPISock(\"/dummy/apisock\"),\n\t\tWithUpgrade()}\n\n\tfor n := 0; n < b.N; n++ {\n\t\t_, err := BuildCommand(c)\n\t\tassert.Nil(b, err)\n\t}\n}\n"
  },
  {
    "path": "pkg/daemon/config.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemon\n\nimport (\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/internal/constant\"\n)\n\n// Build runtime nydusd daemon object, which might be persisted later\nfunc WithSocketDir(dir string) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\ts := filepath.Join(dir, d.ID())\n\t\t// this may be failed, should handle that\n\t\tif err := os.MkdirAll(s, 0755); err != nil {\n\t\t\treturn errors.Wrapf(err, \"create socket dir %s\", s)\n\t\t}\n\t\td.States.APISocket = path.Join(s, \"api.sock\")\n\t\treturn nil\n\t}\n}\n\nfunc WithRef(ref int32) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\td.ref = ref\n\t\treturn nil\n\t}\n}\n\nfunc WithLogDir(dir string) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\tif err := os.MkdirAll(dir, 0755); err != nil {\n\t\t\treturn errors.Wrapf(err, \"create logging dir %s\", dir)\n\t\t}\n\t\td.States.LogDir = filepath.Join(dir, d.ID())\n\t\treturn nil\n\t}\n}\n\nfunc WithLogToStdout(logToStdout bool) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\td.States.LogToStdout = logToStdout\n\t\treturn nil\n\t}\n}\n\nfunc WithLogLevel(logLevel string) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\tif logLevel == \"\" {\n\t\t\td.States.LogLevel = constant.DefaultLogLevel\n\t\t} else {\n\t\t\td.States.LogLevel = logLevel\n\t\t}\n\t\treturn nil\n\t}\n}\n\nfunc WithLogRotationSize(logRotationSize int) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\td.States.LogRotationSize = logRotationSize\n\t\treturn nil\n\t}\n}\n\nfunc WithConfigDir(dir string) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\ts := filepath.Join(dir, d.ID())\n\t\t// this may be failed, should handle that\n\t\tif err := os.MkdirAll(s, 0755); err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed to create config dir %s\", s)\n\t\t}\n\t\td.States.ConfigDir = s\n\t\treturn nil\n\t}\n}\n\nfunc WithMountpoint(mountpoint string) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\td.States.Mountpoint = mountpoint\n\t\treturn nil\n\t}\n}\n\nfunc WithNydusdThreadNum(nydusdThreadNum int) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\td.States.ThreadNum = nydusdThreadNum\n\t\treturn nil\n\t}\n}\n\nfunc WithFsDriver(fsDriver string) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\td.States.FsDriver = fsDriver\n\t\treturn nil\n\t}\n}\n\nfunc WithFailoverPolicy(failoverPolicy string) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\td.States.FailoverPolicy = failoverPolicy\n\t\treturn nil\n\t}\n}\n\nfunc WithDaemonMode(daemonMode config.DaemonMode) NewDaemonOpt {\n\treturn func(d *Daemon) error {\n\t\td.States.DaemonMode = daemonMode\n\t\treturn nil\n\t}\n}\n"
  },
  {
    "path": "pkg/daemon/daemon.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemon\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/log\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/config/daemonconfig\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/collector\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/supervisor\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/erofs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/mount\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/retry\"\n)\n\nconst (\n\tAPISocketFileName   = \"api.sock\"\n\tSharedNydusDaemonID = \"shared_daemon\"\n)\n\ntype NewDaemonOpt func(d *Daemon) error\n\n// Fields in this structure should be write-once, and caller should hold `Daemon.mu` when updating fields.\ntype ConfigState struct {\n\t// A unique ID generated by daemon manager to identify the nydusd instance.\n\tID              string\n\tProcessID       int\n\tAPISocket       string\n\tDaemonMode      config.DaemonMode\n\tFsDriver        string\n\tLogDir          string\n\tLogLevel        string\n\tLogRotationSize int\n\tLogToStdout     bool\n\tMountpoint      string\n\tSupervisorPath  string\n\tThreadNum       int\n\tFailoverPolicy  string\n\t// Where the configuration file resides, all rafs instances share the same configuration template\n\tConfigDir string\n}\n\n// TODO: Record queried nydusd state\ntype Daemon struct {\n\tStates ConfigState\n\n\tmu sync.Mutex\n\t// Host all RAFS filesystems managed by this daemon:\n\t// fusedev dedicated mode: one and only one RAFS instance\n\t// fusedev shared mode: zero, one or more RAFS instances\n\t// fscache shared mode: zero, one or more RAFS instances\n\tRafsCache rafs.Cache\n\n\t// Protect nydusd http client\n\tcmu sync.Mutex\n\t// client will be rebuilt on Reconnect, skip marshal/unmarshal\n\tclient NydusdClient\n\n\t// Nil means this daemon object has no supervisor\n\tSupervisor *supervisor.Supervisor\n\tConfig     daemonconfig.DaemonConfig\n\n\t// How much CPU nydusd is utilizing when starts since full prefetch might\n\t// consume many CPU cycles\n\tStartupCPUUtilization float64\n\tVersion               types.BuildTimeInfo\n\n\tref int32\n\t// Cache the nydusd daemon state to avoid frequently querying nydusd by API.\n\tstate types.DaemonState\n}\n\nfunc (d *Daemon) Lock() {\n\td.mu.Lock()\n}\n\nfunc (d *Daemon) Unlock() {\n\td.mu.Unlock()\n}\n\nfunc (d *Daemon) ID() string {\n\treturn d.States.ID\n}\n\nfunc (d *Daemon) Pid() int {\n\treturn d.States.ProcessID\n}\n\nfunc (d *Daemon) IncRef() {\n\tatomic.AddInt32(&d.ref, 1)\n}\n\nfunc (d *Daemon) DecRef() int32 {\n\treturn atomic.AddInt32(&d.ref, -1)\n}\n\nfunc (d *Daemon) GetRef() int32 {\n\treturn atomic.LoadInt32(&d.ref)\n}\n\nfunc (d *Daemon) HostMountpoint() (mnt string) {\n\tmnt = d.States.Mountpoint\n\treturn\n}\n\n// Each nydusd daemon has a copy of configuration json file.\nfunc (d *Daemon) ConfigFile(instanceID string) string {\n\tif instanceID == \"\" {\n\t\treturn filepath.Join(d.States.ConfigDir, \"config.json\")\n\t}\n\treturn filepath.Join(d.States.ConfigDir, instanceID, \"config.json\")\n}\n\n// NydusdThreadNum returns how many working threads are needed of a single nydusd\nfunc (d *Daemon) NydusdThreadNum() int {\n\treturn d.States.ThreadNum\n}\n\nfunc (d *Daemon) GetAPISock() string {\n\treturn d.States.APISocket\n}\n\nfunc (d *Daemon) LogFile() string {\n\treturn filepath.Join(d.States.LogDir, \"nydusd.log\")\n}\n\nfunc (d *Daemon) AddRafsInstance(r *rafs.Rafs) {\n\td.RafsCache.Add(r)\n\td.IncRef()\n\tr.DaemonID = d.ID()\n\tcollector.NewDaemonImageCollector(d.ID(), r.ImageID).Collect()\n}\n\nfunc (d *Daemon) UpdateRafsInstance(r *rafs.Rafs) {\n\td.RafsCache.Add(r)\n}\n\nfunc (d *Daemon) RemoveRafsInstance(snapshotID string) {\n\tif r := d.RafsCache.Get(snapshotID); r != nil {\n\t\tcollector.NewDaemonImageCollector(d.ID(), r.ImageID).Delete()\n\t}\n\td.RafsCache.Remove(snapshotID)\n\td.DecRef()\n}\n\n// Get and cache daemon current working state by querying nydusd:\n// 1. INIT\n// 2. READY: All needed resources are ready.\n// 3. RUNNING\nfunc (d *Daemon) GetState() (types.DaemonState, error) {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn types.DaemonStateUnknown, errors.Wrapf(err, \"get daemon state\")\n\t}\n\tinfo, err := c.GetDaemonInfo()\n\tif err != nil {\n\t\treturn types.DaemonStateUnknown, err\n\t}\n\n\tst := info.DaemonState()\n\n\td.Lock()\n\td.state = st\n\td.Version = info.DaemonVersion()\n\td.Unlock()\n\n\treturn st, nil\n}\n\n// Return the cached nydusd working status, no API is invoked.\nfunc (d *Daemon) State() types.DaemonState {\n\td.Lock()\n\tdefer d.Unlock()\n\treturn d.state\n}\n\n// Reset the cached nydusd working status\nfunc (d *Daemon) ResetState() {\n\td.Lock()\n\tdefer d.Unlock()\n\td.state = types.DaemonStateUnknown\n}\n\n// Wait for the nydusd daemon to reach specified state with timeout.\nfunc (d *Daemon) WaitUntilState(expected types.DaemonState) error {\n\treturn retry.Do(func() error {\n\t\tif expected == d.State() {\n\t\t\treturn nil\n\t\t}\n\n\t\tstate, err := d.GetState()\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"wait until daemon is %s\", expected)\n\t\t}\n\n\t\tif state != expected {\n\t\t\treturn errors.Errorf(\"daemon %s is not %s yet, current state %s\",\n\t\t\t\td.ID(), expected, state)\n\t\t}\n\n\t\treturn nil\n\t},\n\t\tretry.LastErrorOnly(true),\n\t\tretry.Attempts(20), // totally wait for 2 seconds, should be enough\n\t\tretry.Delay(100*time.Millisecond),\n\t)\n}\n\nfunc (d *Daemon) IsSharedDaemon() bool {\n\tif d.States.DaemonMode != \"\" {\n\t\treturn d.States.DaemonMode == config.DaemonModeShared\n\t}\n\n\treturn d.HostMountpoint() == config.GetRootMountpoint()\n}\n\nfunc (d *Daemon) SharedMount(rafs *rafs.Rafs) error {\n\tdefer d.SendStates()\n\n\tswitch d.States.FsDriver {\n\tcase config.FsDriverFscache:\n\t\tif err := d.sharedErofsMount(rafs); err != nil {\n\t\t\treturn errors.Wrapf(err, \"mount erofs\")\n\t\t}\n\t\treturn nil\n\tcase config.FsDriverFusedev:\n\t\treturn d.sharedFusedevMount(rafs)\n\tdefault:\n\t\treturn errors.Errorf(\"unsupported fs driver %s\", d.States.FsDriver)\n\t}\n}\n\nfunc (d *Daemon) sharedFusedevMount(rafs *rafs.Rafs) error {\n\tclient, err := d.GetClient()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"mount instance %s\", rafs.SnapshotID)\n\t}\n\n\tbootstrap, err := rafs.BootstrapFile()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tc, err := daemonconfig.NewDaemonConfig(d.States.FsDriver, d.ConfigFile(rafs.SnapshotID))\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"Failed to reload instance configuration %s\",\n\t\t\td.ConfigFile(rafs.SnapshotID))\n\t}\n\n\tcfg, err := c.DumpString()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"dump instance configuration\")\n\t}\n\n\terr = client.Mount(rafs.RelaMountpoint(), bootstrap, cfg)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"mount rafs instance\")\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) sharedErofsMount(ra *rafs.Rafs) error {\n\tclient, err := d.GetClient()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"bind blob %s\", d.ID())\n\t}\n\n\t// TODO: Why fs cache needing this work dir?\n\tif err := os.MkdirAll(ra.FscacheWorkDir(), 0755); err != nil {\n\t\treturn errors.Wrapf(err, \"failed to create fscache work dir %s\", ra.FscacheWorkDir())\n\t}\n\n\tc, err := daemonconfig.NewDaemonConfig(d.States.FsDriver, d.ConfigFile(ra.SnapshotID))\n\tif err != nil {\n\t\tlog.L.Errorf(\"Failed to reload daemon configuration %s, %s\", d.ConfigFile(ra.SnapshotID), err)\n\t\treturn err\n\t}\n\n\tcfgStr, err := c.DumpString()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := client.BindBlob(cfgStr); err != nil {\n\t\treturn errors.Wrapf(err, \"request to bind fscache blob\")\n\t}\n\n\tmountPoint := ra.GetMountpoint()\n\tif err := os.MkdirAll(mountPoint, 0755); err != nil {\n\t\treturn errors.Wrapf(err, \"create mountpoint %s\", mountPoint)\n\t}\n\n\tfscacheID := erofs.FscacheID(ra.SnapshotID)\n\n\tcfg := c.(*daemonconfig.FscacheDaemonConfig)\n\tra.AddAnnotation(rafs.AnnoFsCacheDomainID, cfg.DomainID)\n\tra.AddAnnotation(rafs.AnnoFsCacheID, fscacheID)\n\n\tif err := erofs.Mount(cfg.DomainID, fscacheID, mountPoint); err != nil {\n\t\tif !errdefs.IsErofsMounted(err) {\n\t\t\treturn errors.Wrapf(err, \"mount erofs to %s\", mountPoint)\n\t\t}\n\t\t// When snapshotter exits (either normally or abnormally), it will not have a\n\t\t// chance to umount erofs mountpoint, so if snapshotter resumes running and mount\n\t\t// again (by a new request to create container), it will need to ignore the mount\n\t\t// error `device or resource busy`.\n\t\tlog.L.Warnf(\"erofs mountpoint %s has been mounted\", mountPoint)\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) SharedUmount(rafs *rafs.Rafs) error {\n\tdefer d.SendStates()\n\n\tswitch d.States.FsDriver {\n\tcase config.FsDriverFscache:\n\t\tif err := d.sharedErofsUmount(rafs); err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed to erofs mount\")\n\t\t}\n\t\treturn nil\n\tcase config.FsDriverFusedev:\n\t\tc, err := d.GetClient()\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"umount instance %s\", rafs.SnapshotID)\n\t\t}\n\t\treturn c.Umount(rafs.RelaMountpoint())\n\tdefault:\n\t\treturn errors.Errorf(\"unsupported fs driver %s\", d.States.FsDriver)\n\t}\n}\n\nfunc (d *Daemon) sharedErofsUmount(ra *rafs.Rafs) error {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"unbind blob %s\", d.ID())\n\t}\n\tdomainID := ra.Annotations[rafs.AnnoFsCacheDomainID]\n\tfscacheID := ra.Annotations[rafs.AnnoFsCacheID]\n\n\tif err := c.UnbindBlob(domainID, fscacheID); err != nil {\n\t\treturn errors.Wrapf(err, \"request to unbind fscache blob, domain %s, fscache %s\", domainID, fscacheID)\n\t}\n\n\tmountpoint := ra.GetMountpoint()\n\tif err := erofs.Umount(mountpoint); err != nil {\n\t\treturn errors.Wrapf(err, \"umount erofs %s mountpoint, %s\", err, mountpoint)\n\t}\n\n\t// delete fscache bootstrap cache file\n\t// erofs generate fscache cache file for bootstrap with fscacheID\n\tif err := c.UnbindBlob(\"\", fscacheID); err != nil {\n\t\tlog.L.Warnf(\"delete bootstrap %s err %s\", fscacheID, err)\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) UmountRafsInstance(r *rafs.Rafs) error {\n\tif d.IsSharedDaemon() {\n\t\tif err := d.SharedUmount(r); err != nil {\n\t\t\treturn errors.Wrapf(err, \"umount fs instance %s\", r.SnapshotID)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) UmountRafsInstances() error {\n\tif d.IsSharedDaemon() {\n\t\td.RafsCache.Lock()\n\t\tdefer d.RafsCache.Unlock()\n\n\t\tinstances := d.RafsCache.ListLocked()\n\n\t\tfor _, r := range instances {\n\t\t\tif err := d.SharedUmount(r); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"umount fs instance %s\", r.SnapshotID)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) SendStates() {\n\tsu := d.Supervisor\n\tif su != nil {\n\t\t// TODO: This should be optional by checking snapshotter's configuration.\n\t\t// FIXME: Is it possible the states are overwritten during two API mounts.\n\t\t// FIXME: What if nydusd does not support sending states.\n\t\terr := su.FetchDaemonStates(func() error {\n\t\t\tif err := d.doSendStates(); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"send daemon %s states\", d.ID())\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t\tif err != nil {\n\t\t\tlog.L.Warnf(\"Daemon %s does not support sending states, %v\", d.ID(), err)\n\t\t}\n\t}\n}\n\nfunc (d *Daemon) doSendStates() error {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"send states %s\", d.ID())\n\t}\n\n\tif err := c.SendFd(); err != nil {\n\t\treturn errors.Wrap(err, \"request to send states\")\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) TakeOver() error {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"takeover daemon %s\", d.ID())\n\t}\n\n\tif err := c.TakeOver(); err != nil {\n\t\treturn errors.Wrap(err, \"request to take over\")\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) Start() error {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"start service\")\n\t}\n\n\tif err := c.Start(); err != nil {\n\t\treturn errors.Wrap(err, \"request to start service\")\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) Exit() error {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"start service\")\n\t}\n\n\tif err := c.Exit(); err != nil {\n\t\treturn errors.Wrap(err, \"request to exit service\")\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) GetDaemonInfo() (*types.DaemonInfo, error) {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get daemon information\")\n\t}\n\n\treturn c.GetDaemonInfo()\n}\n\nfunc (d *Daemon) GetFsMetrics(sid string) (*types.FsMetrics, error) {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get fs metrics\")\n\t}\n\n\treturn c.GetFsMetrics(sid)\n}\n\nfunc (d *Daemon) GetInflightMetrics() (*types.InflightMetrics, error) {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get inflight metrics\")\n\t}\n\n\treturn c.GetInflightMetrics()\n}\n\n// UpdateAuthConfig updates the registry auth for the given rafs instance.\n// It rewrites the daemon config file on disk and, for basic auth, issues a\n// PUT /api/v1/config to hot-reload the credential in the running nydusd.\n// Bearer tokens are only persisted to disk (nydusd does not support runtime\n// token updates).\nfunc (d *Daemon) UpdateAuthConfig(snapshotID string, kc *auth.PassKeyChain) error {\n\tvar configFile, apiID string\n\tif d.IsSharedDaemon() {\n\t\tconfigFile = d.ConfigFile(snapshotID)\n\t\tapiID = \"/\" + snapshotID\n\t} else {\n\t\tconfigFile = d.ConfigFile(\"\")\n\t\tapiID = \"/\"\n\t}\n\n\tcfg, err := daemonconfig.NewDaemonConfig(d.States.FsDriver, configFile)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"load daemon config for auth update\")\n\t}\n\tcfg.FillAuth(kc)\n\tif err := cfg.DumpFile(configFile); err != nil {\n\t\treturn errors.Wrap(err, \"write updated daemon config\")\n\t}\n\n\tif kc.TokenBase() {\n\t\tlog.L.WithField(\"daemon\", d.ID()).Warn(\"bearer token updated on disk only; nydusd API does not support runtime token reload\")\n\t\treturn nil\n\t}\n\n\tclient, err := d.GetClient()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"get client for auth update\")\n\t}\n\treturn client.UpdateConfig(apiID, map[string]string{\"registry_auth\": kc.ToBase64()})\n}\n\nfunc (d *Daemon) GetCacheMetrics(sid string) (*types.CacheMetrics, error) {\n\tc, err := d.GetClient()\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get cache metrics\")\n\t}\n\treturn c.GetCacheMetrics(sid)\n}\n\nfunc (d *Daemon) GetClient() (NydusdClient, error) {\n\td.cmu.Lock()\n\tdefer d.cmu.Unlock()\n\n\tif d.client == nil {\n\t\tsock := d.GetAPISock()\n\t\t// The socket file may be residual from a dead nydusd\n\t\terr := WaitUntilSocketExisted(sock, d.Pid())\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(errdefs.ErrNotFound, \"daemon socket %s\", sock)\n\t\t}\n\t\tclient, err := NewNydusClient(sock)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"create daemon %s client\", d.ID())\n\t\t}\n\t\td.client = client\n\t}\n\n\treturn d.client, nil\n}\n\nfunc (d *Daemon) ResetClient() {\n\td.cmu.Lock()\n\td.client = nil\n\td.cmu.Unlock()\n}\n\nfunc (d *Daemon) Terminate() error {\n\t// if we found pid here, we need to kill and wait process to exit, Pid=0 means somehow we lost\n\t// the daemon pid, so that we can't kill the process, just roughly umount the mountpoint\n\td.Lock()\n\tdefer d.Unlock()\n\n\tif d.Pid() > 0 {\n\t\tp, err := os.FindProcess(d.Pid())\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"find process %d\", d.Pid())\n\t\t}\n\t\tif err = p.Signal(syscall.SIGTERM); err != nil {\n\t\t\treturn errors.Wrapf(err, \"send SIGTERM signal to process %d\", d.Pid())\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (d *Daemon) Wait() error {\n\t// if we found pid here, we need to kill and wait process to exit, Pid=0 means somehow we lost\n\t// the daemon pid, so that we can't kill the process, just roughly umount the mountpoint\n\td.Lock()\n\tdefer d.Unlock()\n\n\tif d.Pid() > 0 {\n\t\tp, err := os.FindProcess(d.Pid())\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"find process %d\", d.Pid())\n\t\t}\n\n\t\t// if nydus-snapshotter restarts, it will break the relationship between nydusd and\n\t\t// nydus-snapshotter, p.Wait() will return err, so here should exclude this case\n\t\tif _, err = p.Wait(); err != nil && !errors.Is(err, syscall.ECHILD) {\n\t\t\tlog.L.Errorf(\"failed to process wait, %v\", err)\n\t\t} else if d.HostMountpoint() != \"\" && config.GetFsDriver() == config.FsDriverFusedev {\n\t\t\t// No need to umount if the nydusd never performs mount. In other word, it does not\n\t\t\t// associate with a host mountpoint.\n\t\t\tif err := mount.WaitUntilUnmounted(d.HostMountpoint()); err != nil {\n\t\t\t\tlog.L.WithError(err).Errorf(\"umount %s\", d.HostMountpoint())\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// When daemon dies, clean up its vestige before start a new one.\nfunc (d *Daemon) ClearVestige() {\n\tmounter := mount.Mounter{}\n\tif d.States.FsDriver == config.FsDriverFscache {\n\t\tinstances := d.RafsCache.List()\n\t\tfor _, i := range instances {\n\t\t\tif err := mounter.Umount(i.GetMountpoint()); err != nil {\n\t\t\t\tlog.L.Warnf(\"Can't umount %s, %v\", d.States.Mountpoint, err)\n\t\t\t}\n\t\t}\n\t} else {\n\t\tlog.L.Infof(\"Unmounting %s when clear vestige\", d.HostMountpoint())\n\t\tif err := mounter.Umount(d.HostMountpoint()); err != nil {\n\t\t\tlog.L.Warnf(\"Can't umount %s, %v\", d.States.Mountpoint, err)\n\t\t}\n\t}\n\n\t// Nydusd judges if it should enter failover phrase by checking\n\t// if unix socket is existed and it can't be connected.\n\tif err := os.Remove(d.GetAPISock()); err != nil {\n\t\tlog.L.Warnf(\"Can't delete residual unix socket %s, %v\", d.GetAPISock(), err)\n\t}\n\n\t// `CheckStatus->ensureClient` only checks if socket file is existed when building http client.\n\t// But the socket file may be residual and will be cleared before starting a new nydusd.\n\t// So clear the client by assigning nil\n\td.ResetClient()\n}\n\nfunc (d *Daemon) CloneRafsInstances(src *Daemon) {\n\tinstances := src.RafsCache.List()\n\td.RafsCache.SetIntances(instances)\n\tref := src.GetRef()\n\tfor ref > 0 {\n\t\td.IncRef()\n\t\tref--\n\t}\n}\n\n// Daemon must be started and reach RUNNING state before call this method\nfunc (d *Daemon) RecoverRafsInstances() error {\n\tif d.IsSharedDaemon() {\n\t\td.RafsCache.Lock()\n\t\tdefer d.RafsCache.Unlock()\n\n\t\tinstances := make([]*rafs.Rafs, 0, 16)\n\t\tfor _, r := range d.RafsCache.ListLocked() {\n\t\t\tinstances = append(instances, r)\n\t\t}\n\n\t\tsort.Slice(instances, func(i, j int) bool {\n\t\t\treturn instances[i].Seq < instances[j].Seq\n\t\t})\n\n\t\tfor _, i := range instances {\n\t\t\tif d.HostMountpoint() != i.GetMountpoint() {\n\t\t\t\tlog.L.Infof(\"Recovered mount instance %s\", i.SnapshotID)\n\t\t\t\tif err := d.SharedMount(i); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Instantiate a daemon object\nfunc NewDaemon(opt ...NewDaemonOpt) (*Daemon, error) {\n\td := &Daemon{}\n\td.States.ID = newID()\n\td.States.DaemonMode = config.DaemonModeDedicated\n\td.RafsCache = rafs.NewRafsCache()\n\n\tfor _, o := range opt {\n\t\terr := o(d)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn d, nil\n}\n\nfunc GetDaemonGitCommit(nydusdPath string) (string, error) {\n\tcmd := exec.Command(nydusdPath, \"--version\")\n\toutput, err := cmd.Output()\n\tif err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"failed to run %s -V\", nydusdPath)\n\t}\n\tre := regexp.MustCompile(`Git Commit:\\s*(.+)`)\n\tmatches := re.FindStringSubmatch(string(output))\n\tif len(matches) > 1 {\n\t\treturn strings.TrimSpace(matches[1]), nil\n\t}\n\treturn \"\", errors.New(\"Git Commit not found in nydusd -V output\")\n}\n"
  },
  {
    "path": "pkg/daemon/daemon_test.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemon\n\nimport (\n\t\"encoding/json\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/config/daemonconfig\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n)\n\nfunc TestMain(m *testing.M) {\n\t// Initialize global config so DumpFile does not panic.\n\tcfg := &config.SnapshotterConfig{}\n\tcfg.Root = os.TempDir()\n\t_ = config.ProcessConfigurations(cfg)\n\tos.Exit(m.Run())\n}\n\n// minimalFuseConfig returns the minimal valid FuseDaemonConfig JSON for tests.\nfunc minimalFuseConfig() []byte {\n\tcfg := daemonconfig.FuseDaemonConfig{\n\t\tDevice: &daemonconfig.DeviceConfig{},\n\t\tMode:   \"direct\",\n\t}\n\tcfg.Device.Backend.BackendType = \"registry\"\n\tb, _ := json.Marshal(cfg)\n\treturn b\n}\n\nfunc TestUpdateAuthConfig(t *testing.T) {\n\ttests := []struct {\n\t\tname         string\n\t\tshared       bool\n\t\tsnapshotID   string\n\t\tkc           *auth.PassKeyChain\n\t\twantAPICall  bool\n\t\twantAPIID    string\n\t\twantDiskAuth string // expected Auth field on disk after update\n\t}{\n\t\t{\n\t\t\tname:         \"shared daemon with basic auth\",\n\t\t\tshared:       true,\n\t\t\tsnapshotID:   \"snap-1\",\n\t\t\tkc:           &auth.PassKeyChain{Username: \"user\", Password: \"pass\"},\n\t\t\twantAPICall:  true,\n\t\t\twantAPIID:    \"/snap-1\",\n\t\t\twantDiskAuth: \"dXNlcjpwYXNz\", // base64(\"user:pass\")\n\t\t},\n\t\t{\n\t\t\tname:         \"dedicated daemon with basic auth\",\n\t\t\tshared:       false,\n\t\t\tsnapshotID:   \"\",\n\t\t\tkc:           &auth.PassKeyChain{Username: \"user\", Password: \"pass\"},\n\t\t\twantAPICall:  true,\n\t\t\twantAPIID:    \"/\",\n\t\t\twantDiskAuth: \"dXNlcjpwYXNz\",\n\t\t},\n\t\t{\n\t\t\tname:        \"bearer token skips API call\",\n\t\t\tshared:      false,\n\t\t\tsnapshotID:  \"\",\n\t\t\tkc:          &auth.PassKeyChain{Username: \"\", Password: \"mytoken\"},\n\t\t\twantAPICall: false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tdir := t.TempDir()\n\n\t\t\t// Write minimal fuse config to the expected path.\n\t\t\tvar configFile string\n\t\t\tif tt.shared && tt.snapshotID != \"\" {\n\t\t\t\tconfigFile = filepath.Join(dir, tt.snapshotID, \"config.json\")\n\t\t\t} else {\n\t\t\t\tconfigFile = filepath.Join(dir, \"config.json\")\n\t\t\t}\n\t\t\trequire.NoError(t, os.MkdirAll(filepath.Dir(configFile), 0o755))\n\t\t\trequire.NoError(t, os.WriteFile(configFile, minimalFuseConfig(), 0o644))\n\n\t\t\t// Set up mock API server.\n\t\t\tvar apiCalled bool\n\t\t\tvar gotID string\n\t\t\tvar gotBody map[string]string\n\n\t\t\tsock := filepath.Join(dir, \"api.sock\")\n\t\t\tts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\t\t\tapiCalled = true\n\t\t\t\tgotID = r.URL.Query().Get(\"id\")\n\t\t\t\t_ = json.NewDecoder(r.Body).Decode(&gotBody)\n\t\t\t\tw.WriteHeader(http.StatusNoContent)\n\t\t\t}))\n\t\t\tlistener, err := net.Listen(\"unix\", sock)\n\t\t\trequire.NoError(t, err)\n\t\t\tts.Listener = listener\n\t\t\tts.Start()\n\t\t\tdefer ts.Close()\n\n\t\t\t// Build a daemon with the right state.\n\t\t\tvar daemonMode config.DaemonMode\n\t\t\tif tt.shared {\n\t\t\t\tdaemonMode = config.DaemonModeShared\n\t\t\t} else {\n\t\t\t\tdaemonMode = config.DaemonModeDedicated\n\t\t\t}\n\n\t\t\td := &Daemon{\n\t\t\t\tStates: ConfigState{\n\t\t\t\t\tConfigDir:  dir,\n\t\t\t\t\tFsDriver:   config.FsDriverFusedev,\n\t\t\t\t\tDaemonMode: daemonMode,\n\t\t\t\t\tAPISocket:  sock,\n\t\t\t\t},\n\t\t\t}\n\t\t\t// Pre-create client to avoid WaitUntilSocketExisted.\n\t\t\tclient, err := NewNydusClient(sock)\n\t\t\trequire.NoError(t, err)\n\t\t\td.client = client\n\n\t\t\terr = d.UpdateAuthConfig(tt.snapshotID, tt.kc)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tassert.Equal(t, tt.wantAPICall, apiCalled)\n\t\t\tif tt.wantAPICall {\n\t\t\t\tassert.Equal(t, tt.wantAPIID, gotID)\n\t\t\t\tassert.Equal(t, tt.kc.ToBase64(), gotBody[\"registry_auth\"])\n\t\t\t}\n\n\t\t\t// Verify config file was updated on disk.\n\t\t\tif tt.wantDiskAuth != \"\" {\n\t\t\t\tcfg, err := daemonconfig.LoadFuseConfig(configFile)\n\t\t\t\trequire.NoError(t, err)\n\t\t\t\tassert.Equal(t, tt.wantDiskAuth, cfg.Device.Backend.Config.Auth)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/daemon/idgen.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage daemon\n\nimport (\n\t\"github.com/rs/xid\"\n)\n\nfunc newID() string {\n\treturn xid.New().String()\n}\n"
  },
  {
    "path": "pkg/daemon/types/types.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage types\n\ntype BuildTimeInfo struct {\n\tPackageVer string `json:\"package_ver\"`\n\tGitCommit  string `json:\"git_commit\"`\n\tBuildTime  string `json:\"build_time\"`\n\tProfile    string `json:\"profile\"`\n\tRustc      string `json:\"rustc\"`\n}\n\ntype DaemonState string\n\nconst (\n\tDaemonStateUnknown   DaemonState = \"UNKNOWN\"\n\tDaemonStateInit      DaemonState = \"INIT\"\n\tDaemonStateReady     DaemonState = \"READY\"\n\tDaemonStateRunning   DaemonState = \"RUNNING\"\n\tDaemonStateDied      DaemonState = \"DIED\"\n\tDaemonStateDestroyed DaemonState = \"DESTROYED\"\n)\n\ntype DaemonInfo struct {\n\tID      string        `json:\"id\"`\n\tVersion BuildTimeInfo `json:\"version\"`\n\tState   DaemonState   `json:\"state\"`\n}\n\nfunc (info *DaemonInfo) DaemonState() DaemonState {\n\treturn info.State\n}\n\nfunc (info *DaemonInfo) DaemonVersion() BuildTimeInfo {\n\treturn info.Version\n}\n\ntype ErrorMessage struct {\n\tCode    string `json:\"code\"`\n\tMessage string `json:\"message\"`\n}\n\ntype MountRequest struct {\n\tFsType string `json:\"fs_type\"`\n\tSource string `json:\"source\"`\n\tConfig string `json:\"config\"`\n}\n\nfunc NewMountRequest(source, config string) MountRequest {\n\treturn MountRequest{\n\t\tFsType: \"rafs\",\n\t\tSource: source,\n\t\tConfig: config,\n\t}\n}\n\ntype FsMetrics struct {\n\tFilesAccountEnabled       bool     `json:\"files_account_enabled\"`\n\tAccessPatternEnabled      bool     `json:\"access_pattern_enabled\"`\n\tMeasureLatency            bool     `json:\"measure_latency\"`\n\tID                        string   `json:\"id\"`\n\tDataRead                  uint64   `json:\"data_read\"`\n\tBlockCountRead            []uint64 `json:\"block_count_read\"`\n\tFopHits                   []uint64 `json:\"fop_hits\"`\n\tFopErrors                 []uint64 `json:\"fop_errors\"`\n\tFopCumulativeLatencyTotal []uint64 `json:\"fop_cumulative_latency_total\"`\n\tReadLatencyDist           []uint64 `json:\"read_latency_dist\"`\n\tNrOpens                   uint64   `json:\"nr_opens\"`\n}\n\ntype InflightMetrics struct {\n\tValues []struct {\n\t\tInode         uint64 `json:\"inode\"`\n\t\tOpcode        uint32 `json:\"opcode\"`\n\t\tUnique        uint64 `json:\"unique\"`\n\t\tTimestampSecs uint64 `json:\"timestamp_secs\"`\n\t}\n}\n\ntype CacheMetrics struct {\n\tID                           string   `json:\"id\"`\n\tUnderlyingFiles              []string `json:\"underlying_files\"`\n\tStorePath                    string   `json:\"store_path\"`\n\tPartialHits                  uint64   `json:\"partial_hits\"`\n\tWholeHits                    uint64   `json:\"whole_hits\"`\n\tTotal                        uint64   `json:\"total\"`\n\tEntriesCount                 uint64   `json:\"entries_count\"`\n\tPrefetchDataAmount           uint64   `json:\"prefetch_data_amount\"`\n\tPrefetchRequestsCount        uint64   `json:\"prefetch_requests_count\"`\n\tPrefetchWorkers              uint     `json:\"prefetch_workers\"`\n\tPrefetchUnmergedChunks       uint64   `json:\"prefetch_unmerged_chunks\"`\n\tPrefetchCumulativeTimeMillis uint64   `json:\"prefetch_cumulative_time_millis\"`\n\tPrefetchBeginTimeSecs        uint64   `json:\"prefetch_begin_time_secs\"`\n\tPrefetchBeginTimeMillis      uint64   `json:\"prefetch_begin_time_millis\"`\n\tPrefetchEndTimeSecs          uint64   `json:\"prefetch_end_time_secs\"`\n\tPrefetchEndTimeMillis        uint64   `json:\"prefetch_end_time_millis\"`\n\tBufferedBackendSize          uint64   `json:\"buffered_backend_size\"`\n\tDataAllReady                 bool     `json:\"data_all_ready\"`\n}\n"
  },
  {
    "path": "pkg/encryption/encryption.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage encryption\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/errdefs\"\n\n\t\"github.com/containers/ocicrypt\"\n\tencconfig \"github.com/containers/ocicrypt/config\"\n\tenchelpers \"github.com/containers/ocicrypt/helpers\"\n\tencocispec \"github.com/containers/ocicrypt/spec\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\n// Copied from containerd/imgcrypt project, copyright The imgcrypt Authors.\n// https://github.com/containerd/imgcrypt/blob/e7500301cabcc9f3cab3daee3f541079b509e95f/images/encryption/encryption.go#LL82C5-L82C5\n// encryptLayer encrypts the layer using the CryptoConfig and creates a new OCI Descriptor.\n// A call to this function may also only manipulate the wrapped keys list.\n// The caller is expected to store the returned encrypted data and OCI Descriptor\nfunc encryptLayer(cc *encconfig.CryptoConfig, dataReader content.ReaderAt, desc ocispec.Descriptor) (ocispec.Descriptor, io.Reader, ocicrypt.EncryptLayerFinalizer, error) {\n\tvar (\n\t\tsize int64\n\t\td    digest.Digest\n\t\terr  error\n\t)\n\n\tencLayerReader, encLayerFinalizer, err := ocicrypt.EncryptLayer(cc.EncryptConfig, ocicrypt.ReaderFromReaderAt(dataReader), desc)\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, nil, nil, err\n\t}\n\n\t// were data touched ?\n\tif encLayerReader != nil {\n\t\tsize = 0\n\t\td = \"\"\n\t} else {\n\t\tsize = desc.Size\n\t\td = desc.Digest\n\t}\n\n\tnewDesc := ocispec.Descriptor{\n\t\tDigest:   d,\n\t\tSize:     size,\n\t\tPlatform: desc.Platform,\n\t}\n\n\tswitch desc.MediaType {\n\tcase images.MediaTypeDockerSchema2LayerGzip:\n\t\tnewDesc.MediaType = encocispec.MediaTypeLayerGzipEnc\n\tcase images.MediaTypeDockerSchema2Layer:\n\t\tnewDesc.MediaType = encocispec.MediaTypeLayerEnc\n\tcase encocispec.MediaTypeLayerGzipEnc:\n\t\tnewDesc.MediaType = encocispec.MediaTypeLayerGzipEnc\n\tcase encocispec.MediaTypeLayerZstdEnc:\n\t\tnewDesc.MediaType = encocispec.MediaTypeLayerZstdEnc\n\tcase encocispec.MediaTypeLayerEnc:\n\t\tnewDesc.MediaType = encocispec.MediaTypeLayerEnc\n\n\t// TODO: Mediatypes to be added in ocispec\n\tcase ocispec.MediaTypeImageLayerGzip:\n\t\tnewDesc.MediaType = encocispec.MediaTypeLayerGzipEnc\n\tcase ocispec.MediaTypeImageLayerZstd:\n\t\tnewDesc.MediaType = encocispec.MediaTypeLayerZstdEnc\n\tcase ocispec.MediaTypeImageLayer:\n\t\tnewDesc.MediaType = encocispec.MediaTypeLayerEnc\n\n\tdefault:\n\t\treturn ocispec.Descriptor{}, nil, nil, fmt.Errorf(\"unsupporter layer MediaType: %s\", desc.MediaType)\n\t}\n\n\treturn newDesc, encLayerReader, encLayerFinalizer, nil\n}\n\n// Copied from containerd/imgcrypt project, copyright The imgcrypt Authors.\n// https://github.com/containerd/imgcrypt/blob/e7500301cabcc9f3cab3daee3f541079b509e95f/images/encryption/encryption.go#LL164C11-L164C11\n// decryptLayer decrypts the layer using the CryptoConfig and creates a new OCI Descriptor.\n// The caller is expected to store the returned plain data and OCI Descriptor\nfunc decryptLayer(cc *encconfig.CryptoConfig, dataReader content.ReaderAt, desc ocispec.Descriptor, unwrapOnly bool) (ocispec.Descriptor, io.Reader, error) {\n\tresultReader, d, err := ocicrypt.DecryptLayer(cc.DecryptConfig, ocicrypt.ReaderFromReaderAt(dataReader), desc, unwrapOnly)\n\tif err != nil || unwrapOnly {\n\t\treturn ocispec.Descriptor{}, nil, err\n\t}\n\n\tnewDesc := ocispec.Descriptor{\n\t\tDigest:   d,\n\t\tSize:     0,\n\t\tPlatform: desc.Platform,\n\t}\n\n\tswitch desc.MediaType {\n\tcase encocispec.MediaTypeLayerGzipEnc:\n\t\tnewDesc.MediaType = images.MediaTypeDockerSchema2LayerGzip\n\tcase encocispec.MediaTypeLayerZstdEnc:\n\t\tnewDesc.MediaType = ocispec.MediaTypeImageLayerZstd\n\tcase encocispec.MediaTypeLayerEnc:\n\t\tnewDesc.MediaType = images.MediaTypeDockerSchema2Layer\n\tdefault:\n\t\treturn ocispec.Descriptor{}, nil, fmt.Errorf(\"unsupporter layer MediaType: %s\", desc.MediaType)\n\t}\n\treturn newDesc, resultReader, nil\n}\n\n// Copied from containerd/imgcrypt project, copyright The imgcrypt Authors.\n// https://github.com/containerd/imgcrypt/blob/e7500301cabcc9f3cab3daee3f541079b509e95f/images/encryption/encryption.go#LL250C5-L250C5\nfunc ingestReader(ctx context.Context, cs content.Ingester, ref string, r io.Reader) (digest.Digest, int64, error) {\n\tcw, err := content.OpenWriter(ctx, cs, content.WithRef(ref))\n\tif err != nil {\n\t\treturn \"\", 0, fmt.Errorf(\"failed to open writer: %w\", err)\n\t}\n\tdefer cw.Close()\n\n\tif _, err := content.CopyReader(cw, r); err != nil {\n\t\treturn \"\", 0, fmt.Errorf(\"copy failed: %w\", err)\n\t}\n\n\tst, err := cw.Status()\n\tif err != nil {\n\t\treturn \"\", 0, fmt.Errorf(\"failed to get state: %w\", err)\n\t}\n\n\tif err := cw.Commit(ctx, st.Offset, \"\"); err != nil {\n\t\tif !errdefs.IsAlreadyExists(err) {\n\t\t\treturn \"\", 0, fmt.Errorf(\"failed commit on ref %q: %w\", ref, err)\n\t\t}\n\t}\n\n\treturn cw.Digest(), st.Offset, nil\n}\n\n// Encrypt Nydus bootstrap layer\nfunc EncryptNydusBootstrap(ctx context.Context, cs content.Store, desc ocispec.Descriptor, encryptRecipients []string) (ocispec.Descriptor, error) {\n\tvar (\n\t\tresultReader      io.Reader\n\t\tnewDesc           ocispec.Descriptor\n\t\tencLayerFinalizer ocicrypt.EncryptLayerFinalizer\n\t)\n\n\tdataReader, err := cs.ReaderAt(ctx, desc)\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, err\n\t}\n\tdefer dataReader.Close()\n\n\tcc, err := enchelpers.CreateCryptoConfig(encryptRecipients, []string{})\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"create encrypt config failed: %w\", err)\n\t}\n\tnewDesc, resultReader, encLayerFinalizer, err = encryptLayer(&cc, dataReader, desc)\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to encrypt bootstrap layer: %w\", err)\n\t}\n\tnewDesc.Annotations = ocicrypt.FilterOutAnnotations(desc.Annotations)\n\n\t// some operations, such as changing recipients, may not touch the layer at all\n\tif resultReader != nil {\n\t\tvar ref string\n\t\t// If we have the digest, write blob with checks\n\t\thaveDigest := newDesc.Digest.String() != \"\"\n\t\tif haveDigest {\n\t\t\tref = fmt.Sprintf(\"encrypted-bootstrap-%s\", newDesc.Digest.String())\n\t\t} else {\n\t\t\tref = fmt.Sprintf(\"encrypted-bootstrap-%d-%d\", rand.Int(), rand.Int())\n\t\t}\n\n\t\tif haveDigest {\n\t\t\t// Write blob if digest is known beforehand\n\t\t\tif err := content.WriteBlob(ctx, cs, ref, resultReader, newDesc); err != nil {\n\t\t\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to write config: %w\", err)\n\t\t\t}\n\t\t} else {\n\t\t\tnewDesc.Digest, newDesc.Size, err = ingestReader(ctx, cs, ref, resultReader)\n\t\t\tif err != nil {\n\t\t\t\treturn ocispec.Descriptor{}, err\n\t\t\t}\n\t\t}\n\t}\n\n\t// After performing encryption, call finalizer to get annotations\n\tif encLayerFinalizer != nil {\n\t\tannotations, err := encLayerFinalizer()\n\t\tif err != nil {\n\t\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"error getting annotations from encLayer finalizer: %w\", err)\n\t\t}\n\t\tfor k, v := range annotations {\n\t\t\tnewDesc.Annotations[k] = v\n\t\t}\n\t}\n\treturn newDesc, err\n}\n\n// Decrypt the Nydus boostrap layer.\n// If unwrapOnly is set we will only try to decrypt the layer encryption key and return,\n// the layer itself won't be decrypted actually.\nfunc DeryptNydusBootstrap(ctx context.Context, cs content.Store, desc ocispec.Descriptor, decryptKeys []string, unwrapOnly bool) (ocispec.Descriptor, error) {\n\tvar (\n\t\tresultReader io.Reader\n\t\tnewDesc      ocispec.Descriptor\n\t)\n\n\tdataReader, err := cs.ReaderAt(ctx, desc)\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, err\n\t}\n\tdefer dataReader.Close()\n\n\tcc, err := enchelpers.CreateCryptoConfig([]string{}, decryptKeys)\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"create decrypt config failed: %w\", err)\n\t}\n\tnewDesc, resultReader, err = decryptLayer(&cc, dataReader, desc, unwrapOnly)\n\tif err != nil || unwrapOnly {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to decrypt bootstrap layer: %w\", err)\n\t}\n\n\tnewDesc.Annotations = ocicrypt.FilterOutAnnotations(desc.Annotations)\n\n\t// some operations, such as changing recipients, may not touch the layer at all\n\tif resultReader != nil {\n\t\tvar ref string\n\t\t// If we have the digest, write blob with checks\n\t\thaveDigest := newDesc.Digest.String() != \"\"\n\t\tif haveDigest {\n\t\t\tref = fmt.Sprintf(\"decrypted-bootstrap-%s\", newDesc.Digest.String())\n\t\t} else {\n\t\t\tref = fmt.Sprintf(\"decrypted-bootstrap-%d-%d\", rand.Int(), rand.Int())\n\t\t}\n\n\t\tif haveDigest {\n\t\t\t// Write blob if digest is known beforehand\n\t\t\tif err := content.WriteBlob(ctx, cs, ref, resultReader, newDesc); err != nil {\n\t\t\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to write config: %w\", err)\n\t\t\t}\n\t\t} else {\n\t\t\tnewDesc.Digest, newDesc.Size, err = ingestReader(ctx, cs, ref, resultReader)\n\t\t\tif err != nil {\n\t\t\t\treturn ocispec.Descriptor{}, err\n\t\t\t}\n\t\t}\n\t}\n\treturn newDesc, err\n}\n"
  },
  {
    "path": "pkg/errdefs/errors.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage errdefs\n\nimport (\n\tstderrors \"errors\"\n\t\"net\"\n\t\"syscall\"\n\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/pkg/errors\"\n)\n\nvar (\n\tErrAlreadyExists   = errdefs.ErrAlreadyExists\n\tErrNotFound        = errdefs.ErrNotFound\n\tErrInvalidArgument = errors.New(\"invalid argument\")\n\tErrUnavailable     = errors.New(\"unavailable\")\n\tErrNotImplemented  = errors.New(\"not implemented\") // represents not supported and unimplemented\n\tErrDeviceBusy      = errors.New(\"device busy\")     // represents not supported and unimplemented\n)\n\n// IsAlreadyExists returns true if the error is due to already exists\nfunc IsAlreadyExists(err error) bool {\n\treturn errors.Is(err, ErrAlreadyExists)\n}\n\n// IsNotFound returns true if the error is due to a missing object\nfunc IsNotFound(err error) bool {\n\treturn errors.Is(err, ErrNotFound)\n}\n\n// IsConnectionClosed returns true if error is due to connection closed\n// this is used when snapshotter closed by sig term\nfunc IsConnectionClosed(err error) bool {\n\tswitch err := err.(type) {\n\tcase *net.OpError:\n\t\treturn err.Err.Error() == \"use of closed network connection\"\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc IsErofsMounted(err error) bool {\n\treturn stderrors.Is(err, syscall.EBUSY)\n}\n"
  },
  {
    "path": "pkg/fanotify/conn/conn.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage conn\n\nimport (\n\t\"bufio\"\n\t\"encoding/json\"\n)\n\ntype Client struct {\n\tReader *bufio.Reader\n}\n\ntype EventInfo struct {\n\tPath    string `json:\"path\"`\n\tSize    uint32 `json:\"size\"`\n\tElapsed uint64 `json:\"elapsed\"`\n}\n\nfunc (c *Client) GetEventInfo() (*EventInfo, error) {\n\teventInfo := EventInfo{}\n\n\teventByte, err := c.Reader.ReadBytes('\\n')\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := json.Unmarshal(eventByte, &eventInfo); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &eventInfo, nil\n}\n"
  },
  {
    "path": "pkg/fanotify/fanotify.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage fanotify\n\nimport (\n\t\"bufio\"\n\t\"encoding/csv\"\n\t\"fmt\"\n\t\"io\"\n\t\"log/syslog\"\n\t\"os\"\n\t\"os/exec\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/fanotify/conn\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/display\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/sirupsen/logrus\"\n)\n\ntype Server struct {\n\tBinaryPath   string\n\tContainerPid uint32\n\tImageName    string\n\tPersistFile  string\n\tReadable     bool\n\tOverwrite    bool\n\tTimeout      time.Duration\n\tClient       *conn.Client\n\tCmd          *exec.Cmd\n\tLogWriter    *syslog.Writer\n}\n\nfunc NewServer(binaryPath string, containerPid uint32, imageName string, persistFile string, readable bool, overwrite bool, timeout time.Duration, logWriter *syslog.Writer) *Server {\n\treturn &Server{\n\t\tBinaryPath:   binaryPath,\n\t\tContainerPid: containerPid,\n\t\tImageName:    imageName,\n\t\tPersistFile:  persistFile,\n\t\tReadable:     readable,\n\t\tOverwrite:    overwrite,\n\t\tTimeout:      timeout,\n\t\tLogWriter:    logWriter,\n\t}\n}\n\nfunc (fserver *Server) RunServer() error {\n\tif !fserver.Overwrite {\n\t\tif file, err := os.Stat(fserver.PersistFile); err == nil && !file.IsDir() {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\tcmd := exec.Command(fserver.BinaryPath)\n\tcmd.SysProcAttr = &syscall.SysProcAttr{\n\t\tCloneflags: syscall.CLONE_NEWNS,\n\t\tSetpgid:    true,\n\t}\n\tcmd.Env = append(cmd.Env, \"_MNTNS_PID=\"+fmt.Sprint(fserver.ContainerPid))\n\tcmd.Env = append(cmd.Env, \"_TARGET=/\")\n\tcmd.Stderr = fserver.LogWriter\n\n\tnotifyR, err := cmd.StdoutPipe()\n\tif err != nil {\n\t\treturn err\n\t}\n\tfserver.Client = &conn.Client{\n\t\tReader: bufio.NewReader(notifyR),\n\t}\n\n\tif err := cmd.Start(); err != nil {\n\t\treturn err\n\t}\n\tfserver.Cmd = cmd\n\n\tgo func() {\n\t\tif err := cmd.Wait(); err != nil {\n\t\t\tlogrus.WithError(err).Errorf(\"Failed to wait for fserver to finish\")\n\t\t}\n\t}()\n\n\tgo func() {\n\t\tif err := fserver.RunReceiver(); err != nil {\n\t\t\tlogrus.WithError(err).Errorf(\"Failed to receive event information from server\")\n\t\t}\n\t}()\n\n\tif fserver.Timeout > 0 {\n\t\tgo func() {\n\t\t\ttime.Sleep(fserver.Timeout)\n\t\t\tfserver.StopServer()\n\t\t}()\n\t}\n\n\treturn nil\n}\n\nfunc (fserver *Server) RunReceiver() error {\n\tf, err := os.OpenFile(fserver.PersistFile, os.O_CREATE|os.O_WRONLY, 0644)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to open file %q\", fserver.PersistFile)\n\t}\n\tdefer f.Close()\n\n\tpersistCsvFile := fmt.Sprintf(\"%s.csv\", fserver.PersistFile)\n\tfCsv, err := os.Create(persistCsvFile)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to create file %q\", persistCsvFile)\n\t}\n\tdefer fCsv.Close()\n\n\tcsvWriter := csv.NewWriter(fCsv)\n\tif err := csvWriter.Write([]string{\"path\", \"size\", \"elapsed\"}); err != nil {\n\t\treturn errors.Wrapf(err, \"failed to write csv header\")\n\t}\n\tcsvWriter.Flush()\n\n\tfor {\n\t\teventInfo, err := fserver.Client.GetEventInfo()\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\tlogrus.Infoln(\"Get EOF from fanotify server, break event receiver\")\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"failed to get event information: %v\", err)\n\t\t}\n\n\t\tif eventInfo != nil {\n\t\t\tfmt.Fprintln(f, eventInfo.Path)\n\n\t\t\tvar line []string\n\t\t\tif fserver.Readable {\n\t\t\t\tline = []string{eventInfo.Path, display.ByteToReadableIEC(eventInfo.Size), display.MicroSecondToReadable(eventInfo.Elapsed)}\n\t\t\t} else {\n\t\t\t\tline = []string{eventInfo.Path, fmt.Sprint(eventInfo.Size), fmt.Sprint(eventInfo.Elapsed)}\n\t\t\t}\n\t\t\tif err := csvWriter.Write(line); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"failed to write csv\")\n\t\t\t}\n\t\t\tcsvWriter.Flush()\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (fserver *Server) StopServer() {\n\tif fserver.Cmd != nil {\n\t\tlogrus.Infof(\"Send SIGTERM signal to process group %d\", fserver.Cmd.Process.Pid)\n\t\tif err := syscall.Kill(-fserver.Cmd.Process.Pid, syscall.SIGTERM); err != nil {\n\t\t\tlogrus.WithError(err).Errorf(\"Stop process group %d failed!\", fserver.Cmd.Process.Pid)\n\t\t}\n\t\tif _, err := fserver.Cmd.Process.Wait(); err != nil {\n\t\t\tlogrus.WithError(err).Errorf(\"Failed to wait for fanotify server\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/filesystem/config.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage filesystem\n\nimport (\n\t\"github.com/containerd/nydus-snapshotter/pkg/cache\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/index\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/manager\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/referrer\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/signature\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/stargz\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/tarfs\"\n\t\"github.com/pkg/errors\"\n)\n\ntype NewFSOpt func(d *Filesystem) error\n\nfunc WithNydusdBinaryPath(p string) NewFSOpt {\n\treturn func(fs *Filesystem) error {\n\t\tfs.nydusdBinaryPath = p\n\t\treturn nil\n\t}\n}\n\nfunc WithManagers(managers []*manager.Manager) NewFSOpt {\n\treturn func(fs *Filesystem) error {\n\t\tif fs.enabledManagers == nil {\n\t\t\tfs.enabledManagers = map[string]*manager.Manager{}\n\t\t}\n\t\tfor _, pm := range managers {\n\t\t\tfs.enabledManagers[pm.FsDriver] = pm\n\t\t}\n\t\treturn nil\n\t}\n}\n\nfunc WithCacheManager(cm *cache.Manager) NewFSOpt {\n\treturn func(fs *Filesystem) error {\n\t\tif cm == nil {\n\t\t\treturn errors.New(\"cache manager cannot be nil\")\n\t\t}\n\n\t\tfs.cacheMgr = cm\n\t\treturn nil\n\t}\n}\n\nfunc WithReferrerManager(rm *referrer.Manager) NewFSOpt {\n\treturn func(fs *Filesystem) error {\n\t\tif rm == nil {\n\t\t\treturn errors.New(\"referrer manager cannot be nil\")\n\t\t}\n\n\t\tfs.referrerMgr = rm\n\t\treturn nil\n\t}\n}\n\nfunc WithIndexManager(im *index.Manager) NewFSOpt {\n\treturn func(fs *Filesystem) error {\n\t\tif im == nil {\n\t\t\treturn errors.New(\"index manager cannot be nil\")\n\t\t}\n\n\t\tfs.indexMgr = im\n\t\treturn nil\n\t}\n}\n\nfunc WithTarfsManager(tm *tarfs.Manager) NewFSOpt {\n\treturn func(fs *Filesystem) error {\n\t\tif tm == nil {\n\t\t\treturn errors.New(\"tarfs manager cannot be nil\")\n\t\t}\n\t\tfs.tarfsMgr = tm\n\t\treturn nil\n\t}\n}\n\nfunc WithVerifier(verifier *signature.Verifier) NewFSOpt {\n\treturn func(fs *Filesystem) error {\n\t\tfs.verifier = verifier\n\t\treturn nil\n\t}\n}\n\nfunc WithRootMountpoint(mountpoint string) NewFSOpt {\n\treturn func(fs *Filesystem) error {\n\t\tfs.rootMountpoint = mountpoint\n\t\treturn nil\n\t}\n}\n\nfunc WithEnableStargz(enable bool) NewFSOpt {\n\treturn func(fs *Filesystem) error {\n\t\tif enable {\n\t\t\tfs.stargzResolver = stargz.NewResolver()\n\t\t}\n\t\treturn nil\n\t}\n}\n"
  },
  {
    "path": "pkg/filesystem/fs.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// Abstraction layer of underlying file systems. The file system could be mounted by one\n// or more nydusd daemons. fs package hides the details\n\npackage filesystem\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"github.com/containerd/containerd/v2/core/snapshots\"\n\t\"github.com/containerd/containerd/v2/core/snapshots/storage\"\n\tsnpkg \"github.com/containerd/containerd/v2/pkg/snapshotters\"\n\t\"github.com/containerd/log\"\n\t\"github.com/mohae/deepcopy\"\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x/sync/errgroup\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/config/daemonconfig\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/cache\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/index\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/manager\"\n\tracache \"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/referrer\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/signature\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/stargz\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/tarfs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/erofs\"\n)\n\ntype Filesystem struct {\n\tfusedevSharedDaemon *daemon.Daemon\n\tfscacheSharedDaemon *daemon.Daemon\n\tenabledManagers     map[string]*manager.Manager\n\tcacheMgr            *cache.Manager\n\treferrerMgr         *referrer.Manager\n\tindexMgr            *index.Manager\n\tstargzResolver      *stargz.Resolver\n\ttarfsMgr            *tarfs.Manager\n\tverifier            *signature.Verifier\n\tnydusdBinaryPath    string\n\trootMountpoint      string\n\tsnapshotMutexMap    sync.Map\n}\n\n// NewFileSystem initialize Filesystem instance\n// It does mount image layers by starting nydusd doing FUSE mount or not.\nfunc NewFileSystem(ctx context.Context, opt ...NewFSOpt) (*Filesystem, error) {\n\tvar fs Filesystem\n\tfor _, o := range opt {\n\t\terr := o(&fs)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tif config.GetDaemonMode() == config.DaemonModeNone {\n\t\treturn &fs, nil\n\t}\n\trecoveringDaemons := make(map[string]*daemon.Daemon, 0)\n\tliveDaemons := make(map[string]*daemon.Daemon, 0)\n\tfor _, fsManager := range fs.enabledManagers {\n\t\terr := fsManager.Recover(ctx, &recoveringDaemons, &liveDaemons)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"reconnect daemons and recover filesystem instance\")\n\t\t}\n\t}\n\n\tvar hasFscacheSharedDaemon = false\n\tvar hasFusedevSharedDaemon = false\n\tfor _, daemon := range liveDaemons {\n\t\tif daemon.States.FsDriver == config.FsDriverFscache {\n\t\t\thasFscacheSharedDaemon = true\n\t\t} else if daemon.States.FsDriver == config.FsDriverFusedev && daemon.IsSharedDaemon() {\n\t\t\thasFusedevSharedDaemon = true\n\t\t}\n\t}\n\tfor _, daemon := range recoveringDaemons {\n\t\tif daemon.States.FsDriver == config.FsDriverFscache {\n\t\t\thasFscacheSharedDaemon = true\n\t\t} else if daemon.States.FsDriver == config.FsDriverFusedev && daemon.IsSharedDaemon() {\n\t\t\thasFusedevSharedDaemon = true\n\t\t}\n\t}\n\n\t// Try to bring up the shared daemon early.\n\t// With found recovering daemons, it must be the case that snapshotter is being restarted.\n\t// Situations that shared daemon is not found:\n\t//   1. The first time this nydus-snapshotter runs\n\t//   2. Daemon record is wrongly deleted from DB. Above reconnecting already gathers\n\t//\t\tall daemons but still not found shared daemon. The best workaround is to start\n\t//\t\ta new nydusd for it.\n\t// TODO: We still need to consider shared daemon the time sequence of initializing daemon,\n\t// start daemon commit its state to DB and retrieving its state.\n\tif fscacheManager, ok := fs.enabledManagers[config.FsDriverFscache]; ok {\n\t\tif !hasFscacheSharedDaemon && fs.fscacheSharedDaemon == nil {\n\t\t\tlog.L.Infof(\"initializing shared nydus daemon for fscache\")\n\t\t\tif err := fs.initSharedDaemon(fscacheManager); err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"start shared nydusd daemon for fscache\")\n\t\t\t}\n\t\t}\n\t} else if hasFscacheSharedDaemon {\n\t\treturn nil, errors.Errorf(\"shared fscache daemon is present, but manager is missing\")\n\t}\n\tif fusedevManager, ok := fs.enabledManagers[config.FsDriverFusedev]; ok {\n\t\tif config.IsFusedevSharedModeEnabled() && !hasFusedevSharedDaemon && fs.fusedevSharedDaemon == nil {\n\t\t\tlog.L.Infof(\"initializing shared nydus daemon for fusedev\")\n\t\t\tif err := fs.initSharedDaemon(fusedevManager); err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"start shared nydusd daemon for fusedev\")\n\t\t\t}\n\t\t}\n\t} else if hasFusedevSharedDaemon {\n\t\treturn nil, errors.Errorf(\"shared fusedev daemon is present, but manager is missing\")\n\t}\n\n\t// Try to bring all persisted and stopped nydusd up and remount Rafs\n\tegRecover, _ := errgroup.WithContext(context.Background())\n\tfor _, d := range recoveringDaemons {\n\t\td := d\n\t\tegRecover.Go(func() error {\n\t\t\td.ClearVestige()\n\t\t\tfsManager, err := fs.getManager(d.States.FsDriver)\n\t\t\tif err != nil {\n\t\t\t\tlog.L.Warnf(\"Failed to get filesystem manager for daemon %s, skipping recovery: %v\", d.States.ID, err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif err := fsManager.StartDaemon(d); err != nil {\n\t\t\t\tlog.L.Warnf(\"Failed to start daemon %s during recovery, skipping: %v\", d.ID(), err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif err := d.WaitUntilState(types.DaemonStateRunning); err != nil {\n\t\t\t\tlog.L.Warnf(\"Failed to wait for daemon %s to become running, skipping: %v\", d.ID(), err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif err := d.RecoverRafsInstances(); err != nil {\n\t\t\t\tlog.L.Warnf(\"Failed to recover mounts for daemon %s, skipping: %v\", d.ID(), err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tfs.TryRetainSharedDaemon(d)\n\t\t\treturn nil\n\t\t})\n\t}\n\tif err := egRecover.Wait(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Only check nydusd binary commit when there are live daemons that may need hot upgrade.\n\tif len(liveDaemons) > 0 {\n\t\tnewNydusImageBinaryCommit, err := daemon.GetDaemonGitCommit(fs.nydusdBinaryPath)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"failed to get git commit from nydusd binary at path: %s\", fs.nydusdBinaryPath)\n\t\t}\n\n\t\tegLive, _ := errgroup.WithContext(context.Background())\n\t\tfor _, d := range liveDaemons {\n\t\t\td := d\n\t\t\tegLive.Go(func() error {\n\t\t\t\tif d.Supervisor == nil {\n\t\t\t\t\tlog.L.Warnf(\"Daemon %s is skipped for hot upgrade because recover policy is not set to 'failover'\", d.ID())\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tdaemonInfo, err := d.GetDaemonInfo()\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.L.Warnf(\"Failed to get daemon info from daemon %s, skipping: %v\", d.ID(), err)\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\t\t\t\tif newNydusImageBinaryCommit != daemonInfo.DaemonVersion().GitCommit {\n\t\t\t\t\tfsManager, err := fs.getManager(d.States.FsDriver)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlog.L.Warnf(\"Failed to get filesystem manager for daemon %s, skipping: %v\", d.ID(), err)\n\t\t\t\t\t\treturn nil\n\t\t\t\t\t}\n\t\t\t\t\tnewDaemon, upgradeErr := fsManager.DoDaemonUpgrade(d, fs.nydusdBinaryPath, fsManager)\n\t\t\t\t\tif upgradeErr != nil {\n\t\t\t\t\t\tlog.L.Warnf(\"Daemon %s hot upgrade failed, skipping: %v\", d.ID(), upgradeErr)\n\t\t\t\t\t\treturn nil\n\t\t\t\t\t}\n\t\t\t\t\tfs.TryRetainSharedDaemon(newDaemon)\n\t\t\t\t} else {\n\t\t\t\t\tfs.TryRetainSharedDaemon(d)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t})\n\t\t}\n\t\tif err := egLive.Wait(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\treturn &fs, nil\n}\n\nfunc (fs *Filesystem) TryRetainSharedDaemon(d *daemon.Daemon) {\n\tswitch d.States.FsDriver {\n\tcase config.FsDriverFscache:\n\t\tif fs.fscacheSharedDaemon == nil {\n\t\t\tlog.L.Debug(\"retain fscache shared daemon\")\n\t\t\tfs.fscacheSharedDaemon = d\n\t\t\td.IncRef()\n\t\t}\n\tcase config.FsDriverFusedev:\n\t\tif fs.fusedevSharedDaemon == nil && d.HostMountpoint() == fs.rootMountpoint {\n\t\t\tlog.L.Debug(\"retain fusedev shared daemon\")\n\t\t\tfs.fusedevSharedDaemon = d\n\t\t\td.IncRef()\n\t\t}\n\t}\n}\n\nfunc (fs *Filesystem) TryStopSharedDaemon() {\n\tif fs.fusedevSharedDaemon != nil {\n\t\tif fs.fusedevSharedDaemon.GetRef() == 1 {\n\t\t\tif fusedevManager, ok := fs.enabledManagers[config.FsDriverFusedev]; ok {\n\t\t\t\tif err := fusedevManager.DestroyDaemon(fs.fusedevSharedDaemon); err != nil {\n\t\t\t\t\tlog.L.WithError(err).Errorf(\"Terminate shared daemon %s failed\", fs.fusedevSharedDaemon.ID())\n\t\t\t\t} else {\n\t\t\t\t\tfs.fusedevSharedDaemon = nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif fs.fscacheSharedDaemon != nil {\n\t\tif fs.fscacheSharedDaemon.GetRef() == 1 {\n\t\t\tif fscacheManager, ok := fs.enabledManagers[config.FsDriverFscache]; ok {\n\t\t\t\tif err := fscacheManager.DestroyDaemon(fs.fscacheSharedDaemon); err != nil {\n\t\t\t\t\tlog.L.WithError(err).Errorf(\"Terminate shared daemon %s failed\", fs.fscacheSharedDaemon.ID())\n\t\t\t\t} else {\n\t\t\t\t\tfs.fscacheSharedDaemon = nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// WaitUntilReady wait until daemon ready by snapshotID, it will wait until nydus domain socket established\n// and the status of nydusd daemon must be ready\nfunc (fs *Filesystem) WaitUntilReady(snapshotID string) error {\n\trafs := racache.RafsGlobalCache.Get(snapshotID)\n\tif rafs == nil {\n\t\t// If NoneDaemon mode, there's no need to wait for daemon ready\n\t\tif config.GetDaemonMode() == config.DaemonModeNone {\n\t\t\treturn nil\n\t\t}\n\t\treturn errors.Wrapf(errdefs.ErrNotFound, \"no instance %s\", snapshotID)\n\t}\n\n\tif rafs.GetFsDriver() == config.FsDriverFscache || rafs.GetFsDriver() == config.FsDriverFusedev {\n\t\td, err := fs.getDaemonByRafs(rafs)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"snapshot id %s daemon id %s\", snapshotID, rafs.DaemonID)\n\t\t}\n\n\t\tif err := d.WaitUntilState(types.DaemonStateRunning); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// For shared daemons, we need to use the correct cache ID to query metrics.\n\t\t// For fscache, the cache is registered with fscacheID (a digest), not the raw snapshot ID.\n\t\t// For fusedev, the cache is registered with the snapshot ID.\n\t\tsid := \"\"\n\t\tif d.IsSharedDaemon() {\n\t\t\tif rafs.GetFsDriver() == config.FsDriverFscache {\n\t\t\t\t// For fscache, use the fscache ID from annotations if available\n\t\t\t\tif fscacheID, ok := rafs.Annotations[racache.AnnoFsCacheID]; ok && fscacheID != \"\" {\n\t\t\t\t\tsid = fscacheID\n\t\t\t\t} else {\n\t\t\t\t\t// Fallback: compute fscacheID if not in annotations yet\n\t\t\t\t\tsid = erofs.FscacheID(rafs.SnapshotID)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// For fusedev, use the snapshot ID directly\n\t\t\t\tsid = rafs.SnapshotID\n\t\t\t}\n\t\t}\n\n\t\tcacheMetrics, err := d.GetCacheMetrics(sid)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed to get cache metric\")\n\t\t}\n\t\tlog.L.Debugf(\"Found %d underlying files for rafs instance %s\", len(cacheMetrics.UnderlyingFiles), rafs.SnapshotID)\n\n\t\t// Lock the daemon's RafsCache when modifying rafs fields to prevent\n\t\t// race conditions with concurrent reads (e.g., during cache cleanup)\n\t\td.RafsCache.Lock()\n\t\trafs.UnderlyingFiles = cacheMetrics.UnderlyingFiles\n\t\td.RafsCache.Unlock()\n\n\t\tfsManager, err := fs.getManager(rafs.GetFsDriver())\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"failed to get manager\")\n\t\t}\n\t\terr = fsManager.UpdateRafsInstance(rafs)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"failed to update rafs instance\")\n\t\t}\n\t\tlog.L.Debugf(\"Nydus remote snapshot %s is ready\", snapshotID)\n\t}\n\n\treturn nil\n}\n\n// Mount will be called when containerd snapshotter prepare remote snapshotter\n// this method will fork nydus daemon and manage it in the internal store, and indexed by snapshotID\n// It must set up all necessary resources during Mount procedure and revoke any step if necessary.\nfunc (fs *Filesystem) Mount(ctx context.Context, snapshotID string, labels map[string]string, s *storage.Snapshot) (err error) {\n\tmu := fs.getSnapshotMutex(snapshotID)\n\tmu.Lock()\n\tdefer mu.Unlock()\n\n\trafs := racache.RafsGlobalCache.Get(snapshotID)\n\tif rafs != nil {\n\t\t// Instance already exists, how could this happen? Can containerd handle this case?\n\t\treturn nil\n\t}\n\n\tfsDriver := config.GetFsDriver()\n\tif label.IsTarfsDataLayer(labels) {\n\t\tfsDriver = config.FsDriverBlockdev\n\t}\n\tisSharedFusedev := fsDriver == config.FsDriverFusedev && config.GetDaemonMode() == config.DaemonModeShared\n\tuseSharedDaemon := fsDriver == config.FsDriverFscache || isSharedFusedev\n\n\tvar imageID string\n\timageID, ok := labels[snpkg.TargetRefLabel]\n\tif !ok {\n\t\t// FIXME: Buildkit does not pass labels defined in containerd's fashion. So\n\t\t// we have to use stargz snapshotter specific labels until Buildkit generalize it the necessary\n\t\t// labels for all remote snapshotters.\n\t\timageID, ok = labels[\"containerd.io/snapshot/remote/stargz.reference\"]\n\t\tif !ok {\n\t\t\treturn errors.Errorf(\"failed to find image ref of snapshot %s, labels %v\", snapshotID, labels)\n\t\t}\n\t}\n\n\trafs, err = racache.NewRafs(snapshotID, imageID, fsDriver)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"create rafs instance %s\", snapshotID)\n\t}\n\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tif umountErr := fs.Umount(ctx, snapshotID); umountErr != nil {\n\t\t\t\tlog.L.WithError(umountErr).Warnf(\"failed to umount snapshot %s during cleanup\", snapshotID)\n\t\t\t}\n\t\t\tracache.RafsGlobalCache.Remove(snapshotID)\n\t\t}\n\t}()\n\n\tfsManager, err := fs.getManager(fsDriver)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"get filesystem manager for snapshot %s\", snapshotID)\n\t}\n\n\tvar d *daemon.Daemon\n\tif fsDriver == config.FsDriverFscache || fsDriver == config.FsDriverFusedev {\n\t\tbootstrap, err := rafs.BootstrapFile()\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"find bootstrap file snapshot %s\", snapshotID)\n\t\t}\n\n\t\t// Nydusd uses cache manager's directory to store blob caches. So cache\n\t\t// manager knows where to find those blobs.\n\t\tcacheDir := fs.cacheMgr.CacheDir()\n\n\t\tif err := fs.copyBlobMetaFiles(bootstrap, cacheDir); err != nil {\n\t\t\tlog.L.Warnf(\"Failed to copy blob.meta files to cache: %v\", err)\n\t\t}\n\n\t\tif useSharedDaemon {\n\t\t\td, err = fs.getSharedDaemon(fsDriver)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\tmp, err := fs.decideDaemonMountpoint(fsDriver, false, rafs)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\td, err = fs.createDaemon(fsManager, config.DaemonModeDedicated, mp, 0)\n\t\t\t// if daemon already exists for snapshotID, just return\n\t\t\tif err != nil && !errdefs.IsAlreadyExists(err) {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\t// Fscache driver stores blob cache bitmap and blob header files here\n\t\tworkDir := rafs.FscacheWorkDir()\n\t\tparams := map[string]string{\n\t\t\tdaemonconfig.Bootstrap: bootstrap,\n\t\t\tdaemonconfig.WorkDir:   workDir,\n\t\t\tdaemonconfig.CacheDir:  cacheDir,\n\t\t}\n\t\tcfg := deepcopy.Copy(*fsManager.DaemonConfig).(daemonconfig.DaemonConfig)\n\t\terr = daemonconfig.SupplementDaemonConfig(cfg, imageID, snapshotID, false, labels, params)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"supplement configuration\")\n\t\t}\n\n\t\t// TODO: How to manage rafs configurations on-disk? separated json config file or DB record?\n\t\t// In order to recover erofs mount, the configuration file has to be persisted.\n\t\tvar configSubDir string\n\t\tif useSharedDaemon {\n\t\t\tconfigSubDir = snapshotID\n\t\t} else {\n\t\t\t// Associate daemon config object when creating a new daemon object to avoid\n\t\t\t// reading disk file again and again.\n\t\t\t// For shared daemon, each rafs instance has its own configuration, so we don't\n\t\t\t// attach a config interface to daemon in this case.\n\t\t\td.Config = cfg\n\t\t}\n\n\t\terr = cfg.DumpFile(d.ConfigFile(configSubDir))\n\t\tif err != nil {\n\t\t\tif errors.Is(err, errdefs.ErrAlreadyExists) {\n\t\t\t\tlog.L.Debugf(\"Configuration file %s already exits\", d.ConfigFile(configSubDir))\n\t\t\t} else {\n\t\t\t\treturn errors.Wrap(err, \"dump daemon configuration file\")\n\t\t\t}\n\t\t}\n\n\t\td.AddRafsInstance(rafs)\n\n\t\t// if publicKey is not empty we should verify bootstrap file of image\n\t\terr = fs.verifier.Verify(labels, bootstrap)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"verify signature of daemon %s\", d.ID())\n\t\t}\n\t}\n\n\tswitch fsDriver {\n\tcase config.FsDriverFscache:\n\t\terr = fs.mountRemote(fsManager, useSharedDaemon, d, rafs)\n\t\tif err != nil {\n\t\t\terr = errors.Wrapf(err, \"mount file system by daemon %s, snapshot %s\", d.ID(), snapshotID)\n\t\t}\n\tcase config.FsDriverFusedev:\n\t\terr = fs.mountRemote(fsManager, useSharedDaemon, d, rafs)\n\t\tif err != nil {\n\t\t\terr = errors.Wrapf(err, \"mount file system by daemon %s, snapshot %s\", d.ID(), snapshotID)\n\t\t}\n\tcase config.FsDriverBlockdev:\n\t\terr = fs.tarfsMgr.MountTarErofs(snapshotID, s, labels, rafs)\n\t\tif err != nil {\n\t\t\terr = errors.Wrapf(err, \"mount tarfs for snapshot %s\", snapshotID)\n\t\t}\n\tcase config.FsDriverNodev:\n\t\t// Nothing to do\n\tcase config.FsDriverProxy:\n\t\tif label.IsNydusProxyMode(labels) {\n\t\t\tif v, ok := labels[label.CRILayerDigest]; ok {\n\t\t\t\trafs.AddAnnotation(label.CRILayerDigest, v)\n\t\t\t}\n\t\t\trafs.AddAnnotation(label.NydusProxyMode, \"true\")\n\t\t\trafs.SetMountpoint(path.Join(rafs.GetSnapshotDir(), \"fs\"))\n\t\t}\n\tdefault:\n\t\terr = errors.Errorf(\"unknown filesystem driver %s for snapshot %s\", fsDriver, snapshotID)\n\t}\n\n\t// Persist it after associate instance after all the states are calculated.\n\tif err == nil {\n\t\tif err := fsManager.AddRafsInstance(rafs); err != nil {\n\t\t\t// In the CoCo scenario, the existence of a rafs instance is not a concern, as the CoCo guest image pull\n\t\t\t// does not utilize snapshots on the host. Therefore, we expect it to pass normally regardless of its existence.\n\t\t\t// However, for the convenience of troubleshooting, we tend to print relevant logs.\n\t\t\tif config.GetFsDriver() == config.FsDriverProxy {\n\t\t\t\tlog.L.Warnf(\"RAFS instance has associated with snapshot %s possibly: %v\", snapshotID, err)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn errors.Wrapf(err, \"create instance %s\", snapshotID)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (fs *Filesystem) getSnapshotMutex(snapshotID string) *sync.Mutex {\n\tmu, _ := fs.snapshotMutexMap.LoadOrStore(snapshotID, &sync.Mutex{})\n\treturn mu.(*sync.Mutex)\n}\n\nfunc (fs *Filesystem) copyBlobMetaFiles(bootstrap, cacheDir string) error {\n\tbootstrapDir := filepath.Dir(bootstrap)\n\tpattern := filepath.Join(bootstrapDir, \"*.blob.meta\")\n\tmatches, err := filepath.Glob(pattern)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"glob blob meta files\")\n\t}\n\n\tfor _, srcPath := range matches {\n\t\tfileName := filepath.Base(srcPath)\n\t\tdstPath := filepath.Join(cacheDir, fileName)\n\n\t\tif err := os.Link(srcPath, dstPath); err != nil {\n\t\t\tlog.L.Warnf(\"Failed to create hardlink for %s: %v, falling back to copy\", fileName, err)\n\t\t\tif err := fs.copyFile(srcPath, dstPath); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"copy blob meta file %s\", fileName)\n\t\t\t}\n\t\t\tlog.L.Debugf(\"Copied blob meta file: %s -> %s\", srcPath, dstPath)\n\t\t} else {\n\t\t\tlog.L.Debugf(\"Created hardlink for blob meta: %s -> %s\", srcPath, dstPath)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (fs *Filesystem) copyFile(src, dst string) error {\n\tsource, err := os.Open(src)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer source.Close()\n\n\tdestination, err := os.Create(dst)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer destination.Close()\n\n\t_, err = io.Copy(destination, source)\n\treturn err\n}\n\nfunc (fs *Filesystem) Umount(_ context.Context, snapshotID string) error {\n\trafs := racache.RafsGlobalCache.Get(snapshotID)\n\tif rafs == nil {\n\t\tlog.L.Debugf(\"no RAFS filesystem instance associated with snapshot %s\", snapshotID)\n\t\treturn nil\n\t}\n\n\tfsDriver := rafs.GetFsDriver()\n\tif fsDriver == config.FsDriverNodev {\n\t\treturn nil\n\t}\n\tfsManager, err := fs.getManager(fsDriver)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"get manager for filesystem instance %s\", rafs.DaemonID)\n\t}\n\n\tswitch fsDriver {\n\tcase config.FsDriverFscache, config.FsDriverFusedev:\n\t\tdaemon, err := fs.getDaemonByRafs(rafs)\n\t\tif err != nil {\n\t\t\tlog.L.Debugf(\"snapshot %s has no associated nydusd\", snapshotID)\n\t\t\treturn errors.Wrapf(err, \"get daemon with ID %s for snapshot %s\", rafs.DaemonID, snapshotID)\n\t\t}\n\n\t\tdaemon.RemoveRafsInstance(snapshotID)\n\t\tif err := fsManager.RemoveRafsInstance(snapshotID); err != nil {\n\t\t\treturn errors.Wrapf(err, \"remove snapshot %s\", snapshotID)\n\t\t}\n\t\tif err := daemon.UmountRafsInstance(rafs); err != nil {\n\t\t\treturn errors.Wrapf(err, \"umount instance %s\", snapshotID)\n\t\t}\n\t\t// Once daemon's reference reaches 0, destroy the whole daemon\n\t\tif daemon.GetRef() == 0 {\n\t\t\tif err := fsManager.DestroyDaemon(daemon); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"destroy daemon %s\", daemon.ID())\n\t\t\t}\n\t\t}\n\tcase config.FsDriverBlockdev:\n\t\tif err := fs.tarfsMgr.UmountTarErofs(snapshotID); err != nil {\n\t\t\treturn errors.Wrapf(err, \"umount tar erofs on snapshot %s\", snapshotID)\n\t\t}\n\t\tif err := fsManager.RemoveRafsInstance(snapshotID); err != nil {\n\t\t\treturn errors.Wrapf(err, \"remove snapshot %s\", snapshotID)\n\t\t}\n\tcase config.FsDriverNodev, config.FsDriverProxy:\n\t\t// For proxy mode, we still need to clean up the DB entry to prevent\n\t\t// \"already exists\" errors on subsequent Mount() calls.\n\t\tif err := fsManager.RemoveRafsInstance(snapshotID); err != nil {\n\t\t\t// Log but don't fail - the entry might not exist\n\t\t\tlog.L.Debugf(\"remove instance %s from DB: %v\", snapshotID, err)\n\t\t}\n\tdefault:\n\t\treturn errors.Errorf(\"unknown filesystem driver %s for snapshot %s\", fsDriver, snapshotID)\n\t}\n\n\treturn nil\n}\n\n// How much space the layer/blob cache filesystem is occupying\n// The blob digest mush have `sha256:` prefixed, otherwise, throw errors.\nfunc (fs *Filesystem) CacheUsage(ctx context.Context, blobDigest string) (snapshots.Usage, error) {\n\tlog.L.Infof(\"cache usage %s\", blobDigest)\n\tdigest := digest.Digest(blobDigest)\n\tif err := digest.Validate(); err != nil {\n\t\treturn snapshots.Usage{}, errors.Wrapf(err, \"invalid blob digest from label %q, digest=%s\",\n\t\t\tsnpkg.TargetLayerDigestLabel, blobDigest)\n\t}\n\tblobID := digest.Hex()\n\treturn fs.cacheMgr.CacheUsage(ctx, blobID)\n}\n\nfunc (fs *Filesystem) RemoveCache(blobDigest string) error {\n\tlog.L.Infof(\"remove cache %s\", blobDigest)\n\tdigest := digest.Digest(blobDigest)\n\tif err := digest.Validate(); err != nil {\n\t\treturn errors.Wrapf(err, \"invalid blob digest from label %q, digest=%s\",\n\t\t\tsnpkg.TargetLayerDigestLabel, blobDigest)\n\t}\n\tblobID := digest.Hex()\n\n\tif fscacheManager, ok := fs.enabledManagers[config.FsDriverFscache]; ok {\n\t\tif fscacheManager != nil {\n\t\t\tc, err := fs.fscacheSharedDaemon.GetClient()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t// delete fscache blob cache file\n\t\t\t// TODO: skip error for blob not existing\n\t\t\tif err := c.UnbindBlob(\"\", blobID); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\n\treturn fs.cacheMgr.RemoveBlobCache(blobID)\n}\n\n// WalkManagers iterates over all enabled managers and calls the provided function\nfunc (fs *Filesystem) WalkManagers(fn func(*manager.Manager) error) error {\n\tfor _, mgr := range fs.enabledManagers {\n\t\tif err := fn(mgr); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// GetCacheConfig returns the cache directory from the cache manager\nfunc (fs *Filesystem) GetCacheDir() (string, error) {\n\tif fs.cacheMgr == nil {\n\t\treturn \"\", errors.New(\"cache manager is not initialized\")\n\t}\n\treturn fs.cacheMgr.CacheDir(), nil\n}\n\n// Try to stop all the running daemons if they are not referenced by any snapshots\n// Clean up resources along with the daemons.\nfunc (fs *Filesystem) Teardown(ctx context.Context) error {\n\tfor _, fsManager := range fs.enabledManagers {\n\t\tif fsManager.FsDriver == config.FsDriverFscache || fsManager.FsDriver == config.FsDriverFusedev {\n\t\t\tfor _, d := range fsManager.ListDaemons() {\n\t\t\t\tfor _, instance := range d.RafsCache.List() {\n\t\t\t\t\terr := fs.Umount(ctx, instance.SnapshotID)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlog.L.Errorf(\"Failed to umount snapshot %s, %s\", instance.SnapshotID, err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// } else if fsManager.FsDriver == config.FsDriverBlockdev {\n\t\t\t// TODO: support tarfs\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (fs *Filesystem) MountPoint(snapshotID string) (string, error) {\n\trafs := racache.RafsGlobalCache.Get(snapshotID)\n\tif rafs != nil {\n\t\treturn rafs.GetMountpoint(), nil\n\t}\n\n\treturn \"\", errdefs.ErrNotFound\n}\n\nfunc (fs *Filesystem) BootstrapFile(id string) (string, error) {\n\trafs := racache.RafsGlobalCache.Get(id)\n\tif rafs == nil {\n\t\treturn \"\", errors.Errorf(\"no RAFS instance for %s\", id)\n\t}\n\treturn rafs.BootstrapFile()\n}\n\n// daemon mountpoint to rafs mountpoint\n// calculate rafs mountpoint for snapshots mount slice.\nfunc (fs *Filesystem) mountRemote(fsManager *manager.Manager, useSharedDaemon bool,\n\td *daemon.Daemon, r *racache.Rafs) error {\n\n\tif useSharedDaemon {\n\t\tif fsManager.FsDriver == config.FsDriverFusedev {\n\t\t\tr.SetMountpoint(path.Join(d.HostMountpoint(), r.SnapshotID))\n\t\t} else {\n\t\t\tr.SetMountpoint(path.Join(r.GetSnapshotDir(), \"mnt\"))\n\t\t}\n\t\tif err := d.SharedMount(r); err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed to mount\")\n\t\t}\n\t} else {\n\t\tr.SetMountpoint(path.Join(d.HostMountpoint()))\n\t\terr := fsManager.StartDaemon(d)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"start daemon\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (fs *Filesystem) decideDaemonMountpoint(fsDriver string, isSharedDaemonMode bool, rafs *racache.Rafs) (string, error) {\n\tm := \"\"\n\n\tif fsDriver == config.FsDriverFscache || fsDriver == config.FsDriverFusedev {\n\t\tif isSharedDaemonMode {\n\t\t\tm = fs.rootMountpoint\n\t\t} else {\n\t\t\tm = path.Join(rafs.GetSnapshotDir(), \"mnt\")\n\t\t}\n\t\tif err := os.MkdirAll(m, 0755); err != nil {\n\t\t\treturn \"\", errors.Wrapf(err, \"create directory %s\", m)\n\t\t}\n\t}\n\n\treturn m, nil\n}\n\n// 1. Create a daemon instance\n// 2. Build command line\n// 3. Start daemon\nfunc (fs *Filesystem) initSharedDaemon(fsManager *manager.Manager) (err error) {\n\tvar daemonMode config.DaemonMode\n\tswitch fsManager.FsDriver {\n\tcase config.FsDriverFscache:\n\t\tdaemonMode = config.DaemonModeShared\n\tcase config.FsDriverFusedev:\n\t\tdaemonMode = config.DaemonModeShared\n\tdefault:\n\t\treturn errors.Errorf(\"unsupported filesystem driver %s\", fsManager.FsDriver)\n\t}\n\n\tmp, err := fs.decideDaemonMountpoint(fsManager.FsDriver, true, nil)\n\tif err != nil {\n\t\treturn err\n\t} else if mp == \"\" {\n\t\treturn errors.Errorf(\"got null mountpoint for fsDriver %s\", fsManager.FsDriver)\n\t}\n\n\td, err := fs.createDaemon(fsManager, daemonMode, mp, 0)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"initialize shared daemon\")\n\t}\n\n\t// FIXME: Daemon record should not be removed after starting daemon failure.\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tif err := fsManager.DeleteDaemon(d); err != nil {\n\t\t\t\tlog.L.Errorf(\"Start nydusd daemon error %v\", err)\n\t\t\t}\n\t\t}\n\t}()\n\n\t// Shared nydusd daemon does not need configuration to start process but\n\t// it is loaded when requesting mount api\n\t// Dump the configuration file since it is reloaded when recovering the nydusd\n\td.Config = *fsManager.DaemonConfig\n\terr = d.Config.DumpFile(d.ConfigFile(\"\"))\n\tif err != nil && !errors.Is(err, errdefs.ErrAlreadyExists) {\n\t\treturn errors.Wrapf(err, \"dump configuration file %s\", d.ConfigFile(\"\"))\n\t}\n\n\tif err := fsManager.StartDaemon(d); err != nil {\n\t\treturn errors.Wrap(err, \"start shared daemon\")\n\t}\n\n\tfs.TryRetainSharedDaemon(d)\n\n\treturn\n}\n\n// createDaemon create new nydus daemon by snapshotID and imageID\nfunc (fs *Filesystem) createDaemon(fsManager *manager.Manager, daemonMode config.DaemonMode,\n\tmountpoint string, ref int32) (d *daemon.Daemon, err error) {\n\topts := []daemon.NewDaemonOpt{\n\t\tdaemon.WithRef(ref),\n\t\tdaemon.WithSocketDir(config.GetSocketRoot()),\n\t\tdaemon.WithConfigDir(config.GetConfigRoot()),\n\t\tdaemon.WithLogDir(config.GetLogDir()),\n\t\tdaemon.WithLogLevel(config.GetLogLevel()),\n\t\tdaemon.WithLogRotationSize(config.GetDaemonLogRotationSize()),\n\t\tdaemon.WithLogToStdout(config.GetLogToStdout()),\n\t\tdaemon.WithNydusdThreadNum(config.GetDaemonThreadsNumber()),\n\t\tdaemon.WithFsDriver(fsManager.FsDriver),\n\t\tdaemon.WithDaemonMode(daemonMode),\n\t}\n\n\tif fsManager.FsDriver == config.FsDriverFusedev {\n\t\topts = append(opts, daemon.WithFailoverPolicy(config.GetDaemonFailoverPolicy()))\n\t}\n\n\t// For fscache driver, no need to provide mountpoint to nydusd daemon.\n\tif mountpoint != \"\" {\n\t\topts = append(opts, daemon.WithMountpoint(mountpoint))\n\t}\n\n\td, err = daemon.NewDaemon(opts...)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"new daemon\")\n\t}\n\n\tif err = fsManager.AddDaemon(d); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif fsManager.SupervisorSet != nil {\n\t\t// Supervisor is strongly associated with real running nydusd daemon.\n\t\tsu := fsManager.SupervisorSet.NewSupervisor(d.ID())\n\t\tif su == nil {\n\t\t\t_ = fsManager.DeleteDaemon(d)\n\t\t\treturn nil, errors.Errorf(\"create supervisor for daemon %s\", d.ID())\n\t\t}\n\t\td.Supervisor = su\n\t}\n\n\treturn d, nil\n}\n\nfunc (fs *Filesystem) getManager(fsDriver string) (*manager.Manager, error) {\n\tif fsManager, ok := fs.enabledManagers[fsDriver]; ok {\n\t\treturn fsManager, nil\n\t}\n\n\treturn nil, errors.Errorf(\"no manager for filesystem driver %s\", fsDriver)\n}\n\nfunc (fs *Filesystem) getSharedDaemon(fsDriver string) (*daemon.Daemon, error) {\n\tswitch fsDriver {\n\tcase config.FsDriverFscache:\n\t\tif fs.fscacheSharedDaemon != nil {\n\t\t\treturn fs.fscacheSharedDaemon, nil\n\t\t}\n\tcase config.FsDriverFusedev:\n\t\tif fs.fusedevSharedDaemon != nil {\n\t\t\treturn fs.fusedevSharedDaemon, nil\n\t\t}\n\t}\n\n\treturn nil, errors.Errorf(\"no shared daemon for filesystem driver %s\", fsDriver)\n}\n\nfunc (fs *Filesystem) getDaemonByRafs(rafs *racache.Rafs) (*daemon.Daemon, error) {\n\tswitch rafs.GetFsDriver() {\n\tcase config.FsDriverFscache, config.FsDriverFusedev:\n\t\tif fsManager, ok := fs.enabledManagers[rafs.GetFsDriver()]; ok {\n\t\t\tif d := fsManager.GetByDaemonID(rafs.DaemonID); d != nil {\n\t\t\t\treturn d, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil, errdefs.ErrNotFound\n}\n\nfunc (fs *Filesystem) GetDaemonByID(id string) (*daemon.Daemon, error) {\n\tfor _, manager := range fs.enabledManagers {\n\t\tif d := manager.GetByDaemonID(id); d != nil {\n\t\t\treturn d, nil\n\t\t}\n\t}\n\treturn nil, errdefs.ErrNotFound\n}\n"
  },
  {
    "path": "pkg/filesystem/index_adaptor.go",
    "content": "/*\n * Copyright (c) 2025. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage filesystem\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\n\tsnpkg \"github.com/containerd/containerd/v2/pkg/snapshotters\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/pkg/errors\"\n)\n\nfunc (fs *Filesystem) IndexDetectEnabled() bool {\n\treturn fs.indexMgr != nil\n}\n\n// CheckIndexAlternative attempts to find a nydus alternative manifest in the original OCI index manifest\nfunc (fs *Filesystem) CheckIndexAlternative(ctx context.Context, labels map[string]string) bool {\n\tif !fs.IndexDetectEnabled() {\n\t\treturn false\n\t}\n\n\tref, ok := labels[snpkg.TargetRefLabel]\n\tif !ok {\n\t\treturn false\n\t}\n\n\tmanifestDigest := digest.Digest(labels[snpkg.TargetManifestDigestLabel])\n\tif manifestDigest.Validate() != nil {\n\t\treturn false\n\t}\n\n\tlogger := log.G(ctx).WithField(\"ref\", ref).WithField(\"digest\", manifestDigest.String())\n\tlogger.Debug(\"attempting index-based nydus detection\")\n\n\t// Early exit if the labels explicitly indicate the presence of a nydus index alternative\n\thasIndexAlternative, ok := labels[label.NydusIndexAlternative]\n\tif ok && hasIndexAlternative == \"true\" {\n\t\tlogger.Debug(\"detected nydus alternative via label\")\n\t\treturn true\n\t}\n\n\tif _, err := fs.indexMgr.CheckIndexAlternative(ctx, ref, manifestDigest); err != nil {\n\t\treturn false\n\t}\n\tlogger.Debug(\"detected nydus alternative via index manifest\")\n\n\treturn true\n}\n\n// TryFetchMetadataFromIndex attempts to fetch metadata from the nydus index alternative\nfunc (fs *Filesystem) TryFetchMetadataFromIndex(ctx context.Context, labels map[string]string, metadataPath string) error {\n\tref, ok := labels[snpkg.TargetRefLabel]\n\tif !ok {\n\t\treturn fmt.Errorf(\"empty label %s\", snpkg.TargetRefLabel)\n\t}\n\n\tmanifestDigest := digest.Digest(labels[snpkg.TargetManifestDigestLabel])\n\tif err := manifestDigest.Validate(); err != nil {\n\t\treturn fmt.Errorf(\"invalid label %s=%s\", snpkg.TargetManifestDigestLabel, manifestDigest)\n\t}\n\n\t// Early exit if the file already exists\n\tif _, err := os.Stat(metadataPath); err == nil {\n\t\tlog.G(ctx).WithField(\"ref\", ref).WithField(\"digest\", manifestDigest.String()).WithField(\"metadataPath\", metadataPath).Debugf(\"metadata file already exists\")\n\t\treturn nil\n\t}\n\n\tif err := fs.indexMgr.TryFetchMetadata(ctx, ref, manifestDigest, metadataPath); err != nil {\n\t\treturn errors.Wrap(err, \"try fetch metadata\")\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/filesystem/referer_adaptor.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage filesystem\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\tsnpkg \"github.com/containerd/containerd/v2/pkg/snapshotters\"\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/pkg/errors\"\n)\n\nfunc (fs *Filesystem) ReferrerDetectEnabled() bool {\n\treturn fs.referrerMgr != nil\n}\n\nfunc (fs *Filesystem) CheckReferrer(ctx context.Context, labels map[string]string) bool {\n\tif !fs.ReferrerDetectEnabled() {\n\t\treturn false\n\t}\n\n\tref, ok := labels[snpkg.TargetRefLabel]\n\tif !ok {\n\t\treturn false\n\t}\n\n\tmanifestDigest := digest.Digest(labels[snpkg.TargetManifestDigestLabel])\n\tif manifestDigest.Validate() != nil {\n\t\treturn false\n\t}\n\n\tif _, err := fs.referrerMgr.CheckReferrer(ctx, ref, manifestDigest); err != nil {\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nfunc (fs *Filesystem) TryFetchMetadata(ctx context.Context, labels map[string]string, metadataPath string) error {\n\tref, ok := labels[snpkg.TargetRefLabel]\n\tif !ok {\n\t\treturn fmt.Errorf(\"empty label %s\", snpkg.TargetRefLabel)\n\t}\n\n\tmanifestDigest := digest.Digest(labels[snpkg.TargetManifestDigestLabel])\n\tif err := manifestDigest.Validate(); err != nil {\n\t\treturn fmt.Errorf(\"invalid label %s=%s\", snpkg.TargetManifestDigestLabel, manifestDigest)\n\t}\n\n\tif err := fs.referrerMgr.TryFetchMetadata(ctx, ref, manifestDigest, metadataPath); err != nil {\n\t\treturn errors.Wrap(err, \"try fetch metadata\")\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/filesystem/stargz_adaptor.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage filesystem\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/KarpelesLab/reflink\"\n\t\"github.com/containerd/containerd/v2/core/snapshots/storage\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/stargz\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/registry\"\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/pkg/errors\"\n)\n\nfunc (fs *Filesystem) UpperPath(id string) string {\n\treturn filepath.Join(config.GetSnapshotsRootDir(), id, \"fs\")\n}\n\nfunc (fs *Filesystem) StargzEnabled() bool {\n\treturn fs.stargzResolver != nil\n}\n\n// Detect if the blob is type of estargz by downloading its footer since estargz image does not\n// have any characteristic annotation.\nfunc (fs *Filesystem) IsStargzDataLayer(labels map[string]string) (bool, *stargz.Blob) {\n\n\tref, layerDigest := registry.ParseLabels(labels)\n\tif ref == \"\" || layerDigest == \"\" {\n\t\treturn false, nil\n\t}\n\n\tlog.L.Infof(\"Checking stargz image ref %s digest %s\", ref, layerDigest)\n\n\tkeychain, err := auth.GetKeyChainByRef(ref, labels)\n\tif err != nil {\n\t\tlog.L.WithError(err).Warn(\"get keychain from image reference\")\n\t\treturn false, nil\n\t}\n\tblob, err := fs.stargzResolver.GetBlob(ref, layerDigest, keychain)\n\tif err != nil {\n\t\tlog.L.WithError(err).Warn(\"get stargz blob\")\n\t\treturn false, nil\n\t}\n\toff, err := blob.GetTocOffset()\n\tif err != nil {\n\t\tlog.L.WithError(err).Warn(\"get toc offset\")\n\t\treturn false, nil\n\t}\n\tif off <= 0 {\n\t\tlog.L.WithError(err).Warnf(\"Invalid stargz toc offset %d\", off)\n\t\treturn false, nil\n\t}\n\n\treturn true, blob\n}\n\nfunc (fs *Filesystem) MergeStargzMetaLayer(ctx context.Context, s storage.Snapshot) error {\n\tmergedDir := fs.UpperPath(s.ParentIDs[0])\n\tmergedBootstrap := filepath.Join(mergedDir, \"image.boot\")\n\tif _, err := os.Stat(mergedBootstrap); err == nil {\n\t\treturn nil\n\t}\n\n\tbootstraps := []string{}\n\tfor idx, snapshotID := range s.ParentIDs {\n\t\tfiles, err := os.ReadDir(fs.UpperPath(snapshotID))\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"read snapshot dir\")\n\t\t}\n\n\t\tbootstrapName := \"\"\n\t\tblobMetaName := \"\"\n\t\tfor _, file := range files {\n\t\t\tif digest.Digest(fmt.Sprintf(\"sha256:%s\", file.Name())).Validate() == nil {\n\t\t\t\tbootstrapName = file.Name()\n\t\t\t}\n\t\t\tif strings.HasSuffix(file.Name(), \"blob.meta\") {\n\t\t\t\tblobMetaName = file.Name()\n\t\t\t}\n\t\t}\n\t\tif bootstrapName == \"\" {\n\t\t\treturn fmt.Errorf(\"can't find bootstrap for snapshot %s\", snapshotID)\n\t\t}\n\n\t\t// The blob meta file is generated in corresponding snapshot dir for each layer,\n\t\t// but we need copy them to fscache work dir for nydusd use. This is not an\n\t\t// efficient method, but currently nydusd only supports reading blob meta files\n\t\t// from the same dir, so it is a workaround. If performance is a concern, it is\n\t\t// best to convert the estargz image TOC file to a bootstrap / blob meta file\n\t\t// at build time.\n\t\tif blobMetaName != \"\" && idx != 0 {\n\t\t\tsourcePath := filepath.Join(fs.UpperPath(snapshotID), blobMetaName)\n\t\t\t// This path is same with `d.FscacheWorkDir()`, it's for fscache work dir.\n\t\t\ttargetPath := filepath.Join(fs.UpperPath(s.ParentIDs[0]), blobMetaName)\n\t\t\tif err := reflink.Auto(sourcePath, targetPath); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"copy source blob.meta to target\")\n\t\t\t}\n\t\t}\n\n\t\tbootstrapPath := filepath.Join(fs.UpperPath(snapshotID), bootstrapName)\n\t\tbootstraps = append([]string{bootstrapPath}, bootstraps...)\n\t}\n\n\tif len(bootstraps) == 1 {\n\t\tif err := reflink.Auto(bootstraps[0], mergedBootstrap); err != nil {\n\t\t\treturn errors.Wrap(err, \"copy source meta blob to target\")\n\t\t}\n\t} else {\n\t\ttf, err := os.CreateTemp(mergedDir, \"merging-stargz\")\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"create temp file for merging stargz layers\")\n\t\t}\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\tos.Remove(tf.Name())\n\t\t\t}\n\t\t\ttf.Close()\n\t\t}()\n\n\t\toptions := []string{\n\t\t\t\"merge\",\n\t\t\t\"--bootstrap\", tf.Name(),\n\t\t}\n\t\toptions = append(options, bootstraps...)\n\t\tcmd := exec.Command(fs.nydusdBinaryPath, options...)\n\t\tcmd.Stderr = os.Stderr\n\t\tcmd.Stdout = os.Stdout\n\t\tlog.G(ctx).Infof(\"nydus image command %v\", options)\n\t\terr = cmd.Run()\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"merging stargz layers\")\n\t\t}\n\n\t\terr = os.Rename(tf.Name(), mergedBootstrap)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"rename merged stargz layers\")\n\t\t}\n\t\tif err := os.Chmod(mergedBootstrap, 0440); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Generate nydus bootstrap from stargz layers\n// Download estargz TOC part from each layer as `nydus-image` conversion source.\n// After conversion, a nydus metadata or bootstrap is used to pointing to each estargz blob\nfunc (fs *Filesystem) PrepareStargzMetaLayer(blob *stargz.Blob, storagePath string, _ map[string]string) error {\n\tref := blob.GetImageReference()\n\tlayerDigest := blob.GetDigest()\n\n\tif !fs.StargzEnabled() {\n\t\treturn fmt.Errorf(\"stargz compatibility is not enabled\")\n\t}\n\n\tblobID := digest.Digest(layerDigest).Hex()\n\tconvertedBootstrap := filepath.Join(storagePath, blobID)\n\tstargzFile := filepath.Join(storagePath, stargz.TocFileName)\n\tif _, err := os.Stat(convertedBootstrap); err == nil {\n\t\treturn nil\n\t}\n\n\tstart := time.Now()\n\tdefer func() {\n\t\tduration := time.Since(start)\n\t\tlog.L.Infof(\"total stargz prepare layer duration %d\", duration.Milliseconds())\n\t}()\n\n\tr, err := blob.ReadToc()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"read TOC, image reference: %s, layer digest: %s\", ref, layerDigest)\n\t}\n\tstarGzToc, err := os.OpenFile(stargzFile, os.O_CREATE|os.O_RDWR, 0640)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"create stargz index\")\n\t}\n\n\tdefer starGzToc.Close()\n\n\t_, err = io.Copy(starGzToc, r)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"save stargz index\")\n\t}\n\terr = os.Chmod(stargzFile, 0440)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tblobMetaPath := filepath.Join(fs.cacheMgr.CacheDir(), fmt.Sprintf(\"%s.blob.meta\", blobID))\n\tif config.GetFsDriver() == config.FsDriverFscache {\n\t\t// For fscache, the cache directory is managed linux fscache driver, so the blob.meta file\n\t\t// can't be stored there.\n\t\tif err := os.MkdirAll(storagePath, 0750); err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed to create fscache work dir %s\", storagePath)\n\t\t}\n\t\tblobMetaPath = filepath.Join(storagePath, fmt.Sprintf(\"%s.blob.meta\", blobID))\n\t}\n\n\ttf, err := os.CreateTemp(storagePath, \"converting-stargz\")\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"create temp file for merging stargz layers\")\n\t}\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tos.Remove(tf.Name())\n\t\t}\n\t\ttf.Close()\n\t}()\n\n\toptions := []string{\n\t\t\"create\",\n\t\t\"--source-type\", \"stargz_index\",\n\t\t\"--bootstrap\", tf.Name(),\n\t\t\"--blob-id\", blobID,\n\t\t\"--repeatable\",\n\t\t\"--disable-check\",\n\t\t// FIXME: allow user to specify fs version and automatically detect\n\t\t// chunk size and compressor from estargz TOC file.\n\t\t\"--fs-version\", \"6\",\n\t\t\"--chunk-size\", \"0x400000\",\n\t\t\"--blob-meta\", blobMetaPath,\n\t}\n\toptions = append(options, filepath.Join(storagePath, stargz.TocFileName))\n\tcmd := exec.Command(fs.nydusdBinaryPath, options...)\n\tcmd.Stderr = os.Stderr\n\tcmd.Stdout = os.Stdout\n\tlog.L.Infof(\"nydus image command %v\", options)\n\terr = cmd.Run()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"converting stargz layer\")\n\t}\n\n\terr = os.Rename(tf.Name(), convertedBootstrap)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"rename converted stargz layer\")\n\t}\n\n\tif err := os.Chmod(convertedBootstrap, 0440); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (fs *Filesystem) StargzLayer(labels map[string]string) bool {\n\treturn labels[label.StargzLayer] != \"\"\n}\n"
  },
  {
    "path": "pkg/filesystem/tarfs_adaptor.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage filesystem\n\nimport (\n\t\"context\"\n\n\t\"github.com/containerd/containerd/v2/core/snapshots/storage\"\n\tsnpkg \"github.com/containerd/containerd/v2/pkg/snapshotters\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/pkg/errors\"\n)\n\nfunc (fs *Filesystem) TarfsEnabled() bool {\n\treturn fs.tarfsMgr != nil\n}\n\nfunc (fs *Filesystem) PrepareTarfsLayer(ctx context.Context, labels map[string]string, snapshotID, upperDirPath string) error {\n\tref, ok := labels[snpkg.TargetRefLabel]\n\tif !ok {\n\t\treturn errors.Errorf(\"not found image reference label\")\n\t}\n\tlayerDigest := digest.Digest(labels[snpkg.TargetLayerDigestLabel])\n\tif layerDigest.Validate() != nil {\n\t\treturn errors.Errorf(\"not found layer digest label\")\n\t}\n\tmanifestDigest := digest.Digest(labels[snpkg.TargetManifestDigestLabel])\n\tif manifestDigest.Validate() != nil {\n\t\treturn errors.Errorf(\"not found manifest digest label\")\n\t}\n\n\tok, err := fs.tarfsMgr.CheckTarfsHintAnnotation(ctx, ref, manifestDigest)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"check tarfs hint annotaion\")\n\t}\n\tif !ok {\n\t\treturn errors.Errorf(\"this image is not recommended for tarfs\")\n\t}\n\n\tlimiter := fs.tarfsMgr.GetConcurrentLimiter(ref)\n\tif limiter != nil {\n\t\tif err := limiter.Acquire(context.Background(), 1); err != nil {\n\t\t\treturn errors.Wrapf(err, \"concurrent limiter acquire\")\n\t\t}\n\t}\n\n\tif err := fs.tarfsMgr.PrepareLayer(snapshotID, ref, manifestDigest, layerDigest, upperDirPath); err != nil {\n\t\tlog.L.WithError(err).Errorf(\"async prepare tarfs layer of snapshot ID %s\", snapshotID)\n\t}\n\tif limiter != nil {\n\t\tlimiter.Release(1)\n\t}\n\n\tlayerBlobID := layerDigest.Hex()\n\tlabels[label.NydusTarfsLayer] = layerBlobID\n\n\treturn nil\n}\n\nfunc (fs *Filesystem) MergeTarfsLayers(s storage.Snapshot, storageLocater func(string) string) error {\n\treturn fs.tarfsMgr.MergeLayers(s, storageLocater)\n}\n\nfunc (fs *Filesystem) DetachTarfsLayer(snapshotID string) error {\n\treturn fs.tarfsMgr.DetachLayer(snapshotID)\n}\n\nfunc (fs *Filesystem) ExportBlockData(s storage.Snapshot, perLayer bool, labels map[string]string,\n\tstorageLocater func(string) string) ([]string, error) {\n\treturn fs.tarfsMgr.ExportBlockData(s, perLayer, labels, storageLocater)\n}\n\nfunc (fs *Filesystem) GetTarfsImageDiskFilePath(id string) (string, error) {\n\tif fs.tarfsMgr == nil {\n\t\treturn \"\", errors.New(\"tarfs mode is not enabled\")\n\t}\n\treturn fs.tarfsMgr.ImageDiskFilePath(id), nil\n}\n\nfunc (fs *Filesystem) GetTarfsLayerDiskFilePath(id string) (string, error) {\n\tif fs.tarfsMgr == nil {\n\t\treturn \"\", errors.New(\"tarfs mode is not enabled\")\n\t}\n\treturn fs.tarfsMgr.LayerDiskFilePath(id), nil\n}\n"
  },
  {
    "path": "pkg/index/detector.go",
    "content": "/*\n * Copyright (c) 2025. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage index\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"slices\"\n\n\t\"github.com/containerd/platforms\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/converter\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote\"\n)\n\n// Containerd restricts the max size of manifest index to 8M, follow it.\nconst maxManifestIndexSize = 0x800000\n\ntype detector struct {\n\tremote *remote.Remote\n}\n\nfunc newDetector(keyChain *auth.PassKeyChain, insecure bool) *detector {\n\treturn &detector{\n\t\tremote: remote.New(keyChain, insecure),\n\t}\n}\n\n// checkIndexAlternative attempts to find a nydus alternative manifest\n// within an OCI index manifest for the specified manifest digest.\nfunc (d *detector) checkIndexAlternative(ctx context.Context, ref string, manifestDigest digest.Digest) (*ocispec.Descriptor, error) {\n\thandle := func() (*ocispec.Descriptor, error) {\n\t\t// Create a new fetcher to request.\n\t\tfetcher, err := d.remote.Fetcher(ctx, ref)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"get fetcher\")\n\t\t}\n\n\t\tresolver := d.remote.Resolve(ctx, ref)\n\t\t_, desc, err := resolver.Resolve(ctx, ref)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"resolve reference %s\", ref)\n\t\t}\n\n\t\trc, err := fetcher.Fetch(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"fetch index manifest\")\n\t\t}\n\t\tdefer rc.Close()\n\n\t\t// Parse image manifest list from index.\n\t\tvar index ocispec.Index\n\t\tbytes, err := io.ReadAll(io.LimitReader(rc, maxManifestIndexSize))\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"read index manifest\")\n\t\t}\n\t\tif err := json.Unmarshal(bytes, &index); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"unmarshal index manifest\")\n\t\t}\n\n\t\tnydusDesc, err := d.findNydusManifestInIndex(index, manifestDigest)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\trc, err = fetcher.Fetch(ctx, *nydusDesc)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"fetch nydus image manifest\")\n\t\t}\n\t\tdefer rc.Close()\n\n\t\tvar manifest ocispec.Manifest\n\t\tbytes, err = io.ReadAll(rc)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"read manifest\")\n\t\t}\n\t\tif err := json.Unmarshal(bytes, &manifest); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"unmarshal manifest\")\n\t\t}\n\t\tif len(manifest.Layers) < 1 {\n\t\t\treturn nil, fmt.Errorf(\"invalid manifest\")\n\t\t}\n\t\tmetaLayer := manifest.Layers[len(manifest.Layers)-1]\n\t\tif !label.IsNydusMetaLayer(metaLayer.Annotations) {\n\t\t\treturn nil, fmt.Errorf(\"invalid nydus manifest\")\n\t\t}\n\n\t\treturn &metaLayer, nil\n\t}\n\n\tdesc, err := handle()\n\tif err != nil && d.remote.RetryWithPlainHTTP(ref, err) {\n\t\treturn handle()\n\t}\n\n\treturn desc, err\n}\n\n// findNydusManifestInIndex finds a nydus alternative manifest within an OCI index\n// for the specified manifest digest. It returns the nydus manifest descriptor.\nfunc (d *detector) findNydusManifestInIndex(index ocispec.Index, originalDigest digest.Digest) (*ocispec.Descriptor, error) {\n\tvar originalDesc *ocispec.Descriptor\n\tfor _, manifest := range index.Manifests {\n\t\tif manifest.Digest == originalDigest {\n\t\t\toriginalDesc = &manifest\n\t\t\tbreak\n\t\t}\n\t}\n\tif originalDesc == nil {\n\t\treturn nil, fmt.Errorf(\"original manifest %s not found in index\", originalDigest)\n\t}\n\n\tpMatcher := platforms.NewMatcher(*originalDesc.Platform)\n\tfor _, manifest := range index.Manifests {\n\t\tif pMatcher.Match(*manifest.Platform) &&\n\t\t\t(d.hasNydusFeatures(manifest.Platform) || d.hasNydusArtifactType(&manifest)) {\n\t\t\treturn &manifest, nil\n\t\t}\n\t}\n\n\treturn nil, fmt.Errorf(\"no nydus alternative found in index for %s\", originalDigest)\n}\n\n// hasNydusFeatures checks if the platform descriptor contains nydus features.\nfunc (d *detector) hasNydusFeatures(platform *ocispec.Platform) bool {\n\tif platform == nil {\n\t\treturn false\n\t}\n\n\treturn slices.Contains(platform.OSFeatures, converter.ManifestOSFeatureNydus)\n}\n\n// hasNydusArtifactType checks if the descriptor is of nydus artifact type.\nfunc (d *detector) hasNydusArtifactType(desc *ocispec.Descriptor) bool {\n\tif desc == nil {\n\t\treturn false\n\t}\n\treturn desc.ArtifactType == converter.ManifestArtifactTypeNydus\n}\n\n// fetchMetadata fetches and unpacks nydus metadata file to specified path.\nfunc (d *detector) fetchMetadata(ctx context.Context, ref string, desc ocispec.Descriptor, metadataPath string) error {\n\thandle := func() error {\n\t\tresolver := d.remote.Resolve(ctx, ref)\n\t\tfetcher, err := resolver.Fetcher(ctx, ref)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"get fetcher\")\n\t\t}\n\n\t\trc, err := fetcher.Fetch(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"fetch nydus metadata\")\n\t\t}\n\t\tdefer rc.Close()\n\n\t\t// Unpack nydus metadata file to specified path.\n\t\tif err := remote.Unpack(rc, converter.BootstrapFileNameInLayer, metadataPath); err != nil {\n\t\t\tos.Remove(metadataPath)\n\t\t\treturn errors.Wrap(err, \"unpack metadata from layer\")\n\t\t}\n\n\t\treturn nil\n\t}\n\n\terr := handle()\n\tif err != nil && d.remote.RetryWithPlainHTTP(ref, err) {\n\t\treturn handle()\n\t}\n\n\treturn err\n}\n"
  },
  {
    "path": "pkg/index/detector_test.go",
    "content": "/*\n * Copyright (c) 2025. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage index\n\nimport (\n\t\"testing\"\n\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestHasNydusFeatures(t *testing.T) {\n\td := &detector{}\n\n\ttests := []struct {\n\t\tname     string\n\t\tplatform *ocispec.Platform\n\t\texpected bool\n\t}{\n\t\t{\n\t\t\tname:     \"nil platform\",\n\t\t\tplatform: nil,\n\t\t\texpected: false,\n\t\t},\n\t\t{\n\t\t\tname: \"platform without os features\",\n\t\t\tplatform: &ocispec.Platform{\n\t\t\t\tOS:           \"linux\",\n\t\t\t\tArchitecture: \"amd64\",\n\t\t\t},\n\t\t\texpected: false,\n\t\t},\n\t\t{\n\t\t\tname: \"platform with nydus features\",\n\t\t\tplatform: &ocispec.Platform{\n\t\t\t\tOS:           \"linux\",\n\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\tOSFeatures:   []string{\"nydus.remoteimage.v1\"},\n\t\t\t},\n\t\t\texpected: true,\n\t\t},\n\t\t{\n\t\t\tname: \"platform with multiple features including nydus\",\n\t\t\tplatform: &ocispec.Platform{\n\t\t\t\tOS:           \"linux\",\n\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\tOSFeatures:   []string{\"feature1\", \"nydus.remoteimage.v1\", \"feature2\"},\n\t\t\t},\n\t\t\texpected: true,\n\t\t},\n\t\t{\n\t\t\tname: \"platform with non-nydus features\",\n\t\t\tplatform: &ocispec.Platform{\n\t\t\t\tOS:           \"linux\",\n\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\tOSFeatures:   []string{\"feature1\", \"feature2\"},\n\t\t\t},\n\t\t\texpected: false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tresult := d.hasNydusFeatures(tt.platform)\n\t\t\tassert.Equal(t, tt.expected, result)\n\t\t})\n\t}\n}\n\nfunc TestFindNydusManifestInIndex(t *testing.T) {\n\td := &detector{}\n\n\tmanifestDigest := digest.FromString(\"test-manifest\")\n\tnydusManifestDigest := digest.FromString(\"nydus-manifest\")\n\n\ttests := []struct {\n\t\tname           string\n\t\tindex          ocispec.Index\n\t\tmanifestDigest digest.Digest\n\t\texpectedDigest *digest.Digest\n\t\texpectError    bool\n\t\terrorContains  string\n\t}{\n\t\t{\n\t\t\tname: \"original manifest not found in index\",\n\t\t\tindex: ocispec.Index{\n\t\t\t\tManifests: []ocispec.Descriptor{},\n\t\t\t},\n\t\t\tmanifestDigest: manifestDigest,\n\t\t\texpectError:    true,\n\t\t\terrorContains:  \"not found in index\",\n\t\t},\n\t\t{\n\t\t\tname: \"no nydus alternative found\",\n\t\t\tindex: ocispec.Index{\n\t\t\t\tManifests: []ocispec.Descriptor{\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: manifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: digest.FromString(\"other-manifest\"),\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmanifestDigest: manifestDigest,\n\t\t\texpectError:    true,\n\t\t\terrorContains:  \"no nydus alternative found\",\n\t\t},\n\t\t{\n\t\t\tname: \"nydus alternative found\",\n\t\t\tindex: ocispec.Index{\n\t\t\t\tManifests: []ocispec.Descriptor{\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: manifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: nydusManifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t\tOSFeatures:   []string{\"nydus.remoteimage.v1\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmanifestDigest: manifestDigest,\n\t\t\texpectedDigest: &nydusManifestDigest,\n\t\t\texpectError:    false,\n\t\t},\n\t\t{\n\t\t\tname: \"multiple nydus alternatives, returns first match\",\n\t\t\tindex: ocispec.Index{\n\t\t\t\tManifests: []ocispec.Descriptor{\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: manifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: nydusManifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t\tOSFeatures:   []string{\"nydus.remoteimage.v1\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: digest.FromString(\"second-nydus-manifest\"),\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t\tOSFeatures:   []string{\"nydus.remoteimage.v1\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmanifestDigest: manifestDigest,\n\t\t\texpectedDigest: &nydusManifestDigest,\n\t\t\texpectError:    false,\n\t\t},\n\t\t{\n\t\t\tname: \"nydus alternative with different architecture ignored\",\n\t\t\tindex: ocispec.Index{\n\t\t\t\tManifests: []ocispec.Descriptor{\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: manifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: digest.FromString(\"nydus-arm64\"),\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"arm64\",\n\t\t\t\t\t\t\tOSFeatures:   []string{\"nydus.remoteimage.v1\"},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmanifestDigest: manifestDigest,\n\t\t\texpectError:    true,\n\t\t\terrorContains:  \"no nydus alternative found\",\n\t\t},\n\t\t{\n\t\t\tname: \"nydus alternative found with artifact type\",\n\t\t\tindex: ocispec.Index{\n\t\t\t\tManifests: []ocispec.Descriptor{\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: manifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: nydusManifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\tArtifactType: \"application/vnd.nydus.image.manifest.v1+json\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmanifestDigest: manifestDigest,\n\t\t\texpectedDigest: &nydusManifestDigest,\n\t\t\texpectError:    false,\n\t\t},\n\t\t{\n\t\t\tname: \"different artifact type is ignored\",\n\t\t\tindex: ocispec.Index{\n\t\t\t\tManifests: []ocispec.Descriptor{\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: manifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tDigest: nydusManifestDigest,\n\t\t\t\t\t\tPlatform: &ocispec.Platform{\n\t\t\t\t\t\t\tOS:           \"linux\",\n\t\t\t\t\t\t\tArchitecture: \"amd64\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\tArtifactType: \"application/foo+bar\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmanifestDigest: manifestDigest,\n\t\t\texpectError:    true,\n\t\t\terrorContains:  \"no nydus alternative found\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tresult, err := d.findNydusManifestInIndex(tt.index, tt.manifestDigest)\n\n\t\t\tif tt.expectError {\n\t\t\t\tassert.Error(t, err)\n\t\t\t\tif tt.errorContains != \"\" {\n\t\t\t\t\tassert.Contains(t, err.Error(), tt.errorContains)\n\t\t\t\t}\n\t\t\t\tassert.Nil(t, result)\n\t\t\t} else {\n\t\t\t\tassert.NoError(t, err)\n\t\t\t\tassert.NotNil(t, result)\n\t\t\t\tassert.Equal(t, *tt.expectedDigest, result.Digest)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/index/manager.go",
    "content": "/*\n * Copyright (c) 2025. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage index\n\nimport (\n\t\"context\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/golang/groupcache/lru\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x/sync/singleflight\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n)\n\nvar ErrNoNydusAlternative = errors.New(\"no alternative nydus descriptor found in index\")\n\ntype Manager struct {\n\tinsecure bool\n\tcache    *lru.Cache\n\tsg       singleflight.Group\n}\n\nfunc NewManager(insecure bool) *Manager {\n\tmanager := Manager{\n\t\tinsecure: insecure,\n\t\tcache:    lru.New(500),\n\t\tsg:       singleflight.Group{},\n\t}\n\n\treturn &manager\n}\n\n// CheckIndexAlternative attempts to find a nydus alternative manifest\n// within an OCI index manifest for the specified manifest digest.\nfunc (manager *Manager) CheckIndexAlternative(ctx context.Context, ref string, manifestDigest digest.Digest) (*ocispec.Descriptor, error) {\n\tnydusDesc, err, _ := manager.sg.Do(manifestDigest.String(), func() (interface{}, error) {\n\t\t// Try to get nydus metadata layer descriptor from LRU cache.\n\t\tdesc, ok := manager.cache.Get(manifestDigest)\n\t\tif ok {\n\t\t\tmetaLayer, ok := desc.(ocispec.Descriptor)\n\t\t\tif ok {\n\t\t\t\treturn &metaLayer, nil\n\t\t\t}\n\t\t\treturn nil, ErrNoNydusAlternative\n\t\t}\n\n\t\tkeyChain, err := auth.GetKeyChainByRef(ref, nil)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"get key chain\")\n\t\t}\n\n\t\t// No LRU cache found, try to detect nydus alternative in index manifest.\n\t\tdetector := newDetector(keyChain, manager.insecure)\n\t\tmetaLayer, err := detector.checkIndexAlternative(ctx, ref, manifestDigest)\n\t\tif err != nil {\n\t\t\t// Cache empty result to avoid repeated failures.\n\t\t\t// The index manifest can't change as it would change its digest so checking once is enough\n\t\t\tmanager.cache.Add(manifestDigest, nil)\n\t\t\treturn nil, errors.Wrap(err, \"check index alternative\")\n\t\t}\n\n\t\t// Cache the result for future use\n\t\tmanager.cache.Add(manifestDigest, *metaLayer)\n\n\t\treturn metaLayer, nil\n\t})\n\n\tlogger := log.G(ctx).WithField(\"ref\", ref).WithField(\"digest\", manifestDigest.String())\n\tif err == ErrNoNydusAlternative {\n\t\treturn nil, err\n\t} else if err != nil {\n\t\tlogger.WithError(err).Warn(\"index detection failed\")\n\t\treturn nil, err\n\t}\n\n\treturn nydusDesc.(*ocispec.Descriptor), nil\n}\n\n// TryFetchMetadata try to fetch and unpack nydus metadata file to specified path.\nfunc (manager *Manager) TryFetchMetadata(ctx context.Context, ref string, manifestDigest digest.Digest, metadataPath string) error {\n\tmetaLayer, err := manager.CheckIndexAlternative(ctx, ref, manifestDigest)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"check index alternative\")\n\t}\n\n\tkeyChain, err := auth.GetKeyChainByRef(ref, nil)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"get key chain\")\n\t}\n\n\tdetector := newDetector(keyChain, manager.insecure)\n\treturn detector.fetchMetadata(ctx, ref, *metaLayer, metadataPath)\n}\n"
  },
  {
    "path": "pkg/index/manager_test.go",
    "content": "/*\n * Copyright (c) 2025. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage index\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestCheckIndexAlternative(t *testing.T) {\n\tmanifestDigest := digest.FromString(\"test-manifest\")\n\tref := \"registry.example.com/test/repo:latest\"\n\n\texpectedDesc := &ocispec.Descriptor{\n\t\tDigest: digest.FromString(\"meta-layer\"),\n\t}\n\n\tt.Run(\"cache hit, nydus present\", func(t *testing.T) {\n\t\tmanager := NewManager(false)\n\t\tmanager.cache.Add(manifestDigest, *expectedDesc)\n\n\t\tresult, err := manager.CheckIndexAlternative(context.Background(), ref, manifestDigest)\n\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, expectedDesc, result)\n\t})\n\n\tt.Run(\"cache hit, no nydus\", func(t *testing.T) {\n\t\tmanager := NewManager(false)\n\t\tmanager.cache.Add(manifestDigest, nil)\n\n\t\t_, err := manager.CheckIndexAlternative(context.Background(), ref, manifestDigest)\n\n\t\tassert.Error(t, err)\n\t\tassert.Contains(t, err.Error(), \"no alternative nydus descriptor found in index\")\n\t})\n}\n"
  },
  {
    "path": "pkg/label/label.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage label\n\nimport (\n\tsnpkg \"github.com/containerd/containerd/v2/pkg/snapshotters\"\n)\n\n// For package compatibility, we still keep the old exported name here.\nvar AppendLabelsHandlerWrapper = snpkg.AppendInfoHandlerWrapper\n\n// For package compatibility, we still keep the old exported name here.\nconst (\n\tCRIImageRef       = snpkg.TargetRefLabel\n\tCRIImageLayers    = snpkg.TargetImageLayersLabel\n\tCRILayerDigest    = snpkg.TargetLayerDigestLabel\n\tCRIManifestDigest = snpkg.TargetManifestDigestLabel\n)\n\nconst (\n\t// Marker for remote snapshotter to handle the pull request.\n\t// During image pull, the containerd client calls Prepare API with the label containerd.io/snapshot.ref.\n\t// This is a containerd-defined label which contains ChainID that targets a committed snapshot that the\n\t// client is trying to prepare.\n\tTargetSnapshotRef = \"containerd.io/snapshot.ref\"\n\n\t// A bool flag to mark the blob as a Nydus data blob, set by image builders.\n\tNydusDataLayer = \"containerd.io/snapshot/nydus-blob\"\n\t// A bool flag to mark the blob as a nydus bootstrap, set by image builders.\n\tNydusMetaLayer = \"containerd.io/snapshot/nydus-bootstrap\"\n\t// The referenced blob sha256 in format of `sha256:xxx`, set by image builders.\n\tNydusRefLayer = \"containerd.io/snapshot/nydus-ref\"\n\t// The blobID of associated layer, also marking the layer as a nydus tarfs, set by the snapshotter\n\tNydusTarfsLayer = \"containerd.io/snapshot/nydus-tarfs\"\n\t// Dm-verity information for image block device\n\tNydusImageBlockInfo = \"containerd.io/snapshot/nydus-image-block\"\n\t// Dm-verity information for layer block device\n\tNydusLayerBlockInfo = \"containerd.io/snapshot/nydus-layer-block\"\n\t// Annotation containing secret to pull images from registry, set by the snapshotter.\n\tNydusImagePullSecret = \"containerd.io/snapshot/pullsecret\"\n\t// Annotation containing username to pull images from registry, set by the snapshotter.\n\tNydusImagePullUsername = \"containerd.io/snapshot/pullusername\"\n\t// Proxy image pull actions to other agents.\n\tNydusProxyMode = \"containerd.io/snapshot/nydus-proxy-mode\"\n\t// A bool flag to enable integrity verification of meta data blob\n\tNydusSignature = \"containerd.io/snapshot/nydus-signature\"\n\n\t// A bool flag to mark the blob as a estargz data blob, set by the snapshotter.\n\tStargzLayer = \"containerd.io/snapshot/stargz\"\n\n\t// volatileOpt is a key of an optional label to each snapshot.\n\t// If this optional label of a snapshot is specified, when mounted to rootdir\n\t// this snapshot will include volatile option\n\tOverlayfsVolatileOpt = \"containerd.io/snapshot/overlay.volatile\"\n\n\t// A bool flag to mark it is recommended to run this image with tarfs mode, set by image builders.\n\t// runtime can decide whether to rely on this annotation\n\tTarfsHint = \"containerd.io/snapshot/tarfs-hint\"\n\n\t// An alternative nydus index manifest exists in the original OCI index manifest for this snapshot\n\tNydusIndexAlternative = \"containerd.io/snapshot/nydus-index-alternative\"\n)\n\nfunc IsNydusDataLayer(labels map[string]string) bool {\n\t_, ok := labels[NydusDataLayer]\n\treturn ok\n}\n\nfunc IsNydusMetaLayer(labels map[string]string) bool {\n\t_, ok := labels[NydusMetaLayer]\n\treturn ok\n}\n\nfunc IsTarfsDataLayer(labels map[string]string) bool {\n\t_, ok := labels[NydusTarfsLayer]\n\treturn ok\n}\n\nfunc IsNydusProxyMode(labels map[string]string) bool {\n\t_, ok := labels[NydusProxyMode]\n\treturn ok\n}\n\nfunc HasTarfsHint(labels map[string]string) bool {\n\t_, ok := labels[TarfsHint]\n\treturn ok\n}\n"
  },
  {
    "path": "pkg/layout/layout.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage layout\n\nimport (\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"unsafe\"\n)\n\n// RafsV6 layout: 1k + SuperBlock(128) + SuperBlockExtended(256)\n// RafsV5 layout: 8K superblock\n// So we only need to read the MaxSuperBlockSize size to include both v5 and v6 superblocks\nconst MaxSuperBlockSize = 8 * 1024\nconst (\n\tRafsV5                 string = \"v5\"\n\tRafsV6                 string = \"v6\"\n\tRafsV5SuperVersion     uint32 = 0x500\n\tRafsV5SuperMagic       uint32 = 0x5241_4653\n\tRafsV6SuperMagic       uint32 = 0xE0F5_E1E2\n\tRafsV6SuperBlockSize   uint32 = 1024 + 128 + 256\n\tRafsV6SuperBlockOffset uint32 = 1024\n\tRafsV6ChunkInfoOffset  uint32 = 1024 + 128 + 24\n\tBootstrapFile          string = \"image/image.boot\"\n\tLegacyBootstrapFile    string = \"image.boot\"\n\tDummyMountpoint        string = \"/dummy\"\n)\n\nvar nativeEndian binary.ByteOrder\n\ntype ImageMode int\n\nconst (\n\tOnDemand ImageMode = iota\n\tPreLoad\n)\n\nfunc init() {\n\tbuf := [2]byte{}\n\t*(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xABCD)\n\n\tswitch buf {\n\tcase [2]byte{0xCD, 0xAB}:\n\t\tnativeEndian = binary.LittleEndian\n\tcase [2]byte{0xAB, 0xCD}:\n\t\tnativeEndian = binary.BigEndian\n\tdefault:\n\t\tpanic(\"Could not determine native endianness.\")\n\t}\n}\n\nfunc isRafsV6(buf []byte) bool {\n\treturn nativeEndian.Uint32(buf[RafsV6SuperBlockOffset:]) == RafsV6SuperMagic\n}\n\nfunc DetectFsVersion(header []byte) (string, error) {\n\tif len(header) < 8 {\n\t\treturn \"\", errors.New(\"header buffer to DetectFsVersion is too small\")\n\t}\n\tmagic := binary.LittleEndian.Uint32(header[0:4])\n\tfsVersion := binary.LittleEndian.Uint32(header[4:8])\n\tif magic == RafsV5SuperMagic && fsVersion == RafsV5SuperVersion {\n\t\treturn RafsV5, nil\n\t}\n\n\t// FIXME: detect more magic numbers to reduce collision\n\tif len(header) >= int(RafsV6SuperBlockSize) && isRafsV6(header) {\n\t\treturn RafsV6, nil\n\t}\n\n\treturn \"\", errors.New(\"unknown file system header\")\n}\n"
  },
  {
    "path": "pkg/manager/daemon_adaptor.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage manager\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/command\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/collector\"\n\tmetrics \"github.com/containerd/nydus-snapshotter/pkg/metrics/tool\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/prefetch\"\n)\n\nconst endpointGetBackend string = \"/api/v1/daemons/%s/backend\"\n\n// Spawn a nydusd daemon to serve the daemon instance.\n//\n// When returning from `StartDaemon()` with out error:\n//   - `d.States.ProcessID` will be set to the pid of the nydusd daemon.\n//   - `d.State()` may return any validate state, please call `d.WaitUntilState()` to\n//     ensure the daemon has reached specified state.\n//   - `d` may have not been inserted into daemonStates and store yet.\nfunc (m *Manager) StartDaemon(d *daemon.Daemon) error {\n\tcmd, err := m.BuildDaemonCommand(d, \"\", false)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"create command for daemon %s\", d.ID())\n\t}\n\n\tif err := cmd.Start(); err != nil {\n\t\treturn err\n\t}\n\n\td.Lock()\n\tdefer d.Unlock()\n\n\td.States.ProcessID = cmd.Process.Pid\n\n\t// Profile nydusd daemon CPU usage during its startup.\n\tif config.GetDaemonProfileCPUDuration() > 0 {\n\t\tprocessState, err := metrics.GetProcessStat(cmd.Process.Pid)\n\t\tif err == nil {\n\t\t\ttimer := time.NewTimer(time.Duration(config.GetDaemonProfileCPUDuration()) * time.Second)\n\n\t\t\tgo func() {\n\t\t\t\t<-timer.C\n\t\t\t\tcurrentProcessState, err := metrics.GetProcessStat(cmd.Process.Pid)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.L.WithError(err).Warnf(\"Failed to get daemon %s process state.\", d.ID())\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\td.StartupCPUUtilization, err = metrics.CalculateCPUUtilization(processState, currentProcessState)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.L.WithError(err).Warnf(\"Calculate CPU utilization error\")\n\t\t\t\t}\n\t\t\t}()\n\t\t}\n\t}\n\n\t// Update both states cache and DB\n\t// TODO: Is it right to commit daemon before nydusd successfully started?\n\t// And it brings extra latency of accessing DB. Only write daemon record to\n\t// DB when nydusd is started?\n\terr = m.UpdateDaemon(d)\n\tif err != nil {\n\t\t// Nothing we can do, just ignore it for now\n\t\tlog.L.Errorf(\"Fail to update daemon info (%+v) to DB: %v\", d, err)\n\t}\n\n\t// If nydusd fails startup, manager can't subscribe its death event.\n\t// So we can ignore the subscribing error.\n\tgo func() {\n\t\tif err := daemon.WaitUntilSocketExisted(d.GetAPISock(), d.States.ProcessID); err != nil {\n\t\t\t// FIXME: Should clean the daemon record in DB if the nydusd fails starting\n\t\t\tlog.L.Errorf(\"Nydusd %s probably not started\", d.ID())\n\t\t\treturn\n\t\t}\n\n\t\tif err = m.SubscribeDaemonEvent(d); err != nil {\n\t\t\tlog.L.Errorf(\"Nydusd %s probably not started\", d.ID())\n\t\t\treturn\n\t\t}\n\n\t\tif err := d.WaitUntilState(types.DaemonStateRunning); err != nil {\n\t\t\tlog.L.WithError(err).Errorf(\"daemon %s is not managed to reach RUNNING state\", d.ID())\n\t\t\treturn\n\t\t}\n\n\t\tcollector.NewDaemonEventCollector(types.DaemonStateRunning).Collect()\n\n\t\tif m.CgroupMgr != nil {\n\t\t\tif err := m.CgroupMgr.AddProc(d.States.ProcessID); err != nil {\n\t\t\t\tlog.L.WithError(err).Errorf(\"add daemon %s to cgroup failed\", d.ID())\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\td.Lock()\n\t\tcollector.NewDaemonInfoCollector(&d.Version, 1).Collect()\n\t\td.Unlock()\n\n\t\td.SendStates()\n\t}()\n\n\treturn nil\n}\n\n// Build commandline according to nydusd daemon configuration.\nfunc (m *Manager) BuildDaemonCommand(d *daemon.Daemon, bin string, upgrade bool) (*exec.Cmd, error) {\n\tvar cmdOpts []command.Opt\n\tvar imageReference string\n\n\tnydusdThreadNum := d.NydusdThreadNum()\n\n\tif d.States.FsDriver == config.FsDriverFscache {\n\t\tcmdOpts = append(cmdOpts,\n\t\t\tcommand.WithMode(\"singleton\"),\n\t\t\tcommand.WithFscacheDriver(m.cacheDir))\n\t\tif nydusdThreadNum != 0 {\n\t\t\tcmdOpts = append(cmdOpts, command.WithFscacheThreads(nydusdThreadNum))\n\t\t}\n\t} else {\n\t\tcmdOpts = append(cmdOpts, command.WithMode(\"fuse\"), command.WithMountpoint(d.HostMountpoint()))\n\t\tif nydusdThreadNum != 0 {\n\t\t\tcmdOpts = append(cmdOpts, command.WithThreadNum(nydusdThreadNum))\n\t\t}\n\n\t\tswitch {\n\t\tcase d.IsSharedDaemon():\n\t\t\tbreak\n\t\tcase !d.IsSharedDaemon():\n\t\t\trafs := d.RafsCache.Head()\n\t\t\tif rafs == nil {\n\t\t\t\treturn nil, errors.Wrapf(errdefs.ErrNotFound, \"daemon %s no rafs instance associated\", d.ID())\n\t\t\t}\n\n\t\t\timageReference = rafs.ImageID\n\n\t\t\tbootstrap, err := rafs.BootstrapFile()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrapf(err, \"locate bootstrap %s\", bootstrap)\n\t\t\t}\n\n\t\t\tcmdOpts = append(cmdOpts,\n\t\t\t\tcommand.WithConfig(d.ConfigFile(\"\")),\n\t\t\t\tcommand.WithBootstrap(bootstrap),\n\t\t\t)\n\t\t\tif config.IsBackendSourceEnabled() {\n\t\t\t\tconfigAPIPath := fmt.Sprintf(endpointGetBackend, d.States.ID)\n\t\t\t\tcmdOpts = append(cmdOpts,\n\t\t\t\t\tcommand.WithBackendSource(config.SystemControllerAddress()+configAPIPath),\n\t\t\t\t)\n\t\t\t}\n\t\tdefault:\n\t\t\treturn nil, errors.Errorf(\"invalid daemon mode %s \", d.States.DaemonMode)\n\t\t}\n\t}\n\n\tif d.Supervisor != nil {\n\t\tcmdOpts = append(cmdOpts,\n\t\t\tcommand.WithSupervisor(d.Supervisor.Sock()),\n\t\t\tcommand.WithID(d.ID()))\n\t}\n\n\tif imageReference != \"\" {\n\t\tprefetchfiles := prefetch.Pm.GetPrefetchInfo(imageReference)\n\t\tif prefetchfiles != \"\" {\n\t\t\tcmdOpts = append(cmdOpts, command.WithPrefetchFiles(prefetchfiles))\n\t\t\tprefetch.Pm.DeleteFromPrefetchMap(imageReference)\n\t\t}\n\t}\n\n\tcmdOpts = append(cmdOpts,\n\t\tcommand.WithLogLevel(d.States.LogLevel),\n\t\tcommand.WithAPISock(d.GetAPISock()))\n\n\tif d.States.LogRotationSize > 0 {\n\t\tcmdOpts = append(cmdOpts, command.WithLogRotationSize(d.States.LogRotationSize))\n\t}\n\n\tif upgrade {\n\t\tcmdOpts = append(cmdOpts, command.WithUpgrade())\n\t}\n\n\tif !d.States.LogToStdout {\n\t\tcmdOpts = append(cmdOpts, command.WithLogFile(d.LogFile()))\n\t}\n\n\tif d.States.FsDriver == config.FsDriverFusedev {\n\t\tcmdOpts = append(cmdOpts, command.WithFailoverPolicy(d.States.FailoverPolicy))\n\t}\n\n\targs, err := command.BuildCommand(cmdOpts)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar nydusdPath string\n\tif bin != \"\" {\n\t\tnydusdPath = bin\n\t} else {\n\t\tnydusdPath = m.NydusdBinaryPath\n\t}\n\n\tlog.L.Infof(\"nydusd command: %s %s\", nydusdPath, strings.Join(args, \" \"))\n\n\tcmd := exec.Command(nydusdPath, args...)\n\n\t// nydusd standard output and standard error rather than its logs are\n\t// always redirected to snapshotter's respectively\n\tcmd.Stdout = os.Stdout\n\tcmd.Stderr = os.Stderr\n\n\treturn cmd, nil\n}\n"
  },
  {
    "path": "pkg/manager/daemon_cache.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage manager\n\nimport (\n\t\"sync\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n)\n\n// Daemon state cache to speed up access.\ntype DaemonCache struct {\n\tmu            sync.Mutex\n\tidxByDaemonID map[string]*daemon.Daemon // index by ID\n}\n\nfunc newDaemonCache() *DaemonCache {\n\treturn &DaemonCache{\n\t\tidxByDaemonID: make(map[string]*daemon.Daemon),\n\t}\n}\n\n// Return nil if the daemon is never inserted or managed,\n// otherwise returns the previously inserted daemon pointer.\n// Allowing replace an existed daemon since some fields in Daemon can change after restarting nydusd.\nfunc (s *DaemonCache) Add(daemon *daemon.Daemon) *daemon.Daemon {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\told := s.idxByDaemonID[daemon.ID()]\n\ts.idxByDaemonID[daemon.ID()] = daemon\n\treturn old\n}\n\nfunc (s *DaemonCache) removeLocked(d *daemon.Daemon) *daemon.Daemon {\n\told := s.idxByDaemonID[d.ID()]\n\tdelete(s.idxByDaemonID, d.ID())\n\treturn old\n}\n\nfunc (s *DaemonCache) Remove(d *daemon.Daemon) *daemon.Daemon {\n\ts.mu.Lock()\n\told := s.removeLocked(d)\n\ts.mu.Unlock()\n\n\treturn old\n}\n\nfunc (s *DaemonCache) RemoveByDaemonID(id string) *daemon.Daemon {\n\treturn s.GetByDaemonID(id, func(d *daemon.Daemon) { s.removeLocked(d) })\n}\n\n// Also recover daemon runtime state here\nfunc (s *DaemonCache) Update(d *daemon.Daemon) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tlog.L.Infof(\"Recovering daemon ID %s\", d.ID())\n\n\ts.idxByDaemonID[d.ID()] = d\n}\n\nfunc (s *DaemonCache) GetByDaemonID(id string, op func(d *daemon.Daemon)) *daemon.Daemon {\n\tvar daemon *daemon.Daemon\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\tdaemon = s.idxByDaemonID[id]\n\n\tif daemon != nil && op != nil {\n\t\top(daemon)\n\t}\n\n\treturn daemon\n}\n\nfunc (s *DaemonCache) List() []*daemon.Daemon {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif len(s.idxByDaemonID) == 0 {\n\t\treturn nil\n\t}\n\n\tlisted := make([]*daemon.Daemon, 0, len(s.idxByDaemonID))\n\tfor _, d := range s.idxByDaemonID {\n\t\tlisted = append(listed, d)\n\t}\n\n\treturn listed\n}\n\nfunc (s *DaemonCache) Size() int {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\treturn len(s.idxByDaemonID)\n}\n"
  },
  {
    "path": "pkg/manager/daemon_cache_test.go",
    "content": "/*\n   Copyright The nydus Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage manager\n\nimport (\n\t\"testing\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestDaemonStatesCache(t *testing.T) {\n\tstates := newDaemonCache()\n\n\td1 := &daemon.Daemon{States: daemon.ConfigState{ID: \"d1\"}}\n\td2 := &daemon.Daemon{States: daemon.ConfigState{ID: \"d2\"}}\n\n\tstates.Add(d1)\n\tstates.Add(d2)\n\n\tanotherD1 := states.GetByDaemonID(\"d1\", nil)\n\tanotherD2 := states.GetByDaemonID(\"d2\", nil)\n\n\tassert.Equal(t, anotherD1, d1)\n\tassert.Equal(t, anotherD2, d2)\n\n\tdaemons := states.List()\n\tassert.Equal(t, len(daemons), 2)\n\tassert.True(t, daemons[0] == d1 || daemons[1] == d1)\n\tassert.True(t, daemons[0] == d2 || daemons[1] == d2)\n\n\tassert.Equal(t, states.Size(), 2)\n\n\tstates.Remove(d1)\n\n\tassert.Equal(t, states.Size(), 1)\n\n\tstates.RemoveByDaemonID(\"d2\")\n\n\tassert.Equal(t, states.Size(), 0)\n\n\tstates.Update(d2)\n\n\tassert.Equal(t, states.Size(), 1)\n\n\tstates.RemoveByDaemonID(\"d2\")\n\tassert.Equal(t, states.Size(), 0)\n}\n"
  },
  {
    "path": "pkg/manager/daemon_event.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage manager\n\nimport (\n\t\"fmt\"\n\t\"path\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/collector\"\n\t\"github.com/pkg/errors\"\n)\n\nfunc (m *Manager) SubscribeDaemonEvent(d *daemon.Daemon) error {\n\tif err := m.monitor.Subscribe(d.ID(), d.GetAPISock(), m.LivenessNotifier); err != nil {\n\t\tlog.L.Errorf(\"Nydusd %s probably not started\", d.ID())\n\t\treturn errors.Wrapf(err, \"subscribe daemon %s\", d.ID())\n\t}\n\treturn nil\n}\n\nfunc (m *Manager) UnsubscribeDaemonEvent(d *daemon.Daemon) error {\n\t// Starting a new nydusd will re-subscribe\n\tif err := m.monitor.Unsubscribe(d.ID()); err != nil {\n\t\tlog.L.Warnf(\"fail to unsubscribe daemon %s, %v\", d.ID(), err)\n\t\treturn errors.Wrapf(err, \"unsubscribe daemon %s\", d.ID())\n\t}\n\treturn nil\n}\n\nfunc (m *Manager) handleDaemonDeathEvent() {\n\t// TODO: ratelimit for daemon recovery operations?\n\tfor ev := range m.LivenessNotifier {\n\t\tlog.L.Warnf(\"Daemon %s died! socket path %s\", ev.daemonID, ev.path)\n\n\t\td := m.GetByDaemonID(ev.daemonID)\n\t\tif d == nil {\n\t\t\tlog.L.Warnf(\"Daemon %s was not found, may have been removed\", ev.daemonID)\n\t\t\tcontinue\n\t\t}\n\n\t\td.Lock()\n\t\tcollector.NewDaemonInfoCollector(&d.Version, -1).Collect()\n\t\td.Unlock()\n\n\t\td.ResetState()\n\n\t\tswitch m.RecoverPolicy {\n\t\tcase config.RecoverPolicyRestart:\n\t\t\tlog.L.Infof(\"Restart daemon %s\", ev.daemonID)\n\t\t\tgo m.doDaemonRestart(d)\n\t\tcase config.RecoverPolicyFailover:\n\t\t\tlog.L.Infof(\"Do failover for daemon %s\", ev.daemonID)\n\t\t\tgo m.doDaemonFailover(d)\n\t\tdefault:\n\t\t\t// RecoverPolicyNone or RecoverPolicyInvalid - do nothing\n\t\t}\n\t}\n}\n\nfunc (m *Manager) doDaemonFailover(d *daemon.Daemon) {\n\tif err := d.Wait(); err != nil {\n\t\tlog.L.Warnf(\"fail to wait for daemon, %v\", err)\n\t}\n\n\t// Starting a new nydusd will re-subscribe\n\tif err := m.UnsubscribeDaemonEvent(d); err != nil {\n\t\tlog.L.Warnf(\"fail to unsubscribe daemon %s, %v\", d.ID(), err)\n\t}\n\n\tsu := m.SupervisorSet.GetSupervisor(d.ID())\n\tif err := su.SendStatesTimeout(time.Second * 10); err != nil {\n\t\tlog.L.Errorf(\"Send states error, %s\", err)\n\t\treturn\n\t}\n\n\t// Failover nydusd still depends on the old supervisor\n\n\tif err := m.StartDaemon(d); err != nil {\n\t\tlog.L.Errorf(\"fail to start daemon %s when recovering\", d.ID())\n\t\treturn\n\t}\n\n\tif err := d.WaitUntilState(types.DaemonStateInit); err != nil {\n\t\tlog.L.WithError(err).Errorf(\"daemon didn't reach state %s,\", types.DaemonStateInit)\n\t\treturn\n\t}\n\n\tif err := d.TakeOver(); err != nil {\n\t\tlog.L.Errorf(\"fail to takeover, %s\", err)\n\t\treturn\n\t}\n\n\tif err := d.Start(); err != nil {\n\t\tlog.L.Errorf(\"fail to start service, %s\", err)\n\t\treturn\n\t}\n}\n\nfunc (m *Manager) doDaemonRestart(d *daemon.Daemon) {\n\tif err := d.Wait(); err != nil {\n\t\tlog.L.Warnf(\"fails to wait for daemon, %v\", err)\n\t}\n\n\t// Starting a new nydusd will re-subscribe\n\tif err := m.UnsubscribeDaemonEvent(d); err != nil {\n\t\tlog.L.Warnf(\"fails to unsubscribe daemon %s, %v\", d.ID(), err)\n\t}\n\n\td.ClearVestige()\n\tif err := m.StartDaemon(d); err != nil {\n\t\tlog.L.Errorf(\"fails to start daemon %s when recovering\", d.ID())\n\t\treturn\n\t}\n\n\t// Mount rafs instance by http API\n\tinstances := d.RafsCache.List()\n\tfor _, r := range instances {\n\t\t// For dedicated nydusd daemon, Rafs has already been mounted during starting nydusd\n\t\tif d.HostMountpoint() == r.GetMountpoint() {\n\t\t\tbreak\n\t\t}\n\n\t\tif err := d.SharedMount(r); err != nil {\n\t\t\tlog.L.Warnf(\"Failed to mount rafs instance, %v\", err)\n\t\t}\n\t}\n}\n\n// Provide minimal parameters since most of it can be recovered by nydusd states.\n// Create a new daemon in Manger to take over the service.\nfunc (m *Manager) DoDaemonUpgrade(d *daemon.Daemon, nydusdPath string, manager *Manager) (*daemon.Daemon, error) {\n\tsupervisor := d.Supervisor\n\n\tnewDaemon := &daemon.Daemon{\n\t\tStates:     d.States,\n\t\tSupervisor: supervisor,\n\t}\n\tnewDaemon.CloneRafsInstances(d)\n\n\ts := path.Base(d.GetAPISock())\n\tnext, err := buildNextAPISocket(s)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tupgradingSocket := path.Join(path.Dir(d.GetAPISock()), next)\n\tnewDaemon.States.APISocket = upgradingSocket\n\n\tcmd, err := manager.BuildDaemonCommand(newDaemon, nydusdPath, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := supervisor.SendStatesTimeout(time.Second * 10); err != nil {\n\t\treturn nil, errors.Wrap(err, \"Send states\")\n\t}\n\n\tif err := cmd.Start(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"start process\")\n\t}\n\n\tnewDaemon.States.ProcessID = cmd.Process.Pid\n\n\tif err := newDaemon.WaitUntilState(types.DaemonStateInit); err != nil {\n\t\treturn nil, errors.Wrap(err, \"wait until init state\")\n\t}\n\n\tif err := newDaemon.TakeOver(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"take over resources\")\n\t}\n\n\tif err := newDaemon.WaitUntilState(types.DaemonStateReady); err != nil {\n\t\treturn nil, errors.Wrap(err, \"wait unit ready state\")\n\t}\n\n\tif err := manager.UnsubscribeDaemonEvent(d); err != nil {\n\t\treturn nil, errors.Wrap(err, \"unsubscribe daemon event\")\n\t}\n\n\t// Let the older daemon exit without umount\n\tif err := d.Exit(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"old daemon exits\")\n\t}\n\n\tif err := newDaemon.Start(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"start file system service\")\n\t}\n\n\tif err := manager.SubscribeDaemonEvent(newDaemon); err != nil {\n\t\treturn nil, errors.Wrap(err, \"subscribe new daemon event\")\n\t}\n\n\tif err := newDaemon.WaitUntilState(types.DaemonStateRunning); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"wait for daemon %s\", d.ID())\n\t}\n\tif err := newDaemon.RecoverRafsInstances(); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"recover mounts for daemon %s\", d.ID())\n\t}\n\n\tlog.L.Infof(\"Started service of upgraded daemon on socket %s\", newDaemon.GetAPISock())\n\n\tif err := manager.UpdateDaemon(newDaemon); err != nil {\n\t\treturn nil, err\n\t}\n\n\tlog.L.Infof(\"Upgraded daemon success on socket %s\", newDaemon.GetAPISock())\n\treturn newDaemon, err\n}\n\n// Name next api socket path based on currently api socket path listened on.\n// The principle is to add a suffix number to api[0-9]+.sock\nfunc buildNextAPISocket(cur string) (string, error) {\n\tn := strings.Split(cur, \".\")\n\tif len(n) != 2 {\n\t\treturn \"\", errors.Errorf(\"invalid api socket path format: %s\", cur)\n\t}\n\tr := regexp.MustCompile(`[0-9]+`)\n\tm := r.Find([]byte(n[0]))\n\tvar num int\n\tif m == nil {\n\t\tnum = 1\n\t} else {\n\t\tvar err error\n\t\tnum, err = strconv.Atoi(string(m))\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tnum++\n\t}\n\n\tnextSocket := fmt.Sprintf(\"api%d.sock\", num)\n\treturn nextSocket, nil\n}\n"
  },
  {
    "path": "pkg/manager/manager.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage manager\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/config/daemonconfig\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/cgroup\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/collector\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/store\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/supervisor\"\n)\n\n// Manage RAFS filesystem instances and nydusd daemons.\ntype Manager struct {\n\t// Protect fields `store` and `daemonStates`\n\tmu       sync.Mutex\n\tcacheDir string\n\tFsDriver string\n\tstore    Store\n\n\t// Fields below are used to manage nydusd daemons.\n\t//\n\t// The `daemonCache` is cache for nydusd daemons stored in `store`.\n\t// You should update `store` first before modifying cached state.\n\tdaemonCache      *DaemonCache\n\tDaemonConfig     *daemonconfig.DaemonConfig // Daemon configuration template.\n\tCgroupMgr        *cgroup.Manager\n\tmonitor          LivenessMonitor\n\tLivenessNotifier chan deathEvent // TODO: Close me\n\tNydusdBinaryPath string\n\tRecoverPolicy    config.DaemonRecoverPolicy\n\tSupervisorSet    *supervisor.SupervisorsSet\n}\n\ntype Opt struct {\n\tCacheDir         string\n\tCgroupMgr        *cgroup.Manager\n\tDaemonConfig     *daemonconfig.DaemonConfig\n\tDatabase         *store.Database\n\tFsDriver         string\n\tNydusdBinaryPath string\n\tRecoverPolicy    config.DaemonRecoverPolicy\n\tRootDir          string // Nydus-snapshotter work directory\n}\n\nfunc NewManager(opt Opt) (*Manager, error) {\n\ts, err := store.NewDaemonRafsStore(opt.Database)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tmonitor, err := newMonitor()\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"create daemons liveness monitor\")\n\t}\n\n\tvar supervisorSet *supervisor.SupervisorsSet\n\tif opt.RecoverPolicy == config.RecoverPolicyFailover {\n\t\tsupervisorSet, err = supervisor.NewSupervisorSet(filepath.Join(opt.RootDir, \"supervisor\"))\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"create supervisor set\")\n\t\t}\n\t}\n\n\tmgr := &Manager{\n\t\tstore:            s,\n\t\tNydusdBinaryPath: opt.NydusdBinaryPath,\n\t\tcacheDir:         opt.CacheDir,\n\t\tdaemonCache:      newDaemonCache(),\n\t\tmonitor:          monitor,\n\t\tLivenessNotifier: make(chan deathEvent, 32),\n\t\tRecoverPolicy:    opt.RecoverPolicy,\n\t\tSupervisorSet:    supervisorSet,\n\t\tDaemonConfig:     opt.DaemonConfig,\n\t\tCgroupMgr:        opt.CgroupMgr,\n\t\tFsDriver:         opt.FsDriver,\n\t}\n\n\t// FIXME: How to get error if monitor goroutine terminates with error?\n\t// TODO: Shutdown monitor immediately after snapshotter receive Exit signal\n\tmgr.monitor.Run()\n\tgo mgr.handleDaemonDeathEvent()\n\n\treturn mgr, nil\n}\n\nfunc (m *Manager) Lock() {\n\tm.mu.Lock()\n}\n\nfunc (m *Manager) Unlock() {\n\tm.mu.Unlock()\n}\n\nfunc (m *Manager) CacheDir() string {\n\treturn m.cacheDir\n}\n\n// Recover nydusd daemons and RAFS instances on startup.\n//\n// To be safe:\n// - Never ever delete any records from DB\n// - Only cache daemon information from DB, do not actually start/create daemons\n// - Only cache RAFS instance information from DB, do not actually recover RAFS runtime state.\nfunc (m *Manager) Recover(ctx context.Context,\n\trecoveringDaemons *map[string]*daemon.Daemon, liveDaemons *map[string]*daemon.Daemon) error {\n\tif err := m.recoverDaemons(ctx, recoveringDaemons, liveDaemons); err != nil {\n\t\treturn errors.Wrapf(err, \"recover nydusd daemons\")\n\t}\n\tif err := m.recoverRafsInstances(ctx, recoveringDaemons, liveDaemons); err != nil {\n\t\treturn errors.Wrapf(err, \"recover RAFS instances\")\n\t}\n\treturn nil\n}\n\nfunc (m *Manager) AddRafsInstance(r *rafs.Rafs) error {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\n\tseq, err := m.store.NextInstanceSeq()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tr.Seq = seq\n\n\treturn m.store.AddRafsInstance(r)\n}\n\nfunc (m *Manager) UpdateRafsInstance(r *rafs.Rafs) error {\n\treturn m.store.UpdateRafsInstance(r)\n}\n\nfunc (m *Manager) RemoveRafsInstance(snapshotID string) error {\n\treturn m.store.DeleteRafsInstance(snapshotID)\n}\n\nfunc (m *Manager) recoverRafsInstances(ctx context.Context,\n\trecoveringDaemons *map[string]*daemon.Daemon, liveDaemons *map[string]*daemon.Daemon) error {\n\tif err := m.store.WalkRafsInstances(ctx, func(r *rafs.Rafs) error {\n\t\tif r.GetFsDriver() != m.FsDriver {\n\t\t\treturn nil\n\t\t}\n\n\t\tlog.L.Debugf(\"found RAFS instance %#v\", r)\n\t\tif r.GetFsDriver() == config.FsDriverFscache || r.GetFsDriver() == config.FsDriverFusedev {\n\t\t\td := (*recoveringDaemons)[r.DaemonID]\n\t\t\tif d != nil {\n\t\t\t\td.AddRafsInstance(r)\n\t\t\t}\n\t\t\td = (*liveDaemons)[r.DaemonID]\n\t\t\tif d != nil {\n\t\t\t\td.AddRafsInstance(r)\n\t\t\t}\n\t\t\trafs.RafsGlobalCache.Add(r)\n\t\t} else if r.GetFsDriver() == config.FsDriverBlockdev {\n\t\t\trafs.RafsGlobalCache.Add(r)\n\t\t}\n\n\t\treturn nil\n\t}); err != nil {\n\t\treturn errors.Wrapf(err, \"walk instances to reconnect\")\n\t}\n\n\treturn nil\n}\n\n// Add an instantiated daemon to be managed by the manager.\n//\n// Return ErrAlreadyExists if a daemon with the same daemon ID already exists.\nfunc (m *Manager) AddDaemon(daemon *daemon.Daemon) error {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\n\tif old := m.daemonCache.GetByDaemonID(daemon.ID(), nil); old != nil {\n\t\treturn errdefs.ErrAlreadyExists\n\t}\n\tif err := m.store.AddDaemon(daemon); err != nil {\n\t\treturn errors.Wrapf(err, \"add daemon %s\", daemon.ID())\n\t}\n\tm.daemonCache.Add(daemon)\n\treturn nil\n}\n\nfunc (m *Manager) UpdateDaemon(daemon *daemon.Daemon) error {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\n\treturn m.UpdateDaemonLocked(daemon)\n}\n\n// Notice: updating daemon states cache and DB should be protect by `mu` lock\nfunc (m *Manager) UpdateDaemonLocked(daemon *daemon.Daemon) error {\n\tif old := m.daemonCache.GetByDaemonID(daemon.ID(), nil); old == nil {\n\t\treturn errdefs.ErrNotFound\n\t}\n\tif err := m.store.UpdateDaemon(daemon); err != nil {\n\t\treturn errors.Wrapf(err, \"update daemon state for %s\", daemon.ID())\n\t}\n\tm.daemonCache.Add(daemon)\n\treturn nil\n}\n\nfunc (m *Manager) DeleteDaemon(daemon *daemon.Daemon) error {\n\tif daemon == nil {\n\t\treturn nil\n\t}\n\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\n\tif err := m.store.DeleteDaemon(daemon.ID()); err != nil {\n\t\treturn errors.Wrapf(err, \"delete daemon state for %s\", daemon.ID())\n\t}\n\tm.daemonCache.Remove(daemon)\n\treturn nil\n}\n\nfunc (m *Manager) GetByDaemonID(id string) *daemon.Daemon {\n\treturn m.daemonCache.GetByDaemonID(id, nil)\n}\n\nfunc (m *Manager) ListDaemons() []*daemon.Daemon {\n\treturn m.daemonCache.List()\n}\n\n// FIXME: should handle the inconsistent status caused by any step\n// in the function that returns an error.\nfunc (m *Manager) DestroyDaemon(d *daemon.Daemon) error {\n\tlog.L.Infof(\"Destroy nydusd daemon %s. Host mountpoint %s\", d.ID(), d.HostMountpoint())\n\n\t// First remove the record from DB, so any failures below won't cause stale records in DB.\n\tif err := m.DeleteDaemon(d); err != nil {\n\t\treturn errors.Wrapf(err, \"delete daemon %s\", d.ID())\n\t}\n\n\tdefer m.cleanUpDaemonResources(d)\n\n\t// Clean up any remaining RAFS instances that were not individually\n\t// unmounted (e.g., during forced shutdown or error recovery paths).\n\tfor _, r := range d.RafsCache.List() {\n\t\td.RemoveRafsInstance(r.SnapshotID)\n\t}\n\n\tif err := d.UmountRafsInstances(); err != nil {\n\t\tlog.L.Errorf(\"Failed to detach all fs instances from daemon %s, %s\", d.ID(), err)\n\t}\n\n\tif err := m.UnsubscribeDaemonEvent(d); err != nil {\n\t\tlog.L.Warnf(\"Unable to unsubscribe, daemon ID %s, %s\", d.ID(), err)\n\t}\n\n\tif m.SupervisorSet != nil {\n\t\tif err := m.SupervisorSet.DestroySupervisor(d.ID()); err != nil {\n\t\t\tlog.L.Warnf(\"Failed to delete supervisor for daemon %s, %s\", d.ID(), err)\n\t\t}\n\t}\n\n\t// Graceful nydusd termination will umount itself.\n\tif err := d.Terminate(); err != nil {\n\t\tlog.L.Warnf(\"Fails to terminate daemon, %v\", err)\n\t}\n\n\tif err := d.Wait(); err != nil {\n\t\tlog.L.Warnf(\"Failed to wait for daemon, %v\", err)\n\t}\n\n\tcollector.NewDaemonEventCollector(types.DaemonStateDestroyed).Collect()\n\td.Lock()\n\tcollector.NewDaemonInfoCollector(&d.Version, -1).Collect()\n\td.Unlock()\n\n\treturn nil\n}\n\nfunc (m *Manager) cleanUpDaemonResources(d *daemon.Daemon) {\n\t// TODO: use recycle bin to stage directories/files to be deleted.\n\tresource := []string{d.States.ConfigDir, d.States.LogDir}\n\tif !d.IsSharedDaemon() {\n\t\tsocketDir := path.Dir(d.GetAPISock())\n\t\tresource = append(resource, socketDir)\n\t}\n\n\tfor _, dir := range resource {\n\t\tif err := os.RemoveAll(dir); err != nil {\n\t\t\tlog.L.Errorf(\"failed to remove dir %s err %v\", dir, err)\n\t\t}\n\t}\n\n\tlog.L.Infof(\"Deleting resources %v\", resource)\n}\n\nfunc (m *Manager) recoverDaemons(ctx context.Context,\n\trecoveringDaemons *map[string]*daemon.Daemon, liveDaemons *map[string]*daemon.Daemon) error {\n\tif err := m.store.WalkDaemons(ctx, func(s *daemon.ConfigState) error {\n\t\tif s.FsDriver != m.FsDriver {\n\t\t\treturn nil\n\t\t}\n\n\t\tlog.L.Debugf(\"found daemon states %#v\", s)\n\t\topt := make([]daemon.NewDaemonOpt, 0)\n\t\tvar d, _ = daemon.NewDaemon(opt...)\n\t\td.States = *s\n\n\t\tm.daemonCache.Update(d)\n\n\t\tif m.SupervisorSet != nil {\n\t\t\tsu := m.SupervisorSet.NewSupervisor(d.ID())\n\t\t\tif su == nil {\n\t\t\t\treturn errors.Errorf(\"create supervisor for daemon %s\", d.ID())\n\t\t\t}\n\t\t\td.Supervisor = su\n\t\t}\n\n\t\tif d.States.FsDriver == config.FsDriverFusedev {\n\t\t\tcfg, err := daemonconfig.NewDaemonConfig(d.States.FsDriver, d.ConfigFile(\"\"))\n\t\t\tif err != nil {\n\t\t\t\tlog.L.Errorf(\"Failed to reload daemon configuration %s, %s\", d.ConfigFile(\"\"), err)\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\td.Config = cfg\n\t\t}\n\n\t\tstate, err := d.GetState()\n\t\tif err != nil {\n\t\t\tlog.L.Warnf(\"Daemon %s died somehow. Clean up its vestige!, %s\", d.ID(), err)\n\t\t\t(*recoveringDaemons)[d.ID()] = d\n\t\t\t//nolint:nilerr\n\t\t\treturn nil\n\t\t}\n\n\t\tif state != types.DaemonStateRunning {\n\t\t\tlog.L.Warnf(\"daemon %s is not running: %s\", d.ID(), state)\n\t\t\treturn nil\n\t\t}\n\n\t\t// FIXME: Should put the a daemon back file system shared damon field.\n\t\tlog.L.Infof(\"found RUNNING daemon %s during reconnecting\", d.ID())\n\t\t(*liveDaemons)[d.ID()] = d\n\n\t\tif m.CgroupMgr != nil {\n\t\t\tif err := m.CgroupMgr.AddProc(d.States.ProcessID); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"add daemon %s to cgroup failed\", d.ID())\n\t\t\t}\n\t\t}\n\t\td.Lock()\n\t\tcollector.NewDaemonInfoCollector(&d.Version, 1).Collect()\n\t\td.Unlock()\n\n\t\tgo func() {\n\t\t\tif err := daemon.WaitUntilSocketExisted(d.GetAPISock(), d.Pid()); err != nil {\n\t\t\t\tlog.L.Errorf(\"Nydusd %s probably not started\", d.ID())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif err = m.SubscribeDaemonEvent(d); err != nil {\n\t\t\t\tlog.L.Errorf(\"Nydusd %s probably not started\", d.ID())\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Snapshotter's lost the daemons' states after exit, refetch them.\n\t\t\td.SendStates()\n\t\t}()\n\n\t\treturn nil\n\t}); err != nil {\n\t\treturn errors.Wrapf(err, \"walk daemons to reconnect\")\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/manager/monitor.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage manager\n\nimport (\n\t\"net\"\n\t\"sync\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x/sys/unix\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/collector\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/retry\"\n)\n\n// LivenessMonitor liveness of a nydusd daemon.\ntype LivenessMonitor interface {\n\t// Subscribe death event of a nydusd daemon.\n\t// `path` is where the monitor is listening on.\n\tSubscribe(id string, path string, notifier chan<- deathEvent) error\n\t// Unsubscribe death event of a nydusd daemon.\n\tUnsubscribe(id string) error\n\t// Run the monitor, wait for nydusd death event.\n\tRun()\n\t// Stop the monitor and release all the resources.\n\tDestroy()\n}\n\ntype target struct {\n\t// A connection to the nydusd. Should close it when stopping the liveness monitor!\n\tuc *net.UnixConn\n\t// Notify subscriber that the nydusd is dead via the channel\n\tnotifier chan<- deathEvent\n\t// `id` is usually the daemon ID\n\tid   string\n\tpath string\n}\n\ntype FD = uintptr\n\ntype livenessMonitor struct {\n\tmu sync.Mutex\n\t// Get a subscribing target by the target ID (usually is the daemon ID)\n\tsubscribers map[string]*target\n\t// Get a subscribing target by the connection FD. Each liveness\n\t// probe has a unique connection FD which is listened for epoll event.\n\tset     map[FD]*target\n\tepollFd int\n}\n\ntype deathEvent struct {\n\tdaemonID string\n\tpath     string\n}\n\nfunc newMonitor() (_ *livenessMonitor, err error) {\n\tvar epollFd int\n\tepollFd, err = unix.EpollCreate1(unix.EPOLL_CLOEXEC)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"create daemons monitor\")\n\t}\n\n\tm := &livenessMonitor{\n\t\tepollFd:     epollFd,\n\t\tsubscribers: make(map[string]*target),\n\t\tset:         make(map[uintptr]*target),\n\t}\n\n\treturn m, nil\n}\n\nfunc (m *livenessMonitor) Subscribe(id string, path string, notifier chan<- deathEvent) (err error) {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\n\tif s, ok := m.subscribers[id]; ok && s.path == path {\n\t\tlog.L.Warnf(\"Daemon %s is already subscribed!\", id)\n\t\treturn errdefs.ErrAlreadyExists\n\t}\n\n\tvar (\n\t\tc       net.Conn\n\t\trawConn syscall.RawConn\n\t)\n\n\terr = retry.Do(func() (err error) {\n\t\t// Don't forget close me!\n\t\tif c, err = net.Dial(\"unix\", path); err != nil {\n\t\t\tlog.L.Errorf(\"Fails to connect to %s, %v\", path, err)\n\t\t\treturn\n\t\t}\n\n\t\treturn nil\n\t},\n\t\tretry.LastErrorOnly(true),\n\t\tretry.Attempts(20), // totally wait for 2 seconds, should be enough\n\t\tretry.Delay(100*time.Millisecond))\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tuc, ok := c.(*net.UnixConn)\n\tif !ok {\n\t\treturn errors.Errorf(\"a unix socket connection is required\")\n\t}\n\n\tif rawConn, err = uc.SyscallConn(); err != nil {\n\t\treturn\n\t}\n\n\terr = rawConn.Control(func(fd FD) {\n\t\terr = unix.SetNonblock(int(fd), true)\n\t\tif err != nil {\n\t\t\tlog.L.Errorf(\"Failed to set file. daemon id %s path %s. %v\", id, path, err)\n\t\t\treturn\n\t\t}\n\n\t\tevent := unix.EpollEvent{\n\t\t\tFd:     int32(fd),\n\t\t\tEvents: unix.EPOLLHUP | unix.EPOLLERR | unix.EPOLLET,\n\t\t}\n\n\t\terr = unix.EpollCtl(m.epollFd, unix.EPOLL_CTL_ADD, int(fd), &event)\n\t\tif err != nil {\n\t\t\tlog.L.Errorf(\"Failed to control epoll. daemon id %s path %s. %v\", id, path, err)\n\t\t\treturn\n\t\t}\n\t\ttarget := &target{uc: uc, id: id, path: path}\n\n\t\t// Only add subscribed target when everything is OK.\n\t\tm.set[fd] = target\n\t\tm.subscribers[id] = target\n\t\ttarget.notifier = notifier\n\t})\n\n\tlog.L.Infof(\"Subscribe daemon %s liveness event, path=%s.\", id, path)\n\n\treturn\n}\n\nfunc (m *livenessMonitor) Unsubscribe(id string) (err error) {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\n\treturn m.unsubscribe(id)\n}\n\nfunc (m *livenessMonitor) unsubscribe(id string) (err error) {\n\ttarget, ok := m.subscribers[id]\n\tif !ok {\n\t\treturn errdefs.ErrNotFound\n\t}\n\n\tdelete(m.subscribers, id)\n\n\tvar rawConn syscall.RawConn\n\tif rawConn, err = target.uc.SyscallConn(); err != nil {\n\t\tlog.L.Errorf(\"Fail to access underlying FD, id=%s\", id)\n\t\treturn\n\t}\n\n\t// No longer wait for event, delete it from interest list.\n\tif err = rawConn.Control(func(fd uintptr) {\n\t\tif err := unix.EpollCtl(m.epollFd, unix.EPOLL_CTL_DEL, int(fd), &unix.EpollEvent{}); err != nil {\n\t\t\tlog.L.Errorf(\"Fail to delete event fd %d for supervisor %s\", int(fd), id)\n\t\t\treturn\n\t\t}\n\t\tdelete(m.set, fd)\n\t}); err != nil {\n\t\treturn errors.Wrapf(err, \"remove target FD in the interested list, id=%s\", id)\n\t}\n\n\tif err = target.uc.Close(); err != nil {\n\t\tlog.L.Errorf(\"Fails to close unix connection for daemon %s\", id)\n\t\treturn\n\t}\n\n\treturn nil\n}\n\nfunc (m *livenessMonitor) Run() {\n\tvar events [512]unix.EpollEvent\n\tgo func() {\n\t\tdefer log.L.Infof(\"Exiting liveness monitor\")\n\t\tlog.L.Infof(\"Run daemons monitor...\")\n\t\tfor {\n\t\t\tn, err := unix.EpollWait(m.epollFd, events[:], -1)\n\t\t\tif err != nil {\n\t\t\t\tif err == unix.EINTR {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// `Destroy` should close the epoll fd thus to exit the goroutine.\n\t\t\t\tlog.L.Errorf(\"Monitor fails to wait events, %v. Exiting!\", err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tfor i := 0; i < n; i++ {\n\t\t\t\tev := events[i]\n\n\t\t\t\tm.mu.Lock()\n\t\t\t\ttarget, ok := m.set[uintptr(ev.Fd)]\n\t\t\t\tm.mu.Unlock()\n\t\t\t\t// There is a race that it is waken before unsubscribing,\n\t\t\t\t// so the target can't be found.\n\t\t\t\tif !ok {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tif ev.Events&(unix.EPOLLHUP|unix.EPOLLERR) != 0 {\n\t\t\t\t\tlog.L.Warnf(\"Daemon %s died\", target.id)\n\t\t\t\t\tcollector.NewDaemonEventCollector(types.DaemonStateDied).Collect()\n\t\t\t\t\t// Notify subscribers that death event happens\n\t\t\t\t\ttarget.notifier <- deathEvent{daemonID: target.id, path: target.path}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}()\n}\n\nfunc (m *livenessMonitor) Destroy() {\n\tm.mu.Lock()\n\tdefer m.mu.Unlock()\n\n\tfor i := range m.subscribers {\n\t\tif err := m.unsubscribe(i); err != nil {\n\t\t\tlog.L.Warnf(\"fail to unsubscribe %s\", i)\n\t\t}\n\t}\n\n\tif m.epollFd > 0 {\n\t\t// Closing epoll fd does not waken `EpollWait`. So ending events loop can not be\n\t\t// done via closing the file. But liveness monitor is running with nydus-snapshotter\n\t\t// in the whole life. So we don't stop the loop now.\n\t\tunix.Close(m.epollFd)\n\t}\n}\n"
  },
  {
    "path": "pkg/manager/monitor_test.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage manager\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"net\"\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc startUnixServer(ctx context.Context, sock string) {\n\n\tos.RemoveAll(sock)\n\n\tlistener, err := net.Listen(\"unix\", sock)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tvar conn net.Conn\n\tconn, err = listener.Accept()\n\tif err != nil {\n\t\tlog.Fatal()\n\t}\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\tconn.Close()\n\t\t\treturn\n\t\tdefault:\n\t\t\ttime.Sleep(200 * time.Millisecond)\n\t\t}\n\t}\n\n}\n\nfunc TestLivenessMonitor(t *testing.T) {\n\tsockPattern := \"liveness_monitor_sock\"\n\n\ts1, err1 := os.CreateTemp(\"\", sockPattern)\n\tassert.Nil(t, err1)\n\ts1.Close()\n\n\ts2, err2 := os.CreateTemp(\"\", sockPattern)\n\tassert.Nil(t, err2)\n\ts2.Close()\n\n\tctx1, cancel1 := context.WithCancel(context.Background())\n\tctx2, cancel2 := context.WithCancel(context.Background())\n\n\tgo startUnixServer(ctx1, s1.Name())\n\tgo startUnixServer(ctx2, s2.Name())\n\n\tmonitor, _ := newMonitor()\n\tassert.NotNil(t, monitor)\n\n\ttime.Sleep(time.Millisecond * 200)\n\n\tnotifier := make(chan deathEvent, 10)\n\n\te1 := monitor.Subscribe(\"daemon_1\", s1.Name(), notifier)\n\tassert.Nil(t, e1)\n\te1 = monitor.Subscribe(\"daemon_1\", s1.Name(), notifier)\n\tassert.NotNil(t, e1)\n\te2 := monitor.Subscribe(\"daemon_2\", s2.Name(), notifier)\n\tassert.Nil(t, e2)\n\n\tt.Cleanup(func() {\n\t\tos.Remove(s1.Name())\n\t\tos.Remove(s2.Name())\n\t})\n\n\tmonitor.Run()\n\n\ttime.Sleep(time.Millisecond * 200)\n\n\t// Daemon 1 dies and unblock from channel `n1`\n\tcancel1()\n\tevent := <-notifier\n\tassert.Equal(t, event.daemonID, \"daemon_1\")\n\n\terr := monitor.Unsubscribe(\"daemon_2\")\n\tassert.Nil(t, err)\n\tcancel2()\n\n\t// Should not block here.\n\tassert.Equal(t, len(notifier), 0)\n\n\ttime.Sleep(time.Second * 1)\n\n\tmonitor.Destroy()\n\n\tassert.Equal(t, len(monitor.set), 0)\n\tassert.Equal(t, len(monitor.subscribers), 0)\n}\n"
  },
  {
    "path": "pkg/manager/store.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage manager\n\nimport (\n\t\"context\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/store\"\n)\n\n// Nydus daemons and fs instances persistence storage.\ntype Store interface {\n\t// If the daemon is inserted to DB before, return error ErrAlreadyExisted.\n\tAddDaemon(d *daemon.Daemon) error\n\tUpdateDaemon(d *daemon.Daemon) error\n\tDeleteDaemon(id string) error\n\tWalkDaemons(ctx context.Context, cb func(*daemon.ConfigState) error) error\n\tCleanupDaemons(ctx context.Context) error\n\n\tAddRafsInstance(r *rafs.Rafs) error\n\tUpdateRafsInstance(r *rafs.Rafs) error\n\tDeleteRafsInstance(snapshotID string) error\n\tWalkRafsInstances(ctx context.Context, cb func(*rafs.Rafs) error) error\n\n\tNextInstanceSeq() (uint64, error)\n}\n\nvar _ Store = &store.DaemonRafsStore{}\n"
  },
  {
    "path": "pkg/metrics/collector/cache.go",
    "content": "/*\n * Copyright (c) 2025. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage collector\n\nimport (\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/data\"\n)\n\ntype CacheMetricsCollector struct {\n\tMetrics  *types.CacheMetrics\n\tImageRef string\n\tDaemonID string\n}\n\ntype CacheMetricsVecCollector struct {\n\tMetricsVec []CacheMetricsCollector\n}\n\nfunc (c *CacheMetricsCollector) Collect() {\n\tif c.Metrics == nil {\n\t\tlog.L.Warnf(\"can not collect cache metrics: Metrics is nil\")\n\t\treturn\n\t}\n\n\tprefetchTotalDuration := (c.Metrics.PrefetchEndTimeSecs*1000 +\n\t\tc.Metrics.PrefetchCumulativeTimeMillis) -\n\t\t(c.Metrics.PrefetchBeginTimeSecs*1000 +\n\t\t\tc.Metrics.PrefetchCumulativeTimeMillis)\n\n\tdata.CachePartialHits.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.PartialHits))\n\tdata.CacheWholeHits.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.WholeHits))\n\tdata.CacheTotalRequests.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.Total))\n\tdata.CacheEntriesCount.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.EntriesCount))\n\tdata.CachePrefetchDataBytes.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.PrefetchDataAmount))\n\tdata.CachePrefetchRequestsCount.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.PrefetchRequestsCount))\n\tdata.CachePrefetchWorkers.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.PrefetchWorkers))\n\tdata.CachePrefetchUnmergedChunks.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.PrefetchUnmergedChunks))\n\tdata.CachePrefetchCumulativeTimeMillis.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.PrefetchCumulativeTimeMillis))\n\tdata.CachePrefetchTotalDurationMillis.WithLabelValues(c.ImageRef).Set(float64(prefetchTotalDuration))\n\tdata.CacheBufferedBackendSize.WithLabelValues(c.ImageRef).Set(float64(c.Metrics.BufferedBackendSize))\n}\n\nfunc (c *CacheMetricsVecCollector) Collect() {\n\tfor _, cacheMetrics := range c.MetricsVec {\n\t\tcacheMetrics.Collect()\n\t}\n}\n"
  },
  {
    "path": "pkg/metrics/collector/collector.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage collector\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/data\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/tool\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\ntype Collector interface {\n\t// Collect metrics to prometheus data.\n\tCollect()\n}\n\nfunc NewDaemonEventCollector(ev types.DaemonState) *DaemonEventCollector {\n\treturn &DaemonEventCollector{event: ev}\n}\n\nfunc NewFsMetricsCollector(m *types.FsMetrics, imageRef string) *FsMetricsCollector {\n\treturn &FsMetricsCollector{m, imageRef}\n}\n\nfunc NewFsMetricsVecCollector() *FsMetricsVecCollector {\n\treturn &FsMetricsVecCollector{}\n}\n\nfunc NewInflightMetricsVecCollector(hungIOInterval time.Duration) *InflightMetricsVecCollector {\n\treturn &InflightMetricsVecCollector{\n\t\tHungIOInterval: hungIOInterval,\n\t}\n}\n\nfunc NewDaemonInfoCollector(version *types.BuildTimeInfo, value float64) *DaemonInfoCollector {\n\treturn &DaemonInfoCollector{version, value}\n}\n\nfunc NewDaemonImageCollector(daemonID, imageRef string) *DaemonImageCollector {\n\treturn &DaemonImageCollector{DaemonID: daemonID, ImageRef: imageRef}\n}\n\nfunc NewSnapshotterMetricsCollector(ctx context.Context, cacheDir string, pid int) (*SnapshotterMetricsCollector, error) {\n\tcurrentStat, err := tool.GetProcessStat(pid)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"can not get current stat\")\n\t}\n\treturn &SnapshotterMetricsCollector{ctx, cacheDir, pid, currentStat}, nil\n}\n\nfunc NewSnapshotMetricsTimer(method SnapshotMethod) *prometheus.Timer {\n\treturn CollectSnapshotMetricsTimer(data.SnapshotEventElapsedHists, method)\n}\n\nfunc NewCacheMetricsCollector(m *types.CacheMetrics, imageRef, daemonID string) *CacheMetricsCollector {\n\treturn &CacheMetricsCollector{m, imageRef, daemonID}\n}\n\nfunc NewCacheMetricsVecCollector() *CacheMetricsVecCollector {\n\treturn &CacheMetricsVecCollector{}\n}\n"
  },
  {
    "path": "pkg/metrics/collector/daemon.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage collector\n\nimport (\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/data\"\n)\n\ntype DaemonEventCollector struct {\n\tevent types.DaemonState\n}\n\ntype DaemonInfoCollector struct {\n\tVersion *types.BuildTimeInfo\n\tvalue   float64\n}\n\ntype DaemonResourceCollector struct {\n\tDaemonID string\n\tValue    float64\n}\n\ntype DaemonImageCollector struct {\n\tDaemonID string\n\tImageRef string\n}\n\nfunc (d *DaemonEventCollector) Collect() {\n\tdata.NydusdEventCount.WithLabelValues(string(d.event)).Inc()\n}\n\nfunc (d *DaemonInfoCollector) Collect() {\n\tif d.Version == nil {\n\t\tlog.L.Warnf(\"failed to collect daemon count, version is invalid\")\n\t\treturn\n\t}\n\tdata.NydusdCount.WithLabelValues(d.Version.PackageVer).Add(d.value)\n}\n\nfunc (d *DaemonResourceCollector) Collect() {\n\tdata.NydusdRSS.WithLabelValues(d.DaemonID).Set(d.Value)\n}\n\nfunc (d *DaemonImageCollector) Collect() {\n\tdata.NydusdImageInfo.WithLabelValues(d.DaemonID, d.ImageRef).Set(1)\n}\n\nfunc (d *DaemonImageCollector) Delete() {\n\tdata.NydusdImageInfo.DeleteLabelValues(d.DaemonID, d.ImageRef)\n}\n"
  },
  {
    "path": "pkg/metrics/collector/fs.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage collector\n\nimport (\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/data\"\n\tmtypes \"github.com/containerd/nydus-snapshotter/pkg/metrics/types\"\n)\n\nvar OPCodeMap = map[uint32]string{\n\t15: \"OP_READ\",\n}\n\ntype FsMetricsCollector struct {\n\tMetrics  *types.FsMetrics\n\tImageRef string\n}\n\ntype FsMetricsVecCollector struct {\n\tMetricsVec []FsMetricsCollector\n}\n\ntype InflightMetricsVecCollector struct {\n\tMetricsVec     []*types.InflightMetrics\n\tHungIOInterval time.Duration\n}\n\nfunc (f *FsMetricsCollector) Collect() {\n\tif f.Metrics == nil {\n\t\tlog.L.Warnf(\"can not collect FS metrics: Metrics is nil\")\n\t\treturn\n\t}\n\tdata.FsTotalRead.WithLabelValues(f.ImageRef).Set(float64(f.Metrics.DataRead))\n\tdata.FsReadHit.WithLabelValues(f.ImageRef).Set(float64(f.Metrics.FopHits[mtypes.Read]))\n\tdata.FsReadError.WithLabelValues(f.ImageRef).Set(float64(f.Metrics.FopErrors[mtypes.Read]))\n\n\tfor _, h := range data.MetricHists {\n\t\to, err := h.ToConstHistogram(f.Metrics, f.ImageRef)\n\t\tif err != nil {\n\t\t\tlog.L.Warnf(\"failed to new const histogram for %s, error: %v\", h.Desc.String(), err)\n\t\t\treturn\n\t\t}\n\t\th.Save(o)\n\t}\n}\n\nfunc (i *InflightMetricsVecCollector) Collect() {\n\tif i.MetricsVec == nil {\n\t\tlog.L.Warnf(\"can not collect inflight metrics: Metrics is nil\")\n\t\treturn\n\t}\n\n\t// The TimestampSecs of inflight IO is the beginning time of this request.\n\t// We can calculate the elapsed time by time.Now().Unix() - TimestampSecs.\n\t// The inflight IOs which have a longer elapsed time than the HungIOInterval (default 10 seconds) are hung IOs.\n\ttotalHungIOMap := 0\n\tnowTime := time.Now()\n\tfor _, daemonInflightIOMetrics := range i.MetricsVec {\n\t\tfor _, inflightIOMetric := range daemonInflightIOMetrics.Values {\n\t\t\telapsed := nowTime.Sub(time.Unix(int64(inflightIOMetric.TimestampSecs), 0))\n\t\t\tif elapsed >= i.HungIOInterval {\n\t\t\t\ttotalHungIOMap++\n\t\t\t\tlog.L.Debugf(\"Record hung IO, Inode: %v, Opcode: %v, Unique: %v, Elapsed: %v\",\n\t\t\t\t\tinflightIOMetric.Inode, inflightIOMetric.Opcode, inflightIOMetric.Unique, elapsed)\n\t\t\t}\n\t\t}\n\t}\n\tdata.TotalHungIO.Set(float64(totalHungIOMap))\n}\n\nfunc (f *FsMetricsVecCollector) Clear() {\n\tfor _, h := range data.MetricHists {\n\t\th.Clear()\n\t}\n}\n\nfunc (f *FsMetricsVecCollector) Collect() {\n\tf.Clear()\n\tfor _, fsMetrics := range f.MetricsVec {\n\t\tfsMetrics.Collect()\n\t}\n}\n"
  },
  {
    "path": "pkg/metrics/collector/snapshotter.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage collector\n\nimport (\n\t\"context\"\n\n\t\"github.com/containerd/continuity/fs\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/data\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/tool\"\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\ntype SnapshotterMetricsCollector struct {\n\tctx      context.Context\n\tcacheDir string\n\tpid      int\n\tlastStat *tool.Stat\n}\n\ntype SnapshotMethod string\n\nconst (\n\tSnapshotMethodUnknown SnapshotMethod = \"UNKNOWN\"\n\tSnapshotMethodPrepare SnapshotMethod = \"PREPARE\"\n\tSnapshotMethodMount   SnapshotMethod = \"MOUNTS\"\n\tSnapshotMethodCleanup SnapshotMethod = \"CLEANUP\"\n\tSnapshotMethodRemove  SnapshotMethod = \"REMOVE\"\n)\n\nfunc (s *SnapshotterMetricsCollector) CollectCacheUsage() {\n\tdu, err := fs.DiskUsage(s.ctx, s.cacheDir)\n\tif err != nil {\n\t\tlog.L.Warnf(\"Get disk usage failed: %v\", err)\n\t} else {\n\t\tdata.CacheUsage.Set(float64(du.Size) / 1024)\n\t}\n}\n\nfunc (s *SnapshotterMetricsCollector) CollectResourceUsage() {\n\tcurrentStat, err := tool.GetProcessStat(s.pid)\n\tif err != nil {\n\t\tlog.L.Warnf(\"Can not get current process stat.\")\n\t\treturn\n\t}\n\n\tif s.lastStat == nil {\n\t\tlog.L.Debug(\"Can not get resource usage information: lastStat is nil\")\n\t\ts.lastStat = currentStat\n\t\treturn\n\t}\n\n\tcpuSys := (currentStat.Stime - s.lastStat.Stime) / tool.ClkTck\n\tcpuUsr := (currentStat.Utime - s.lastStat.Utime) / tool.ClkTck\n\n\tcpuPercent, err := tool.CalculateCPUUtilization(s.lastStat, currentStat)\n\tif err != nil {\n\t\tlog.L.WithError(err).Warnf(\"Failed to calculate CPU utilization\")\n\t}\n\n\ts.lastStat = currentStat\n\n\tmemory := currentStat.Rss * tool.PageSize\n\trunTime := currentStat.Uptime - currentStat.Start/tool.ClkTck\n\n\tdata.CPUSystem.Set(tool.FormatFloat64(cpuSys, 2))\n\tdata.CPUUser.Set(tool.FormatFloat64(cpuUsr, 2))\n\tdata.CPUUsage.Set(tool.FormatFloat64(cpuPercent, 2))\n\tdata.MemoryUsage.Set(tool.FormatFloat64(memory/1024, 2))\n\tdata.Fds.Set(currentStat.Fds)\n\tdata.RunTime.Set(tool.FormatFloat64(runTime, 2))\n\tdata.Thread.Set(currentStat.Thread)\n}\n\nfunc (s *SnapshotterMetricsCollector) Collect() {\n\ts.CollectCacheUsage()\n\ts.CollectResourceUsage()\n}\n\nfunc CollectSnapshotMetricsTimer(h *prometheus.HistogramVec, event SnapshotMethod) *prometheus.Timer {\n\treturn prometheus.NewTimer(\n\t\tprometheus.ObserverFunc(\n\t\t\t(func(v float64) {\n\t\t\t\th.WithLabelValues(string(event)).Observe(tool.FormatFloat64(v*1000, 6))\n\t\t\t})))\n}\n"
  },
  {
    "path": "pkg/metrics/data/auth.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage data\n\nimport (\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar (\n\t// CredentialRenewals counts credential renewal attempts per image ref,\n\t// labeled by outcome (\"success\" or \"failure\").\n\tCredentialRenewals = prometheus.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"snapshotter_credential_renewals_total\",\n\t\t\tHelp: \"Total number of credential renewal attempts, labeled by image ref and result (success or failure).\",\n\t\t},\n\t\t[]string{imageRefLabel, credentialResultLabel},\n\t)\n\n\t// CredentialStoreEntries tracks the number of credentials currently held\n\t// in the renewal store per image ref.\n\tCredentialStoreEntries = prometheus.NewGaugeVec(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_credential_store_entries\",\n\t\t\tHelp: \"Number of credentials currently tracked in the renewal store per image ref.\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t)\n)\n"
  },
  {
    "path": "pkg/metrics/data/cache.go",
    "content": "/*\n * Copyright (c) 2025. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage data\n\nimport (\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/types/ttl\"\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar (\n\tCachePartialHits = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_partial_hits\",\n\t\t\tHelp: \"Number of partial cache hits (IO needs a part of the chunk)\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCacheWholeHits = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_whole_hits\",\n\t\t\tHelp: \"Number of whole cache hits (IO needs the entire chunk)\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCacheTotalRequests = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_total_requests\",\n\t\t\tHelp: \"Total number of cache read requests. Cache hit percentage = (partial_hits + whole_hits) / total\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCacheEntriesCount = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_entries_count\",\n\t\t\tHelp: \"Number of chunks in ready status\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCachePrefetchDataBytes = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_prefetch_data_bytes\",\n\t\t\tHelp: \"Total amount of data prefetched, in bytes\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCachePrefetchRequestsCount = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_prefetch_requests_count\",\n\t\t\tHelp: \"Total prefetch requests issued from storage/blobs or rafs filesystem layer for each file that needs prefetch\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCachePrefetchWorkers = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_prefetch_workers\",\n\t\t\tHelp: \"Number of prefetch workers\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCachePrefetchUnmergedChunks = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_prefetch_unmerged_chunks\",\n\t\t\tHelp: \"Number of unmerged chunks\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCachePrefetchCumulativeTimeMillis = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_prefetch_cumulative_time_millis\",\n\t\t\tHelp: \"Cumulative time latencies in milliseconds of each prefetch request which can be handled in parallel. It starts when the request is born including nydusd processing and schedule and end when the chunk is downloaded and stored. The average prefetch latency can be calculated by `prefetch_cumulative_time_millis / prefetch_requests_count`\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCachePrefetchTotalDurationMillis = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_prefetch_duration_millis\",\n\t\t\tHelp: \"Total wall clock duration of the prefetch, in milliseconds\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tCacheBufferedBackendSize = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_cache_buffered_backend_size\",\n\t\t\tHelp: \"Size of the buffered backend, in bytes\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n)\n"
  },
  {
    "path": "pkg/metrics/data/daemon.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage data\n\nimport (\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/types/ttl\"\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar (\n\tNydusdEventCount = prometheus.NewCounterVec(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"nydusd_lifetime_event_counts\",\n\t\t\tHelp: \"The lifetime events of nydus daemon.\",\n\t\t},\n\t\t[]string{nydusdEventLabel},\n\t)\n\tNydusdCount = prometheus.NewGaugeVec(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_counts\",\n\t\t\tHelp: \"The counts of nydus daemon.\",\n\t\t},\n\t\t[]string{nydusdVersionLabel},\n\t)\n\tNydusdRSS = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_rss_kilobytes\",\n\t\t\tHelp: \"Memory usage (RSS) of nydus daemon.\",\n\t\t},\n\t\t[]string{daemonIDLabel},\n\t\tttl.DefaultTTL,\n\t)\n\tNydusdImageInfo = prometheus.NewGaugeVec(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_image_info\",\n\t\t\tHelp: \"Mapping of nydus daemon to served image references.\",\n\t\t},\n\t\t[]string{daemonIDLabel, imageRefLabel},\n\t)\n)\n"
  },
  {
    "path": "pkg/metrics/data/fs.go",
    "content": "/*\n * Copyright (c) 2021. Alibaba Cloud. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage data\n\nimport (\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\tmtypes \"github.com/containerd/nydus-snapshotter/pkg/metrics/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/types/ttl\"\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar (\n\tFsTotalRead = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_total_read_bytes\",\n\t\t\tHelp: \"Total bytes read against the nydus filesystem\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\n\tFsReadHit = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_read_hits\",\n\t\t\tHelp: \"Total number of successful read operations.\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\tFsReadError = ttl.NewGaugeVecWithTTL(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_read_errors\",\n\t\t\tHelp: \"Total number of failed read operations.\",\n\t\t},\n\t\t[]string{imageRefLabel},\n\t\tttl.DefaultTTL,\n\t)\n\tTotalHungIO = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"nydusd_hung_io_counts\",\n\t\t\tHelp: \"Total number of hung IOs.\",\n\t\t},\n\t)\n)\n\n// Fs metric histograms\nvar MetricHists = []*mtypes.MetricHistogram{\n\t{\n\t\tDesc: prometheus.NewDesc(\n\t\t\t\"nydusd_cumulative_read_block_bytes\",\n\t\t\t\"Cumulative read size histogram for different block size, in bytes.\",\n\t\t\t[]string{imageRefLabel},\n\t\t\tprometheus.Labels{},\n\t\t),\n\t\tBuckets: []uint64{1, 4, 16, 64, 128, 512, 1024, 2048},\n\t\tGetCounters: func(m *types.FsMetrics) []uint64 {\n\t\t\treturn m.BlockCountRead\n\t\t},\n\t},\n\t{\n\t\tDesc: prometheus.NewDesc(\n\t\t\t\"nydusd_read_latency_microseconds\",\n\t\t\t\"Read latency histogram, in microseconds\",\n\t\t\t[]string{imageRefLabel},\n\t\t\tprometheus.Labels{},\n\t\t),\n\t\tBuckets: []uint64{1, 20, 50, 100, 500, 1000, 2000, 4000},\n\t\tGetCounters: func(m *types.FsMetrics) []uint64 {\n\t\t\treturn m.ReadLatencyDist\n\t\t},\n\t},\n}\n"
  },
  {
    "path": "pkg/metrics/data/labels.go",
    "content": "package data\n\nconst (\n\timageRefLabel         = \"image_ref\"\n\tnydusdEventLabel      = \"nydusd_event\"\n\tnydusdVersionLabel    = \"version\"\n\tdaemonIDLabel         = \"daemon_id\"\n\tsnapshotEventLabel    = \"snapshot_operation\"\n\tcredentialResultLabel = \"result\"\n)\n"
  },
  {
    "path": "pkg/metrics/data/snapshotter.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage data\n\nimport (\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar (\n\tdefaultDurationBuckets = []float64{.5, 1, 5, 10, 50, 100, 150, 200, 250, 300, 350, 400, 600, 1000}\n)\n\nvar (\n\tSnapshotEventElapsedHists = prometheus.NewHistogramVec(\n\t\tprometheus.HistogramOpts{\n\t\t\tName:    \"snapshotter_snapshot_operation_elapsed_milliseconds\",\n\t\t\tHelp:    \"The elapsed time for snapshot events.\",\n\t\t\tBuckets: defaultDurationBuckets,\n\t\t},\n\t\t[]string{snapshotEventLabel},\n\t)\n\n\tCacheUsage = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_cache_usage_kilobytes\",\n\t\t\tHelp: \"Disk usage of snapshotter local cache.\",\n\t\t},\n\t)\n\n\tCPUUsage = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_cpu_usage_percentage\",\n\t\t\tHelp: \"CPU usage percentage of snapshotter.\",\n\t\t},\n\t)\n\n\tMemoryUsage = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_memory_usage_kilobytes\",\n\t\t\tHelp: \"Memory usage (RSS) of snapshotter.\",\n\t\t},\n\t)\n\n\tCPUSystem = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_cpu_system_time_seconds\",\n\t\t\tHelp: \"CPU time of snapshotter in system.\",\n\t\t},\n\t)\n\n\tCPUUser = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_cpu_user_time_seconds\",\n\t\t\tHelp: \"CPU time of snapshotter in user.\",\n\t\t},\n\t)\n\n\tFds = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_fd_counts\",\n\t\t\tHelp: \"Fd counts of snapshotter.\",\n\t\t},\n\t)\n\n\tRunTime = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_run_time_seconds\",\n\t\t\tHelp: \"Running time of snapshotter from starting.\",\n\t\t},\n\t)\n\n\tThread = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_thread_counts\",\n\t\t\tHelp: \"Thread counts of snapshotter.\",\n\t\t},\n\t)\n\n\tCacheBlobsDeleted = prometheus.NewCounter(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"snapshotter_cache_blobs_deleted_total\",\n\t\t\tHelp: \"Total number of cache blobs deleted during cleanup.\",\n\t\t},\n\t)\n\n\tCacheBlobsInUse = prometheus.NewGauge(\n\t\tprometheus.GaugeOpts{\n\t\t\tName: \"snapshotter_cache_blobs_in_use\",\n\t\t\tHelp: \"Number of cache blobs currently in use by running daemons.\",\n\t\t},\n\t)\n\n\tCacheBlobDeletionErrors = prometheus.NewCounter(\n\t\tprometheus.CounterOpts{\n\t\t\tName: \"snapshotter_cache_blob_deletion_errors_total\",\n\t\t\tHelp: \"Total number of errors encountered while deleting cache blobs.\",\n\t\t},\n\t)\n)\n"
  },
  {
    "path": "pkg/metrics/listener.go",
    "content": "/*\n * Copyright (c) 2021. Ant Group. All rights reserved.\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage metrics\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/registry\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/prometheus/client_golang/prometheus/promhttp\"\n)\n\n// Endpoint for prometheus metrics\nvar endpointPromMetrics = \"/v1/metrics\"\n\nfunc trapClosedConnErr(err error) error {\n\tif err == nil || errors.Is(err, net.ErrClosed) {\n\t\treturn nil\n\t}\n\treturn err\n}\n\n// NewListener creates a new TCP listener bound to the given address.\nfunc NewMetricsHTTPListenerServer(addr string) error {\n\tif addr == \"\" {\n\t\treturn fmt.Errorf(\"the address for metrics HTTP server is invalid\")\n\t}\n\n\thttp.Handle(endpointPromMetrics, promhttp.HandlerFor(registry.Registry, promhttp.HandlerOpts{\n\t\tErrorHandling: promhttp.HTTPErrorOnError,\n\t}))\n\n\tl, err := net.Listen(\"tcp\", addr)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"metrics server listener, addr=%s\", addr)\n\t}\n\n\tgo func() {\n\t\tif err := http.Serve(l, nil); trapClosedConnErr(err) != nil {\n\t\t\tlog.L.Errorf(\"Metrics server fails to listen or serve %s: %v\", addr, err)\n\t\t}\n\t}()\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/metrics/registry/registry.go",
    "content": "/*\n * Copyright (c) 2021. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage registry\n\nimport (\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/data\"\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar (\n\tRegistry = prometheus.NewRegistry()\n)\n\nfunc init() {\n\tRegistry.MustRegister(\n\t\tdata.FsTotalRead,\n\t\tdata.FsReadHit,\n\t\tdata.FsReadError,\n\t\tdata.TotalHungIO,\n\t\tdata.NydusdEventCount,\n\t\tdata.NydusdCount,\n\t\tdata.NydusdRSS,\n\t\tdata.NydusdImageInfo,\n\t\tdata.SnapshotEventElapsedHists,\n\t\tdata.CacheUsage,\n\t\tdata.CPUUsage,\n\t\tdata.MemoryUsage,\n\t\tdata.CPUSystem,\n\t\tdata.CPUUser,\n\t\tdata.Fds,\n\t\tdata.RunTime,\n\t\tdata.Thread,\n\t\tdata.CachePartialHits,\n\t\tdata.CacheWholeHits,\n\t\tdata.CacheTotalRequests,\n\t\tdata.CacheEntriesCount,\n\t\tdata.CachePrefetchDataBytes,\n\t\tdata.CachePrefetchRequestsCount,\n\t\tdata.CachePrefetchWorkers,\n\t\tdata.CachePrefetchUnmergedChunks,\n\t\tdata.CachePrefetchCumulativeTimeMillis,\n\t\tdata.CachePrefetchTotalDurationMillis,\n\t\tdata.CacheBufferedBackendSize,\n\t\tdata.CacheBlobsDeleted,\n\t\tdata.CacheBlobsInUse,\n\t\tdata.CacheBlobDeletionErrors,\n\t\tdata.CredentialRenewals,\n\t\tdata.CredentialStoreEntries,\n\t)\n\n\tfor _, m := range data.MetricHists {\n\t\tRegistry.MustRegister(m)\n\t}\n}\n"
  },
  {
    "path": "pkg/metrics/serve.go",
    "content": "/*\n * Copyright (c) 2021. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage metrics\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/manager\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/collector\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/tool\"\n)\n\ntype ServerOpt func(*Server) error\n\ntype Server struct {\n\tmanagers          []*manager.Manager\n\tsnCollectors      []*collector.SnapshotterMetricsCollector\n\tfsCollector       *collector.FsMetricsVecCollector\n\tcacheCollector    *collector.CacheMetricsVecCollector\n\tinflightCollector *collector.InflightMetricsVecCollector\n\thungIOInterval    time.Duration\n\tcollectInterval   time.Duration\n}\n\nfunc WithProcessManagers(managers []*manager.Manager) ServerOpt {\n\treturn func(s *Server) error {\n\t\ts.managers = append(s.managers, managers...)\n\t\treturn nil\n\t}\n}\n\nfunc WithCollectInterval(interval time.Duration) ServerOpt {\n\treturn func(s *Server) error {\n\t\tif interval < 0 {\n\t\t\treturn fmt.Errorf(\"collect interval (%v) must be positive\", interval)\n\t\t}\n\t\ts.collectInterval = interval\n\t\treturn nil\n\t}\n}\n\nfunc WithHungIOInterval(hungIOInterval time.Duration) ServerOpt {\n\treturn func(s *Server) error {\n\t\tif hungIOInterval < 0 {\n\t\t\treturn fmt.Errorf(\"hung IO interval (%v) must be positive\", hungIOInterval)\n\t\t}\n\t\ts.hungIOInterval = hungIOInterval\n\t\treturn nil\n\t}\n}\n\nfunc NewServer(ctx context.Context, opts ...ServerOpt) (*Server, error) {\n\tvar s Server\n\tfor _, o := range opts {\n\t\tif err := o(&s); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\ts.fsCollector = collector.NewFsMetricsVecCollector()\n\ts.inflightCollector = collector.NewInflightMetricsVecCollector(s.hungIOInterval)\n\ts.cacheCollector = collector.NewCacheMetricsVecCollector()\n\tfor _, pm := range s.managers {\n\t\tsnCollector, err := collector.NewSnapshotterMetricsCollector(ctx, pm.CacheDir(), os.Getpid())\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"new snapshotter metrics collector failed\")\n\t\t}\n\t\ts.snCollectors = append(s.snCollectors, snCollector)\n\t}\n\n\treturn &s, nil\n}\n\nfunc (s *Server) CollectDaemonResourceMetrics(_ context.Context) {\n\tvar daemonResource collector.DaemonResourceCollector\n\tfor _, pm := range s.managers {\n\t\t// Collect daemon resource usage metrics.\n\t\tdaemons := pm.ListDaemons()\n\t\tfor _, d := range daemons {\n\t\t\tmemRSS, err := tool.GetProcessMemoryRSSKiloBytes(d.Pid())\n\t\t\tif err != nil {\n\t\t\t\tlog.L.Warnf(\"Failed to get daemon %s RSS memory\", d.ID())\n\t\t\t}\n\n\t\t\tdaemonResource.DaemonID = d.ID()\n\t\t\tdaemonResource.Value = memRSS\n\t\t\tdaemonResource.Collect()\n\t\t}\n\t}\n}\n\nfunc (s *Server) CollectFsMetrics(ctx context.Context) {\n\tvar fsMetricsVec []collector.FsMetricsCollector\n\n\tfor _, pm := range s.managers {\n\t\t// Collect FS metrics from fusedev daemons.\n\t\tif pm.FsDriver != config.FsDriverFusedev {\n\t\t\tcontinue\n\t\t}\n\n\t\tdaemons := pm.ListDaemons()\n\t\tfor _, d := range daemons {\n\t\t\t// Skip daemons that are not serving\n\t\t\tif d.State() != types.DaemonStateRunning {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfor _, i := range d.RafsCache.List() {\n\t\t\t\tvar sid string\n\n\t\t\t\tif d.IsSharedDaemon() {\n\t\t\t\t\tsid = i.SnapshotID\n\t\t\t\t} else {\n\t\t\t\t\tsid = \"\"\n\t\t\t\t}\n\n\t\t\t\tfsMetrics, err := d.GetFsMetrics(sid)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.G(ctx).Errorf(\"failed to get fs metric: %v\", err)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tfsMetricsVec = append(fsMetricsVec, collector.FsMetricsCollector{\n\t\t\t\t\tMetrics:  fsMetrics,\n\t\t\t\t\tImageRef: i.ImageID,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tif fsMetricsVec != nil {\n\t\ts.fsCollector.MetricsVec = fsMetricsVec\n\t\ts.fsCollector.Collect()\n\t}\n}\n\nfunc (s *Server) CollectCacheMetrics(ctx context.Context) {\n\tvar cacheMetricsVec []collector.CacheMetricsCollector\n\n\tfor _, pm := range s.managers {\n\t\tdaemons := pm.ListDaemons()\n\t\tfor _, d := range daemons {\n\t\t\t// Skip daemons that are not serving\n\t\t\tif d.State() != types.DaemonStateRunning {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfor _, i := range d.RafsCache.List() {\n\t\t\t\tvar sid string\n\n\t\t\t\tif d.IsSharedDaemon() {\n\t\t\t\t\tsid = i.SnapshotID\n\t\t\t\t} else {\n\t\t\t\t\tsid = \"\"\n\t\t\t\t}\n\n\t\t\t\tcacheMetrics, err := d.GetCacheMetrics(sid)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.G(ctx).Errorf(\"failed to get cache metric: %v\", err)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tcacheMetricsVec = append(cacheMetricsVec, collector.CacheMetricsCollector{\n\t\t\t\t\tMetrics:  cacheMetrics,\n\t\t\t\t\tImageRef: i.ImageID,\n\t\t\t\t\tDaemonID: d.ID(),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tif cacheMetricsVec != nil {\n\t\ts.cacheCollector.MetricsVec = cacheMetricsVec\n\t\ts.cacheCollector.Collect()\n\t}\n}\n\nfunc (s *Server) CollectInflightMetrics(ctx context.Context) {\n\tinflightMetricsVec := make([]*types.InflightMetrics, 0, 16)\n\tfor _, pm := range s.managers {\n\t\t// Collect inflight metrics from fusedev daemons.\n\t\tif pm.FsDriver != config.FsDriverFusedev {\n\t\t\tcontinue\n\t\t}\n\n\t\tdaemons := pm.ListDaemons()\n\t\tfor _, d := range daemons {\n\n\t\t\t// Only count for daemon that is serving\n\t\t\tif d.State() != types.DaemonStateRunning {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tinflightMetrics, err := d.GetInflightMetrics()\n\t\t\tif err != nil {\n\t\t\t\tlog.G(ctx).Errorf(\"failed to get inflight metric: %v\", err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tinflightMetricsVec = append(inflightMetricsVec, inflightMetrics)\n\t\t}\n\t}\n\n\tif inflightMetricsVec != nil {\n\t\ts.inflightCollector.MetricsVec = inflightMetricsVec\n\t\ts.inflightCollector.Collect()\n\t}\n}\n\nfunc (s *Server) StartCollectMetrics(ctx context.Context) error {\n\ttimer := time.NewTicker(s.collectInterval)\n\t// The timer period is the same as the interval for determining hung IOs.\n\t//\n\t// Since the elapsed time of hung IO is configuration dependent,\n\t// e.g. timeout * retry times when the backend is a registry.\n\t// Therefore, we cannot get complete hung IO data after 1 minute.\n\tInflightTimer := time.NewTicker(s.hungIOInterval)\n\nouter:\n\tfor {\n\t\tselect {\n\t\tcase <-timer.C:\n\t\t\ts.CollectFsMetrics(ctx)\n\t\t\ts.CollectCacheMetrics(ctx)\n\t\t\ts.CollectDaemonResourceMetrics(ctx)\n\t\t\t// Collect snapshotter metrics.\n\t\t\tfor _, snCollector := range s.snCollectors {\n\t\t\t\tsnCollector.Collect()\n\t\t\t}\n\t\tcase <-InflightTimer.C:\n\t\t\ts.CollectInflightMetrics(ctx)\n\t\tcase <-ctx.Done():\n\t\t\tlog.G(ctx).Infof(\"cancel metrics collecting\")\n\t\t\tbreak outer\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/metrics/tool/common.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage tool\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/containerd/log\"\n)\n\nconst (\n\t// Constant value for linux platform except alpha and ia64.\n\tdefaultClkTck = 100\n)\n\nfunc FormatFloat64(f float64, point int) float64 {\n\tvar value float64\n\tswitch point {\n\tcase 6:\n\t\tvalue, _ = strconv.ParseFloat(fmt.Sprintf(\"%.6f\", f), 64)\n\tcase 2:\n\t\tfallthrough\n\tdefault:\n\t\tvalue, _ = strconv.ParseFloat(fmt.Sprintf(\"%.2f\", f), 64)\n\t}\n\n\treturn value\n}\n\n// FIXME: return error\nfunc ParseFloat64(val string) float64 {\n\tfloatVal, _ := strconv.ParseFloat(val, 64)\n\treturn floatVal\n}\n\nfunc GetClkTck() float64 {\n\tgetconfPath, err := exec.LookPath(\"getconf\")\n\tif err != nil {\n\t\tlog.L.Warnf(\"can not find getconf in the system PATH, error %v\", err)\n\t\treturn defaultClkTck\n\t}\n\tout, err := exec.Command(getconfPath, \"CLK_TCK\").Output()\n\tif err != nil {\n\t\tlog.L.Warnf(\"get CLK_TCK failed: %v\", err)\n\t\treturn defaultClkTck\n\t}\n\treturn ParseFloat64(strings.ReplaceAll(string(out), \"\\n\", \"\"))\n}\n\nfunc GetPageSize() float64 {\n\treturn float64(os.Getpagesize())\n}\n"
  },
  {
    "path": "pkg/metrics/tool/stat.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage tool\n\nimport (\n\t\"os\"\n\t\"path\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/pkg/errors\"\n)\n\n// Please refer to https://man7.org/linux/man-pages/man5/proc.5.html for the metrics meanings\ntype Stat struct {\n\tUtime  float64\n\tStime  float64\n\tCutime float64\n\tCstime float64\n\tThread float64\n\tStart  float64\n\tRss    float64\n\tFds    float64\n\tUptime float64\n}\n\nvar (\n\tClkTck   = GetClkTck()\n\tPageSize = GetPageSize()\n)\n\nfunc CalculateCPUUtilization(begin *Stat, now *Stat) (float64, error) {\n\tif begin == nil || now == nil {\n\t\treturn 0.0, errdefs.ErrInvalidArgument\n\t}\n\n\tcpuSys := (now.Stime - begin.Stime) / ClkTck\n\tcpuUsr := (now.Utime - begin.Utime) / ClkTck\n\ttotal := cpuSys + cpuUsr\n\n\tseconds := now.Uptime - begin.Uptime\n\n\tcpuPercent := (total / seconds) * 100\n\n\treturn cpuPercent, nil\n}\n\nfunc GetProcessMemoryRSSKiloBytes(pid int) (float64, error) {\n\tstat, err := GetProcessStat(pid)\n\tif err != nil {\n\t\treturn 0.0, errors.Wrapf(err, \"get process stat\")\n\t}\n\n\treturn stat.Rss * PageSize / 1024, nil\n}\n\nfunc GetProcessStat(pid int) (*Stat, error) {\n\tuptimeBytes, err := os.ReadFile(path.Join(\"/proc\", \"uptime\"))\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get uptime\")\n\t}\n\tuptime := ParseFloat64(strings.Split(string(uptimeBytes), \" \")[0])\n\n\tstatBytes, err := os.ReadFile(path.Join(\"/proc\", strconv.Itoa(pid), \"stat\"))\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get process %d stat\", pid)\n\t}\n\tsplitAfterStat := strings.SplitAfter(string(statBytes), \")\")\n\n\tif len(splitAfterStat) == 0 || len(splitAfterStat) == 1 {\n\t\treturn nil, errors.Errorf(\"Can not find process, PID: %d\", pid)\n\t}\n\tinfos := strings.Split(splitAfterStat[1], \" \")\n\n\tfiles, err := os.ReadDir(path.Join(\"/proc\", strconv.Itoa(pid), \"fdinfo\"))\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"read fdinfo\")\n\t}\n\n\treturn &Stat{\n\t\tUtime:  ParseFloat64(infos[12]),\n\t\tStime:  ParseFloat64(infos[13]),\n\t\tCutime: ParseFloat64(infos[14]),\n\t\tCstime: ParseFloat64(infos[15]),\n\t\tThread: ParseFloat64(infos[18]),\n\t\tStart:  ParseFloat64(infos[20]),\n\t\tRss:    ParseFloat64(infos[22]),\n\t\tFds:    float64(len(files)),\n\t\tUptime: uptime,\n\t}, nil\n}\n\nfunc GetProcessRunningState(pid int) (string, error) {\n\tstatBytes, err := os.ReadFile(path.Join(\"/proc\", strconv.Itoa(pid), \"stat\"))\n\tif err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"get process %d stat\", pid)\n\t}\n\n\tsegments := strings.Split(string(statBytes), \" \")\n\tstate := segments[2]\n\treturn state, nil\n}\n\nfunc IsZombieProcess(pid int) (bool, error) {\n\ts, err := GetProcessRunningState(pid)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\treturn s == \"Z\", nil\n}\n"
  },
  {
    "path": "pkg/metrics/tool/stat_test.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage tool\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestFindZombie(t *testing.T) {\n\ts, err := GetProcessRunningState(1)\n\n\tassert.NoError(t, err)\n\n\tassert.Contains(t, []string{\"Ss\", \"S\"}, s)\n}\n"
  },
  {
    "path": "pkg/metrics/types/ttl/gauge.go",
    "content": "/*\n * Copyright (c) 2021. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage ttl\n\nimport (\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\nvar (\n\tdefaultCleanUpPeriod = 10 * time.Minute\n\tDefaultTTL           = 3 * time.Minute\n)\n\ntype LabelWithValue struct {\n\tname  string\n\tvalue string\n}\n\ntype GaugeVec struct {\n\tlabelName     []string\n\tttl           time.Duration\n\tlabelValueMap map[LabelWithValue]time.Time\n\tmu            sync.Mutex\n\t*prometheus.GaugeVec\n}\n\ntype GaugeWithTTL struct {\n\tlabelValue []string\n\tvec        *GaugeVec\n\tgauge      prometheus.Gauge\n}\n\nfunc NewGaugeVecWithTTL(opts prometheus.GaugeOpts, labelNames []string, ttl time.Duration) *GaugeVec {\n\tgaugeVec := prometheus.NewGaugeVec(opts, labelNames)\n\tres := &GaugeVec{\n\t\tlabelName:     labelNames,\n\t\tttl:           ttl,\n\t\tGaugeVec:      gaugeVec,\n\t\tlabelValueMap: make(map[LabelWithValue]time.Time),\n\t}\n\tgo res.cleanUpExpired()\n\treturn res\n}\n\nfunc (gv *GaugeVec) cleanUpExpired() {\n\ttimer := time.NewTicker(defaultCleanUpPeriod)\n\n\tfor range timer.C {\n\t\tgv.mu.Lock()\n\t\tfor k, v := range gv.labelValueMap {\n\t\t\tif time.Now().After(v) {\n\t\t\t\tgv.DeleteLabelValues(k.value)\n\t\t\t\tdelete(gv.labelValueMap, k)\n\t\t\t}\n\t\t}\n\t\tgv.mu.Unlock()\n\t}\n}\n\nfunc (gv *GaugeVec) WithLabelValues(val ...string) *GaugeWithTTL {\n\tgauge := gv.GaugeVec.WithLabelValues(val...)\n\treturn &GaugeWithTTL{\n\t\tvec:        gv,\n\t\tlabelValue: val,\n\t\tgauge:      gauge,\n\t}\n}\n\nfunc (gwt *GaugeWithTTL) Set(val float64) {\n\tgwt.vec.mu.Lock()\n\tgwt.vec.labelValueMap[LabelWithValue{\n\t\tname:  strings.Join(gwt.vec.labelName, \",\"),\n\t\tvalue: strings.Join(gwt.labelValue, \",\"),\n\t}] = time.Now().Add(gwt.vec.ttl)\n\tgwt.vec.mu.Unlock()\n\tgwt.gauge.Set(val)\n}\n"
  },
  {
    "path": "pkg/metrics/types/ttl/gauge_test.go",
    "content": "/*\n * Copyright (c) 2021. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage ttl\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/prometheus/client_golang/prometheus\"\n\tdto \"github.com/prometheus/client_model/go\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestNewGaugeVecWithTTL(t *testing.T) {\n\tdefaultCleanUpPeriod = 5 * time.Second\n\tg := NewGaugeVecWithTTL(prometheus.GaugeOpts{\n\t\tName: \"nydusd_fuse_connection_waiting_count\",\n\t\tHelp: \"nydusd_fuse_connection_waiting_count\",\n\t},\n\t\t[]string{\"daemon_id\"},\n\t\t3*time.Second,\n\t)\n\tg.WithLabelValues(\"value1\").Set(10)\n\tg.WithLabelValues(\"value2\").Set(10)\n\tmetricsCh := make(chan prometheus.Metric, 2)\n\tgo g.Collect(metricsCh)\n\n\tvar metricsSlice []*dto.Metric\n\tvar mu sync.Mutex\n\tvar wg sync.WaitGroup\n\twg.Add(2)\n\tgo func() {\n\t\tfor m := range metricsCh {\n\t\t\tvar metrics dto.Metric\n\t\t\terr := m.Write(&metrics)\n\t\t\tassert.Nil(t, err)\n\t\t\tmetricsSlice = append(metricsSlice, &metrics)\n\t\t\twg.Done()\n\t\t}\n\t}()\n\twg.Wait()\n\tassert.Equal(t, 2, len(metricsSlice))\n\tmetricsSlice = []*dto.Metric{}\n\n\ttime.Sleep(3 * time.Second)\n\tg.WithLabelValues(\"value1\").Set(10)\n\tg.mu.Lock()\n\tassert.Equal(t, 2, len(g.labelValueMap))\n\tg.mu.Unlock()\n\ttime.Sleep(3 * time.Second)\n\tg.mu.Lock()\n\tassert.Equal(t, 1, len(g.labelValueMap))\n\tg.mu.Unlock()\n\tmetricsCh = make(chan prometheus.Metric, 2)\n\tgo g.Collect(metricsCh)\n\tgo func() {\n\t\tfor m := range metricsCh {\n\t\t\tvar metrics dto.Metric\n\t\t\terr := m.Write(&metrics)\n\t\t\tassert.Nil(t, err)\n\t\t\tmu.Lock()\n\t\t\tmetricsSlice = append(metricsSlice, &metrics)\n\t\t\tmu.Unlock()\n\t\t}\n\t}()\n\n\ttime.Sleep(6 * time.Second)\n\tmu.Lock()\n\tassert.Equal(t, 1, len(metricsSlice))\n\tmu.Unlock()\n\tg.mu.Lock()\n\tassert.Equal(t, 0, len(g.labelValueMap))\n\tg.mu.Unlock()\n}\n"
  },
  {
    "path": "pkg/metrics/types/types.go",
    "content": "/*\n * Copyright (c) 2021. Alibaba Cloud. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage fs\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/prometheus/client_golang/prometheus\"\n)\n\ntype Fop int\n\nconst (\n\tGetattr = iota\n\tReadlink\n\tOpen\n\tRelease\n\tRead\n\tStatfs\n\tGetxattr\n\tListxattr\n\tOpendir\n\tLookup\n\tReaddir\n\tReaddirplus\n\tAccess\n\tForget\n\tBatchForget\n\n\tMaxFops\n)\n\nfunc GetMaxFops() uint {\n\treturn MaxFops\n}\n\nfunc MakeFopBuckets() []uint64 {\n\ts := make([]uint64, 0, MaxFops)\n\tfor i := 0; i < MaxFops; i++ {\n\t\ts = append(s, uint64(i))\n\t}\n\n\treturn s\n}\n\ntype GetCountersFn func(*types.FsMetrics) []uint64\n\ntype MetricHistogram struct {\n\tDesc        *prometheus.Desc\n\tBuckets     []uint64\n\tGetCounters GetCountersFn\n\n\t// Save the last generated histogram metric\n\tconstHists []prometheus.Metric\n}\n\nfunc (h *MetricHistogram) ToConstHistogram(m *types.FsMetrics, imageRef string) (prometheus.Metric, error) {\n\tvar count, sum uint64\n\tcounters := h.GetCounters(m)\n\thmap := make(map[float64]uint64)\n\n\tif len(counters) != len(h.Buckets) {\n\t\treturn nil, fmt.Errorf(\"length of counters(%d) and buckets(%d) not equal: %+v\", len(counters), len(h.Buckets), h.Buckets)\n\t}\n\n\tfor i, c := range counters {\n\t\tcount += c\n\t\tsum += h.Buckets[i] * c\n\t\thmap[float64(h.Buckets[i])] = count\n\t}\n\n\treturn prometheus.MustNewConstHistogram(\n\t\th.Desc,\n\t\tcount, float64(sum),\n\t\thmap,\n\t\timageRef,\n\t), nil\n}\n\nfunc (h *MetricHistogram) Clear() {\n\th.constHists = nil\n}\n\nfunc (h *MetricHistogram) Save(m prometheus.Metric) {\n\th.constHists = append(h.constHists, m)\n}\n\n// Implement prometheus.Collector interface\nfunc (h *MetricHistogram) Describe(ch chan<- *prometheus.Desc) {\n\tif h.Desc != nil {\n\t\tch <- h.Desc\n\t}\n}\n\nfunc (h *MetricHistogram) Collect(ch chan<- prometheus.Metric) {\n\tif h.constHists != nil {\n\t\tfor _, hist := range h.constHists {\n\t\t\tch <- hist\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/pprof/listener.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage pprof\n\nimport (\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/pprof\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/pkg/errors\"\n)\n\nfunc NewPprofHTTPListener(addr string) error {\n\tif addr == \"\" {\n\t\treturn errors.New(\"the address for pprof HTTP server is invalid\")\n\t}\n\n\thttp.Handle(\"/debug/pprof/threadcreate\", pprof.Handler(\"threadcreate\"))\n\thttp.Handle(\"/debug/pprof/goroutine\", pprof.Handler(\"goroutine\"))\n\thttp.Handle(\"/debug/pprof/allocs\", pprof.Handler(\"allocs\"))\n\thttp.Handle(\"/debug/pprof/block\", pprof.Handler(\"block\"))\n\thttp.Handle(\"/debug/pprof/mutex\", pprof.Handler(\"mutex\"))\n\thttp.Handle(\"/debug/pprof/heap\", pprof.Handler(\"heap\"))\n\n\tl, err := net.Listen(\"tcp\", addr)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"pprof server listener, addr=%s\", addr)\n\t}\n\n\tgo func() {\n\t\tlog.L.Infof(\"Start pprof HTTP server on %s\", addr)\n\n\t\tif err := http.Serve(l, nil); err != nil && !errors.Is(err, net.ErrClosed) {\n\t\t\tlog.L.Errorf(\"Pprof server fails to listen or serve %s: %v\", addr, err)\n\t\t}\n\t}()\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/prefetch/prefetch.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage prefetch\n\nimport (\n\t\"encoding/json\"\n\t\"sync\"\n\n\t\"github.com/containerd/log\"\n)\n\ntype prefetchInfo struct {\n\tprefetchMap   map[string]string\n\tprefetchMutex sync.Mutex\n}\n\nvar Pm prefetchInfo\n\nfunc (p *prefetchInfo) SetPrefetchFiles(body []byte) error {\n\tp.prefetchMutex.Lock()\n\tdefer p.prefetchMutex.Unlock()\n\n\tvar prefetchMsg []map[string]string\n\tif err := json.Unmarshal(body, &prefetchMsg); err != nil {\n\t\treturn err\n\t}\n\n\tif p.prefetchMap == nil {\n\t\tp.prefetchMap = make(map[string]string)\n\t}\n\tfor _, item := range prefetchMsg {\n\t\timage := item[\"image\"]\n\t\tprefetchfiles := item[\"prefetch\"]\n\t\tp.prefetchMap[image] = prefetchfiles\n\t}\n\n\tlog.L.Infof(\"received prefetch list from nri plugin: %v \", p.prefetchMap)\n\treturn nil\n}\n\nfunc (p *prefetchInfo) GetPrefetchInfo(image string) string {\n\tp.prefetchMutex.Lock()\n\tdefer p.prefetchMutex.Unlock()\n\n\tif prefetchfiles, ok := p.prefetchMap[image]; ok {\n\t\treturn prefetchfiles\n\t}\n\treturn \"\"\n}\n\nfunc (p *prefetchInfo) DeleteFromPrefetchMap(image string) {\n\tp.prefetchMutex.Lock()\n\tdefer p.prefetchMutex.Unlock()\n\n\tdelete(p.prefetchMap, image)\n}\n"
  },
  {
    "path": "pkg/rafs/rafs.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage rafs\n\nimport (\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"github.com/mohae/deepcopy\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/errdefs\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n)\n\nconst (\n\tAnnoFsCacheDomainID string = \"fscache.domainid\"\n\tAnnoFsCacheID       string = \"fscache.id\"\n)\n\ntype NewRafsOpt func(r *Rafs) error\n\nfunc init() {\n\t// TODO\n\t// A set of RAFS filesystem instances associated with a nydusd daemon.\n\tRafsGlobalCache = Cache{instances: make(map[string]*Rafs)}\n}\n\n// Global cache to hold all RAFS instances.\nvar RafsGlobalCache Cache\n\ntype Cache struct {\n\tmu        sync.Mutex\n\tinstances map[string]*Rafs\n}\n\nfunc NewRafsCache() Cache {\n\treturn Cache{instances: make(map[string]*Rafs)}\n}\n\nfunc (rs *Cache) Lock() {\n\trs.mu.Lock()\n}\n\nfunc (rs *Cache) Unlock() {\n\trs.mu.Unlock()\n}\n\nfunc (rs *Cache) Add(r *Rafs) {\n\trs.mu.Lock()\n\trs.instances[r.SnapshotID] = r\n\trs.mu.Unlock()\n}\n\nfunc (rs *Cache) Remove(snapshotID string) {\n\trs.mu.Lock()\n\tdelete(rs.instances, snapshotID)\n\trs.mu.Unlock()\n}\n\nfunc (rs *Cache) Get(snapshotID string) *Rafs {\n\trs.mu.Lock()\n\tdefer rs.mu.Unlock()\n\n\treturn rs.instances[snapshotID]\n}\n\nfunc (rs *Cache) Len() int {\n\trs.mu.Lock()\n\tdefer rs.mu.Unlock()\n\n\treturn len(rs.instances)\n}\n\nfunc (rs *Cache) Head() *Rafs {\n\trs.mu.Lock()\n\tdefer rs.mu.Unlock()\n\tfor _, v := range rs.instances {\n\t\treturn v\n\t}\n\n\treturn nil\n}\n\nfunc (rs *Cache) List() map[string]*Rafs {\n\trs.mu.Lock()\n\tdefer rs.mu.Unlock()\n\n\tinstances := deepcopy.Copy(rs.instances).(map[string]*Rafs)\n\n\treturn instances\n}\n\nfunc (rs *Cache) ListLocked() map[string]*Rafs {\n\treturn rs.instances\n}\n\nfunc (rs *Cache) SetIntances(instances map[string]*Rafs) {\n\trs.Lock()\n\tdefer rs.Unlock()\n\trs.instances = instances\n}\n\n// The whole struct will be persisted\ntype Rafs struct {\n\tSeq             uint64\n\tImageID         string // Usually is the image reference\n\tDaemonID        string\n\tFsDriver        string\n\tSnapshotID      string // Given by containerd\n\tSnapshotDir     string\n\tUnderlyingFiles []string // Underlying cache blob files\n\t// 1. A host kernel EROFS/TARFS mountpoint\n\t// 2. Absolute path to each rafs instance root directory.\n\tMountpoint  string\n\tAnnotations map[string]string\n}\n\nfunc NewRafs(snapshotID, imageID, fsDriver string) (*Rafs, error) {\n\tsnapshotDir := path.Join(config.GetSnapshotsRootDir(), snapshotID)\n\trafs := &Rafs{\n\t\tFsDriver:        fsDriver,\n\t\tImageID:         imageID,\n\t\tSnapshotID:      snapshotID,\n\t\tSnapshotDir:     snapshotDir,\n\t\tAnnotations:     make(map[string]string),\n\t\tUnderlyingFiles: []string{},\n\t}\n\n\tif err := os.MkdirAll(snapshotDir, 0755); err != nil {\n\t\treturn nil, err\n\t}\n\n\tRafsGlobalCache.Add(rafs)\n\n\treturn rafs, nil\n}\n\nfunc (r *Rafs) AddAnnotation(k, v string) {\n\tr.Annotations[k] = v\n}\n\nfunc (r *Rafs) GetSnapshotDir() string {\n\treturn r.SnapshotDir\n}\n\nfunc (r *Rafs) GetFsDriver() string {\n\tif r.FsDriver != \"\" {\n\t\treturn r.FsDriver\n\t}\n\n\treturn config.GetFsDriver()\n}\n\n// Blob caches' chunk bitmap and meta headers are stored here.\nfunc (r *Rafs) FscacheWorkDir() string {\n\treturn filepath.Join(r.SnapshotDir, \"fs\")\n}\n\nfunc (r *Rafs) SetMountpoint(mp string) {\n\tr.Mountpoint = mp\n}\n\n// Get top level mount point for the RAFS instance:\n//   - FUSE with dedicated mode: the FUSE filesystem mount point, the RAFS filesystem is directly\n//     mounted at the mount point.\n//   - FUSE with shared mode: the FUSE filesystem mount point, the RAFS filesystem is mounted\n//     at a subdirectory under the mount point.\n//   - EROFS/fscache: the EROFS filesystem mount point.\nfunc (r *Rafs) GetMountpoint() string {\n\treturn r.Mountpoint\n}\n\n// Get the sub-directory under a FUSE mount point to mount a RAFS instance.\n// For a nydusd daemon in shared mode, one or more RAFS filesystem instances can be mounted\n// to sub-directories of the FUSE filesystem. This method returns the subdirectory for a\n// RAFS filesystem instance.\nfunc (r *Rafs) RelaMountpoint() string {\n\treturn filepath.Join(\"/\", r.SnapshotID)\n}\n\nfunc (r *Rafs) BootstrapFile() (string, error) {\n\t// meta files are stored at <snapshot_id>/fs/image/image.boot\n\tbootstrap := filepath.Join(r.SnapshotDir, \"fs\", \"image\", \"image.boot\")\n\t_, err := os.Stat(bootstrap)\n\tif err == nil {\n\t\treturn bootstrap, nil\n\t}\n\n\tif os.IsNotExist(err) {\n\t\t// check legacy location for backward compatibility\n\t\tbootstrap = filepath.Join(r.SnapshotDir, \"fs\", \"image.boot\")\n\t\t_, err = os.Stat(bootstrap)\n\t\tif err == nil {\n\t\t\treturn bootstrap, nil\n\t\t}\n\t}\n\n\treturn \"\", errors.Wrapf(errdefs.ErrNotFound, \"bootstrap %s\", bootstrap)\n}\n"
  },
  {
    "path": "pkg/referrer/manager.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage referrer\n\nimport (\n\t\"context\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/golang/groupcache/lru\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x/sync/singleflight\"\n)\n\ntype Manager struct {\n\tinsecure bool\n\tcache    *lru.Cache\n\tsg       singleflight.Group\n}\n\nfunc NewManager(insecure bool) *Manager {\n\tmanager := Manager{\n\t\tinsecure: insecure,\n\t\tcache:    lru.New(500),\n\t\tsg:       singleflight.Group{},\n\t}\n\n\treturn &manager\n}\n\n// CheckReferrer attempts to fetch the referrers and parse out\n// the nydus image by specified manifest digest.\nfunc (manager *Manager) CheckReferrer(ctx context.Context, ref string, manifestDigest digest.Digest) (*ocispec.Descriptor, error) {\n\tmetaLayer, err, _ := manager.sg.Do(manifestDigest.String(), func() (interface{}, error) {\n\t\t// Try to get nydus metadata layer descriptor from LRU cache.\n\t\tif metaLayer, ok := manager.cache.Get(manifestDigest); ok {\n\t\t\tdesc := metaLayer.(ocispec.Descriptor)\n\t\t\treturn &desc, nil\n\t\t}\n\n\t\tkeyChain, err := auth.GetKeyChainByRef(ref, nil)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"get key chain\")\n\t\t}\n\n\t\t// No LRU cache found, try to fetch referrers and parse out\n\t\t// the nydus metadata layer descriptor.\n\t\treferrer := newReferrer(keyChain, manager.insecure)\n\t\tmetaLayer, err := referrer.checkReferrer(ctx, ref, manifestDigest)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"check referrer\")\n\t\t}\n\n\t\t// FIXME: how to invalidate the LRU cache if referrers update?\n\t\tmanager.cache.Add(manifestDigest, *metaLayer)\n\n\t\treturn metaLayer, nil\n\t})\n\n\tif err != nil {\n\t\tlog.L.WithField(\"ref\", ref).WithError(err).Warn(\"check referrer\")\n\t\treturn nil, err\n\t}\n\n\treturn metaLayer.(*ocispec.Descriptor), nil\n}\n\n// TryFetchMetadata try to fetch and unpack nydus metadata file to specified path.\nfunc (manager *Manager) TryFetchMetadata(ctx context.Context, ref string, manifestDigest digest.Digest, metadataPath string) error {\n\tmetaLayer, err := manager.CheckReferrer(ctx, ref, manifestDigest)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"check referrer\")\n\t}\n\n\tkeyChain, err := auth.GetKeyChainByRef(ref, nil)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"get key chain\")\n\t}\n\n\treferrer := newReferrer(keyChain, manager.insecure)\n\treturn referrer.fetchMetadata(ctx, ref, *metaLayer, metadataPath)\n}\n"
  },
  {
    "path": "pkg/referrer/referrer.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage referrer\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/converter\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n)\n\n// Containerd restricts the max size of manifest index to 8M, follow it.\nconst maxManifestIndexSize = 0x800000\n\ntype referrer struct {\n\tremote *remote.Remote\n}\n\nfunc newReferrer(keyChain *auth.PassKeyChain, insecure bool) *referrer {\n\treturn &referrer{\n\t\tremote: remote.New(keyChain, insecure),\n\t}\n}\n\n// checkReferrer fetches the referrers and parses out the nydus\n// image by specified manifest digest.\n// it's using distribution list referrers API.\nfunc (r *referrer) checkReferrer(ctx context.Context, ref string, manifestDigest digest.Digest) (*ocispec.Descriptor, error) {\n\thandle := func() (*ocispec.Descriptor, error) {\n\t\t// Create an new resolver to request.\n\t\tfetcher, err := r.remote.Fetcher(ctx, ref)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"get fetcher\")\n\t\t}\n\n\t\t// Fetch image referrers from remote registry.\n\t\trc, _, err := fetcher.(remotes.ReferrersFetcher).FetchReferrers(ctx, manifestDigest)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"fetch referrers\")\n\t\t}\n\t\tdefer rc.Close()\n\n\t\t// Parse image manifest list from referrers.\n\t\tvar index ocispec.Index\n\t\tbytes, err := io.ReadAll(io.LimitReader(rc, maxManifestIndexSize))\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"read referrers\")\n\t\t}\n\t\tif err := json.Unmarshal(bytes, &index); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"unmarshal referrers index\")\n\t\t}\n\t\tif len(index.Manifests) == 0 {\n\t\t\treturn nil, fmt.Errorf(\"empty referrer list\")\n\t\t}\n\n\t\t// Prefer to fetch the last manifest and check if it is a nydus image.\n\t\t// TODO: should we search by matching ArtifactType?\n\t\trc, err = fetcher.Fetch(ctx, index.Manifests[0])\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"fetch referrers\")\n\t\t}\n\t\tdefer rc.Close()\n\n\t\tvar manifest ocispec.Manifest\n\t\tbytes, err = io.ReadAll(rc)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"read manifest\")\n\t\t}\n\t\tif err := json.Unmarshal(bytes, &manifest); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"unmarshal manifest\")\n\t\t}\n\t\tif len(manifest.Layers) < 1 {\n\t\t\treturn nil, fmt.Errorf(\"invalid manifest\")\n\t\t}\n\t\tmetaLayer := manifest.Layers[len(manifest.Layers)-1]\n\t\tif !label.IsNydusMetaLayer(metaLayer.Annotations) {\n\t\t\treturn nil, fmt.Errorf(\"invalid nydus manifest\")\n\t\t}\n\n\t\treturn &metaLayer, nil\n\t}\n\n\tdesc, err := handle()\n\tif err != nil && r.remote.RetryWithPlainHTTP(ref, err) {\n\t\treturn handle()\n\t}\n\n\treturn desc, err\n}\n\n// fetchMetadata fetches and unpacks nydus metadata file to specified path.\nfunc (r *referrer) fetchMetadata(ctx context.Context, ref string, desc ocispec.Descriptor, metadataPath string) error {\n\thandle := func() error {\n\t\t// Create an new resolver to request.\n\t\tresolver := r.remote.Resolve(ctx, ref)\n\t\tfetcher, err := resolver.Fetcher(ctx, ref)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"get fetcher\")\n\t\t}\n\n\t\t// Unpack nydus metadata file to specified path.\n\t\trc, err := fetcher.Fetch(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"fetch nydus metadata\")\n\t\t}\n\t\tdefer rc.Close()\n\n\t\tif err := remote.Unpack(rc, converter.BootstrapFileNameInLayer, metadataPath); err != nil {\n\t\t\tos.Remove(metadataPath)\n\t\t\treturn errors.Wrap(err, \"unpack metadata from layer\")\n\t\t}\n\n\t\treturn nil\n\t}\n\n\t// Check if metafile already exists to avoid unnecessary fetch\n\tif _, err := os.Stat(metadataPath); err == nil {\n\t\treturn nil\n\t}\n\n\terr := handle()\n\tif err != nil && r.remote.RetryWithPlainHTTP(ref, err) {\n\t\treturn handle()\n\t}\n\n\treturn err\n}\n"
  },
  {
    "path": "pkg/remote/remote.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage remote\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/docker\"\n\t\"github.com/distribution/reference\"\n\t\"github.com/pkg/errors\"\n)\n\n// IsErrHTTPResponseToHTTPSClient returns whether err is\n// \"http: server gave HTTP response to HTTPS client\"\nfunc isErrHTTPResponseToHTTPSClient(err error) bool {\n\t// The error string is unexposed as of Go 1.16, so we can't use `errors.Is`.\n\t// https://github.com/golang/go/issues/44855\n\tconst unexposed = \"server gave HTTP response to HTTPS client\"\n\treturn strings.Contains(err.Error(), unexposed)\n}\n\n// IsErrConnectionRefused return whether err is\n// \"connect: connection refused\"\nfunc isErrConnectionRefused(err error) bool {\n\tconst errMessage = \"connect: connection refused\"\n\treturn strings.Contains(err.Error(), errMessage)\n}\n\ntype Remote struct {\n\t// The resolver is used for image pull or fetches requests. The best practice\n\t// in containerd is that each resolver instance is used only once for a request\n\t// and is destroyed when the request completes. When a registry token expires,\n\t// the resolver does not re-apply for a new token, so it's better to create a\n\t// new resolver instance using resolverFunc for each request.\n\tresolverFunc func(plainHTTP bool) remotes.Resolver\n\t// withPlainHTTP attempts to request the remote registry using http instead\n\t// of https.\n\twithPlainHTTP bool\n\t// insecure indicates that the registry is explicitly configured as insecure.\n\t// HTTP fallback is only allowed when insecure is true,\n\t// matching Docker's --insecure-registry semantics.\n\tinsecure bool\n}\n\nfunc New(keyChain *auth.PassKeyChain, insecure bool) *Remote {\n\t// nolint:unparam\n\tcredFunc := func(string) (string, string, error) {\n\t\tif keyChain == nil {\n\t\t\treturn \"\", \"\", nil\n\t\t}\n\t\treturn keyChain.Username, keyChain.Password, nil\n\t}\n\n\tnewClient := func(insecure bool) *http.Client {\n\t\tclient := http.DefaultClient\n\t\ttransport := http.DefaultTransport.(*http.Transport)\n\t\ttransport.TLSClientConfig = &tls.Config{\n\t\t\tInsecureSkipVerify: insecure,\n\t\t}\n\t\tclient.Transport = transport\n\t\treturn client\n\t}\n\n\tresolverFunc := func(plainHTTP bool) remotes.Resolver {\n\t\tregistryHosts := docker.ConfigureDefaultRegistries(\n\t\t\tdocker.WithAuthorizer(\n\t\t\t\tdocker.NewDockerAuthorizer(\n\t\t\t\t\tdocker.WithAuthClient(newClient(insecure)),\n\t\t\t\t\tdocker.WithAuthCreds(credFunc),\n\t\t\t\t),\n\t\t\t),\n\t\t\tdocker.WithClient(newClient(insecure)),\n\t\t\tdocker.WithPlainHTTP(func(_ string) (bool, error) {\n\t\t\t\treturn plainHTTP, nil\n\t\t\t}),\n\t\t)\n\n\t\treturn docker.NewResolver(docker.ResolverOptions{\n\t\t\tHosts: registryHosts,\n\t\t})\n\t}\n\n\treturn &Remote{\n\t\tresolverFunc:  resolverFunc,\n\t\twithPlainHTTP: false,\n\t\tinsecure:      insecure,\n\t}\n}\n\nfunc (remote *Remote) RetryWithPlainHTTP(ref string, err error) bool {\n\tif !remote.insecure {\n\t\treturn false\n\t}\n\n\tretry := err != nil && (isErrHTTPResponseToHTTPSClient(err) || isErrConnectionRefused(err))\n\tif !retry {\n\t\treturn false\n\t}\n\n\tparsed, _ := reference.ParseNormalizedNamed(ref)\n\tif parsed != nil {\n\t\thost := reference.Domain(parsed)\n\t\t// If the error message includes the current registry host string, it\n\t\t// implies that we can retry the request with plain HTTP.\n\t\tif strings.Contains(err.Error(), fmt.Sprintf(\"/%s/\", host)) {\n\t\t\tlog.G(context.TODO()).WithError(err).Warningf(\"retrying with http for %s\", host)\n\t\t\tremote.withPlainHTTP = true\n\t\t}\n\t}\n\n\treturn remote.withPlainHTTP\n}\n\nfunc (remote *Remote) Resolve(_ context.Context, _ string) remotes.Resolver {\n\treturn remote.resolverFunc(remote.withPlainHTTP)\n}\n\nfunc (remote *Remote) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) {\n\tresolver := remote.Resolve(ctx, ref)\n\tfetcher, err := resolver.Fetcher(ctx, ref)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"get fetcher\")\n\t}\n\treturn fetcher, nil\n}\n"
  },
  {
    "path": "pkg/remote/remote_test.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage remote\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestRetryWithPlainHTTP(t *testing.T) {\n\tconst host = \"myregistry.example.com\"\n\tref := fmt.Sprintf(\"%s/repo/image:latest\", host)\n\thttpResponseErr := fmt.Errorf(\"Get https://%s/v2/: server gave HTTP response to HTTPS client\", host)\n\tconnRefusedErr := fmt.Errorf(\"Get https://%s/v2/: connect: connection refused\", host)\n\totherErr := fmt.Errorf(\"some unrelated error\")\n\n\ttests := []struct {\n\t\tname     string\n\t\tinsecure bool\n\t\terr      error\n\t\twant     bool\n\t}{\n\t\t{\n\t\t\tname:     \"insecure allows HTTP fallback on HTTP response error\",\n\t\t\tinsecure: true,\n\t\t\terr:      httpResponseErr,\n\t\t\twant:     true,\n\t\t},\n\t\t{\n\t\t\tname:     \"insecure allows HTTP fallback on connection refused\",\n\t\t\tinsecure: true,\n\t\t\terr:      connRefusedErr,\n\t\t\twant:     true,\n\t\t},\n\t\t{\n\t\t\tname:     \"insecure does not fallback on unrelated error\",\n\t\t\tinsecure: true,\n\t\t\terr:      otherErr,\n\t\t\twant:     false,\n\t\t},\n\t\t{\n\t\t\tname:     \"secure blocks HTTP fallback on HTTP response error\",\n\t\t\tinsecure: false,\n\t\t\terr:      httpResponseErr,\n\t\t\twant:     false,\n\t\t},\n\t\t{\n\t\t\tname:     \"secure blocks HTTP fallback on connection refused\",\n\t\t\tinsecure: false,\n\t\t\terr:      connRefusedErr,\n\t\t\twant:     false,\n\t\t},\n\t\t{\n\t\t\tname:     \"nil error returns false\",\n\t\t\tinsecure: true,\n\t\t\terr:      nil,\n\t\t\twant:     false,\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tr := &Remote{insecure: tt.insecure}\n\t\t\tgot := r.RetryWithPlainHTTP(ref, tt.err)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/auth/fetch.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage auth\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/containerd/v2/version\"\n\t\"github.com/containerd/log\"\n\tremoteserrors \"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/errors\"\n)\n\nvar (\n\t// ErrNoToken is returned if a request is successful but the body does not\n\t// contain an authorization token.\n\tErrNoToken = errors.New(\"authorization server did not include a token in the response\")\n)\n\n// GenerateTokenOptions generates options for fetching a token based on a challenge\nfunc GenerateTokenOptions(ctx context.Context, host, username, secret string, c Challenge) (TokenOptions, error) {\n\trealm, ok := c.Parameters[\"realm\"]\n\tif !ok {\n\t\treturn TokenOptions{}, errors.New(\"no realm specified for token auth challenge\")\n\t}\n\n\trealmURL, err := url.Parse(realm)\n\tif err != nil {\n\t\treturn TokenOptions{}, fmt.Errorf(\"invalid token auth challenge realm: %w\", err)\n\t}\n\n\tto := TokenOptions{\n\t\tRealm:    realmURL.String(),\n\t\tService:  c.Parameters[\"service\"],\n\t\tUsername: username,\n\t\tSecret:   secret,\n\t}\n\n\tscope, ok := c.Parameters[\"scope\"]\n\tif ok {\n\t\tto.Scopes = append(to.Scopes, strings.Split(scope, \" \")...)\n\t} else {\n\t\tlog.G(ctx).WithField(\"host\", host).Debug(\"no scope specified for token auth challenge\")\n\t}\n\n\treturn to, nil\n}\n\n// TokenOptions are options for requesting a token\ntype TokenOptions struct {\n\tRealm    string\n\tService  string\n\tScopes   []string\n\tUsername string\n\tSecret   string\n\n\t// FetchRefreshToken enables fetching a refresh token (aka \"identity token\", \"offline token\") along with the bearer token.\n\t//\n\t// For HTTP GET mode (FetchToken), FetchRefreshToken sets `offline_token=true` in the request.\n\t// https://docs.docker.com/registry/spec/auth/token/#requesting-a-token\n\t//\n\t// For HTTP POST mode (FetchTokenWithOAuth), FetchRefreshToken sets `access_type=offline` in the request.\n\t// https://docs.docker.com/registry/spec/auth/oauth/#getting-a-token\n\tFetchRefreshToken bool\n}\n\n// OAuthTokenResponse is response from fetching token with a OAuth POST request\ntype OAuthTokenResponse struct {\n\tAccessToken  string    `json:\"access_token\"`\n\tRefreshToken string    `json:\"refresh_token\"`\n\tExpiresIn    int       `json:\"expires_in\"`\n\tIssuedAt     time.Time `json:\"issued_at\"`\n\tScope        string    `json:\"scope\"`\n}\n\n// FetchTokenWithOAuth fetches a token using a POST request\nfunc FetchTokenWithOAuth(ctx context.Context, client *http.Client, headers http.Header, clientID string, to TokenOptions) (*OAuthTokenResponse, error) {\n\tform := url.Values{}\n\tif len(to.Scopes) > 0 {\n\t\tform.Set(\"scope\", strings.Join(to.Scopes, \" \"))\n\t}\n\tform.Set(\"service\", to.Service)\n\tform.Set(\"client_id\", clientID)\n\n\tif to.Username == \"\" {\n\t\tform.Set(\"grant_type\", \"refresh_token\")\n\t\tform.Set(\"refresh_token\", to.Secret)\n\t} else {\n\t\tform.Set(\"grant_type\", \"password\")\n\t\tform.Set(\"username\", to.Username)\n\t\tform.Set(\"password\", to.Secret)\n\t}\n\tif to.FetchRefreshToken {\n\t\tform.Set(\"access_type\", \"offline\")\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, to.Realm, strings.NewReader(form.Encode()))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded; charset=utf-8\")\n\tfor k, v := range headers {\n\t\treq.Header[k] = append(req.Header[k], v...)\n\t}\n\tif len(req.Header.Get(\"User-Agent\")) == 0 {\n\t\treq.Header.Set(\"User-Agent\", \"containerd/\"+version.Version)\n\t}\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode < 200 || resp.StatusCode >= 400 {\n\t\treturn nil, remoteserrors.NewUnexpectedStatusErr(resp)\n\t}\n\n\tdecoder := json.NewDecoder(resp.Body)\n\n\tvar tr OAuthTokenResponse\n\tif err = decoder.Decode(&tr); err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to decode token response: %w\", err)\n\t}\n\n\tif tr.AccessToken == \"\" {\n\t\treturn nil, ErrNoToken\n\t}\n\n\treturn &tr, nil\n}\n\n// FetchTokenResponse is response from fetching token with GET request\ntype FetchTokenResponse struct {\n\tToken        string    `json:\"token\"`\n\tAccessToken  string    `json:\"access_token\"`\n\tExpiresIn    int       `json:\"expires_in\"`\n\tIssuedAt     time.Time `json:\"issued_at\"`\n\tRefreshToken string    `json:\"refresh_token\"`\n}\n\n// FetchToken fetches a token using a GET request\nfunc FetchToken(ctx context.Context, client *http.Client, headers http.Header, to TokenOptions) (*FetchTokenResponse, error) {\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, to.Realm, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor k, v := range headers {\n\t\treq.Header[k] = append(req.Header[k], v...)\n\t}\n\tif len(req.Header.Get(\"User-Agent\")) == 0 {\n\t\treq.Header.Set(\"User-Agent\", \"containerd/\"+version.Version)\n\t}\n\n\treqParams := req.URL.Query()\n\n\tif to.Service != \"\" {\n\t\treqParams.Add(\"service\", to.Service)\n\t}\n\n\tfor _, scope := range to.Scopes {\n\t\treqParams.Add(\"scope\", scope)\n\t}\n\n\tif to.Secret != \"\" {\n\t\treq.SetBasicAuth(to.Username, to.Secret)\n\t}\n\n\tif to.FetchRefreshToken {\n\t\treqParams.Add(\"offline_token\", \"true\")\n\t}\n\n\treq.URL.RawQuery = reqParams.Encode()\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode < 200 || resp.StatusCode >= 400 {\n\t\treturn nil, remoteserrors.NewUnexpectedStatusErr(resp)\n\t}\n\n\tdecoder := json.NewDecoder(resp.Body)\n\n\tvar tr FetchTokenResponse\n\tif err = decoder.Decode(&tr); err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to decode token response: %w\", err)\n\t}\n\n\t// `access_token` is equivalent to `token` and if both are specified\n\t// the choice is undefined.  Canonicalize `access_token` by sticking\n\t// things in `token`.\n\tif tr.AccessToken != \"\" {\n\t\ttr.Token = tr.AccessToken\n\t}\n\n\tif tr.Token == \"\" {\n\t\treturn nil, ErrNoToken\n\t}\n\n\treturn &tr, nil\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/auth/fetch_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage auth\n\nimport (\n\t\"context\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestGenerateTokenOptions(t *testing.T) {\n\tfor _, tc := range []struct {\n\t\tname     string\n\t\trealm    string\n\t\tservice  string\n\t\tusername string\n\t\tsecret   string\n\t\tscope    string\n\t}{\n\t\t{\n\t\t\tname:     \"MultipleScopes\",\n\t\t\trealm:    \"https://test-realm.com\",\n\t\t\tservice:  \"registry-service\",\n\t\t\tusername: \"username\",\n\t\t\tsecret:   \"secret\",\n\t\t\tscope:    \"repository:foo/bar:pull repository:foo/bar:pull,push\",\n\t\t},\n\t\t{\n\t\t\tname:     \"SingleScope\",\n\t\t\trealm:    \"https://test-realm.com\",\n\t\t\tservice:  \"registry-service\",\n\t\t\tusername: \"username\",\n\t\t\tsecret:   \"secret\",\n\t\t\tscope:    \"repository:foo/bar:pull\",\n\t\t},\n\t\t{\n\t\t\tname:     \"NoScope\",\n\t\t\trealm:    \"https://test-realm.com\",\n\t\t\tservice:  \"registry-service\",\n\t\t\tusername: \"username\",\n\t\t\tsecret:   \"secret\",\n\t\t},\n\t} {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tc := Challenge{\n\t\t\t\tScheme: BearerAuth,\n\t\t\t\tParameters: map[string]string{\n\t\t\t\t\t\"realm\":   tc.realm,\n\t\t\t\t\t\"service\": tc.service,\n\t\t\t\t\t\"scope\":   tc.scope,\n\t\t\t\t},\n\t\t\t}\n\t\t\toptions, err := GenerateTokenOptions(context.Background(), \"host\", tc.username, tc.secret, c)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"unexpected error %v\", err)\n\t\t\t}\n\n\t\t\texpected := TokenOptions{\n\t\t\t\tRealm:    tc.realm,\n\t\t\t\tService:  tc.service,\n\t\t\t\tScopes:   strings.Split(tc.scope, \" \"),\n\t\t\t\tUsername: tc.username,\n\t\t\t\tSecret:   tc.secret,\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(options, expected) {\n\t\t\t\tt.Fatalf(\"expected %v, but got %v\", expected, options)\n\t\t\t}\n\t\t})\n\t}\n\n\tt.Run(\"MissingRealm\", func(t *testing.T) {\n\t\tc := Challenge{\n\t\t\tScheme: BearerAuth,\n\t\t\tParameters: map[string]string{\n\t\t\t\t\"service\": \"service\",\n\t\t\t\t\"scope\":   \"repository:foo/bar:pull,push\",\n\t\t\t},\n\t\t}\n\t\t_, err := GenerateTokenOptions(context.Background(), \"host\", \"username\", \"secret\", c)\n\t\tif err == nil {\n\t\t\tt.Fatal(\"expected an err and got nil\")\n\t\t}\n\t})\n\n\tt.Run(\"RealmParseError\", func(t *testing.T) {\n\t\tc := Challenge{\n\t\t\tScheme: BearerAuth,\n\t\t\tParameters: map[string]string{\n\t\t\t\t\"realm\":   \"127.0.0.1:8080\",\n\t\t\t\t\"service\": \"service\",\n\t\t\t\t\"scope\":   \"repository:foo/bar:pull,push\",\n\t\t\t},\n\t\t}\n\t\t_, err := GenerateTokenOptions(context.Background(), \"host\", \"username\", \"secret\", c)\n\t\tif err == nil {\n\t\t\tt.Fatal(\"expected an err and got nil\")\n\t\t}\n\t})\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/auth/parse.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage auth\n\nimport (\n\t\"net/http\"\n\t\"sort\"\n\t\"strings\"\n)\n\n// AuthenticationScheme defines scheme of the authentication method\ntype AuthenticationScheme byte\n\nconst (\n\t// BasicAuth is scheme for Basic HTTP Authentication RFC 7617\n\tBasicAuth AuthenticationScheme = 1 << iota\n\t// DigestAuth is scheme for HTTP Digest Access Authentication RFC 7616\n\tDigestAuth\n\t// BearerAuth is scheme for OAuth 2.0 Bearer Tokens RFC 6750\n\tBearerAuth\n)\n\n// Challenge carries information from a WWW-Authenticate response header.\n// See RFC 2617.\ntype Challenge struct {\n\t// scheme is the auth-scheme according to RFC 2617\n\tScheme AuthenticationScheme\n\n\t// parameters are the auth-params according to RFC 2617\n\tParameters map[string]string\n}\n\ntype byScheme []Challenge\n\nfunc (bs byScheme) Len() int      { return len(bs) }\nfunc (bs byScheme) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] }\n\n// Sort in priority order: token > digest > basic\nfunc (bs byScheme) Less(i, j int) bool { return bs[i].Scheme > bs[j].Scheme }\n\n// Octet types from RFC 2616.\ntype octetType byte\n\nvar octetTypes [256]octetType\n\nconst (\n\tisToken octetType = 1 << iota\n\tisSpace\n)\n\nfunc init() {\n\t// OCTET      = <any 8-bit sequence of data>\n\t// CHAR       = <any US-ASCII character (octets 0 - 127)>\n\t// CTL        = <any US-ASCII control character (octets 0 - 31) and DEL (127)>\n\t// CR         = <US-ASCII CR, carriage return (13)>\n\t// LF         = <US-ASCII LF, linefeed (10)>\n\t// SP         = <US-ASCII SP, space (32)>\n\t// HT         = <US-ASCII HT, horizontal-tab (9)>\n\t// <\">        = <US-ASCII double-quote mark (34)>\n\t// CRLF       = CR LF\n\t// LWS        = [CRLF] 1*( SP | HT )\n\t// TEXT       = <any OCTET except CTLs, but including LWS>\n\t// separators = \"(\" | \")\" | \"<\" | \">\" | \"@\" | \",\" | \";\" | \":\" | \"\\\" | <\">\n\t//              | \"/\" | \"[\" | \"]\" | \"?\" | \"=\" | \"{\" | \"}\" | SP | HT\n\t// token      = 1*<any CHAR except CTLs or separators>\n\t// qdtext     = <any TEXT except <\">>\n\n\tfor c := 0; c < 256; c++ {\n\t\tvar t octetType\n\t\tisCtl := c <= 31 || c == 127\n\t\tisChar := 0 <= c && c <= 127\n\t\tisSeparator := strings.ContainsRune(\" \\t\\\"(),/:;<=>?@[]\\\\{}\", rune(c))\n\t\tif strings.ContainsRune(\" \\t\\r\\n\", rune(c)) {\n\t\t\tt |= isSpace\n\t\t}\n\t\tif isChar && !isCtl && !isSeparator {\n\t\t\tt |= isToken\n\t\t}\n\t\toctetTypes[c] = t\n\t}\n}\n\n// ParseAuthHeader parses challenges from WWW-Authenticate header\nfunc ParseAuthHeader(header http.Header) []Challenge {\n\tchallenges := []Challenge{}\n\tfor _, h := range header[http.CanonicalHeaderKey(\"WWW-Authenticate\")] {\n\t\tv, p := parseValueAndParams(h)\n\t\tvar s AuthenticationScheme\n\t\tswitch v {\n\t\tcase \"basic\":\n\t\t\ts = BasicAuth\n\t\tcase \"digest\":\n\t\t\ts = DigestAuth\n\t\tcase \"bearer\":\n\t\t\ts = BearerAuth\n\t\tdefault:\n\t\t\tcontinue\n\t\t}\n\t\tchallenges = append(challenges, Challenge{Scheme: s, Parameters: p})\n\t}\n\tsort.Stable(byScheme(challenges))\n\treturn challenges\n}\n\nfunc parseValueAndParams(header string) (value string, params map[string]string) {\n\tparams = make(map[string]string)\n\tvalue, s := expectToken(header)\n\tif value == \"\" {\n\t\treturn\n\t}\n\tvalue = strings.ToLower(value)\n\tfor {\n\t\tvar pkey string\n\t\tpkey, s = expectToken(skipSpace(s))\n\t\tif pkey == \"\" {\n\t\t\treturn\n\t\t}\n\t\tif !strings.HasPrefix(s, \"=\") {\n\t\t\treturn\n\t\t}\n\t\tvar pvalue string\n\t\tpvalue, s = expectTokenOrQuoted(s[1:])\n\t\tpkey = strings.ToLower(pkey)\n\t\tparams[pkey] = pvalue\n\t\ts = skipSpace(s)\n\t\tif !strings.HasPrefix(s, \",\") {\n\t\t\treturn\n\t\t}\n\t\ts = s[1:]\n\t}\n}\n\nfunc skipSpace(s string) (rest string) {\n\ti := 0\n\tfor ; i < len(s); i++ {\n\t\tif octetTypes[s[i]]&isSpace == 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn s[i:]\n}\n\nfunc expectToken(s string) (token, rest string) {\n\ti := 0\n\tfor ; i < len(s); i++ {\n\t\tif octetTypes[s[i]]&isToken == 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn s[:i], s[i:]\n}\n\nfunc expectTokenOrQuoted(s string) (value string, rest string) {\n\tif !strings.HasPrefix(s, \"\\\"\") {\n\t\treturn expectToken(s)\n\t}\n\ts = s[1:]\n\tfor i := 0; i < len(s); i++ {\n\t\tswitch s[i] {\n\t\tcase '\"':\n\t\t\treturn s[:i], s[i+1:]\n\t\tcase '\\\\':\n\t\t\tp := make([]byte, len(s)-1)\n\t\t\tj := copy(p, s[:i])\n\t\t\tescape := true\n\t\t\tfor i = i + 1; i < len(s); i++ {\n\t\t\t\tb := s[i]\n\t\t\t\tswitch {\n\t\t\t\tcase escape:\n\t\t\t\t\tescape = false\n\t\t\t\t\tp[j] = b\n\t\t\t\t\tj++\n\t\t\t\tcase b == '\\\\':\n\t\t\t\t\tescape = true\n\t\t\t\tcase b == '\"':\n\t\t\t\t\treturn string(p[:j]), s[i+1:]\n\t\t\t\tdefault:\n\t\t\t\t\tp[j] = b\n\t\t\t\t\tj++\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn \"\", \"\"\n\t\t}\n\t}\n\treturn \"\", \"\"\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/auth/parse_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage auth\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestParseAuthHeaderBearer(t *testing.T) {\n\theaderTemplate := `Bearer realm=\"%s\",service=\"%s\",scope=\"%s\"`\n\n\tfor _, tc := range []struct {\n\t\tname    string\n\t\trealm   string\n\t\tservice string\n\t\tscope   string\n\t}{\n\t\t{\n\t\t\tname:    \"SingleScope\",\n\t\t\trealm:   \"https://auth.docker.io/token\",\n\t\t\tservice: \"registry.docker.io\",\n\t\t\tscope:   \"repository:foo/bar:pull,push\",\n\t\t},\n\t\t{\n\t\t\tname:    \"MultipleScopes\",\n\t\t\trealm:   \"https://auth.docker.io/token\",\n\t\t\tservice: \"registry.docker.io\",\n\t\t\tscope:   \"repository:foo/bar:pull,push repository:foo/baz:pull repository:foo/foo:push\",\n\t\t},\n\t} {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\texpected := []Challenge{\n\t\t\t\t{\n\t\t\t\t\tScheme: BearerAuth,\n\t\t\t\t\tParameters: map[string]string{\n\t\t\t\t\t\t\"realm\":   tc.realm,\n\t\t\t\t\t\t\"service\": tc.service,\n\t\t\t\t\t\t\"scope\":   tc.scope,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\n\t\t\thdr := http.Header{\n\t\t\t\thttp.CanonicalHeaderKey(\"WWW-Authenticate\"): []string{fmt.Sprintf(\n\t\t\t\t\theaderTemplate, tc.realm, tc.service, tc.scope,\n\t\t\t\t)},\n\t\t\t}\n\t\t\tactual := ParseAuthHeader(hdr)\n\t\t\tif !reflect.DeepEqual(expected, actual) {\n\t\t\t\tt.Fatalf(\"expected %v, but got %v\", expected, actual)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestParseAuthHeader(t *testing.T) {\n\tv := `Bearer realm=\"https://auth.example.io/token\",empty=\"\",service=\"registry.example.io\",scope=\"repository:library/hello-world:pull,push\"`\n\th := http.Header{http.CanonicalHeaderKey(\"WWW-Authenticate\"): []string{v}}\n\tchallenge := ParseAuthHeader(h)\n\n\tactual, ok := challenge[0].Parameters[\"empty\"]\n\tassert.True(t, ok)\n\tassert.Equal(t, \"\", actual)\n\n\tactual, ok = challenge[0].Parameters[\"service\"]\n\tassert.True(t, ok)\n\tassert.Equal(t, \"registry.example.io\", actual)\n}\n\nfunc FuzzParseAuthHeader(f *testing.F) {\n\tf.Add(`Bearer realm=\"https://example.com/token\",service=\"example.com\",scope=\"repository:foo/bar:pull,push\"`)\n\tf.Fuzz(func(t *testing.T, v string) {\n\t\th := http.Header{http.CanonicalHeaderKey(\"WWW-Authenticate\"): []string{v}}\n\t\t_ = ParseAuthHeader(h)\n\t})\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/authorizer.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/docker/auth\"\n\tremoteerrors \"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/errors\"\n)\n\ntype dockerAuthorizer struct {\n\tcredentials func(string) (string, string, error)\n\n\tclient *http.Client\n\theader http.Header\n\tmu     sync.RWMutex\n\n\t// indexed by host name\n\thandlers map[string]*authHandler\n\n\tonFetchRefreshToken OnFetchRefreshToken\n}\n\ntype authorizerConfig struct {\n\tcredentials         func(string) (string, string, error)\n\tclient              *http.Client\n\theader              http.Header\n\tonFetchRefreshToken OnFetchRefreshToken\n}\n\n// AuthorizerOpt configures an authorizer\ntype AuthorizerOpt func(*authorizerConfig)\n\n// WithAuthClient provides the HTTP client for the authorizer\nfunc WithAuthClient(client *http.Client) AuthorizerOpt {\n\treturn func(opt *authorizerConfig) {\n\t\topt.client = client\n\t}\n}\n\n// WithAuthCreds provides a credential function to the authorizer\nfunc WithAuthCreds(creds func(string) (string, string, error)) AuthorizerOpt {\n\treturn func(opt *authorizerConfig) {\n\t\topt.credentials = creds\n\t}\n}\n\n// WithAuthHeader provides HTTP headers for authorization\nfunc WithAuthHeader(hdr http.Header) AuthorizerOpt {\n\treturn func(opt *authorizerConfig) {\n\t\topt.header = hdr\n\t}\n}\n\n// OnFetchRefreshToken is called on fetching request token.\ntype OnFetchRefreshToken func(ctx context.Context, refreshToken string, req *http.Request)\n\n// WithFetchRefreshToken enables fetching \"refresh token\" (aka \"identity token\", \"offline token\").\nfunc WithFetchRefreshToken(f OnFetchRefreshToken) AuthorizerOpt {\n\treturn func(opt *authorizerConfig) {\n\t\topt.onFetchRefreshToken = f\n\t}\n}\n\n// NewDockerAuthorizer creates an authorizer using Docker's registry\n// authentication spec.\n// See https://docs.docker.com/registry/spec/auth/\nfunc NewDockerAuthorizer(opts ...AuthorizerOpt) Authorizer {\n\tvar ao authorizerConfig\n\tfor _, opt := range opts {\n\t\topt(&ao)\n\t}\n\n\tif ao.client == nil {\n\t\tao.client = http.DefaultClient\n\t}\n\n\treturn &dockerAuthorizer{\n\t\tcredentials:         ao.credentials,\n\t\tclient:              ao.client,\n\t\theader:              ao.header,\n\t\thandlers:            make(map[string]*authHandler),\n\t\tonFetchRefreshToken: ao.onFetchRefreshToken,\n\t}\n}\n\n// Authorize handles auth request.\nfunc (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {\n\t// skip if there is no auth handler\n\tah := a.getAuthHandler(req.URL.Host)\n\tif ah == nil {\n\t\treturn nil\n\t}\n\n\tauth, refreshToken, err := ah.authorize(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treq.Header.Set(\"Authorization\", auth)\n\n\tif refreshToken != \"\" {\n\t\ta.mu.RLock()\n\t\tonFetchRefreshToken := a.onFetchRefreshToken\n\t\ta.mu.RUnlock()\n\t\tif onFetchRefreshToken != nil {\n\t\t\tonFetchRefreshToken(ctx, refreshToken, req)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (a *dockerAuthorizer) getAuthHandler(host string) *authHandler {\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\n\treturn a.handlers[host]\n}\n\nfunc (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.Response) error {\n\tlast := responses[len(responses)-1]\n\thost := last.Request.URL.Host\n\n\ta.mu.Lock()\n\tdefer a.mu.Unlock()\n\tfor _, c := range auth.ParseAuthHeader(last.Header) {\n\t\tif c.Scheme == auth.BearerAuth {\n\t\t\tif err := invalidAuthorization(c, responses); err != nil {\n\t\t\t\tdelete(a.handlers, host)\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\t// reuse existing handler\n\t\t\t//\n\t\t\t// assume that one registry will return the common\n\t\t\t// challenge information, including realm and service.\n\t\t\t// and the resource scope is only different part\n\t\t\t// which can be provided by each request.\n\t\t\tif _, ok := a.handlers[host]; ok {\n\t\t\t\treturn nil\n\t\t\t}\n\n\t\t\tvar username, secret string\n\t\t\tif a.credentials != nil {\n\t\t\t\tvar err error\n\t\t\t\tusername, secret, err = a.credentials(host)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcommon, err := auth.GenerateTokenOptions(ctx, host, username, secret, c)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcommon.FetchRefreshToken = a.onFetchRefreshToken != nil\n\n\t\t\ta.handlers[host] = newAuthHandler(a.client, a.header, c.Scheme, common)\n\t\t\treturn nil\n\t\t} else if c.Scheme == auth.BasicAuth && a.credentials != nil {\n\t\t\tusername, secret, err := a.credentials(host)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif username != \"\" && secret != \"\" {\n\t\t\t\tcommon := auth.TokenOptions{\n\t\t\t\t\tUsername: username,\n\t\t\t\t\tSecret:   secret,\n\t\t\t\t}\n\n\t\t\t\ta.handlers[host] = newAuthHandler(a.client, a.header, c.Scheme, common)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\treturn fmt.Errorf(\"failed to find supported auth scheme: %w\", errdefs.ErrNotImplemented)\n}\n\n// authResult is used to control limit rate.\ntype authResult struct {\n\tsync.WaitGroup\n\ttoken        string\n\trefreshToken string\n\terr          error\n}\n\n// authHandler is used to handle auth request per registry server.\ntype authHandler struct {\n\tsync.Mutex\n\n\theader http.Header\n\n\tclient *http.Client\n\n\t// only support basic and bearer schemes\n\tscheme auth.AuthenticationScheme\n\n\t// common contains common challenge answer\n\tcommon auth.TokenOptions\n\n\t// scopedTokens caches token indexed by scopes, which used in\n\t// bearer auth case\n\tscopedTokens map[string]*authResult\n}\n\nfunc newAuthHandler(client *http.Client, hdr http.Header, scheme auth.AuthenticationScheme, opts auth.TokenOptions) *authHandler {\n\treturn &authHandler{\n\t\theader:       hdr,\n\t\tclient:       client,\n\t\tscheme:       scheme,\n\t\tcommon:       opts,\n\t\tscopedTokens: map[string]*authResult{},\n\t}\n}\n\nfunc (ah *authHandler) authorize(ctx context.Context) (string, string, error) {\n\tswitch ah.scheme {\n\tcase auth.BasicAuth:\n\t\treturn ah.doBasicAuth(ctx)\n\tcase auth.BearerAuth:\n\t\treturn ah.doBearerAuth(ctx)\n\tdefault:\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to find supported auth scheme: %s: %w\", string(ah.scheme), errdefs.ErrNotImplemented)\n\t}\n}\n\nfunc (ah *authHandler) doBasicAuth(ctx context.Context) (string, string, error) {\n\tusername, secret := ah.common.Username, ah.common.Secret\n\n\tif username == \"\" || secret == \"\" {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to handle basic auth because missing username or secret\")\n\t}\n\n\tauth := base64.StdEncoding.EncodeToString([]byte(username + \":\" + secret))\n\treturn fmt.Sprintf(\"Basic %s\", auth), \"\", nil\n}\n\nfunc (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken string, err error) {\n\t// copy common tokenOptions\n\tto := ah.common\n\n\tto.Scopes = GetTokenScopes(ctx, to.Scopes)\n\n\t// Docs: https://docs.docker.com/registry/spec/auth/scope\n\tscoped := strings.Join(to.Scopes, \" \")\n\n\tah.Lock()\n\tif r, exist := ah.scopedTokens[scoped]; exist {\n\t\tah.Unlock()\n\t\tr.Wait()\n\t\treturn r.token, r.refreshToken, r.err\n\t}\n\n\t// only one fetch token job\n\tr := new(authResult)\n\tr.Add(1)\n\tah.scopedTokens[scoped] = r\n\tah.Unlock()\n\n\tdefer func() {\n\t\ttoken = fmt.Sprintf(\"Bearer %s\", token)\n\t\tr.token, r.refreshToken, r.err = token, refreshToken, err\n\t\tr.Done()\n\t}()\n\n\t// fetch token for the resource scope\n\tif to.Secret != \"\" {\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\terr = fmt.Errorf(\"failed to fetch oauth token: %w\", err)\n\t\t\t}\n\t\t}()\n\t\t// credential information is provided, use oauth POST endpoint\n\t\t// TODO: Allow setting client_id\n\t\tresp, err := auth.FetchTokenWithOAuth(ctx, ah.client, ah.header, \"containerd-client\", to)\n\t\tif err != nil {\n\t\t\tvar errStatus remoteerrors.ErrUnexpectedStatus\n\t\t\tif errors.As(err, &errStatus) {\n\t\t\t\t// Registries without support for POST may return 404 for POST /v2/token.\n\t\t\t\t// As of September 2017, GCR is known to return 404.\n\t\t\t\t// As of February 2018, JFrog Artifactory is known to return 401.\n\t\t\t\t// As of January 2022, ACR is known to return 400.\n\t\t\t\tif (errStatus.StatusCode == 405 && to.Username != \"\") || errStatus.StatusCode == 404 || errStatus.StatusCode == 401 || errStatus.StatusCode == 400 {\n\t\t\t\t\tresp, err := auth.FetchToken(ctx, ah.client, ah.header, to)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn \"\", \"\", err\n\t\t\t\t\t}\n\t\t\t\t\treturn resp.Token, resp.RefreshToken, nil\n\t\t\t\t}\n\t\t\t\tlog.G(ctx).WithFields(log.Fields{\n\t\t\t\t\t\"status\": errStatus.Status,\n\t\t\t\t\t\"body\":   string(errStatus.Body),\n\t\t\t\t}).Debugf(\"token request failed\")\n\t\t\t}\n\t\t\treturn \"\", \"\", err\n\t\t}\n\t\treturn resp.AccessToken, resp.RefreshToken, nil\n\t}\n\t// do request anonymously\n\tresp, err := auth.FetchToken(ctx, ah.client, ah.header, to)\n\tif err != nil {\n\t\treturn \"\", \"\", fmt.Errorf(\"failed to fetch anonymous token: %w\", err)\n\t}\n\treturn resp.Token, resp.RefreshToken, nil\n}\n\nfunc invalidAuthorization(c auth.Challenge, responses []*http.Response) error {\n\terrStr := c.Parameters[\"error\"]\n\tif errStr == \"\" {\n\t\treturn nil\n\t}\n\n\tn := len(responses)\n\tif n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"server message: %s: %w\", errStr, ErrInvalidAuthorization)\n}\n\nfunc sameRequest(r1, r2 *http.Request) bool {\n\tif r1.Method != r2.Method {\n\t\treturn false\n\t}\n\tif *r1.URL != *r2.URL {\n\t\treturn false\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/config/config_unix.go",
    "content": "//go:build !windows\n\n/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage config\n\nimport (\n\t\"crypto/x509\"\n\t\"path/filepath\"\n)\n\nfunc hostPaths(root, host string) (hosts []string) {\n\tch := hostDirectory(host)\n\tif ch != host {\n\t\thosts = append(hosts, filepath.Join(root, ch))\n\t}\n\n\thosts = append(hosts,\n\t\tfilepath.Join(root, host),\n\t\tfilepath.Join(root, \"_default\"),\n\t)\n\n\treturn\n}\n\nfunc rootSystemPool() (*x509.CertPool, error) {\n\treturn x509.SystemCertPool()\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/config/config_windows.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage config\n\nimport (\n\t\"crypto/x509\"\n\t\"path/filepath\"\n\t\"strings\"\n)\n\nfunc hostPaths(root, host string) (hosts []string) {\n\tch := hostDirectory(host)\n\tif ch != host {\n\t\thosts = append(hosts, filepath.Join(root, strings.Replace(ch, \":\", \"\", -1)))\n\t}\n\n\thosts = append(hosts,\n\t\tfilepath.Join(root, strings.Replace(host, \":\", \"\", -1)),\n\t\tfilepath.Join(root, \"_default\"),\n\t)\n\n\treturn\n}\n\nfunc rootSystemPool() (*x509.CertPool, error) {\n\treturn x509.NewCertPool(), nil\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/config/docker_fuzzer_internal.go",
    "content": "//go:build gofuzz\n\n/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage config\n\nimport (\n\t\"os\"\n\n\tfuzz \"github.com/AdaLogics/go-fuzz-headers\"\n)\n\nfunc FuzzParseHostsFile(data []byte) int {\n\tf := fuzz.NewConsumer(data)\n\tdir, err := os.MkdirTemp(\"\", \"fuzz-\")\n\tif err != nil {\n\t\treturn 0\n\t}\n\terr = f.CreateFiles(dir)\n\tif err != nil {\n\t\treturn 0\n\t}\n\tdefer os.RemoveAll(dir)\n\tb, err := f.GetBytes()\n\tif err != nil {\n\t\treturn 0\n\t}\n\t_, _ = parseHostsFile(dir, b)\n\treturn 1\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/config/hosts.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\n// Package config contains utilities for helping configure the Docker resolver\npackage config\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/docker\"\n\t\"github.com/pelletier/go-toml\"\n)\n\n// UpdateClientFunc is a function that lets you to amend http Client behavior used by registry clients.\ntype UpdateClientFunc func(client *http.Client) error\n\ntype hostConfig struct {\n\tscheme string\n\thost   string\n\tpath   string\n\n\tcapabilities docker.HostCapabilities\n\n\tcaCerts     []string\n\tclientPairs [][2]string\n\tskipVerify  *bool\n\n\theader http.Header\n\n\t// TODO: Add credential configuration (domain alias, username)\n}\n\n// HostOptions is used to configure registry hosts\ntype HostOptions struct {\n\tHostDir       func(string) (string, error)\n\tCredentials   func(host string) (string, string, error)\n\tDefaultTLS    *tls.Config\n\tDefaultScheme string\n\t// UpdateClient will be called after creating http.Client object, so clients can provide extra configuration\n\tUpdateClient   UpdateClientFunc\n\tAuthorizerOpts []docker.AuthorizerOpt\n}\n\n// ConfigureHosts creates a registry hosts function from the provided\n// host creation options. The host directory can read hosts.toml or\n// certificate files laid out in the Docker specific layout.\n// If a `HostDir` function is not required, defaults are used.\nfunc ConfigureHosts(ctx context.Context, options HostOptions) docker.RegistryHosts {\n\treturn func(host string) ([]docker.RegistryHost, error) {\n\t\tvar hosts []hostConfig\n\t\tif options.HostDir != nil {\n\t\t\tdir, err := options.HostDir(host)\n\t\t\tif err != nil && !errdefs.IsNotFound(err) {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif dir != \"\" {\n\t\t\t\tlog.G(ctx).WithField(\"dir\", dir).Debug(\"loading host directory\")\n\t\t\t\thosts, err = loadHostDir(ctx, dir)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If hosts was not set, add a default host\n\t\t// NOTE: Check nil here and not empty, the host may be\n\t\t// intentionally configured to not have any endpoints\n\t\tif hosts == nil {\n\t\t\thosts = make([]hostConfig, 1)\n\t\t}\n\t\tif len(hosts) > 0 && hosts[len(hosts)-1].host == \"\" {\n\t\t\tif host == \"docker.io\" {\n\t\t\t\thosts[len(hosts)-1].scheme = \"https\"\n\t\t\t\thosts[len(hosts)-1].host = \"registry-1.docker.io\"\n\t\t\t} else if docker.IsLocalhost(host) {\n\t\t\t\thosts[len(hosts)-1].host = host\n\t\t\t\tif options.DefaultScheme == \"\" || options.DefaultScheme == \"http\" {\n\t\t\t\t\thosts[len(hosts)-1].scheme = \"http\"\n\n\t\t\t\t\t// Skipping TLS verification for localhost\n\t\t\t\t\tvar skipVerify = true\n\t\t\t\t\thosts[len(hosts)-1].skipVerify = &skipVerify\n\t\t\t\t} else {\n\t\t\t\t\thosts[len(hosts)-1].scheme = options.DefaultScheme\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\thosts[len(hosts)-1].host = host\n\t\t\t\tif options.DefaultScheme != \"\" {\n\t\t\t\t\thosts[len(hosts)-1].scheme = options.DefaultScheme\n\t\t\t\t} else {\n\t\t\t\t\thosts[len(hosts)-1].scheme = \"https\"\n\t\t\t\t}\n\t\t\t}\n\t\t\thosts[len(hosts)-1].path = \"/v2\"\n\t\t\thosts[len(hosts)-1].capabilities = docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush\n\t\t}\n\n\t\tvar defaultTLSConfig *tls.Config\n\t\tif options.DefaultTLS != nil {\n\t\t\tdefaultTLSConfig = options.DefaultTLS\n\t\t} else {\n\t\t\tdefaultTLSConfig = &tls.Config{}\n\t\t}\n\n\t\tdefaultTransport := &http.Transport{\n\t\t\tProxy: http.ProxyFromEnvironment,\n\t\t\tDialContext: (&net.Dialer{\n\t\t\t\tTimeout:       30 * time.Second,\n\t\t\t\tKeepAlive:     30 * time.Second,\n\t\t\t\tFallbackDelay: 300 * time.Millisecond,\n\t\t\t}).DialContext,\n\t\t\tMaxIdleConns:          10,\n\t\t\tIdleConnTimeout:       30 * time.Second,\n\t\t\tTLSHandshakeTimeout:   10 * time.Second,\n\t\t\tTLSClientConfig:       defaultTLSConfig,\n\t\t\tExpectContinueTimeout: 5 * time.Second,\n\t\t}\n\n\t\tclient := &http.Client{\n\t\t\tTransport: defaultTransport,\n\t\t}\n\t\tif options.UpdateClient != nil {\n\t\t\tif err := options.UpdateClient(client); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\tauthOpts := []docker.AuthorizerOpt{docker.WithAuthClient(client)}\n\t\tif options.Credentials != nil {\n\t\t\tauthOpts = append(authOpts, docker.WithAuthCreds(options.Credentials))\n\t\t}\n\t\tauthOpts = append(authOpts, options.AuthorizerOpts...)\n\t\tauthorizer := docker.NewDockerAuthorizer(authOpts...)\n\n\t\trhosts := make([]docker.RegistryHost, len(hosts))\n\t\tfor i, host := range hosts {\n\n\t\t\trhosts[i].Scheme = host.scheme\n\t\t\trhosts[i].Host = host.host\n\t\t\trhosts[i].Path = host.path\n\t\t\trhosts[i].Capabilities = host.capabilities\n\t\t\trhosts[i].Header = host.header\n\n\t\t\tif host.caCerts != nil || host.clientPairs != nil || host.skipVerify != nil {\n\t\t\t\ttr := defaultTransport.Clone()\n\t\t\t\ttlsConfig := tr.TLSClientConfig\n\t\t\t\tif host.skipVerify != nil {\n\t\t\t\t\ttlsConfig.InsecureSkipVerify = *host.skipVerify\n\t\t\t\t}\n\t\t\t\tif host.caCerts != nil {\n\t\t\t\t\tif tlsConfig.RootCAs == nil {\n\t\t\t\t\t\trootPool, err := rootSystemPool()\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"unable to initialize cert pool: %w\", err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttlsConfig.RootCAs = rootPool\n\t\t\t\t\t}\n\t\t\t\t\tfor _, f := range host.caCerts {\n\t\t\t\t\t\tdata, err := os.ReadFile(f)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"unable to read CA cert %q: %w\", f, err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif !tlsConfig.RootCAs.AppendCertsFromPEM(data) {\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"unable to load CA cert %q\", f)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif host.clientPairs != nil {\n\t\t\t\t\tfor _, pair := range host.clientPairs {\n\t\t\t\t\t\tcertPEMBlock, err := os.ReadFile(pair[0])\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"unable to read CERT file %q: %w\", pair[0], err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar keyPEMBlock []byte\n\t\t\t\t\t\tif pair[1] != \"\" {\n\t\t\t\t\t\t\tkeyPEMBlock, err = os.ReadFile(pair[1])\n\t\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"unable to read CERT file %q: %w\", pair[1], err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Load key block from same PEM file\n\t\t\t\t\t\t\tkeyPEMBlock = certPEMBlock\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, fmt.Errorf(\"failed to load X509 key pair: %w\", err)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttlsConfig.Certificates = append(tlsConfig.Certificates, cert)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tc := *client\n\t\t\t\tc.Transport = tr\n\t\t\t\tif options.UpdateClient != nil {\n\t\t\t\t\tif err := options.UpdateClient(&c); err != nil {\n\t\t\t\t\t\treturn nil, err\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trhosts[i].Client = &c\n\t\t\t\trhosts[i].Authorizer = docker.NewDockerAuthorizer(append(authOpts, docker.WithAuthClient(&c))...)\n\t\t\t} else {\n\t\t\t\trhosts[i].Client = client\n\t\t\t\trhosts[i].Authorizer = authorizer\n\t\t\t}\n\t\t}\n\n\t\treturn rhosts, nil\n\t}\n\n}\n\n// HostDirFromRoot returns a function which finds a host directory\n// based at the given root.\nfunc HostDirFromRoot(root string) func(string) (string, error) {\n\treturn func(host string) (string, error) {\n\t\tfor _, p := range hostPaths(root, host) {\n\t\t\tif _, err := os.Stat(p); err == nil {\n\t\t\t\treturn p, nil\n\t\t\t} else if !os.IsNotExist(err) {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t}\n\t\treturn \"\", errdefs.ErrNotFound\n\t}\n}\n\n// hostDirectory converts \":port\" to \"_port_\" in directory names\nfunc hostDirectory(host string) string {\n\tidx := strings.LastIndex(host, \":\")\n\tif idx > 0 {\n\t\treturn host[:idx] + \"_\" + host[idx+1:] + \"_\"\n\t}\n\treturn host\n}\n\nfunc loadHostDir(ctx context.Context, hostsDir string) ([]hostConfig, error) {\n\tb, err := os.ReadFile(filepath.Join(hostsDir, \"hosts.toml\"))\n\tif err != nil && !os.IsNotExist(err) {\n\t\treturn nil, err\n\t}\n\n\tif len(b) == 0 {\n\t\t// If hosts.toml does not exist, fallback to checking for\n\t\t// certificate files based on Docker's certificate file\n\t\t// pattern (\".crt\", \".cert\", \".key\" files)\n\t\treturn loadCertFiles(ctx, hostsDir)\n\t}\n\n\thosts, err := parseHostsFile(hostsDir, b)\n\tif err != nil {\n\t\tlog.G(ctx).WithError(err).Error(\"failed to decode hosts.toml\")\n\t\t// Fallback to checking certificate files\n\t\treturn loadCertFiles(ctx, hostsDir)\n\t}\n\n\treturn hosts, nil\n}\n\ntype hostFileConfig struct {\n\t// Capabilities determine what operations a host is\n\t// capable of performing. Allowed values\n\t//  - pull\n\t//  - resolve\n\t//  - push\n\tCapabilities []string `toml:\"capabilities\"`\n\n\t// CACert are the public key certificates for TLS\n\t// Accepted types\n\t// - string - Single file with certificate(s)\n\t// - []string - Multiple files with certificates\n\tCACert interface{} `toml:\"ca\"`\n\n\t// Client keypair(s) for TLS with client authentication\n\t// Accepted types\n\t// - string - Single file with public and private keys\n\t// - []string - Multiple files with public and private keys\n\t// - [][2]string - Multiple keypairs with public and private keys in separate files\n\tClient interface{} `toml:\"client\"`\n\n\t// SkipVerify skips verification of the server's certificate chain\n\t// and host name. This should only be used for testing or in\n\t// combination with other methods of verifying connections.\n\tSkipVerify *bool `toml:\"skip_verify\"`\n\n\t// Header are additional header files to send to the server\n\tHeader map[string]interface{} `toml:\"header\"`\n\n\t// OverridePath indicates the API root endpoint is defined in the URL\n\t// path rather than by the API specification.\n\t// This may be used with non-compliant OCI registries to override the\n\t// API root endpoint.\n\tOverridePath bool `toml:\"override_path\"`\n\n\t// TODO: Credentials: helper? name? username? alternate domain? token?\n}\n\nfunc parseHostsFile(baseDir string, b []byte) ([]hostConfig, error) {\n\ttree, err := toml.LoadBytes(b)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse TOML: %w\", err)\n\t}\n\n\t// HACK: we want to keep toml parsing structures private in this package, however go-toml ignores private embedded types.\n\t// so we remap it to a public type within the func body, so technically it's public, but not possible to import elsewhere.\n\t//nolint:unused\n\ttype HostFileConfig = hostFileConfig\n\n\tc := struct {\n\t\tHostFileConfig\n\t\t// Server specifies the default server. When `host` is\n\t\t// also specified, those hosts are tried first.\n\t\tServer string `toml:\"server\"`\n\t\t// HostConfigs store the per-host configuration\n\t\tHostConfigs map[string]hostFileConfig `toml:\"host\"`\n\t}{}\n\n\torderedHosts, err := getSortedHosts(tree)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar (\n\t\thosts []hostConfig\n\t)\n\n\tif err := tree.Unmarshal(&c); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Parse hosts array\n\tfor _, host := range orderedHosts {\n\t\tconfig := c.HostConfigs[host]\n\n\t\tparsed, err := parseHostConfig(host, baseDir, config)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\thosts = append(hosts, parsed)\n\t}\n\n\t// Parse root host config and append it as the last element\n\tparsed, err := parseHostConfig(c.Server, baseDir, c.HostFileConfig)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\thosts = append(hosts, parsed)\n\n\treturn hosts, nil\n}\n\nfunc parseHostConfig(server string, baseDir string, config hostFileConfig) (hostConfig, error) {\n\tvar (\n\t\tresult = hostConfig{}\n\t\terr    error\n\t)\n\n\tif server != \"\" {\n\t\tif !strings.HasPrefix(server, \"http\") {\n\t\t\tserver = \"https://\" + server\n\t\t}\n\t\tu, err := url.Parse(server)\n\t\tif err != nil {\n\t\t\treturn hostConfig{}, fmt.Errorf(\"unable to parse server %v: %w\", server, err)\n\t\t}\n\t\tresult.scheme = u.Scheme\n\t\tresult.host = u.Host\n\t\tif len(u.Path) > 0 {\n\t\t\tu.Path = path.Clean(u.Path)\n\t\t\tif !strings.HasSuffix(u.Path, \"/v2\") && !config.OverridePath {\n\t\t\t\tu.Path = u.Path + \"/v2\"\n\t\t\t}\n\t\t} else if !config.OverridePath {\n\t\t\tu.Path = \"/v2\"\n\t\t}\n\t\tresult.path = u.Path\n\t}\n\n\tresult.skipVerify = config.SkipVerify\n\n\tif len(config.Capabilities) > 0 {\n\t\tfor _, c := range config.Capabilities {\n\t\t\tswitch strings.ToLower(c) {\n\t\t\tcase \"pull\":\n\t\t\t\tresult.capabilities |= docker.HostCapabilityPull\n\t\t\tcase \"resolve\":\n\t\t\t\tresult.capabilities |= docker.HostCapabilityResolve\n\t\t\tcase \"push\":\n\t\t\t\tresult.capabilities |= docker.HostCapabilityPush\n\t\t\tdefault:\n\t\t\t\treturn hostConfig{}, fmt.Errorf(\"unknown capability %v\", c)\n\t\t\t}\n\t\t}\n\t} else {\n\t\tresult.capabilities = docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush\n\t}\n\n\tif config.CACert != nil {\n\t\tswitch cert := config.CACert.(type) {\n\t\tcase string:\n\t\t\tresult.caCerts = []string{makeAbsPath(cert, baseDir)}\n\t\tcase []interface{}:\n\t\t\tresult.caCerts, err = makeStringSlice(cert, func(p string) string {\n\t\t\t\treturn makeAbsPath(p, baseDir)\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\treturn hostConfig{}, err\n\t\t\t}\n\t\tdefault:\n\t\t\treturn hostConfig{}, fmt.Errorf(\"invalid type %v for \\\"ca\\\"\", cert)\n\t\t}\n\t}\n\n\tif config.Client != nil {\n\t\tswitch client := config.Client.(type) {\n\t\tcase string:\n\t\t\tresult.clientPairs = [][2]string{{makeAbsPath(client, baseDir), \"\"}}\n\t\tcase []interface{}:\n\t\t\t// []string or [][2]string\n\t\t\tfor _, pairs := range client {\n\t\t\t\tswitch p := pairs.(type) {\n\t\t\t\tcase string:\n\t\t\t\t\tresult.clientPairs = append(result.clientPairs, [2]string{makeAbsPath(p, baseDir), \"\"})\n\t\t\t\tcase []interface{}:\n\t\t\t\t\tslice, err := makeStringSlice(p, func(s string) string {\n\t\t\t\t\t\treturn makeAbsPath(s, baseDir)\n\t\t\t\t\t})\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn hostConfig{}, err\n\t\t\t\t\t}\n\t\t\t\t\tif len(slice) != 2 {\n\t\t\t\t\t\treturn hostConfig{}, fmt.Errorf(\"invalid pair %v for \\\"client\\\"\", p)\n\t\t\t\t\t}\n\n\t\t\t\t\tvar pair [2]string\n\t\t\t\t\tcopy(pair[:], slice)\n\t\t\t\t\tresult.clientPairs = append(result.clientPairs, pair)\n\t\t\t\tdefault:\n\t\t\t\t\treturn hostConfig{}, fmt.Errorf(\"invalid type %T for \\\"client\\\"\", p)\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\treturn hostConfig{}, fmt.Errorf(\"invalid type %v for \\\"client\\\"\", client)\n\t\t}\n\t}\n\n\tif config.Header != nil {\n\t\theader := http.Header{}\n\t\tfor key, ty := range config.Header {\n\t\t\tswitch value := ty.(type) {\n\t\t\tcase string:\n\t\t\t\theader[key] = []string{value}\n\t\t\tcase []interface{}:\n\t\t\t\theader[key], err = makeStringSlice(value, nil)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn hostConfig{}, err\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn hostConfig{}, fmt.Errorf(\"invalid type %v for header %q\", ty, key)\n\t\t\t}\n\t\t}\n\t\tresult.header = header\n\t}\n\n\treturn result, nil\n}\n\n// getSortedHosts returns the list of hosts as they defined in the file.\nfunc getSortedHosts(root *toml.Tree) ([]string, error) {\n\titer, ok := root.Get(\"host\").(*toml.Tree)\n\tif !ok {\n\t\treturn nil, errors.New(\"invalid `host` tree\")\n\t}\n\n\tlist := append([]string{}, iter.Keys()...)\n\n\t// go-toml stores TOML sections in the map object, so no order guaranteed.\n\t// We retrieve line number for each key and sort the keys by position.\n\tsort.Slice(list, func(i, j int) bool {\n\t\th1 := iter.GetPath([]string{list[i]}).(*toml.Tree)\n\t\th2 := iter.GetPath([]string{list[j]}).(*toml.Tree)\n\t\treturn h1.Position().Line < h2.Position().Line\n\t})\n\n\treturn list, nil\n}\n\n// makeStringSlice is a helper func to convert from []interface{} to []string.\n// Additionally an optional cb func may be passed to perform string mapping.\nfunc makeStringSlice(slice []interface{}, cb func(string) string) ([]string, error) {\n\tout := make([]string, len(slice))\n\tfor i, value := range slice {\n\t\tstr, ok := value.(string)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"unable to cast %v to string\", value)\n\t\t}\n\n\t\tif cb != nil {\n\t\t\tout[i] = cb(str)\n\t\t} else {\n\t\t\tout[i] = str\n\t\t}\n\t}\n\treturn out, nil\n}\n\nfunc makeAbsPath(p string, base string) string {\n\tif filepath.IsAbs(p) {\n\t\treturn p\n\t}\n\treturn filepath.Join(base, p)\n}\n\n// loadCertsDir loads certs from certsDir like \"/etc/docker/certs.d\" .\n// Compatible with Docker file layout\n//   - files ending with \".crt\" are treated as CA certificate files\n//   - files ending with \".cert\" are treated as client certificates, and\n//     files with the same name but ending with \".key\" are treated as the\n//     corresponding private key.\n//     NOTE: If a \".key\" file is missing, this function will just return\n//     the \".cert\", which may contain the private key. If the \".cert\" file\n//     does not contain the private key, the caller should detect and error.\nfunc loadCertFiles(ctx context.Context, certsDir string) ([]hostConfig, error) {\n\tfs, err := os.ReadDir(certsDir)\n\tif err != nil && !os.IsNotExist(err) {\n\t\treturn nil, err\n\t}\n\thosts := make([]hostConfig, 1)\n\tfor _, f := range fs {\n\t\tif f.IsDir() {\n\t\t\tcontinue\n\t\t}\n\t\tif strings.HasSuffix(f.Name(), \".crt\") {\n\t\t\thosts[0].caCerts = append(hosts[0].caCerts, filepath.Join(certsDir, f.Name()))\n\t\t}\n\t\tif strings.HasSuffix(f.Name(), \".cert\") {\n\t\t\tvar pair [2]string\n\t\t\tcertFile := f.Name()\n\t\t\tpair[0] = filepath.Join(certsDir, certFile)\n\t\t\t// Check if key also exists\n\t\t\tkeyFile := filepath.Join(certsDir, certFile[:len(certFile)-5]+\".key\")\n\t\t\tif _, err := os.Stat(keyFile); err == nil {\n\t\t\t\tpair[1] = keyFile\n\t\t\t} else if !os.IsNotExist(err) {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\thosts[0].clientPairs = append(hosts[0].clientPairs, pair)\n\t\t}\n\t}\n\treturn hosts, nil\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/config/hosts_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage config\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/containerd/log/logtest\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/docker\"\n)\n\nconst allCaps = docker.HostCapabilityPull | docker.HostCapabilityResolve | docker.HostCapabilityPush\n\nfunc TestDefaultHosts(t *testing.T) {\n\tctx := logtest.WithT(context.Background(), t)\n\tresolve := ConfigureHosts(ctx, HostOptions{})\n\n\tfor _, tc := range []struct {\n\t\thost     string\n\t\texpected []docker.RegistryHost\n\t}{\n\t\t{\n\t\t\thost: \"docker.io\",\n\t\t\texpected: []docker.RegistryHost{\n\t\t\t\t{\n\t\t\t\t\tScheme:       \"https\",\n\t\t\t\t\tHost:         \"registry-1.docker.io\",\n\t\t\t\t\tPath:         \"/v2\",\n\t\t\t\t\tCapabilities: allCaps,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t} {\n\t\thosts, err := resolve(tc.host)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"[%s] resolve failed: %v\", tc.host, err)\n\t\t\tcontinue\n\t\t}\n\t\tif len(hosts) != len(tc.expected) {\n\t\t\tt.Errorf(\"[%s] unexpected number of hosts %d, expected %d\", tc.host, len(hosts), len(tc.expected))\n\t\t\tcontinue\n\t\t}\n\t\tfor j := range hosts {\n\t\t\tif !compareRegistryHost(hosts[j], tc.expected[j]) {\n\n\t\t\t\tt.Errorf(\"[%s] [%d] unexpected host %v, expected %v\", tc.host, j, hosts[j], tc.expected[j])\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t}\n\n\t}\n}\n\nfunc TestParseHostFile(t *testing.T) {\n\tconst testtoml = `\nserver = \"https://test-default.registry\"\nca = \"/etc/path/default\"\n[header]\n  x-custom-1 = \"custom header\"\n\n[host.\"https://mirror.registry\"]\n  capabilities = [\"pull\"]\n  ca = \"/etc/certs/mirror.pem\"\n  skip_verify = false\n  [host.\"https://mirror.registry\".header]\n    x-custom-2 = [\"value1\", \"value2\"]\n\n[host.\"https://mirror-bak.registry/us\"]\n  capabilities = [\"pull\"]\n  skip_verify = true\n\n[host.\"http://mirror.registry\"]\n  capabilities = [\"pull\"]\n\n[host.\"https://test-1.registry\"]\n  capabilities = [\"pull\", \"resolve\", \"push\"]\n  ca = [\"/etc/certs/test-1-ca.pem\", \"/etc/certs/special.pem\"]\n  client = [[\"/etc/certs/client.cert\", \"/etc/certs/client.key\"],[\"/etc/certs/client.pem\", \"\"]]\n\n[host.\"https://test-2.registry\"]\n  client = \"/etc/certs/client.pem\"\n\n[host.\"https://test-3.registry\"]\n  client = [\"/etc/certs/client-1.pem\", \"/etc/certs/client-2.pem\"]\n\n[host.\"https://noncompliantmirror.registry/v2/namespaceprefix\"]\n  capabilities = [\"pull\"]\n  override_path = true\n\n[host.\"https://noprefixnoncompliant.registry\"]\n  override_path = true\n`\n\tvar tb, fb = true, false\n\texpected := []hostConfig{\n\t\t{\n\t\t\tscheme:       \"https\",\n\t\t\thost:         \"mirror.registry\",\n\t\t\tpath:         \"/v2\",\n\t\t\tcapabilities: docker.HostCapabilityPull,\n\t\t\tcaCerts:      []string{filepath.FromSlash(\"/etc/certs/mirror.pem\")},\n\t\t\tskipVerify:   &fb,\n\t\t\theader:       http.Header{\"x-custom-2\": {\"value1\", \"value2\"}},\n\t\t},\n\t\t{\n\t\t\tscheme:       \"https\",\n\t\t\thost:         \"mirror-bak.registry\",\n\t\t\tpath:         \"/us/v2\",\n\t\t\tcapabilities: docker.HostCapabilityPull,\n\t\t\tskipVerify:   &tb,\n\t\t},\n\t\t{\n\t\t\tscheme:       \"http\",\n\t\t\thost:         \"mirror.registry\",\n\t\t\tpath:         \"/v2\",\n\t\t\tcapabilities: docker.HostCapabilityPull,\n\t\t},\n\t\t{\n\t\t\tscheme:       \"https\",\n\t\t\thost:         \"test-1.registry\",\n\t\t\tpath:         \"/v2\",\n\t\t\tcapabilities: allCaps,\n\t\t\tcaCerts:      []string{filepath.FromSlash(\"/etc/certs/test-1-ca.pem\"), filepath.FromSlash(\"/etc/certs/special.pem\")},\n\t\t\tclientPairs: [][2]string{\n\t\t\t\t{filepath.FromSlash(\"/etc/certs/client.cert\"), filepath.FromSlash(\"/etc/certs/client.key\")},\n\t\t\t\t{filepath.FromSlash(\"/etc/certs/client.pem\"), \"\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tscheme:       \"https\",\n\t\t\thost:         \"test-2.registry\",\n\t\t\tpath:         \"/v2\",\n\t\t\tcapabilities: allCaps,\n\t\t\tclientPairs: [][2]string{\n\t\t\t\t{filepath.FromSlash(\"/etc/certs/client.pem\")},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tscheme:       \"https\",\n\t\t\thost:         \"test-3.registry\",\n\t\t\tpath:         \"/v2\",\n\t\t\tcapabilities: allCaps,\n\t\t\tclientPairs: [][2]string{\n\t\t\t\t{filepath.FromSlash(\"/etc/certs/client-1.pem\")},\n\t\t\t\t{filepath.FromSlash(\"/etc/certs/client-2.pem\")},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tscheme:       \"https\",\n\t\t\thost:         \"noncompliantmirror.registry\",\n\t\t\tpath:         \"/v2/namespaceprefix\",\n\t\t\tcapabilities: docker.HostCapabilityPull,\n\t\t},\n\t\t{\n\t\t\tscheme:       \"https\",\n\t\t\thost:         \"noprefixnoncompliant.registry\",\n\t\t\tcapabilities: allCaps,\n\t\t},\n\t\t{\n\t\t\tscheme:       \"https\",\n\t\t\thost:         \"test-default.registry\",\n\t\t\tpath:         \"/v2\",\n\t\t\tcapabilities: allCaps,\n\t\t\tcaCerts:      []string{filepath.FromSlash(\"/etc/path/default\")},\n\t\t\theader:       http.Header{\"x-custom-1\": {\"custom header\"}},\n\t\t},\n\t}\n\thosts, err := parseHostsFile(\"\", []byte(testtoml))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdefer func() {\n\t\tif t.Failed() {\n\t\t\tt.Log(\"HostConfigs...\\nActual:\\n\" + printHostConfig(hosts) + \"Expected:\\n\" + printHostConfig(expected))\n\t\t}\n\t}()\n\n\tif len(hosts) != len(expected) {\n\t\tt.Fatalf(\"Unexpected number of hosts %d, expected %d\", len(hosts), len(expected))\n\t}\n\n\tfor i := range hosts {\n\t\tif !compareHostConfig(hosts[i], expected[i]) {\n\t\t\tt.Fatalf(\"Mismatch at host %d\", i)\n\t\t}\n\t}\n}\n\nfunc TestLoadCertFiles(t *testing.T) {\n\tdir := t.TempDir()\n\n\ttype testCase struct {\n\t\tinput hostConfig\n\t}\n\tcases := map[string]testCase{\n\t\t\"crt only\": {\n\t\t\tinput: hostConfig{host: \"testing.io\", caCerts: []string{filepath.Join(dir, \"testing.io\", \"ca.crt\")}},\n\t\t},\n\t\t\"crt and cert pair\": {\n\t\t\tinput: hostConfig{\n\t\t\t\thost:    \"testing.io\",\n\t\t\t\tcaCerts: []string{filepath.Join(dir, \"testing.io\", \"ca.crt\")},\n\t\t\t\tclientPairs: [][2]string{\n\t\t\t\t\t{\n\t\t\t\t\t\tfilepath.Join(dir, \"testing.io\", \"client.cert\"),\n\t\t\t\t\t\tfilepath.Join(dir, \"testing.io\", \"client.key\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"cert pair only\": {\n\t\t\tinput: hostConfig{\n\t\t\t\thost: \"testing.io\",\n\t\t\t\tclientPairs: [][2]string{\n\t\t\t\t\t{\n\t\t\t\t\t\tfilepath.Join(dir, \"testing.io\", \"client.cert\"),\n\t\t\t\t\t\tfilepath.Join(dir, \"testing.io\", \"client.key\"),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor name, tc := range cases {\n\t\tt.Run(name, func(t *testing.T) {\n\n\t\t\thostDir := filepath.Join(dir, tc.input.host)\n\t\t\tif err := os.MkdirAll(hostDir, 0700); err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdefer os.RemoveAll(hostDir)\n\n\t\t\tfor _, f := range tc.input.caCerts {\n\t\t\t\tif err := os.WriteFile(f, testKey, 0600); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor _, pair := range tc.input.clientPairs {\n\t\t\t\tif err := os.WriteFile(pair[0], testKey, 0600); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif err := os.WriteFile(pair[1], testKey, 0600); err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconfigs, err := loadHostDir(context.Background(), hostDir)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif len(configs) != 1 {\n\t\t\t\tt.Fatalf(\"\\nexpected:\\n%+v\\ngot:\\n%+v\", tc.input, configs)\n\t\t\t}\n\n\t\t\tcfg := configs[0]\n\t\t\tcfg.host = tc.input.host\n\n\t\t\tif !compareHostConfig(cfg, tc.input) {\n\t\t\t\tt.Errorf(\"\\nexpected:\\n%+v:\\n\\ngot:\\n%+v\", tc.input, cfg)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc compareRegistryHost(j, k docker.RegistryHost) bool {\n\tif j.Scheme != k.Scheme {\n\t\treturn false\n\t}\n\tif j.Host != k.Host {\n\t\treturn false\n\t}\n\tif j.Path != k.Path {\n\t\treturn false\n\t}\n\tif j.Capabilities != k.Capabilities {\n\t\treturn false\n\t}\n\t// Not comparing TLS configs or authorizations\n\treturn true\n}\n\nfunc compareHostConfig(j, k hostConfig) bool {\n\tif j.scheme != k.scheme {\n\t\treturn false\n\t}\n\tif j.host != k.host {\n\t\treturn false\n\t}\n\tif j.path != k.path {\n\t\treturn false\n\t}\n\tif j.capabilities != k.capabilities {\n\t\treturn false\n\t}\n\n\tif len(j.caCerts) != len(k.caCerts) {\n\t\treturn false\n\t}\n\tfor i := range j.caCerts {\n\t\tif j.caCerts[i] != k.caCerts[i] {\n\t\t\treturn false\n\t\t}\n\t}\n\tif len(j.clientPairs) != len(k.clientPairs) {\n\t\treturn false\n\t}\n\tfor i := range j.clientPairs {\n\t\tif j.clientPairs[i][0] != k.clientPairs[i][0] {\n\t\t\treturn false\n\t\t}\n\t\tif j.clientPairs[i][1] != k.clientPairs[i][1] {\n\t\t\treturn false\n\t\t}\n\t}\n\tif j.skipVerify != nil && k.skipVerify != nil {\n\t\tif *j.skipVerify != *k.skipVerify {\n\t\t\treturn false\n\t\t}\n\t} else if j.skipVerify != nil || k.skipVerify != nil {\n\t\treturn false\n\t}\n\n\tif len(j.header) != len(k.header) {\n\t\treturn false\n\t}\n\tfor key := range j.header {\n\t\tif len(j.header[key]) != len(k.header[key]) {\n\t\t\treturn false\n\t\t}\n\t\tfor i := range j.header[key] {\n\t\t\tif j.header[key][i] != k.header[key][i] {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\n\treturn true\n}\n\nfunc printHostConfig(hc []hostConfig) string {\n\tb := bytes.NewBuffer(nil)\n\tfor i := range hc {\n\t\tfmt.Fprintf(b, \"\\t[%d]\\tscheme: %q\\n\", i, hc[i].scheme)\n\t\tfmt.Fprintf(b, \"\\t\\thost: %q\\n\", hc[i].host)\n\t\tfmt.Fprintf(b, \"\\t\\tpath: %q\\n\", hc[i].path)\n\t\tfmt.Fprintf(b, \"\\t\\tcaps: %03b\\n\", hc[i].capabilities)\n\t\tfmt.Fprintf(b, \"\\t\\tca: %#v\\n\", hc[i].caCerts)\n\t\tfmt.Fprintf(b, \"\\t\\tclients: %#v\\n\", hc[i].clientPairs)\n\t\tif hc[i].skipVerify == nil {\n\t\t\tfmt.Fprintf(b, \"\\t\\tskip-verify: %v\\n\", hc[i].skipVerify)\n\t\t} else {\n\t\t\tfmt.Fprintf(b, \"\\t\\tskip-verify: %t\\n\", *hc[i].skipVerify)\n\t\t}\n\t\tfmt.Fprintf(b, \"\\t\\theader: %#v\\n\", hc[i].header)\n\t}\n\treturn b.String()\n}\n\nvar (\n\ttestKey = []byte(`-----BEGIN PRIVATE KEY-----\n\tMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDa+zvPgFXwra4S\n\t0DzEWRgZHxVTDG1sJsnN/jOaHCNpRyABGVW5kdei9WFWv3dpiELI+guQMjdUL++w\n\tM68bs6cXKW+1nW6u5uWuGwklOwkoKoeHkkn/vHef7ybk+5qdk6AYY0DKQsrBBOvj\n\tf0WAnG+1xi8VIOEBmce0/47MexOiuILVkjokgdmDCOc8ShkT6/EJTCsI1wDew/4G\n\t9IiRzw2xSM0ZATAtEC3HEBRLJGWZQtuKlLCuzJ+erOWUcg2cjnSgR3PmaAXE//5g\n\tSoeqEbtTo1satf9AR4VvreIAI8m0eyo8ABMLTkZovEFcUUHetL63hdqItjCeRfrQ\n\tzK4LMRFbAgMBAAECggEBAJtP6UHo0gtcA8SQMSlJz4+xvhwjClDUyfjyPIMnRe5b\n\tZdWhtG1jhT+tLhaqwfT1kfidcCobk6aAQU4FukK5jt8cooB7Yo9mcKylvDzNvFbi\n\tozGCjj113JpwsnNiCG2O0NO7Qa6y5L810GCQWik3yvtvzuD7atsJyN0VDKD3Ahw7\n\t1X8z76grZFlhVMCTAA3vAJ2y2p3sd+TGC/PIhnsvChwxEorGCnMj93mBaUI7zZRY\n\tEZhlk4ZvC9sUvlVUuYC+wAHjasgN9s3AzsOBSx+Xt3NaXQHzhL0mVo/vu/pjjFBs\n\tWBLR1PBoIfveTJPOp+Hrr4cuCK0NuX9sWlWPYLl5A2ECgYEA5fq3n4PhbJ2BuTS5\n\tAVgOmjRpk1eogb6aSY+cx7Mr++ADF9EYXc5tgKoUsDeeiiyK2lv6IKavoTWT1kdd\n\tshiclyEzp2CxG5GtbC/g2XHiBLepgo1fjfev3btCmIeGVBjglOx4F3gEsRygrAID\n\tzcz94m2I+uqLT8hvWnccIqScglkCgYEA88H2ji4Nvx6TmqCLcER0vNDVoxxDfgGb\n\tiohvenD2jmmdTnezTddsgECAI8L0BPNS/0vBCduTjs5BqhKbIfQvuK5CANMUcxuQ\n\ttwWH8kPvTYJVgsmWP6sSXSz3PohWC5EA9xACExGtyN6d7sLUCV0SBhjlcgMvGuDM\n\tlP6NjyyWctMCgYBKdfGr+QQsqZaNw48+6ybXMK8aIKCTWYYU2SW21sEf7PizZmTQ\n\tQnzb0rWeFHQFYsSWTH9gwPdOZ8107GheuG9C02IpCDpvpawTwjC31pKKWnjMpz9P\n\t9OkBDpdSUVbhtahJL4L2fkpumck/x+s5X+y3uiVGsFfovgmnrbbzVH7ECQKBgQCC\n\tMYs7DaYR+obkA/P2FtozL2esIyB5YOpu58iDIWrPTeHTU2PVo8Y0Cj9m2m3zZvNh\n\toFiOp1T85XV1HVL2o7IJdimSvyshAAwfdTjTUS2zvHVn0bwKbZj1Y1r7b15l9yEI\n\t1OgGv16O9zhrmmweRDOoRgvnBYRXWtJqkjuRyULiOQKBgQC/lSYigV32Eb8Eg1pv\n\t7OcPWv4qV4880lRE0MXuQ4VFa4+pqvdziYFYQD4jDYJ4IX9l//bsobL0j7z0P0Gk\n\twDFti9bRwRoO1ntqoA8n2pDLlLRGl0dyjB6fHzp27oqtyf1HRlHiow7Gqx5b5JOk\n\ttycYKwA3DuaSyqPe6MthLneq8w==\n\t-----END PRIVATE KEY-----\n\t`)\n)\n"
  },
  {
    "path": "pkg/remote/remotes/docker/converter.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes\"\n\tdigest \"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\n// LegacyConfigMediaType should be replaced by OCI image spec.\n//\n// More detail: docker/distribution#1622\nconst LegacyConfigMediaType = \"application/octet-stream\"\n\n// ConvertManifest changes application/octet-stream to schema2 config media type if need.\n//\n// NOTE:\n// 1. original manifest will be deleted by next gc round.\n// 2. don't cover manifest list.\nfunc ConvertManifest(ctx context.Context, store content.Store, desc ocispec.Descriptor) (ocispec.Descriptor, error) {\n\tif !(desc.MediaType == images.MediaTypeDockerSchema2Manifest ||\n\t\tdesc.MediaType == ocispec.MediaTypeImageManifest) {\n\n\t\tlog.G(ctx).Warnf(\"do nothing for media type: %s\", desc.MediaType)\n\t\treturn desc, nil\n\t}\n\n\t// read manifest data\n\tmb, err := content.ReadBlob(ctx, store, desc)\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to read index data: %w\", err)\n\t}\n\n\tvar manifest ocispec.Manifest\n\tif err := json.Unmarshal(mb, &manifest); err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to unmarshal data into manifest: %w\", err)\n\t}\n\n\t// check config media type\n\tif manifest.Config.MediaType != LegacyConfigMediaType {\n\t\treturn desc, nil\n\t}\n\n\tmanifest.Config.MediaType = images.MediaTypeDockerSchema2Config\n\tdata, err := json.MarshalIndent(manifest, \"\", \"   \")\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to marshal manifest: %w\", err)\n\t}\n\n\t// update manifest with gc labels\n\tdesc.Digest = digest.Canonical.FromBytes(data)\n\tdesc.Size = int64(len(data))\n\n\tlabels := map[string]string{}\n\tfor i, c := range append([]ocispec.Descriptor{manifest.Config}, manifest.Layers...) {\n\t\tlabels[fmt.Sprintf(\"containerd.io/gc.ref.content.%d\", i)] = c.Digest.String()\n\t}\n\n\tref := remotes.MakeRefKey(ctx, desc)\n\tif err := content.WriteBlob(ctx, store, ref, bytes.NewReader(data), desc, content.WithLabels(labels)); err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to update content: %w\", err)\n\t}\n\treturn desc, nil\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/converter_fuzz.go",
    "content": "//go:build gofuzz\n\n/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"os\"\n\n\tfuzz \"github.com/AdaLogics/go-fuzz-headers\"\n\t\"github.com/containerd/containerd/v2/plugins/content/local\"\n\t\"github.com/containerd/log\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/sirupsen/logrus\"\n)\n\nfunc FuzzConvertManifest(data []byte) int {\n\tctx := context.Background()\n\n\t// Do not log the message below\n\t// level=warning msg=\"do nothing for media type: ...\"\n\tlog.G(ctx).Logger.SetLevel(logrus.PanicLevel)\n\n\tf := fuzz.NewConsumer(data)\n\tdesc := ocispec.Descriptor{}\n\terr := f.GenerateStruct(&desc)\n\tif err != nil {\n\t\treturn 0\n\t}\n\ttmpdir, err := os.MkdirTemp(\"\", \"fuzzing-\")\n\tif err != nil {\n\t\treturn 0\n\t}\n\tcs, err := local.NewStore(tmpdir)\n\tif err != nil {\n\t\treturn 0\n\t}\n\t_, _ = ConvertManifest(ctx, cs, desc)\n\treturn 1\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/errcode.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// ErrorCoder is the base interface for ErrorCode and Error allowing\n// users of each to just call ErrorCode to get the real ID of each\ntype ErrorCoder interface {\n\tErrorCode() ErrorCode\n}\n\n// ErrorCode represents the error type. The errors are serialized via strings\n// and the integer format may change and should *never* be exported.\ntype ErrorCode int\n\nvar _ error = ErrorCode(0)\n\n// ErrorCode just returns itself\nfunc (ec ErrorCode) ErrorCode() ErrorCode {\n\treturn ec\n}\n\n// Error returns the ID/Value\nfunc (ec ErrorCode) Error() string {\n\t// NOTE(stevvooe): Cannot use message here since it may have unpopulated args.\n\treturn strings.ToLower(strings.Replace(ec.String(), \"_\", \" \", -1))\n}\n\n// Descriptor returns the descriptor for the error code.\nfunc (ec ErrorCode) Descriptor() ErrorDescriptor {\n\td, ok := errorCodeToDescriptors[ec]\n\n\tif !ok {\n\t\treturn ErrorCodeUnknown.Descriptor()\n\t}\n\n\treturn d\n}\n\n// String returns the canonical identifier for this error code.\nfunc (ec ErrorCode) String() string {\n\treturn ec.Descriptor().Value\n}\n\n// Message returned the human-readable error message for this error code.\nfunc (ec ErrorCode) Message() string {\n\treturn ec.Descriptor().Message\n}\n\n// MarshalText encodes the receiver into UTF-8-encoded text and returns the\n// result.\nfunc (ec ErrorCode) MarshalText() (text []byte, err error) {\n\treturn []byte(ec.String()), nil\n}\n\n// UnmarshalText decodes the form generated by MarshalText.\nfunc (ec *ErrorCode) UnmarshalText(text []byte) error {\n\tdesc, ok := idToDescriptors[string(text)]\n\n\tif !ok {\n\t\tdesc = ErrorCodeUnknown.Descriptor()\n\t}\n\n\t*ec = desc.Code\n\n\treturn nil\n}\n\n// WithMessage creates a new Error struct based on the passed-in info and\n// overrides the Message property.\nfunc (ec ErrorCode) WithMessage(message string) Error {\n\treturn Error{\n\t\tCode:    ec,\n\t\tMessage: message,\n\t}\n}\n\n// WithDetail creates a new Error struct based on the passed-in info and\n// set the Detail property appropriately\nfunc (ec ErrorCode) WithDetail(detail interface{}) Error {\n\treturn Error{\n\t\tCode:    ec,\n\t\tMessage: ec.Message(),\n\t}.WithDetail(detail)\n}\n\n// WithArgs creates a new Error struct and sets the Args slice\nfunc (ec ErrorCode) WithArgs(args ...interface{}) Error {\n\treturn Error{\n\t\tCode:    ec,\n\t\tMessage: ec.Message(),\n\t}.WithArgs(args...)\n}\n\n// Error provides a wrapper around ErrorCode with extra Details provided.\ntype Error struct {\n\tCode    ErrorCode   `json:\"code\"`\n\tMessage string      `json:\"message\"`\n\tDetail  interface{} `json:\"detail,omitempty\"`\n\n\t// TODO(duglin): See if we need an \"args\" property so we can do the\n\t// variable substitution right before showing the message to the user\n}\n\nvar _ error = Error{}\n\n// ErrorCode returns the ID/Value of this Error\nfunc (e Error) ErrorCode() ErrorCode {\n\treturn e.Code\n}\n\n// Error returns a human readable representation of the error.\nfunc (e Error) Error() string {\n\treturn fmt.Sprintf(\"%s: %s\", e.Code.Error(), e.Message)\n}\n\n// WithDetail will return a new Error, based on the current one, but with\n// some Detail info added\nfunc (e Error) WithDetail(detail interface{}) Error {\n\treturn Error{\n\t\tCode:    e.Code,\n\t\tMessage: e.Message,\n\t\tDetail:  detail,\n\t}\n}\n\n// WithArgs uses the passed-in list of interface{} as the substitution\n// variables in the Error's Message string, but returns a new Error\nfunc (e Error) WithArgs(args ...interface{}) Error {\n\treturn Error{\n\t\tCode:    e.Code,\n\t\tMessage: fmt.Sprintf(e.Code.Message(), args...),\n\t\tDetail:  e.Detail,\n\t}\n}\n\n// ErrorDescriptor provides relevant information about a given error code.\ntype ErrorDescriptor struct {\n\t// Code is the error code that this descriptor describes.\n\tCode ErrorCode\n\n\t// Value provides a unique, string key, often captilized with\n\t// underscores, to identify the error code. This value is used as the\n\t// keyed value when serializing api errors.\n\tValue string\n\n\t// Message is a short, human readable description of the error condition\n\t// included in API responses.\n\tMessage string\n\n\t// Description provides a complete account of the errors purpose, suitable\n\t// for use in documentation.\n\tDescription string\n\n\t// HTTPStatusCode provides the http status code that is associated with\n\t// this error condition.\n\tHTTPStatusCode int\n}\n\n// ParseErrorCode returns the value by the string error code.\n// `ErrorCodeUnknown` will be returned if the error is not known.\nfunc ParseErrorCode(value string) ErrorCode {\n\ted, ok := idToDescriptors[value]\n\tif ok {\n\t\treturn ed.Code\n\t}\n\n\treturn ErrorCodeUnknown\n}\n\n// Errors provides the envelope for multiple errors and a few sugar methods\n// for use within the application.\ntype Errors []error\n\nvar _ error = Errors{}\n\nfunc (errs Errors) Error() string {\n\tswitch len(errs) {\n\tcase 0:\n\t\treturn \"<nil>\"\n\tcase 1:\n\t\treturn errs[0].Error()\n\tdefault:\n\t\tmsg := \"errors:\\n\"\n\t\tfor _, err := range errs {\n\t\t\tmsg += err.Error() + \"\\n\"\n\t\t}\n\t\treturn msg\n\t}\n}\n\n// Len returns the current number of errors.\nfunc (errs Errors) Len() int {\n\treturn len(errs)\n}\n\n// MarshalJSON converts slice of error, ErrorCode or Error into a\n// slice of Error - then serializes\nfunc (errs Errors) MarshalJSON() ([]byte, error) {\n\tvar tmpErrs struct {\n\t\tErrors []Error `json:\"errors,omitempty\"`\n\t}\n\n\tfor _, daErr := range errs {\n\t\tvar err Error\n\n\t\tswitch daErr := daErr.(type) {\n\t\tcase ErrorCode:\n\t\t\terr = daErr.WithDetail(nil)\n\t\tcase Error:\n\t\t\terr = daErr\n\t\tdefault:\n\t\t\terr = ErrorCodeUnknown.WithDetail(daErr)\n\n\t\t}\n\n\t\t// If the Error struct was setup and they forgot to set the\n\t\t// Message field (meaning its \"\") then grab it from the ErrCode\n\t\tmsg := err.Message\n\t\tif msg == \"\" {\n\t\t\tmsg = err.Code.Message()\n\t\t}\n\n\t\ttmpErrs.Errors = append(tmpErrs.Errors, Error{\n\t\t\tCode:    err.Code,\n\t\t\tMessage: msg,\n\t\t\tDetail:  err.Detail,\n\t\t})\n\t}\n\n\treturn json.Marshal(tmpErrs)\n}\n\n// UnmarshalJSON deserializes []Error and then converts it into slice of\n// Error or ErrorCode\nfunc (errs *Errors) UnmarshalJSON(data []byte) error {\n\tvar tmpErrs struct {\n\t\tErrors []Error\n\t}\n\n\tif err := json.Unmarshal(data, &tmpErrs); err != nil {\n\t\treturn err\n\t}\n\n\tvar newErrs Errors\n\tfor _, daErr := range tmpErrs.Errors {\n\t\t// If Message is empty or exactly matches the Code's message string\n\t\t// then just use the Code, no need for a full Error struct\n\t\tif daErr.Detail == nil && (daErr.Message == \"\" || daErr.Message == daErr.Code.Message()) {\n\t\t\t// Error's w/o details get converted to ErrorCode\n\t\t\tnewErrs = append(newErrs, daErr.Code)\n\t\t} else {\n\t\t\t// Error's w/ details are untouched\n\t\t\tnewErrs = append(newErrs, Error{\n\t\t\t\tCode:    daErr.Code,\n\t\t\t\tMessage: daErr.Message,\n\t\t\t\tDetail:  daErr.Detail,\n\t\t\t})\n\t\t}\n\t}\n\n\t*errs = newErrs\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/errdesc.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"sort\"\n\t\"sync\"\n)\n\nvar (\n\terrorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{}\n\tidToDescriptors        = map[string]ErrorDescriptor{}\n\tgroupToDescriptors     = map[string][]ErrorDescriptor{}\n)\n\nvar (\n\t// ErrorCodeUnknown is a generic error that can be used as a last\n\t// resort if there is no situation-specific error message that can be used\n\tErrorCodeUnknown = Register(\"errcode\", ErrorDescriptor{\n\t\tValue:   \"UNKNOWN\",\n\t\tMessage: \"unknown error\",\n\t\tDescription: `Generic error returned when the error does not have an\n\t\t\t                                            API classification.`,\n\t\tHTTPStatusCode: http.StatusInternalServerError,\n\t})\n\n\t// ErrorCodeUnsupported is returned when an operation is not supported.\n\tErrorCodeUnsupported = Register(\"errcode\", ErrorDescriptor{\n\t\tValue:   \"UNSUPPORTED\",\n\t\tMessage: \"The operation is unsupported.\",\n\t\tDescription: `The operation was unsupported due to a missing\n\t\timplementation or invalid set of parameters.`,\n\t\tHTTPStatusCode: http.StatusMethodNotAllowed,\n\t})\n\n\t// ErrorCodeUnauthorized is returned if a request requires\n\t// authentication.\n\tErrorCodeUnauthorized = Register(\"errcode\", ErrorDescriptor{\n\t\tValue:   \"UNAUTHORIZED\",\n\t\tMessage: \"authentication required\",\n\t\tDescription: `The access controller was unable to authenticate\n\t\tthe client. Often this will be accompanied by a\n\t\tWww-Authenticate HTTP response header indicating how to\n\t\tauthenticate.`,\n\t\tHTTPStatusCode: http.StatusUnauthorized,\n\t})\n\n\t// ErrorCodeDenied is returned if a client does not have sufficient\n\t// permission to perform an action.\n\tErrorCodeDenied = Register(\"errcode\", ErrorDescriptor{\n\t\tValue:   \"DENIED\",\n\t\tMessage: \"requested access to the resource is denied\",\n\t\tDescription: `The access controller denied access for the\n\t\toperation on a resource.`,\n\t\tHTTPStatusCode: http.StatusForbidden,\n\t})\n\n\t// ErrorCodeUnavailable provides a common error to report unavailability\n\t// of a service or endpoint.\n\tErrorCodeUnavailable = Register(\"errcode\", ErrorDescriptor{\n\t\tValue:          \"UNAVAILABLE\",\n\t\tMessage:        \"service unavailable\",\n\t\tDescription:    \"Returned when a service is not available\",\n\t\tHTTPStatusCode: http.StatusServiceUnavailable,\n\t})\n\n\t// ErrorCodeTooManyRequests is returned if a client attempts too many\n\t// times to contact a service endpoint.\n\tErrorCodeTooManyRequests = Register(\"errcode\", ErrorDescriptor{\n\t\tValue:   \"TOOMANYREQUESTS\",\n\t\tMessage: \"too many requests\",\n\t\tDescription: `Returned when a client attempts to contact a\n\t\tservice too many times`,\n\t\tHTTPStatusCode: http.StatusTooManyRequests,\n\t})\n)\n\nvar nextCode = 1000\nvar registerLock sync.Mutex\n\n// Register will make the passed-in error known to the environment and\n// return a new ErrorCode\nfunc Register(group string, descriptor ErrorDescriptor) ErrorCode {\n\tregisterLock.Lock()\n\tdefer registerLock.Unlock()\n\n\tdescriptor.Code = ErrorCode(nextCode)\n\n\tif _, ok := idToDescriptors[descriptor.Value]; ok {\n\t\tpanic(fmt.Sprintf(\"ErrorValue %q is already registered\", descriptor.Value))\n\t}\n\tif _, ok := errorCodeToDescriptors[descriptor.Code]; ok {\n\t\tpanic(fmt.Sprintf(\"ErrorCode %v is already registered\", descriptor.Code))\n\t}\n\n\tgroupToDescriptors[group] = append(groupToDescriptors[group], descriptor)\n\terrorCodeToDescriptors[descriptor.Code] = descriptor\n\tidToDescriptors[descriptor.Value] = descriptor\n\n\tnextCode++\n\treturn descriptor.Code\n}\n\ntype byValue []ErrorDescriptor\n\nfunc (a byValue) Len() int           { return len(a) }\nfunc (a byValue) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }\nfunc (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value }\n\n// GetGroupNames returns the list of Error group names that are registered\nfunc GetGroupNames() []string {\n\tkeys := []string{}\n\n\tfor k := range groupToDescriptors {\n\t\tkeys = append(keys, k)\n\t}\n\tsort.Strings(keys)\n\treturn keys\n}\n\n// GetErrorCodeGroup returns the named group of error descriptors\nfunc GetErrorCodeGroup(name string) []ErrorDescriptor {\n\tdesc := groupToDescriptors[name]\n\tsort.Sort(byValue(desc))\n\treturn desc\n}\n\n// GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are\n// registered, irrespective of what group they're in\nfunc GetErrorAllDescriptors() []ErrorDescriptor {\n\tresult := []ErrorDescriptor{}\n\n\tfor _, group := range GetGroupNames() {\n\t\tresult = append(result, GetErrorCodeGroup(group)...)\n\t}\n\tsort.Sort(byValue(result))\n\treturn result\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/fetcher.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/log\"\n\tdigest \"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\ntype dockerFetcher struct {\n\t*dockerBase\n}\n\nfunc (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error) {\n\tctx = log.WithLogger(ctx, log.G(ctx).WithField(\"digest\", desc.Digest))\n\n\thosts := r.filterHosts(HostCapabilityPull)\n\tif len(hosts) == 0 {\n\t\treturn nil, fmt.Errorf(\"no pull hosts: %w\", errdefs.ErrNotFound)\n\t}\n\n\tctx, err := ContextWithRepositoryScope(ctx, r.refspec, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn newHTTPReadSeeker(desc.Size, func(offset int64) (io.ReadCloser, error) {\n\t\t// firstly try fetch via external urls\n\t\tfor _, us := range desc.URLs {\n\t\t\tu, err := url.Parse(us)\n\t\t\tif err != nil {\n\t\t\t\tlog.G(ctx).WithError(err).Debugf(\"failed to parse %q\", us)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif u.Scheme != \"http\" && u.Scheme != \"https\" {\n\t\t\t\tlog.G(ctx).Debug(\"non-http(s) alternative url is unsupported\")\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tctx = log.WithLogger(ctx, log.G(ctx).WithField(\"url\", u))\n\t\t\tlog.G(ctx).Info(\"request\")\n\n\t\t\t// Try this first, parse it\n\t\t\thost := RegistryHost{\n\t\t\t\tClient:       http.DefaultClient,\n\t\t\t\tHost:         u.Host,\n\t\t\t\tScheme:       u.Scheme,\n\t\t\t\tPath:         u.Path,\n\t\t\t\tCapabilities: HostCapabilityPull,\n\t\t\t}\n\t\t\treq := r.request(host, http.MethodGet)\n\t\t\t// Strip namespace from base\n\t\t\treq.path = u.Path\n\t\t\tif u.RawQuery != \"\" {\n\t\t\t\treq.path = req.path + \"?\" + u.RawQuery\n\t\t\t}\n\n\t\t\trc, _, err := r.open(ctx, req, desc.MediaType, offset)\n\t\t\tif err != nil {\n\t\t\t\tif errdefs.IsNotFound(err) {\n\t\t\t\t\tcontinue // try one of the other urls.\n\t\t\t\t}\n\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\treturn rc, nil\n\t\t}\n\n\t\t// Try manifests endpoints for manifests types\n\t\tswitch desc.MediaType {\n\t\tcase images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList,\n\t\t\timages.MediaTypeDockerSchema1Manifest,\n\t\t\tocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:\n\n\t\t\tvar firstErr error\n\t\t\tfor _, host := range r.hosts {\n\t\t\t\treq := r.request(host, http.MethodGet, \"manifests\", desc.Digest.String())\n\t\t\t\tif err := req.addNamespace(r.refspec.Hostname()); err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\trc, _, err := r.open(ctx, req, desc.MediaType, offset)\n\t\t\t\tif err != nil {\n\t\t\t\t\t// Store the error for referencing later\n\t\t\t\t\tif firstErr == nil {\n\t\t\t\t\t\tfirstErr = err\n\t\t\t\t\t}\n\t\t\t\t\tcontinue // try another host\n\t\t\t\t}\n\n\t\t\t\treturn rc, nil\n\t\t\t}\n\n\t\t\treturn nil, firstErr\n\t\t}\n\n\t\t// Finally use blobs endpoints\n\t\tvar firstErr error\n\t\tfor _, host := range r.hosts {\n\t\t\treq := r.request(host, http.MethodGet, \"blobs\", desc.Digest.String())\n\t\t\tif err := req.addNamespace(r.refspec.Hostname()); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\trc, _, err := r.open(ctx, req, desc.MediaType, offset)\n\t\t\tif err != nil {\n\t\t\t\t// Store the error for referencing later\n\t\t\t\tif firstErr == nil {\n\t\t\t\t\tfirstErr = err\n\t\t\t\t}\n\t\t\t\tcontinue // try another host\n\t\t\t}\n\n\t\t\treturn rc, nil\n\t\t}\n\n\t\tif errdefs.IsNotFound(firstErr) {\n\t\t\tfirstErr = fmt.Errorf(\"could not fetch content descriptor %v (%v) from remote: %w\",\n\t\t\t\tdesc.Digest, desc.MediaType, errdefs.ErrNotFound,\n\t\t\t)\n\t\t}\n\n\t\treturn nil, firstErr\n\n\t})\n}\n\nfunc (r dockerFetcher) createGetReq(ctx context.Context, host RegistryHost, mediatype string, ps ...string) (*request, int64, error) {\n\theadReq := r.request(host, http.MethodHead, ps...)\n\tif err := headReq.addNamespace(r.refspec.Hostname()); err != nil {\n\t\treturn nil, 0, err\n\t}\n\tif mediatype == \"\" {\n\t\theadReq.header.Set(\"Accept\", \"*/*\")\n\t} else {\n\t\theadReq.header.Set(\"Accept\", strings.Join([]string{mediatype, `*/*`}, \", \"))\n\t}\n\n\theadResp, err := headReq.doWithRetries(ctx, nil)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\tif headResp.Body != nil {\n\t\theadResp.Body.Close()\n\t}\n\tif headResp.StatusCode > 299 {\n\t\treturn nil, 0, fmt.Errorf(\"unexpected HEAD status code %v: %s\", headReq.String(), headResp.Status)\n\t}\n\n\tgetReq := r.request(host, http.MethodGet, ps...)\n\tif err := getReq.addNamespace(r.refspec.Hostname()); err != nil {\n\t\treturn nil, 0, err\n\t}\n\treturn getReq, headResp.ContentLength, nil\n}\n\nfunc (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (io.ReadCloser, ocispec.Descriptor, error) {\n\tvar desc ocispec.Descriptor\n\tctx = log.WithLogger(ctx, log.G(ctx).WithField(\"digest\", dgst))\n\n\thosts := r.filterHosts(HostCapabilityPull)\n\tif len(hosts) == 0 {\n\t\treturn nil, desc, fmt.Errorf(\"no pull hosts: %w\", errdefs.ErrNotFound)\n\t}\n\n\tctx, err := ContextWithRepositoryScope(ctx, r.refspec, false)\n\tif err != nil {\n\t\treturn nil, desc, err\n\t}\n\n\tvar (\n\t\tgetReq    *request\n\t\tsz        int64\n\t\tfirstErr  error\n\t\tmediaType string\n\t)\n\n\tfor _, host := range r.hosts {\n\t\tgetReq, sz, err = r.createGetReq(ctx, host, mediaType, \"blobs\", dgst.String())\n\t\tif err == nil {\n\t\t\tbreak\n\t\t}\n\t\t// Store the error for referencing later\n\t\tif firstErr == nil {\n\t\t\tfirstErr = err\n\t\t}\n\t}\n\n\tif getReq == nil {\n\t\t// Fall back to the \"manifests\" endpoint\n\t\t// TODO: this change should be upstreamed to containerd.\n\t\tmediaType = strings.Join([]string{\n\t\t\timages.MediaTypeDockerSchema2Manifest,\n\t\t\timages.MediaTypeDockerSchema2ManifestList,\n\t\t\tocispec.MediaTypeImageManifest,\n\t\t\tocispec.MediaTypeImageIndex,\n\t\t}, \", \")\n\t\tfor _, host := range r.hosts {\n\t\t\tgetReq, sz, err = r.createGetReq(ctx, host, mediaType, \"manifests\", dgst.String())\n\t\t\tif err == nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\t// Store the error for referencing later\n\t\t\tif firstErr == nil {\n\t\t\t\tfirstErr = err\n\t\t\t}\n\t\t}\n\t}\n\n\tif getReq == nil {\n\t\tif errdefs.IsNotFound(firstErr) {\n\t\t\tfirstErr = fmt.Errorf(\"could not fetch content %v from remote: %w\", dgst, errdefs.ErrNotFound)\n\t\t}\n\t\tif firstErr == nil {\n\t\t\tfirstErr = fmt.Errorf(\"could not fetch content %v from remote: (unknown)\", dgst)\n\t\t}\n\t\treturn nil, desc, firstErr\n\t}\n\n\tseeker, err := newHTTPReadSeeker(sz, func(offset int64) (rc io.ReadCloser, err error) {\n\t\trc, _, err = r.open(ctx, getReq, mediaType, offset)\n\t\treturn\n\t})\n\tif err != nil {\n\t\treturn nil, desc, err\n\t}\n\n\tdesc = ocispec.Descriptor{\n\t\tMediaType: \"application/octet-stream\",\n\t\tDigest:    dgst,\n\t\tSize:      sz,\n\t}\n\treturn seeker, desc, nil\n}\n\nfunc (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, offset int64) (_ io.ReadCloser, _ int64, retErr error) {\n\tif mediatype == \"\" {\n\t\treq.header.Set(\"Accept\", \"*/*\")\n\t} else {\n\t\treq.header.Set(\"Accept\", strings.Join([]string{mediatype, `*/*`}, \", \"))\n\t}\n\n\tif offset > 0 {\n\t\t// Note: \"Accept-Ranges: bytes\" cannot be trusted as some endpoints\n\t\t// will return the header without supporting the range. The content\n\t\t// range must always be checked.\n\t\treq.header.Set(\"Range\", fmt.Sprintf(\"bytes=%d-\", offset))\n\t}\n\n\tresp, err := req.doWithRetries(ctx, nil)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\tdefer func() {\n\t\tif retErr != nil {\n\t\t\tresp.Body.Close()\n\t\t}\n\t}()\n\n\tif resp.StatusCode > 299 {\n\t\t// TODO(stevvooe): When doing a offset specific request, we should\n\t\t// really distinguish between a 206 and a 200. In the case of 200, we\n\t\t// can discard the bytes, hiding the seek behavior from the\n\t\t// implementation.\n\n\t\tif resp.StatusCode == http.StatusNotFound {\n\t\t\treturn nil, 0, fmt.Errorf(\"content at %v not found: %w\", req.String(), errdefs.ErrNotFound)\n\t\t}\n\t\tvar registryErr Errors\n\t\tif err := json.NewDecoder(resp.Body).Decode(&registryErr); err != nil || registryErr.Len() < 1 {\n\t\t\treturn nil, 0, fmt.Errorf(\"unexpected status code %v: %v\", req.String(), resp.Status)\n\t\t}\n\t\treturn nil, 0, fmt.Errorf(\"unexpected status code %v: %s - Server message: %s\", req.String(), resp.Status, registryErr.Error())\n\t}\n\tcl := resp.ContentLength\n\tif offset > 0 {\n\t\tcr := resp.Header.Get(\"content-range\")\n\t\tif cr != \"\" {\n\t\t\tif !strings.HasPrefix(cr, fmt.Sprintf(\"bytes %d-\", offset)) {\n\t\t\t\treturn nil, 0, fmt.Errorf(\"unhandled content range in response: %v\", cr)\n\n\t\t\t}\n\t\t} else {\n\t\t\t// TODO: Should any cases where use of content range\n\t\t\t// without the proper header be considered?\n\t\t\t// 206 responses?\n\n\t\t\t// Discard up to offset\n\t\t\t// Could use buffer pool here but this case should be rare\n\t\t\tn, err := io.Copy(io.Discard, io.LimitReader(resp.Body, offset))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, 0, fmt.Errorf(\"failed to discard to offset: %w\", err)\n\t\t\t}\n\t\t\tif n != offset {\n\t\t\t\treturn nil, 0, errors.New(\"unable to discard to offset\")\n\t\t\t}\n\t\t\t// Subtract discarded bytes from returned content length to return body\n\t\t\t// size consistent with content-range\n\t\t\tcl = cl - offset\n\t\t}\n\t}\n\n\treturn resp.Body, cl, nil\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/fetcher_fuzz.go",
    "content": "//go:build gofuzz\n\n/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"net/url\"\n\n\tdistribution \"github.com/distribution/reference\"\n)\n\nfunc FuzzFetcher(data []byte) int {\n\tdataLen := len(data)\n\tif dataLen == 0 {\n\t\treturn -1\n\t}\n\n\ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\trw.Header().Set(\"content-range\", fmt.Sprintf(\"bytes %d-%d/%d\", 0, dataLen-1, dataLen))\n\t\trw.Header().Set(\"content-length\", fmt.Sprintf(\"%d\", dataLen))\n\t\trw.Write(data)\n\t}))\n\tdefer s.Close()\n\n\tu, err := url.Parse(s.URL)\n\tif err != nil {\n\t\treturn 0\n\t}\n\n\tf := dockerFetcher{&dockerBase{\n\t\trepository: \"nonempty\",\n\t}}\n\thost := RegistryHost{\n\t\tClient: s.Client(),\n\t\tHost:   u.Host,\n\t\tScheme: u.Scheme,\n\t\tPath:   u.Path,\n\t}\n\n\tctx := context.Background()\n\treq := f.request(host, http.MethodGet)\n\trc, _, err := f.open(ctx, req, \"\", 0)\n\tif err != nil {\n\t\treturn 0\n\t}\n\tb, err := io.ReadAll(rc)\n\tif err != nil {\n\t\treturn 0\n\t}\n\n\texpected := data\n\tif len(b) != len(expected) {\n\t\tpanic(\"len of request is not equal to len of expected but should be\")\n\t}\n\treturn 1\n}\n\nfunc FuzzParseDockerRef(data []byte) int {\n\t_, _ = distribution.ParseDockerRef(string(data))\n\treturn 1\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/fetcher_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"net/url\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestFetcherOpen(t *testing.T) {\n\tcontent := make([]byte, 128)\n\trand.New(rand.NewSource(1)).Read(content)\n\tstart := 0\n\n\ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\tif start > 0 {\n\t\t\trw.Header().Set(\"content-range\", fmt.Sprintf(\"bytes %d-127/128\", start))\n\t\t}\n\t\trw.Header().Set(\"content-length\", fmt.Sprintf(\"%d\", len(content[start:])))\n\t\trw.Write(content[start:])\n\t}))\n\tdefer s.Close()\n\n\tu, err := url.Parse(s.URL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tf := dockerFetcher{&dockerBase{\n\t\trepository: \"nonempty\",\n\t}}\n\n\thost := RegistryHost{\n\t\tClient: s.Client(),\n\t\tHost:   u.Host,\n\t\tScheme: u.Scheme,\n\t\tPath:   u.Path,\n\t}\n\n\tctx := context.Background()\n\n\treq := f.request(host, http.MethodGet)\n\n\tcheckReader := func(o int64) {\n\t\tt.Helper()\n\n\t\trc, cl, err := f.open(ctx, req, \"\", o)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"failed to open: %+v\", err)\n\t\t}\n\t\tb, err := io.ReadAll(rc)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\texpected := content[o:]\n\t\tif len(b) != len(expected) {\n\t\t\tt.Errorf(\"unexpected length %d, expected %d\", len(b), len(expected))\n\t\t\treturn\n\t\t}\n\t\tif cl != int64(len(expected)) {\n\t\t\tt.Errorf(\"unexpected content length %d, expected %d\", cl, len(expected))\n\t\t\treturn\n\t\t}\n\t\tfor i, c := range expected {\n\t\t\tif b[i] != c {\n\t\t\t\tt.Errorf(\"unexpected byte %x at %d, expected %x\", b[i], i, c)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t}\n\n\tcheckReader(0)\n\n\t// Test server ignores content range\n\tcheckReader(25)\n\n\t// Use content range on server\n\tstart = 20\n\tcheckReader(20)\n\n\t// Check returning just last byte and no bytes\n\tstart = 127\n\tcheckReader(127)\n\tstart = 128\n\tcheckReader(128)\n\n\t// Check that server returning a different content range\n\t// then requested errors\n\tstart = 30\n\t_, _, err = f.open(ctx, req, \"\", 20)\n\tif err == nil {\n\t\tt.Fatal(\"expected error opening with invalid server response\")\n\t}\n}\n\n// New set of tests to test new error cases\nfunc TestDockerFetcherOpen(t *testing.T) {\n\ttests := []struct {\n\t\tname                   string\n\t\tmockedStatus           int\n\t\tmockedErr              error\n\t\twant                   io.ReadCloser\n\t\twantLen                int64\n\t\twantErr                bool\n\t\twantServerMessageError bool\n\t\twantPlainError         bool\n\t\tretries                int\n\t}{\n\t\t{\n\t\t\tname:         \"should return status and error.message if it exists if the registry request fails\",\n\t\t\tmockedStatus: 500,\n\t\t\tmockedErr: Errors{Error{\n\t\t\t\tCode:    ErrorCodeUnknown,\n\t\t\t\tMessage: \"Test Error\",\n\t\t\t}},\n\t\t\twant:                   nil,\n\t\t\twantErr:                true,\n\t\t\twantServerMessageError: true,\n\t\t},\n\t\t{\n\t\t\tname:           \"should return just status if the registry request fails and does not return a docker error\",\n\t\t\tmockedStatus:   500,\n\t\t\tmockedErr:      fmt.Errorf(\"Non-docker error\"),\n\t\t\twant:           nil,\n\t\t\twantErr:        true,\n\t\t\twantPlainError: true,\n\t\t}, {\n\t\t\tname:           \"should return StatusRequestTimeout after 5 retries\",\n\t\t\tmockedStatus:   http.StatusRequestTimeout,\n\t\t\tmockedErr:      fmt.Errorf(\"%s\", http.StatusText(http.StatusRequestTimeout)),\n\t\t\twant:           nil,\n\t\t\twantErr:        true,\n\t\t\twantPlainError: true,\n\t\t\tretries:        5,\n\t\t}, {\n\t\t\tname:           \"should return StatusTooManyRequests after 5 retries\",\n\t\t\tmockedStatus:   http.StatusTooManyRequests,\n\t\t\tmockedErr:      fmt.Errorf(\"%s\", http.StatusText(http.StatusTooManyRequests)),\n\t\t\twant:           nil,\n\t\t\twantErr:        true,\n\t\t\twantPlainError: true,\n\t\t\tretries:        5,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\n\t\t\ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\t\t\tif tt.retries > 0 {\n\t\t\t\t\ttt.retries--\n\t\t\t\t}\n\t\t\t\trw.WriteHeader(tt.mockedStatus)\n\t\t\t\tbytes, _ := json.Marshal(tt.mockedErr)\n\t\t\t\trw.Write(bytes)\n\t\t\t}))\n\t\t\tdefer s.Close()\n\n\t\t\tu, err := url.Parse(s.URL)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\n\t\t\tf := dockerFetcher{&dockerBase{\n\t\t\t\trepository: \"ns\",\n\t\t\t}}\n\n\t\t\thost := RegistryHost{\n\t\t\t\tClient: s.Client(),\n\t\t\t\tHost:   u.Host,\n\t\t\t\tScheme: u.Scheme,\n\t\t\t\tPath:   u.Path,\n\t\t\t}\n\n\t\t\treq := f.request(host, http.MethodGet)\n\n\t\t\tgot, cl, err := f.open(context.TODO(), req, \"\", 0)\n\t\t\tassert.Equal(t, tt.wantErr, err != nil)\n\t\t\tassert.Equal(t, tt.want, got)\n\t\t\tassert.Equal(t, tt.wantLen, cl)\n\t\t\tassert.Equal(t, tt.retries, 0)\n\t\t\tif tt.wantErr {\n\t\t\t\tvar expectedError error\n\t\t\t\tif tt.wantServerMessageError {\n\t\t\t\t\texpectedError = fmt.Errorf(\"unexpected status code %v/ns: %v %s - Server message: %s\", s.URL, tt.mockedStatus, http.StatusText(tt.mockedStatus), tt.mockedErr.Error())\n\t\t\t\t} else if tt.wantPlainError {\n\t\t\t\t\texpectedError = fmt.Errorf(\"unexpected status code %v/ns: %v %s\", s.URL, tt.mockedStatus, http.StatusText(tt.mockedStatus))\n\t\t\t\t}\n\t\t\t\tassert.Equal(t, expectedError.Error(), err.Error())\n\n\t\t\t}\n\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/handler.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/containerd/v2/pkg/labels\"\n\t\"github.com/containerd/containerd/v2/pkg/reference\"\n\t\"github.com/containerd/log\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\n// AppendDistributionSourceLabel updates the label of blob with distribution source.\nfunc AppendDistributionSourceLabel(manager content.Manager, ref string) (images.HandlerFunc, error) {\n\trefspec, err := reference.Parse(ref)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tu, err := url.Parse(\"dummy://\" + refspec.Locator)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsource, repo := u.Hostname(), strings.TrimPrefix(u.Path, \"/\")\n\treturn func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {\n\t\tinfo, err := manager.Info(ctx, desc.Digest)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tkey := distributionSourceLabelKey(source)\n\n\t\toriginLabel := \"\"\n\t\tif info.Labels != nil {\n\t\t\toriginLabel = info.Labels[key]\n\t\t}\n\t\tvalue := appendDistributionSourceLabel(originLabel, repo)\n\n\t\t// The repo name has been limited under 256 and the distribution\n\t\t// label might hit the limitation of label size, when blob data\n\t\t// is used as the very, very common layer.\n\t\tif err := labels.Validate(key, value); err != nil {\n\t\t\tlog.G(ctx).Warnf(\"skip to append distribution label: %s\", err)\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tinfo = content.Info{\n\t\t\tDigest: desc.Digest,\n\t\t\tLabels: map[string]string{\n\t\t\t\tkey: value,\n\t\t\t},\n\t\t}\n\t\t_, err = manager.Update(ctx, info, fmt.Sprintf(\"labels.%s\", key))\n\t\treturn nil, err\n\t}, nil\n}\n\nfunc appendDistributionSourceLabel(originLabel, repo string) string {\n\trepos := []string{}\n\tif originLabel != \"\" {\n\t\trepos = strings.Split(originLabel, \",\")\n\t}\n\trepos = append(repos, repo)\n\n\t// use empty string to present duplicate items\n\tfor i := 1; i < len(repos); i++ {\n\t\ttmp, j := repos[i], i-1\n\t\tfor ; j >= 0 && repos[j] >= tmp; j-- {\n\t\t\tif repos[j] == tmp {\n\t\t\t\ttmp = \"\"\n\t\t\t}\n\t\t\trepos[j+1] = repos[j]\n\t\t}\n\t\trepos[j+1] = tmp\n\t}\n\n\ti := 0\n\tfor ; i < len(repos) && repos[i] == \"\"; i++ {\n\t}\n\n\treturn strings.Join(repos[i:], \",\")\n}\n\nfunc distributionSourceLabelKey(source string) string {\n\treturn fmt.Sprintf(\"%s.%s\", labels.LabelDistributionSource, source)\n}\n\n// selectRepositoryMountCandidate will select the repo which has longest\n// common prefix components as the candidate.\nfunc selectRepositoryMountCandidate(refspec reference.Spec, sources map[string]string) string {\n\tu, err := url.Parse(\"dummy://\" + refspec.Locator)\n\tif err != nil {\n\t\t// NOTE: basically, it won't be error here\n\t\treturn \"\"\n\t}\n\n\tsource, target := u.Hostname(), strings.TrimPrefix(u.Path, \"/\")\n\trepoLabel, ok := sources[distributionSourceLabelKey(source)]\n\tif !ok || repoLabel == \"\" {\n\t\treturn \"\"\n\t}\n\n\tn, match := 0, \"\"\n\tcomponents := strings.Split(target, \"/\")\n\tfor _, repo := range strings.Split(repoLabel, \",\") {\n\t\t// the target repo is not a candidate\n\t\tif repo == target {\n\t\t\tcontinue\n\t\t}\n\n\t\tif l := commonPrefixComponents(components, repo); l >= n {\n\t\t\tn, match = l, repo\n\t\t}\n\t}\n\treturn match\n}\n\nfunc commonPrefixComponents(components []string, target string) int {\n\ttargetComponents := strings.Split(target, \"/\")\n\n\ti := 0\n\tfor ; i < len(components) && i < len(targetComponents); i++ {\n\t\tif components[i] != targetComponents[i] {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn i\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/handler_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/containerd/containerd/v2/pkg/labels\"\n\t\"github.com/containerd/containerd/v2/pkg/reference\"\n)\n\nfunc TestAppendDistributionLabel(t *testing.T) {\n\tfor _, tc := range []struct {\n\t\toriginLabel string\n\t\trepo        string\n\t\texpected    string\n\t}{\n\t\t{\n\t\t\toriginLabel: \"\",\n\t\t\trepo:        \"\",\n\t\t\texpected:    \"\",\n\t\t},\n\t\t{\n\t\t\toriginLabel: \"\",\n\t\t\trepo:        \"library/busybox\",\n\t\t\texpected:    \"library/busybox\",\n\t\t},\n\t\t{\n\t\t\toriginLabel: \"library/busybox\",\n\t\t\trepo:        \"library/busybox\",\n\t\t\texpected:    \"library/busybox\",\n\t\t},\n\t\t// remove the duplicate one in origin\n\t\t{\n\t\t\toriginLabel: \"library/busybox,library/redis,library/busybox\",\n\t\t\trepo:        \"library/alpine\",\n\t\t\texpected:    \"library/alpine,library/busybox,library/redis\",\n\t\t},\n\t\t// remove the empty repo\n\t\t{\n\t\t\toriginLabel: \"library/busybox,library/redis,library/busybox\",\n\t\t\trepo:        \"\",\n\t\t\texpected:    \"library/busybox,library/redis\",\n\t\t},\n\t\t{\n\t\t\toriginLabel: \"library/busybox,library/redis,library/busybox\",\n\t\t\trepo:        \"library/redis\",\n\t\t\texpected:    \"library/busybox,library/redis\",\n\t\t},\n\t} {\n\t\tif got := appendDistributionSourceLabel(tc.originLabel, tc.repo); !reflect.DeepEqual(got, tc.expected) {\n\t\t\tt.Fatalf(\"expected %v, but got %v\", tc.expected, got)\n\t\t}\n\t}\n}\n\nfunc TestDistributionSourceLabelKey(t *testing.T) {\n\texpected := labels.LabelDistributionSource + \".testsource\"\n\tif got := distributionSourceLabelKey(\"testsource\"); !reflect.DeepEqual(got, expected) {\n\t\tt.Fatalf(\"expected %v, but got %v\", expected, got)\n\t}\n}\n\nfunc TestCommonPrefixComponents(t *testing.T) {\n\tfor _, tc := range []struct {\n\t\tcomponents []string\n\t\ttarget     string\n\t\texpected   int\n\t}{\n\t\t{\n\t\t\tcomponents: []string{\"foo\"},\n\t\t\ttarget:     \"foo/bar\",\n\t\t\texpected:   1,\n\t\t},\n\t\t{\n\t\t\tcomponents: []string{\"bar\"},\n\t\t\ttarget:     \"foo/bar\",\n\t\t\texpected:   0,\n\t\t},\n\t\t{\n\t\t\tcomponents: []string{\"foo\", \"bar\"},\n\t\t\ttarget:     \"foo/bar\",\n\t\t\texpected:   2,\n\t\t},\n\t} {\n\t\tif got := commonPrefixComponents(tc.components, tc.target); !reflect.DeepEqual(got, tc.expected) {\n\t\t\tt.Fatalf(\"expected %v, but got %v\", tc.expected, got)\n\t\t}\n\t}\n}\n\nfunc TestSelectRepositoryMountCandidate(t *testing.T) {\n\tfor _, tc := range []struct {\n\t\trefspec  reference.Spec\n\t\tsource   map[string]string\n\t\texpected string\n\t}{\n\t\t{\n\t\t\trefspec:  reference.Spec{},\n\t\t\tsource:   map[string]string{\"\": \"\"},\n\t\t\texpected: \"\",\n\t\t},\n\t\t{\n\t\t\trefspec:  reference.Spec{Locator: \"user@host/path\"},\n\t\t\tsource:   map[string]string{labels.LabelDistributionSource + \".host\": \"foo,path,bar\"},\n\t\t\texpected: \"bar\",\n\t\t},\n\t\t{\n\t\t\trefspec:  reference.Spec{Locator: \"user@host/path\"},\n\t\t\tsource:   map[string]string{labels.LabelDistributionSource + \".host\": \"foo,bar,path\"},\n\t\t\texpected: \"bar\",\n\t\t},\n\t} {\n\t\tif got := selectRepositoryMountCandidate(tc.refspec, tc.source); !reflect.DeepEqual(got, tc.expected) {\n\t\t\tt.Fatalf(\"expected %v, but got %v\", tc.expected, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/httpreadseeker.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/log\"\n)\n\nconst maxRetry = 3\n\ntype httpReadSeeker struct {\n\tsize   int64\n\toffset int64\n\trc     io.ReadCloser\n\topen   func(offset int64) (io.ReadCloser, error)\n\tclosed bool\n\n\terrsWithNoProgress int\n}\n\nfunc newHTTPReadSeeker(size int64, open func(offset int64) (io.ReadCloser, error)) (io.ReadCloser, error) {\n\treturn &httpReadSeeker{\n\t\tsize: size,\n\t\topen: open,\n\t}, nil\n}\n\nfunc (hrs *httpReadSeeker) Read(p []byte) (n int, err error) {\n\tif hrs.closed {\n\t\treturn 0, io.EOF\n\t}\n\n\trd, err := hrs.reader()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tn, err = rd.Read(p)\n\thrs.offset += int64(n)\n\tif n > 0 || err == nil {\n\t\thrs.errsWithNoProgress = 0\n\t}\n\tif err == io.ErrUnexpectedEOF {\n\t\t// connection closed unexpectedly. try reconnecting.\n\t\tif n == 0 {\n\t\t\thrs.errsWithNoProgress++\n\t\t\tif hrs.errsWithNoProgress > maxRetry {\n\t\t\t\treturn // too many retries for this offset with no progress\n\t\t\t}\n\t\t}\n\t\tif hrs.rc != nil {\n\t\t\tif clsErr := hrs.rc.Close(); clsErr != nil {\n\t\t\t\tlog.L.WithError(clsErr).Error(\"httpReadSeeker: failed to close ReadCloser\")\n\t\t\t}\n\t\t\thrs.rc = nil\n\t\t}\n\t\tif _, err2 := hrs.reader(); err2 == nil {\n\t\t\treturn n, nil\n\t\t}\n\t}\n\treturn\n}\n\nfunc (hrs *httpReadSeeker) Close() error {\n\tif hrs.closed {\n\t\treturn nil\n\t}\n\thrs.closed = true\n\tif hrs.rc != nil {\n\t\treturn hrs.rc.Close()\n\t}\n\n\treturn nil\n}\n\nfunc (hrs *httpReadSeeker) Seek(offset int64, whence int) (int64, error) {\n\tif hrs.closed {\n\t\treturn 0, fmt.Errorf(\"Fetcher.Seek: closed: %w\", errdefs.ErrUnavailable)\n\t}\n\n\tabs := hrs.offset\n\tswitch whence {\n\tcase io.SeekStart:\n\t\tabs = offset\n\tcase io.SeekCurrent:\n\t\tabs += offset\n\tcase io.SeekEnd:\n\t\tif hrs.size == -1 {\n\t\t\treturn 0, fmt.Errorf(\"Fetcher.Seek: unknown size, cannot seek from end: %w\", errdefs.ErrUnavailable)\n\t\t}\n\t\tabs = hrs.size + offset\n\tdefault:\n\t\treturn 0, fmt.Errorf(\"Fetcher.Seek: invalid whence: %w\", errdefs.ErrInvalidArgument)\n\t}\n\n\tif abs < 0 {\n\t\treturn 0, fmt.Errorf(\"Fetcher.Seek: negative offset: %w\", errdefs.ErrInvalidArgument)\n\t}\n\n\tif abs != hrs.offset {\n\t\tif hrs.rc != nil {\n\t\t\tif err := hrs.rc.Close(); err != nil {\n\t\t\t\tlog.L.WithError(err).Error(\"Fetcher.Seek: failed to close ReadCloser\")\n\t\t\t}\n\n\t\t\thrs.rc = nil\n\t\t}\n\n\t\thrs.offset = abs\n\t}\n\n\treturn hrs.offset, nil\n}\n\nfunc (hrs *httpReadSeeker) reader() (io.Reader, error) {\n\tif hrs.rc != nil {\n\t\treturn hrs.rc, nil\n\t}\n\n\tif hrs.size == -1 || hrs.offset < hrs.size {\n\t\t// only try to reopen the body request if we are seeking to a value\n\t\t// less than the actual size.\n\t\tif hrs.open == nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot open: %w\", errdefs.ErrNotImplemented)\n\t\t}\n\n\t\trc, err := hrs.open(hrs.offset)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"httpReadSeeker: failed open: %w\", err)\n\t\t}\n\n\t\tif hrs.rc != nil {\n\t\t\tif err := hrs.rc.Close(); err != nil {\n\t\t\t\tlog.L.WithError(err).Error(\"httpReadSeeker: failed to close ReadCloser\")\n\t\t\t}\n\t\t}\n\t\thrs.rc = rc\n\t} else {\n\t\t// There is an edge case here where offset == size of the content. If\n\t\t// we seek, we will probably get an error for content that cannot be\n\t\t// sought (?). In that case, we should err on committing the content,\n\t\t// as the length is already satisfied but we just return the empty\n\t\t// reader instead.\n\n\t\thrs.rc = io.NopCloser(bytes.NewReader([]byte{}))\n\t}\n\n\treturn hrs.rc, nil\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/pusher.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes\"\n\tremoteserrors \"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/errors\"\n\tdigest \"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\ntype dockerPusher struct {\n\t*dockerBase\n\tobject string\n\n\t// TODO: namespace tracker\n\ttracker StatusTracker\n}\n\n// Writer implements Ingester API of content store. This allows the client\n// to receive ErrUnavailable when there is already an on-going upload.\n// Note that the tracker MUST implement StatusTrackLocker interface to avoid\n// race condition on StatusTracker.\nfunc (p dockerPusher) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) {\n\tvar wOpts content.WriterOpts\n\tfor _, opt := range opts {\n\t\tif err := opt(&wOpts); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tif wOpts.Ref == \"\" {\n\t\treturn nil, fmt.Errorf(\"ref must not be empty: %w\", errdefs.ErrInvalidArgument)\n\t}\n\treturn p.push(ctx, wOpts.Desc, wOpts.Ref, true)\n}\n\nfunc (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error) {\n\treturn p.push(ctx, desc, remotes.MakeRefKey(ctx, desc), false)\n}\n\nfunc (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref string, unavailableOnFail bool) (content.Writer, error) {\n\tif l, ok := p.tracker.(StatusTrackLocker); ok {\n\t\tl.Lock(ref)\n\t\tdefer l.Unlock(ref)\n\t}\n\tctx, err := ContextWithRepositoryScope(ctx, p.refspec, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstatus, err := p.tracker.GetStatus(ref)\n\tif err == nil {\n\t\tif status.Committed && status.Offset == status.Total {\n\t\t\treturn nil, fmt.Errorf(\"ref %v: %w\", ref, errdefs.ErrAlreadyExists)\n\t\t}\n\t\tif unavailableOnFail && status.ErrClosed == nil {\n\t\t\t// Another push of this ref is happening elsewhere. The rest of function\n\t\t\t// will continue only when `errdefs.IsNotFound(err) == true` (i.e. there\n\t\t\t// is no actively-tracked ref already).\n\t\t\treturn nil, fmt.Errorf(\"push is on-going: %w\", errdefs.ErrUnavailable)\n\t\t}\n\t\t// TODO: Handle incomplete status\n\t} else if !errdefs.IsNotFound(err) {\n\t\treturn nil, fmt.Errorf(\"failed to get status: %w\", err)\n\t}\n\n\thosts := p.filterHosts(HostCapabilityPush)\n\tif len(hosts) == 0 {\n\t\treturn nil, fmt.Errorf(\"no push hosts: %w\", errdefs.ErrNotFound)\n\t}\n\n\tvar (\n\t\tisManifest bool\n\t\texistCheck []string\n\t\thost       = hosts[0]\n\t)\n\n\tswitch desc.MediaType {\n\tcase images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList,\n\t\tocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:\n\t\tisManifest = true\n\t\texistCheck = getManifestPath(p.object, desc.Digest)\n\tdefault:\n\t\texistCheck = []string{\"blobs\", desc.Digest.String()}\n\t}\n\n\treq := p.request(host, http.MethodHead, existCheck...)\n\treq.header.Set(\"Accept\", strings.Join([]string{desc.MediaType, `*/*`}, \", \"))\n\n\tlog.G(ctx).WithField(\"url\", req.String()).Debugf(\"checking and pushing to\")\n\n\tresp, err := req.doWithRetries(ctx, nil)\n\tif err != nil {\n\t\tif !errors.Is(err, ErrInvalidAuthorization) {\n\t\t\treturn nil, err\n\t\t}\n\t\tlog.G(ctx).WithError(err).Debugf(\"Unable to check existence, continuing with push\")\n\t} else {\n\t\tif resp.StatusCode == http.StatusOK {\n\t\t\tvar exists bool\n\t\t\tif isManifest && existCheck[1] != desc.Digest.String() {\n\t\t\t\tdgstHeader := digest.Digest(resp.Header.Get(\"Docker-Content-Digest\"))\n\t\t\t\tif dgstHeader == desc.Digest {\n\t\t\t\t\texists = true\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\texists = true\n\t\t\t}\n\n\t\t\tif exists {\n\t\t\t\tp.tracker.SetStatus(ref, Status{\n\t\t\t\t\tCommitted: true,\n\t\t\t\t\tStatus: content.Status{\n\t\t\t\t\t\tRef:    ref,\n\t\t\t\t\t\tTotal:  desc.Size,\n\t\t\t\t\t\tOffset: desc.Size,\n\t\t\t\t\t\t// TODO: Set updated time?\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\tresp.Body.Close()\n\t\t\t\treturn nil, fmt.Errorf(\"content %v on remote: %w\", desc.Digest, errdefs.ErrAlreadyExists)\n\t\t\t}\n\t\t} else if resp.StatusCode != http.StatusNotFound {\n\t\t\terr := remoteserrors.NewUnexpectedStatusErr(resp)\n\t\t\tlog.G(ctx).WithField(\"resp\", resp).WithField(\"body\", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug(\"unexpected response\")\n\t\t\tresp.Body.Close()\n\t\t\treturn nil, err\n\t\t}\n\t\tresp.Body.Close()\n\t}\n\n\tif isManifest {\n\t\tputPath := getManifestPath(p.object, desc.Digest)\n\t\treq = p.request(host, http.MethodPut, putPath...)\n\t\treq.header.Add(\"Content-Type\", desc.MediaType)\n\t} else {\n\t\t// Start upload request\n\t\treq = p.request(host, http.MethodPost, \"blobs\", \"uploads/\")\n\n\t\tvar resp *http.Response\n\t\tif fromRepo := selectRepositoryMountCandidate(p.refspec, desc.Annotations); fromRepo != \"\" {\n\t\t\tpreq := requestWithMountFrom(req, desc.Digest.String(), fromRepo)\n\t\t\tpctx := ContextWithAppendPullRepositoryScope(ctx, fromRepo)\n\n\t\t\t// NOTE: the fromRepo might be private repo and\n\t\t\t// auth service still can grant token without error.\n\t\t\t// but the post request will fail because of 401.\n\t\t\t//\n\t\t\t// for the private repo, we should remove mount-from\n\t\t\t// query and send the request again.\n\t\t\tresp, err = preq.doWithRetries(pctx, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tif resp.StatusCode == http.StatusUnauthorized {\n\t\t\t\tlog.G(ctx).Debugf(\"failed to mount from repository %s\", fromRepo)\n\n\t\t\t\tresp.Body.Close()\n\t\t\t\tresp = nil\n\t\t\t}\n\t\t}\n\n\t\tif resp == nil {\n\t\t\tresp, err = req.doWithRetries(ctx, nil)\n\t\t\tif err != nil {\n\t\t\t\tif errors.Is(err, ErrInvalidAuthorization) {\n\t\t\t\t\treturn nil, fmt.Errorf(\"push access denied, repository does not exist or may require authorization: %w\", err)\n\t\t\t\t}\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\t\tdefer resp.Body.Close()\n\n\t\tswitch resp.StatusCode {\n\t\tcase http.StatusOK, http.StatusAccepted, http.StatusNoContent:\n\t\tcase http.StatusCreated:\n\t\t\tp.tracker.SetStatus(ref, Status{\n\t\t\t\tCommitted: true,\n\t\t\t\tStatus: content.Status{\n\t\t\t\t\tRef:    ref,\n\t\t\t\t\tTotal:  desc.Size,\n\t\t\t\t\tOffset: desc.Size,\n\t\t\t\t},\n\t\t\t})\n\t\t\treturn nil, fmt.Errorf(\"content %v on remote: %w\", desc.Digest, errdefs.ErrAlreadyExists)\n\t\tdefault:\n\t\t\terr := remoteserrors.NewUnexpectedStatusErr(resp)\n\t\t\tlog.G(ctx).WithField(\"resp\", resp).WithField(\"body\", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug(\"unexpected response\")\n\t\t\treturn nil, err\n\t\t}\n\n\t\tvar (\n\t\t\tlocation = resp.Header.Get(\"Location\")\n\t\t\tlurl     *url.URL\n\t\t\tlhost    = host\n\t\t)\n\t\t// Support paths without host in location\n\t\tif strings.HasPrefix(location, \"/\") {\n\t\t\tlurl, err = url.Parse(lhost.Scheme + \"://\" + lhost.Host + location)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"unable to parse location %v: %w\", location, err)\n\t\t\t}\n\t\t} else {\n\t\t\tif !strings.Contains(location, \"://\") {\n\t\t\t\tlocation = lhost.Scheme + \"://\" + location\n\t\t\t}\n\t\t\tlurl, err = url.Parse(location)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"unable to parse location %v: %w\", location, err)\n\t\t\t}\n\n\t\t\tif lurl.Host != lhost.Host || lhost.Scheme != lurl.Scheme {\n\n\t\t\t\tlhost.Scheme = lurl.Scheme\n\t\t\t\tlhost.Host = lurl.Host\n\t\t\t\tlog.G(ctx).WithField(\"host\", lhost.Host).WithField(\"scheme\", lhost.Scheme).Debug(\"upload changed destination\")\n\n\t\t\t\t// Strip authorizer if change to host or scheme\n\t\t\t\tlhost.Authorizer = nil\n\t\t\t}\n\t\t}\n\t\tq := lurl.Query()\n\t\tq.Add(\"digest\", desc.Digest.String())\n\n\t\treq = p.request(lhost, http.MethodPut)\n\t\treq.header.Set(\"Content-Type\", \"application/octet-stream\")\n\t\treq.path = lurl.Path + \"?\" + q.Encode()\n\t}\n\tp.tracker.SetStatus(ref, Status{\n\t\tStatus: content.Status{\n\t\t\tRef:       ref,\n\t\t\tTotal:     desc.Size,\n\t\t\tExpected:  desc.Digest,\n\t\t\tStartedAt: time.Now(),\n\t\t},\n\t})\n\n\t// TODO: Support chunked upload\n\n\tpushw := newPushWriter(p.dockerBase, ref, desc.Digest, p.tracker, isManifest)\n\n\treq.body = func() (io.ReadCloser, error) {\n\t\tpr, pw := io.Pipe()\n\t\tpushw.setPipe(pw)\n\t\treturn io.NopCloser(pr), nil\n\t}\n\treq.size = desc.Size\n\n\tgo func() {\n\t\tresp, err := req.doWithRetries(ctx, nil)\n\t\tif err != nil {\n\t\t\tpushw.setError(err)\n\t\t\tpushw.Close()\n\t\t\treturn\n\t\t}\n\n\t\tswitch resp.StatusCode {\n\t\tcase http.StatusOK, http.StatusCreated, http.StatusNoContent:\n\t\tdefault:\n\t\t\terr := remoteserrors.NewUnexpectedStatusErr(resp)\n\t\t\tlog.G(ctx).WithField(\"resp\", resp).WithField(\"body\", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug(\"unexpected response\")\n\t\t\tpushw.setError(err)\n\t\t\tpushw.Close()\n\t\t}\n\t\tpushw.setResponse(resp)\n\t}()\n\n\treturn pushw, nil\n}\n\nfunc getManifestPath(object string, dgst digest.Digest) []string {\n\tif i := strings.IndexByte(object, '@'); i >= 0 {\n\t\tif object[i+1:] != dgst.String() {\n\t\t\t// use digest, not tag\n\t\t\tobject = \"\"\n\t\t} else {\n\t\t\t// strip @<digest> for registry path to make tag\n\t\t\tobject = object[:i]\n\t\t}\n\n\t}\n\n\tif object == \"\" {\n\t\treturn []string{\"manifests\", dgst.String()}\n\t}\n\n\treturn []string{\"manifests\", object}\n}\n\ntype pushWriter struct {\n\tbase *dockerBase\n\tref  string\n\n\tpipe *io.PipeWriter\n\n\tpipeC     chan *io.PipeWriter\n\trespC     chan *http.Response\n\tcloseOnce sync.Once\n\terrC      chan error\n\n\tisManifest bool\n\n\texpected digest.Digest\n\ttracker  StatusTracker\n}\n\nfunc newPushWriter(db *dockerBase, ref string, expected digest.Digest, tracker StatusTracker, isManifest bool) *pushWriter {\n\t// Initialize and create response\n\treturn &pushWriter{\n\t\tbase:       db,\n\t\tref:        ref,\n\t\texpected:   expected,\n\t\ttracker:    tracker,\n\t\tpipeC:      make(chan *io.PipeWriter, 1),\n\t\trespC:      make(chan *http.Response, 1),\n\t\terrC:       make(chan error, 1),\n\t\tisManifest: isManifest,\n\t}\n}\n\nfunc (pw *pushWriter) setPipe(p *io.PipeWriter) {\n\tpw.pipeC <- p\n}\n\nfunc (pw *pushWriter) setError(err error) {\n\tpw.errC <- err\n}\nfunc (pw *pushWriter) setResponse(resp *http.Response) {\n\tpw.respC <- resp\n}\n\nfunc (pw *pushWriter) Write(p []byte) (n int, err error) {\n\tstatus, err := pw.tracker.GetStatus(pw.ref)\n\tif err != nil {\n\t\treturn n, err\n\t}\n\n\tif pw.pipe == nil {\n\t\tp, ok := <-pw.pipeC\n\t\tif !ok {\n\t\t\treturn 0, io.ErrClosedPipe\n\t\t}\n\t\tpw.pipe = p\n\t} else {\n\t\tselect {\n\t\tcase p, ok := <-pw.pipeC:\n\t\t\tif !ok {\n\t\t\t\treturn 0, io.ErrClosedPipe\n\t\t\t}\n\t\t\tpw.pipe.CloseWithError(content.ErrReset)\n\t\t\tpw.pipe = p\n\n\t\t\t// If content has already been written, the bytes\n\t\t\t// cannot be written and the caller must reset\n\t\t\tstatus.Offset = 0\n\t\t\tstatus.UpdatedAt = time.Now()\n\t\t\tpw.tracker.SetStatus(pw.ref, status)\n\t\t\treturn 0, content.ErrReset\n\t\tdefault:\n\t\t}\n\t}\n\n\tn, err = pw.pipe.Write(p)\n\tif errors.Is(err, io.ErrClosedPipe) {\n\t\t// if the pipe is closed, we might have the original error on the error\n\t\t// channel - so we should try and get it\n\t\tselect {\n\t\tcase err2 := <-pw.errC:\n\t\t\terr = err2\n\t\tdefault:\n\t\t}\n\t}\n\tstatus.Offset += int64(n)\n\tstatus.UpdatedAt = time.Now()\n\tpw.tracker.SetStatus(pw.ref, status)\n\treturn\n}\n\nfunc (pw *pushWriter) Close() error {\n\t// Ensure pipeC is closed but handle `Close()` being\n\t// called multiple times without panicking\n\tpw.closeOnce.Do(func() {\n\t\tclose(pw.pipeC)\n\t})\n\tif pw.pipe != nil {\n\t\tstatus, err := pw.tracker.GetStatus(pw.ref)\n\t\tif err == nil && !status.Committed {\n\t\t\t// Closing an incomplete writer. Record this as an error so that following write can retry it.\n\t\t\tstatus.ErrClosed = errors.New(\"closed incomplete writer\")\n\t\t\tpw.tracker.SetStatus(pw.ref, status)\n\t\t}\n\t\treturn pw.pipe.Close()\n\t}\n\treturn nil\n}\n\nfunc (pw *pushWriter) Status() (content.Status, error) {\n\tstatus, err := pw.tracker.GetStatus(pw.ref)\n\tif err != nil {\n\t\treturn content.Status{}, err\n\t}\n\treturn status.Status, nil\n\n}\n\nfunc (pw *pushWriter) Digest() digest.Digest {\n\t// TODO: Get rid of this function?\n\treturn pw.expected\n}\n\nfunc (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {\n\t// Check whether read has already thrown an error\n\tif _, err := pw.pipe.Write([]byte{}); err != nil && !errors.Is(err, io.ErrClosedPipe) {\n\t\treturn fmt.Errorf(\"pipe error before commit: %w\", err)\n\t}\n\n\tif err := pw.pipe.Close(); err != nil {\n\t\treturn err\n\t}\n\t// TODO: timeout waiting for response\n\tvar resp *http.Response\n\tselect {\n\tcase err := <-pw.errC:\n\t\treturn err\n\tcase resp = <-pw.respC:\n\t\tdefer resp.Body.Close()\n\tcase p, ok := <-pw.pipeC:\n\t\t// check whether the pipe has changed in the commit, because sometimes Write\n\t\t// can complete successfully, but the pipe may have changed. In that case, the\n\t\t// content needs to be reset.\n\t\tif !ok {\n\t\t\treturn io.ErrClosedPipe\n\t\t}\n\t\tpw.pipe.CloseWithError(content.ErrReset)\n\t\tpw.pipe = p\n\n\t\t// If content has already been written, the bytes\n\t\t// cannot be written again and the caller must reset\n\t\tstatus, err := pw.tracker.GetStatus(pw.ref)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tstatus.Offset = 0\n\t\tstatus.UpdatedAt = time.Now()\n\t\tpw.tracker.SetStatus(pw.ref, status)\n\t\treturn content.ErrReset\n\t}\n\n\t// 201 is specified return status, some registries return\n\t// 200, 202 or 204.\n\tswitch resp.StatusCode {\n\tcase http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted:\n\tdefault:\n\t\treturn remoteserrors.NewUnexpectedStatusErr(resp)\n\t}\n\n\tstatus, err := pw.tracker.GetStatus(pw.ref)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get status: %w\", err)\n\t}\n\n\tif size > 0 && size != status.Offset {\n\t\treturn fmt.Errorf(\"unexpected size %d, expected %d\", status.Offset, size)\n\t}\n\n\tif expected == \"\" {\n\t\texpected = status.Expected\n\t}\n\n\tactual, err := digest.Parse(resp.Header.Get(\"Docker-Content-Digest\"))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid content digest in response: %w\", err)\n\t}\n\n\tif actual != expected {\n\t\treturn fmt.Errorf(\"got digest %s, expected %s\", actual, expected)\n\t}\n\n\tstatus.Committed = true\n\tstatus.UpdatedAt = time.Now()\n\tpw.tracker.SetStatus(pw.ref, status)\n\n\treturn nil\n}\n\nfunc (pw *pushWriter) Truncate(size int64) error {\n\t// TODO: if blob close request and start new request at offset\n\t// TODO: always error on manifest\n\treturn errors.New(\"cannot truncate remote upload\")\n}\n\nfunc requestWithMountFrom(req *request, mount, from string) *request {\n\tcreq := *req\n\n\tsep := \"?\"\n\tif strings.Contains(creq.path, sep) {\n\t\tsep = \"&\"\n\t}\n\n\tcreq.path = creq.path + sep + \"mount=\" + mount + \"&from=\" + from\n\n\treturn &creq\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/pusher_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestGetManifestPath(t *testing.T) {\n\tfor _, tc := range []struct {\n\t\tobject   string\n\t\tdgst     digest.Digest\n\t\texpected []string\n\t}{\n\t\t{\n\t\t\tobject:   \"foo\",\n\t\t\tdgst:     \"bar\",\n\t\t\texpected: []string{\"manifests\", \"foo\"},\n\t\t},\n\t\t{\n\t\t\tobject:   \"foo@bar\",\n\t\t\tdgst:     \"bar\",\n\t\t\texpected: []string{\"manifests\", \"foo\"},\n\t\t},\n\t\t{\n\t\t\tobject:   \"foo@bar\",\n\t\t\tdgst:     \"foobar\",\n\t\t\texpected: []string{\"manifests\", \"foobar\"},\n\t\t},\n\t} {\n\t\tif got := getManifestPath(tc.object, tc.dgst); !reflect.DeepEqual(got, tc.expected) {\n\t\t\tt.Fatalf(\"expected %v, but got %v\", tc.expected, got)\n\t\t}\n\t}\n}\n\n// TestPusherErrClosedRetry tests if retrying work when error occurred on close.\nfunc TestPusherErrClosedRetry(t *testing.T) {\n\tctx := context.Background()\n\n\tp, reg, done := samplePusher(t)\n\tdefer done()\n\n\tlayerContent := []byte(\"test\")\n\treg.uploadable = false\n\tif err := tryUpload(ctx, t, p, layerContent); err == nil {\n\t\tt.Errorf(\"upload should fail but succeeded\")\n\t}\n\n\t// retry\n\treg.uploadable = true\n\tif err := tryUpload(ctx, t, p, layerContent); err != nil {\n\t\tt.Errorf(\"upload should succeed but got %v\", err)\n\t}\n}\n\n// TestPusherErrReset tests the push method if the request needs to be retried\n// i.e when ErrReset occurs\nfunc TestPusherErrReset(t *testing.T) {\n\tp, reg, done := samplePusher(t)\n\tdefer done()\n\n\tp.object = \"latest@sha256:55d31f3af94c797b65b310569803cacc1c9f4a34bf61afcdc8138f89345c8308\"\n\n\treg.uploadable = true\n\treg.putHandlerFunc = func() func(w http.ResponseWriter, r *http.Request) bool {\n\t\t// sets whether the request should timeout so that a reset error can occur and\n\t\t// request will be retried\n\t\tshouldTimeout := true\n\t\treturn func(w http.ResponseWriter, r *http.Request) bool {\n\t\t\tif shouldTimeout {\n\t\t\t\tshouldTimeout = !shouldTimeout\n\t\t\t\tw.WriteHeader(http.StatusRequestTimeout)\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t}()\n\n\tct := []byte(\"manifest-content\")\n\n\tdesc := ocispec.Descriptor{\n\t\tMediaType: ocispec.MediaTypeImageManifest,\n\t\tDigest:    digest.FromBytes(ct),\n\t\tSize:      int64(len(ct)),\n\t}\n\n\tw, err := p.push(context.Background(), desc, remotes.MakeRefKey(context.Background(), desc), false)\n\tassert.NoError(t, err)\n\n\t// first push should fail with ErrReset\n\t_, err = w.Write(ct)\n\tassert.NoError(t, err)\n\terr = w.Commit(context.Background(), desc.Size, desc.Digest)\n\tassert.Equal(t, content.ErrReset, err)\n\n\t// second push should succeed\n\t_, err = w.Write(ct)\n\tassert.NoError(t, err)\n\terr = w.Commit(context.Background(), desc.Size, desc.Digest)\n\tassert.NoError(t, err)\n}\n\nfunc tryUpload(ctx context.Context, t *testing.T, p dockerPusher, layerContent []byte) error {\n\tdesc := ocispec.Descriptor{\n\t\tMediaType: ocispec.MediaTypeImageLayerGzip,\n\t\tDigest:    digest.FromBytes(layerContent),\n\t\tSize:      int64(len(layerContent)),\n\t}\n\tcw, err := p.Writer(ctx, content.WithRef(\"test-1\"), content.WithDescriptor(desc))\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cw.Close()\n\tif _, err := cw.Write(layerContent); err != nil {\n\t\treturn err\n\t}\n\treturn cw.Commit(ctx, 0, \"\")\n}\n\nfunc samplePusher(t *testing.T) (dockerPusher, *uploadableMockRegistry, func()) {\n\treg := &uploadableMockRegistry{\n\t\tavailableContents: make([]string, 0),\n\t}\n\ts := httptest.NewServer(reg)\n\tu, err := url.Parse(s.URL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn dockerPusher{\n\t\tdockerBase: &dockerBase{\n\t\t\trepository: \"sample\",\n\t\t\thosts: []RegistryHost{\n\t\t\t\t{\n\t\t\t\t\tClient:       s.Client(),\n\t\t\t\t\tHost:         u.Host,\n\t\t\t\t\tScheme:       u.Scheme,\n\t\t\t\t\tPath:         u.Path,\n\t\t\t\t\tCapabilities: HostCapabilityPush | HostCapabilityResolve,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tobject:  \"sample\",\n\t\ttracker: NewInMemoryTracker(),\n\t}, reg, s.Close\n}\n\nvar manifestRegexp = regexp.MustCompile(`/([a-z0-9]+)/manifests/(.*)`)\nvar blobUploadRegexp = regexp.MustCompile(`/([a-z0-9]+)/blobs/uploads/(.*)`)\n\n// uploadableMockRegistry provides minimal registry APIs which are enough to serve requests from dockerPusher.\ntype uploadableMockRegistry struct {\n\tavailableContents []string\n\tuploadable        bool\n\tputHandlerFunc    func(w http.ResponseWriter, r *http.Request) bool\n}\n\nfunc (u *uploadableMockRegistry) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tif r.Method == http.MethodPut && u.putHandlerFunc != nil {\n\t\t// if true return the response witout calling default handler\n\t\tif u.putHandlerFunc(w, r) {\n\t\t\treturn\n\t\t}\n\t}\n\tu.defaultHandler(w, r)\n}\n\nfunc (u *uploadableMockRegistry) defaultHandler(w http.ResponseWriter, r *http.Request) {\n\tif r.Method == http.MethodPost {\n\t\tif matches := blobUploadRegexp.FindStringSubmatch(r.URL.Path); len(matches) != 0 {\n\t\t\tif u.uploadable {\n\t\t\t\tw.Header().Set(\"Location\", \"/upload\")\n\t\t\t} else {\n\t\t\t\tw.Header().Set(\"Location\", \"/cannotupload\")\n\t\t\t}\n\t\t\tdgstr := digest.Canonical.Digester()\n\t\t\tif _, err := io.Copy(dgstr.Hash(), r.Body); err != nil {\n\t\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tu.availableContents = append(u.availableContents, dgstr.Digest().String())\n\t\t\tw.WriteHeader(http.StatusAccepted)\n\t\t\treturn\n\t\t}\n\t} else if r.Method == http.MethodPut {\n\t\tmfstMatches := manifestRegexp.FindStringSubmatch(r.URL.Path)\n\t\tif len(mfstMatches) != 0 || strings.HasPrefix(r.URL.Path, \"/upload\") {\n\t\t\tdgstr := digest.Canonical.Digester()\n\t\t\tif _, err := io.Copy(dgstr.Hash(), r.Body); err != nil {\n\t\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tu.availableContents = append(u.availableContents, dgstr.Digest().String())\n\t\t\tw.Header().Set(\"Docker-Content-Digest\", dgstr.Digest().String())\n\t\t\tw.WriteHeader(http.StatusCreated)\n\t\t\treturn\n\t\t} else if r.URL.Path == \"/cannotupload\" {\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t} else if r.Method == http.MethodHead {\n\t\tvar content string\n\t\t// check for both manifest and blob paths\n\t\tif manifestMatch := manifestRegexp.FindStringSubmatch(r.URL.Path); len(manifestMatch) == 3 {\n\t\t\tcontent = manifestMatch[2]\n\t\t} else if blobMatch := blobUploadRegexp.FindStringSubmatch(r.URL.Path); len(blobMatch) == 3 {\n\t\t\tcontent = blobMatch[2]\n\t\t}\n\t\t// if content is not found or if the path is not manifest or blob\n\t\t// we return 404\n\t\tif u.isContentAlreadyExist(content) {\n\t\t\tw.WriteHeader(http.StatusOK)\n\t\t} else {\n\t\t\tw.WriteHeader(http.StatusNotFound)\n\t\t}\n\t\treturn\n\t}\n\tfmt.Println(r)\n\tw.WriteHeader(http.StatusNotFound)\n}\n\n// checks if the content is already present in the registry\nfunc (u *uploadableMockRegistry) isContentAlreadyExist(c string) bool {\n\tfor _, ct := range u.availableContents {\n\t\tif ct == c {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc Test_dockerPusher_push(t *testing.T) {\n\n\tp, reg, done := samplePusher(t)\n\tdefer done()\n\n\treg.uploadable = true\n\n\tmanifestContent := []byte(\"manifest-content\")\n\tmanifestContentDigest := digest.FromBytes(manifestContent)\n\tlayerContent := []byte(\"layer-content\")\n\tlayerContentDigest := digest.FromBytes(layerContent)\n\n\t// using a random object here\n\tbaseObject := \"latest@sha256:55d31f3af94c797b65b310569803cacc1c9f4a34bf61afcdc8138f89345c8308\"\n\n\ttype args struct {\n\t\tcontent           []byte\n\t\tmediatype         string\n\t\tref               string\n\t\tunavailableOnFail bool\n\t}\n\ttests := []struct {\n\t\tname             string\n\t\tdp               dockerPusher\n\t\tdockerBaseObject string\n\t\targs             args\n\t\tcheckerFunc      func(writer *pushWriter) bool\n\t\twantErr          error\n\t}{\n\t\t{\n\t\t\tname:             \"when a manifest is pushed\",\n\t\t\tdp:               p,\n\t\t\tdockerBaseObject: baseObject,\n\t\t\targs: args{\n\t\t\t\tcontent:           manifestContent,\n\t\t\t\tmediatype:         ocispec.MediaTypeImageManifest,\n\t\t\t\tref:               fmt.Sprintf(\"manifest-%s\", manifestContentDigest.String()),\n\t\t\t\tunavailableOnFail: false,\n\t\t\t},\n\t\t\tcheckerFunc: func(writer *pushWriter) bool {\n\t\t\t\tselect {\n\t\t\t\tcase resp := <-writer.respC:\n\t\t\t\t\t// 201 should be the response code when uploading a new manifest\n\t\t\t\t\treturn resp.StatusCode == http.StatusCreated\n\t\t\t\tcase <-writer.errC:\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t},\n\t\t\twantErr: nil,\n\t\t},\n\t\t{\n\t\t\tname:             \"trying to push content that already exists\",\n\t\t\tdp:               p,\n\t\t\tdockerBaseObject: baseObject,\n\t\t\targs: args{\n\t\t\t\tcontent:           manifestContent,\n\t\t\t\tmediatype:         ocispec.MediaTypeImageManifest,\n\t\t\t\tref:               fmt.Sprintf(\"manifest-%s\", manifestContentDigest.String()),\n\t\t\t\tunavailableOnFail: false,\n\t\t\t},\n\t\t\twantErr: fmt.Errorf(\"content %v on remote: %w\", digest.FromBytes(manifestContent), errdefs.ErrAlreadyExists),\n\t\t},\n\t\t{\n\t\t\tname: \"trying to push a blob layer\",\n\t\t\tdp:   p,\n\t\t\t// Not needed to set the base object as it is used to generate path only in case of manifests\n\t\t\t// dockerBaseObject:\n\t\t\targs: args{\n\t\t\t\tcontent:           layerContent,\n\t\t\t\tmediatype:         ocispec.MediaTypeImageLayer,\n\t\t\t\tref:               fmt.Sprintf(\"layer-%s\", layerContentDigest.String()),\n\t\t\t\tunavailableOnFail: false,\n\t\t\t},\n\t\t\tcheckerFunc: func(writer *pushWriter) bool {\n\t\t\t\tselect {\n\t\t\t\tcase resp := <-writer.respC:\n\t\t\t\t\t// 201 should be the response code when uploading a new blob\n\t\t\t\t\treturn resp.StatusCode == http.StatusCreated\n\t\t\t\tcase <-writer.errC:\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t},\n\t\t\twantErr: nil,\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\tt.Run(test.name, func(t *testing.T) {\n\t\t\tdesc := ocispec.Descriptor{\n\t\t\t\tMediaType: test.args.mediatype,\n\t\t\t\tDigest:    digest.FromBytes(test.args.content),\n\t\t\t\tSize:      int64(len(test.args.content)),\n\t\t\t}\n\n\t\t\ttest.dp.object = test.dockerBaseObject\n\n\t\t\tgot, err := test.dp.push(context.Background(), desc, test.args.ref, test.args.unavailableOnFail)\n\n\t\t\tassert.Equal(t, test.wantErr, err)\n\t\t\t// if an error is expected, further comparisons are not required.\n\t\t\tif test.wantErr != nil {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// write the content to the writer, this will be done when a Read() is called on the body of the request\n\t\t\tgot.Write(test.args.content)\n\n\t\t\tpw, ok := got.(*pushWriter)\n\t\t\tif !ok {\n\t\t\t\tassert.Errorf(t, errors.New(\"unable to cast content.Writer to pushWriter\"), \"got %v instead of pushwriter\", got)\n\t\t\t}\n\n\t\t\t// test whether a proper response has been received after the push operation\n\t\t\tassert.True(t, test.checkerFunc(pw))\n\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/referrers.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/log\"\n\tdigest \"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\nfunc (r dockerFetcher) FetchReferrers(ctx context.Context, dgst digest.Digest, artifactTypes ...string) (io.ReadCloser, ocispec.Descriptor, error) {\n\tvar desc ocispec.Descriptor\n\tdesc.MediaType = ocispec.MediaTypeImageIndex\n\tctx = log.WithLogger(ctx, log.G(ctx).WithField(\"digest\", dgst))\n\n\thosts := r.filterHosts(HostCapabilityResolve, HostCapabilityReferrers)\n\tif len(hosts) == 0 {\n\t\treturn nil, desc, fmt.Errorf(\"no pull hosts: %w\", errdefs.ErrNotFound)\n\t}\n\n\tctx, err := ContextWithRepositoryScope(ctx, r.refspec, false)\n\tif err != nil {\n\t\treturn nil, desc, err\n\t}\n\n\tfor _, host := range hosts {\n\t\tvar req *request\n\t\t// if host.Capabilities.Has(HostCapabilityReferrers) {\n\t\treq = r.request(host, http.MethodGet, \"referrers\", dgst.String())\n\t\tfor _, artifactType := range artifactTypes {\n\t\t\tif err := req.addQuery(\"artifactType\", artifactType); err != nil {\n\t\t\t\treturn nil, desc, err\n\t\t\t}\n\t\t}\n\t\tif err := req.addNamespace(r.refspec.Hostname()); err != nil {\n\t\t\treturn nil, desc, err\n\t\t}\n\n\t\trc, cl, err := r.open(ctx, req, desc.MediaType, 0)\n\t\tif err != nil {\n\t\t\tif !errdefs.IsNotFound(err) {\n\t\t\t\treturn nil, desc, err\n\t\t\t}\n\t\t} else {\n\t\t\tdesc.Size = cl\n\t\t\t// Digest is not known ahead of time and there is nothing in the distribution\n\t\t\t// specification defining an HTTP header to return the digest on referrers.\n\t\t\treturn rc, desc, nil\n\t\t}\n\t\t// }\n\t\tif host.Capabilities.Has(HostCapabilityResolve) {\n\t\t\treq = r.request(host, http.MethodGet, \"manifests\", strings.Replace(dgst.String(), \":\", \"-\", 1))\n\t\t\tif err := req.addNamespace(r.refspec.Hostname()); err != nil {\n\t\t\t\treturn nil, desc, err\n\t\t\t}\n\t\t\trc, cl, err := r.open(ctx, req, desc.MediaType, 0)\n\t\t\tif err != nil {\n\t\t\t\tif !errdefs.IsNotFound(err) {\n\t\t\t\t\treturn nil, desc, err\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdesc.Size = cl\n\t\t\t\t// Digest could be resolved here the same as for any manifest, don't include the\n\t\t\t\t// digest for consistency with the referrers endpoint.\n\t\t\t\treturn rc, desc, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil, ocispec.Descriptor{}, fmt.Errorf(\"could not be found at any host: %w\", errdefs.ErrNotFound)\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/registry.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"net/http\"\n)\n\n// HostCapabilities represent the capabilities of the registry\n// host. This also represents the set of operations for which\n// the registry host may be trusted to perform.\n//\n// For example pushing is a capability which should only be\n// performed on an upstream source, not a mirror.\n// Resolving (the process of converting a name into a digest)\n// must be considered a trusted operation and only done by\n// a host which is trusted (or more preferably by secure process\n// which can prove the provenance of the mapping). A public\n// mirror should never be trusted to do a resolve action.\n//\n// | Registry Type    | Pull | Resolve | Push |\n// |------------------|------|---------|------|\n// | Public Registry  | yes  | yes     | yes  |\n// | Private Registry | yes  | yes     | yes  |\n// | Public Mirror    | yes  | no      | no   |\n// | Private Mirror   | yes  | yes     | no   |\ntype HostCapabilities uint8\n\nconst (\n\t// HostCapabilityPull represents the capability to fetch manifests\n\t// and blobs by digest\n\tHostCapabilityPull HostCapabilities = 1 << iota\n\n\t// HostCapabilityResolve represents the capability to fetch manifests\n\t// by name\n\tHostCapabilityResolve\n\n\t// HostCapabilityPush represents the capability to push blobs and\n\t// manifests\n\tHostCapabilityPush\n\n\t// HostCapabilityReferrers represents the capability to generate a\n\t// list of referrers using the OCI Distribution referrers endpoint.\n\tHostCapabilityReferrers\n\n\t// Reserved for future capabilities (i.e. search, catalog, remove)\n)\n\n// Has checks whether the capabilities list has the provide capability\nfunc (c HostCapabilities) Has(t HostCapabilities) bool {\n\treturn c&t == t\n}\n\n// RegistryHost represents a complete configuration for a registry\n// host, representing the capabilities, authorizations, connection\n// configuration, and location.\ntype RegistryHost struct {\n\tClient       *http.Client\n\tAuthorizer   Authorizer\n\tHost         string\n\tScheme       string\n\tPath         string\n\tCapabilities HostCapabilities\n\tHeader       http.Header\n}\n\nfunc (h RegistryHost) isProxy(refhost string) bool {\n\tif refhost != h.Host {\n\t\tif refhost != \"docker.io\" || h.Host != \"registry-1.docker.io\" {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// RegistryHosts fetches the registry hosts for a given namespace,\n// provided by the host component of an distribution image reference.\ntype RegistryHosts func(string) ([]RegistryHost, error)\n\n// Registries joins multiple registry configuration functions, using the same\n// order as provided within the arguments. When an empty registry configuration\n// is returned with a nil error, the next function will be called.\n// NOTE: This function will not join configurations, as soon as a non-empty\n// configuration is returned from a configuration function, it will be returned\n// to the caller.\nfunc Registries(registries ...RegistryHosts) RegistryHosts {\n\treturn func(host string) ([]RegistryHost, error) {\n\t\tfor _, registry := range registries {\n\t\t\tconfig, err := registry(host)\n\t\t\tif err != nil {\n\t\t\t\treturn config, err\n\t\t\t}\n\t\t\tif len(config) > 0 {\n\t\t\t\treturn config, nil\n\t\t\t}\n\t\t}\n\t\treturn nil, nil\n\t}\n}\n\ntype registryOpts struct {\n\tauthorizer Authorizer\n\tplainHTTP  func(string) (bool, error)\n\thost       func(string) (string, error)\n\tclient     *http.Client\n}\n\n// RegistryOpt defines a registry default option\ntype RegistryOpt func(*registryOpts)\n\n// WithPlainHTTP configures registries to use plaintext http scheme\n// for the provided host match function.\nfunc WithPlainHTTP(f func(string) (bool, error)) RegistryOpt {\n\treturn func(opts *registryOpts) {\n\t\topts.plainHTTP = f\n\t}\n}\n\n// WithAuthorizer configures the default authorizer for a registry\nfunc WithAuthorizer(a Authorizer) RegistryOpt {\n\treturn func(opts *registryOpts) {\n\t\topts.authorizer = a\n\t}\n}\n\n// WithHostTranslator defines the default translator to use for registry hosts\nfunc WithHostTranslator(h func(string) (string, error)) RegistryOpt {\n\treturn func(opts *registryOpts) {\n\t\topts.host = h\n\t}\n}\n\n// WithClient configures the default http client for a registry\nfunc WithClient(c *http.Client) RegistryOpt {\n\treturn func(opts *registryOpts) {\n\t\topts.client = c\n\t}\n}\n\n// ConfigureDefaultRegistries is used to create a default configuration for\n// registries. For more advanced configurations or per-domain setups,\n// the RegistryHosts interface should be used directly.\n// NOTE: This function will always return a non-empty value or error\nfunc ConfigureDefaultRegistries(ropts ...RegistryOpt) RegistryHosts {\n\tvar opts registryOpts\n\tfor _, opt := range ropts {\n\t\topt(&opts)\n\t}\n\n\treturn func(host string) ([]RegistryHost, error) {\n\t\tconfig := RegistryHost{\n\t\t\tClient:       opts.client,\n\t\t\tAuthorizer:   opts.authorizer,\n\t\t\tHost:         host,\n\t\t\tScheme:       \"https\",\n\t\t\tPath:         \"/v2\",\n\t\t\tCapabilities: HostCapabilityPull | HostCapabilityResolve | HostCapabilityPush,\n\t\t}\n\n\t\tif config.Client == nil {\n\t\t\tconfig.Client = http.DefaultClient\n\t\t}\n\n\t\tif opts.plainHTTP != nil {\n\t\t\tmatch, err := opts.plainHTTP(host)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif match {\n\t\t\t\tconfig.Scheme = \"http\"\n\t\t\t}\n\t\t}\n\n\t\tif opts.host != nil {\n\t\t\tvar err error\n\t\t\tconfig.Host, err = opts.host(config.Host)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t} else if host == \"docker.io\" {\n\t\t\tconfig.Host = \"registry-1.docker.io\"\n\t\t}\n\n\t\treturn []RegistryHost{config}, nil\n\t}\n}\n\n// MatchAllHosts is a host match function which is always true.\nfunc MatchAllHosts(string) (bool, error) {\n\treturn true, nil\n}\n\n// MatchLocalhost is a host match function which returns true for\n// localhost.\n//\n// Note: this does not handle matching of ip addresses in octal,\n// decimal or hex form.\nfunc MatchLocalhost(host string) (bool, error) {\n\tswitch {\n\tcase host == \"::1\":\n\t\treturn true, nil\n\tcase host == \"[::1]\":\n\t\treturn true, nil\n\t}\n\th, p, err := net.SplitHostPort(host)\n\n\t// addrError helps distinguish between errors of form\n\t// \"no colon in address\" and \"too many colons in address\".\n\t// The former is fine as the host string need not have a\n\t// port. Latter needs to be handled.\n\taddrError := &net.AddrError{\n\t\tErr:  \"missing port in address\",\n\t\tAddr: host,\n\t}\n\tif err != nil {\n\t\tif err.Error() != addrError.Error() {\n\t\t\treturn false, err\n\t\t}\n\t\t// host string without any port specified\n\t\th = host\n\t} else if len(p) == 0 {\n\t\treturn false, errors.New(\"invalid host name format\")\n\t}\n\n\t// use ipv4 dotted decimal for further checking\n\tif h == \"localhost\" {\n\t\th = \"127.0.0.1\"\n\t}\n\tip := net.ParseIP(h)\n\n\treturn ip.IsLoopback(), nil\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/registry_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport \"testing\"\n\nfunc TestHasCapability(t *testing.T) {\n\tvar (\n\t\tpull = HostCapabilityPull\n\t\trslv = HostCapabilityResolve\n\t\tpush = HostCapabilityPush\n\t\tall  = pull | rslv | push\n\t)\n\tfor i, tc := range []struct {\n\t\tc HostCapabilities\n\t\tt HostCapabilities\n\t\te bool\n\t}{\n\t\t{all, pull, true},\n\t\t{all, pull | rslv, true},\n\t\t{all, pull | push, true},\n\t\t{all, all, true},\n\t\t{pull, all, false},\n\t\t{pull, push, false},\n\t\t{rslv, pull, false},\n\t\t{pull | rslv, push, false},\n\t\t{pull | rslv, rslv, true},\n\t} {\n\t\tif a := tc.c.Has(tc.t); a != tc.e {\n\t\t\tt.Fatalf(\"%d: failed, expected %t, got %t\", i, tc.e, a)\n\t\t}\n\t}\n}\n\nfunc TestMatchLocalhost(t *testing.T) {\n\tfor _, tc := range []struct {\n\t\thost  string\n\t\tmatch bool\n\t}{\n\t\t{\"\", false},\n\t\t{\"127.1.1.1\", true},\n\t\t{\"127.0.0.1\", true},\n\t\t{\"127.256.0.1\", false}, // test MatchLocalhost does not panic on invalid ip\n\t\t{\"127.23.34.52\", true},\n\t\t{\"127.0.0.1:5000\", true},\n\t\t{\"registry.org\", false},\n\t\t{\"126.example.com\", false},\n\t\t{\"localhost\", true},\n\t\t{\"localhost:5000\", true},\n\t\t{\"[127:0:0:1]\", false},\n\t\t{\"[::1]\", true},\n\t\t{\"[::1]:\", false},     // invalid ip\n\t\t{\"127.0.1.1:\", false}, // invalid ip\n\t\t{\"[::1]:5000\", true},\n\t\t{\"::1\", true},\n\t} {\n\t\tactual, _ := MatchLocalhost(tc.host)\n\t\tif actual != tc.match {\n\t\t\tif tc.match {\n\t\t\t\tt.Logf(\"Expected match for %s\", tc.host)\n\t\t\t} else {\n\t\t\t\tt.Logf(\"Unexpected match for %s\", tc.host)\n\t\t\t}\n\t\t\tt.Fail()\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/resolver.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"path\"\n\t\"strings\"\n\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/containerd/v2/pkg/reference\"\n\t\"github.com/containerd/containerd/v2/pkg/tracing\"\n\t\"github.com/containerd/containerd/v2/version\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/docker/schema1\" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.\n\tremoteerrors \"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/errors\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"go.opentelemetry.io/otel/attribute\"\n)\n\nvar (\n\t// ErrInvalidAuthorization is used when credentials are passed to a server but\n\t// those credentials are rejected.\n\tErrInvalidAuthorization = errors.New(\"authorization failed\")\n\n\t// MaxManifestSize represents the largest size accepted from a registry\n\t// during resolution. Larger manifests may be accepted using a\n\t// resolution method other than the registry.\n\t//\n\t// NOTE: The max supported layers by some runtimes is 128 and individual\n\t// layers will not contribute more than 256 bytes, making a\n\t// reasonable limit for a large image manifests of 32K bytes.\n\t// 4M bytes represents a much larger upper bound for images which may\n\t// contain large annotations or be non-images. A proper manifest\n\t// design puts large metadata in subobjects, as is consistent the\n\t// intent of the manifest design.\n\tMaxManifestSize int64 = 4 * 1048 * 1048\n)\n\n// Authorizer is used to authorize HTTP requests based on 401 HTTP responses.\n// An Authorizer is responsible for caching tokens or credentials used by\n// requests.\ntype Authorizer interface {\n\t// Authorize sets the appropriate `Authorization` header on the given\n\t// request.\n\t//\n\t// If no authorization is found for the request, the request remains\n\t// unmodified. It may also add an `Authorization` header as\n\t//  \"bearer <some bearer token>\"\n\t//  \"basic <base64 encoded credentials>\"\n\t//\n\t// It may return remotes/errors.ErrUnexpectedStatus, which for example,\n\t// can be used by the caller to find out the status code returned by the registry.\n\tAuthorize(context.Context, *http.Request) error\n\n\t// AddResponses adds a 401 response for the authorizer to consider when\n\t// authorizing requests. The last response should be unauthorized and\n\t// the previous requests are used to consider redirects and retries\n\t// that may have led to the 401.\n\t//\n\t// If response is not handled, returns `ErrNotImplemented`\n\tAddResponses(context.Context, []*http.Response) error\n}\n\n// ResolverOptions are used to configured a new Docker register resolver\ntype ResolverOptions struct {\n\t// Hosts returns registry host configurations for a namespace.\n\tHosts RegistryHosts\n\n\t// Headers are the HTTP request header fields sent by the resolver\n\tHeaders http.Header\n\n\t// Tracker is used to track uploads to the registry. This is used\n\t// since the registry does not have upload tracking and the existing\n\t// mechanism for getting blob upload status is expensive.\n\tTracker StatusTracker\n\n\t// Authorizer is used to authorize registry requests\n\t// Deprecated: use Hosts\n\tAuthorizer Authorizer\n\n\t// Credentials provides username and secret given a host.\n\t// If username is empty but a secret is given, that secret\n\t// is interpreted as a long lived token.\n\t// Deprecated: use Hosts\n\tCredentials func(string) (string, string, error)\n\n\t// Host provides the hostname given a namespace.\n\t// Deprecated: use Hosts\n\tHost func(string) (string, error)\n\n\t// PlainHTTP specifies to use plain http and not https\n\t// Deprecated: use Hosts\n\tPlainHTTP bool\n\n\t// Client is the http client to used when making registry requests\n\t// Deprecated: use Hosts\n\tClient *http.Client\n}\n\n// DefaultHost is the default host function.\nfunc DefaultHost(ns string) (string, error) {\n\tif ns == \"docker.io\" {\n\t\treturn \"registry-1.docker.io\", nil\n\t}\n\treturn ns, nil\n}\n\ntype dockerResolver struct {\n\thosts         RegistryHosts\n\theader        http.Header\n\tresolveHeader http.Header\n\ttracker       StatusTracker\n}\n\n// NewResolver returns a new resolver to a Docker registry\nfunc NewResolver(options ResolverOptions) remotes.Resolver {\n\tif options.Tracker == nil {\n\t\toptions.Tracker = NewInMemoryTracker()\n\t}\n\n\tif options.Headers == nil {\n\t\toptions.Headers = make(http.Header)\n\t}\n\tif _, ok := options.Headers[\"User-Agent\"]; !ok {\n\t\toptions.Headers.Set(\"User-Agent\", \"containerd/\"+version.Version)\n\t}\n\n\tresolveHeader := http.Header{}\n\tif _, ok := options.Headers[\"Accept\"]; !ok {\n\t\t// set headers for all the types we support for resolution.\n\t\tresolveHeader.Set(\"Accept\", strings.Join([]string{\n\t\t\timages.MediaTypeDockerSchema2Manifest,\n\t\t\timages.MediaTypeDockerSchema2ManifestList,\n\t\t\tocispec.MediaTypeImageManifest,\n\t\t\tocispec.MediaTypeImageIndex, \"*/*\",\n\t\t}, \", \"))\n\t} else {\n\t\tresolveHeader[\"Accept\"] = options.Headers[\"Accept\"]\n\t\tdelete(options.Headers, \"Accept\")\n\t}\n\n\tif options.Hosts == nil {\n\t\topts := []RegistryOpt{}\n\t\tif options.Host != nil {\n\t\t\topts = append(opts, WithHostTranslator(options.Host))\n\t\t}\n\n\t\tif options.Authorizer == nil {\n\t\t\toptions.Authorizer = NewDockerAuthorizer(\n\t\t\t\tWithAuthClient(options.Client),\n\t\t\t\tWithAuthHeader(options.Headers),\n\t\t\t\tWithAuthCreds(options.Credentials))\n\t\t}\n\t\topts = append(opts, WithAuthorizer(options.Authorizer))\n\n\t\tif options.Client != nil {\n\t\t\topts = append(opts, WithClient(options.Client))\n\t\t}\n\t\tif options.PlainHTTP {\n\t\t\topts = append(opts, WithPlainHTTP(MatchAllHosts))\n\t\t} else {\n\t\t\topts = append(opts, WithPlainHTTP(MatchLocalhost))\n\t\t}\n\t\toptions.Hosts = ConfigureDefaultRegistries(opts...)\n\t}\n\treturn &dockerResolver{\n\t\thosts:         options.Hosts,\n\t\theader:        options.Headers,\n\t\tresolveHeader: resolveHeader,\n\t\ttracker:       options.Tracker,\n\t}\n}\n\nfunc getManifestMediaType(resp *http.Response) string {\n\t// Strip encoding data (manifests should always be ascii JSON)\n\tcontentType := resp.Header.Get(\"Content-Type\")\n\tif sp := strings.IndexByte(contentType, ';'); sp != -1 {\n\t\tcontentType = contentType[0:sp]\n\t}\n\n\t// As of Apr 30 2019 the registry.access.redhat.com registry does not specify\n\t// the content type of any data but uses schema1 manifests.\n\tif contentType == \"text/plain\" {\n\t\tcontentType = images.MediaTypeDockerSchema1Manifest\n\t}\n\treturn contentType\n}\n\ntype countingReader struct {\n\treader    io.Reader\n\tbytesRead int64\n}\n\nfunc (r *countingReader) Read(p []byte) (int, error) {\n\tn, err := r.reader.Read(p)\n\tr.bytesRead += int64(n)\n\treturn n, err\n}\n\nvar _ remotes.Resolver = &dockerResolver{}\n\nfunc (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocispec.Descriptor, error) {\n\tbase, err := r.resolveDockerBase(ref)\n\tif err != nil {\n\t\treturn \"\", ocispec.Descriptor{}, err\n\t}\n\trefspec := base.refspec\n\tif refspec.Object == \"\" {\n\t\treturn \"\", ocispec.Descriptor{}, reference.ErrObjectRequired\n\t}\n\n\tvar (\n\t\tfirstErr error\n\t\tpaths    [][]string\n\t\tdgst     = refspec.Digest()\n\t\tcaps     = HostCapabilityPull\n\t)\n\n\tif dgst != \"\" {\n\t\tif err := dgst.Validate(); err != nil {\n\t\t\t// need to fail here, since we can't actually resolve the invalid\n\t\t\t// digest.\n\t\t\treturn \"\", ocispec.Descriptor{}, err\n\t\t}\n\n\t\t// turns out, we have a valid digest, make a url.\n\t\tpaths = append(paths, []string{\"manifests\", dgst.String()})\n\n\t\t// fallback to blobs on not found.\n\t\tpaths = append(paths, []string{\"blobs\", dgst.String()})\n\t} else {\n\t\t// Add\n\t\tpaths = append(paths, []string{\"manifests\", refspec.Object})\n\t\tcaps |= HostCapabilityResolve\n\t}\n\n\thosts := base.filterHosts(caps)\n\tif len(hosts) == 0 {\n\t\treturn \"\", ocispec.Descriptor{}, fmt.Errorf(\"no resolve hosts: %w\", errdefs.ErrNotFound)\n\t}\n\n\tctx, err = ContextWithRepositoryScope(ctx, refspec, false)\n\tif err != nil {\n\t\treturn \"\", ocispec.Descriptor{}, err\n\t}\n\n\tfor _, u := range paths {\n\t\tfor _, host := range hosts {\n\t\t\tctx := log.WithLogger(ctx, log.G(ctx).WithField(\"host\", host.Host))\n\n\t\t\treq := base.request(host, http.MethodHead, u...)\n\t\t\tif err := req.addNamespace(base.refspec.Hostname()); err != nil {\n\t\t\t\treturn \"\", ocispec.Descriptor{}, err\n\t\t\t}\n\n\t\t\tfor key, value := range r.resolveHeader {\n\t\t\t\treq.header[key] = append(req.header[key], value...)\n\t\t\t}\n\n\t\t\tlog.G(ctx).Debug(\"resolving\")\n\t\t\tresp, err := req.doWithRetries(ctx, nil)\n\t\t\tif err != nil {\n\t\t\t\tif errors.Is(err, ErrInvalidAuthorization) {\n\t\t\t\t\terr = fmt.Errorf(\"pull access denied, repository does not exist or may require authorization: %w\", err)\n\t\t\t\t}\n\t\t\t\t// Store the error for referencing later\n\t\t\t\tif firstErr == nil {\n\t\t\t\t\tfirstErr = err\n\t\t\t\t}\n\t\t\t\tlog.G(ctx).WithError(err).Info(\"trying next host\")\n\t\t\t\tcontinue // try another host\n\t\t\t}\n\t\t\tresp.Body.Close() // don't care about body contents.\n\n\t\t\tif resp.StatusCode > 299 {\n\t\t\t\tif resp.StatusCode == http.StatusNotFound {\n\t\t\t\t\tlog.G(ctx).Info(\"trying next host - response was http.StatusNotFound\")\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif resp.StatusCode > 399 {\n\t\t\t\t\t// Set firstErr when encountering the first non-404 status code.\n\t\t\t\t\tif firstErr == nil {\n\t\t\t\t\t\tfirstErr = remoteerrors.NewUnexpectedStatusErr(resp)\n\t\t\t\t\t}\n\t\t\t\t\tcontinue // try another host\n\t\t\t\t}\n\t\t\t\treturn \"\", ocispec.Descriptor{}, remoteerrors.NewUnexpectedStatusErr(resp)\n\t\t\t}\n\t\t\tsize := resp.ContentLength\n\t\t\tcontentType := getManifestMediaType(resp)\n\n\t\t\t// if no digest was provided, then only a resolve\n\t\t\t// trusted registry was contacted, in this case use\n\t\t\t// the digest header (or content from GET)\n\t\t\tif dgst == \"\" {\n\t\t\t\t// this is the only point at which we trust the registry. we use the\n\t\t\t\t// content headers to assemble a descriptor for the name. when this becomes\n\t\t\t\t// more robust, we mostly get this information from a secure trust store.\n\t\t\t\tdgstHeader := digest.Digest(resp.Header.Get(\"Docker-Content-Digest\"))\n\n\t\t\t\tif dgstHeader != \"\" && size != -1 {\n\t\t\t\t\tif err := dgstHeader.Validate(); err != nil {\n\t\t\t\t\t\treturn \"\", ocispec.Descriptor{}, fmt.Errorf(\"%q in header not a valid digest: %w\", dgstHeader, err)\n\t\t\t\t\t}\n\t\t\t\t\tdgst = dgstHeader\n\t\t\t\t}\n\t\t\t}\n\t\t\tif dgst == \"\" || size == -1 {\n\t\t\t\tlog.G(ctx).Debug(\"no Docker-Content-Digest header, fetching manifest instead\")\n\n\t\t\t\treq = base.request(host, http.MethodGet, u...)\n\t\t\t\tif err := req.addNamespace(base.refspec.Hostname()); err != nil {\n\t\t\t\t\treturn \"\", ocispec.Descriptor{}, err\n\t\t\t\t}\n\n\t\t\t\tfor key, value := range r.resolveHeader {\n\t\t\t\t\treq.header[key] = append(req.header[key], value...)\n\t\t\t\t}\n\n\t\t\t\tresp, err := req.doWithRetries(ctx, nil)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn \"\", ocispec.Descriptor{}, err\n\t\t\t\t}\n\n\t\t\t\tbodyReader := countingReader{reader: resp.Body}\n\n\t\t\t\tcontentType = getManifestMediaType(resp)\n\t\t\t\terr = func() error {\n\t\t\t\t\tdefer resp.Body.Close()\n\t\t\t\t\tif dgst != \"\" {\n\t\t\t\t\t\t_, err = io.Copy(io.Discard, &bodyReader)\n\t\t\t\t\t\treturn err\n\t\t\t\t\t}\n\n\t\t\t\t\tif contentType == images.MediaTypeDockerSchema1Manifest {\n\t\t\t\t\t\tb, err := schema1.ReadStripSignature(&bodyReader)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn err\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdgst = digest.FromBytes(b)\n\t\t\t\t\t\treturn nil\n\t\t\t\t\t}\n\n\t\t\t\t\tdgst, err = digest.FromReader(&bodyReader)\n\t\t\t\t\treturn err\n\t\t\t\t}()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn \"\", ocispec.Descriptor{}, err\n\t\t\t\t}\n\t\t\t\tsize = bodyReader.bytesRead\n\t\t\t}\n\t\t\t// Prevent resolving to excessively large manifests\n\t\t\tif size > MaxManifestSize {\n\t\t\t\tif firstErr == nil {\n\t\t\t\t\tfirstErr = fmt.Errorf(\"rejecting %d byte manifest for %s: %w\", size, ref, errdefs.ErrNotFound)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tdesc := ocispec.Descriptor{\n\t\t\t\tDigest:    dgst,\n\t\t\t\tMediaType: contentType,\n\t\t\t\tSize:      size,\n\t\t\t}\n\n\t\t\tlog.G(ctx).WithField(\"desc.digest\", desc.Digest).Debug(\"resolved\")\n\t\t\treturn ref, desc, nil\n\t\t}\n\t}\n\n\t// If above loop terminates without return, then there was an error.\n\t// \"firstErr\" contains the first non-404 error. That is, \"firstErr == nil\"\n\t// means that either no registries were given or each registry returned 404.\n\n\tif firstErr == nil {\n\t\tfirstErr = fmt.Errorf(\"%s: %w\", ref, errdefs.ErrNotFound)\n\t}\n\n\treturn \"\", ocispec.Descriptor{}, firstErr\n}\n\nfunc (r *dockerResolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) {\n\tbase, err := r.resolveDockerBase(ref)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn dockerFetcher{\n\t\tdockerBase: base,\n\t}, nil\n}\n\nfunc (r *dockerResolver) Pusher(ctx context.Context, ref string) (remotes.Pusher, error) {\n\tbase, err := r.resolveDockerBase(ref)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn dockerPusher{\n\t\tdockerBase: base,\n\t\tobject:     base.refspec.Object,\n\t\ttracker:    r.tracker,\n\t}, nil\n}\n\nfunc (r *dockerResolver) resolveDockerBase(ref string) (*dockerBase, error) {\n\trefspec, err := reference.Parse(ref)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn r.base(refspec)\n}\n\ntype dockerBase struct {\n\trefspec    reference.Spec\n\trepository string\n\thosts      []RegistryHost\n\theader     http.Header\n}\n\nfunc (r *dockerResolver) base(refspec reference.Spec) (*dockerBase, error) {\n\thost := refspec.Hostname()\n\thosts, err := r.hosts(host)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &dockerBase{\n\t\trefspec:    refspec,\n\t\trepository: strings.TrimPrefix(refspec.Locator, host+\"/\"),\n\t\thosts:      hosts,\n\t\theader:     r.header,\n\t}, nil\n}\n\n// filterHosts returns a set of hosts matching the given capabilities\n// Multiple arguments are treated as \"OR\"\n// Each argument may be a set of capabilities in which all must be satisfied to match\nfunc (r *dockerBase) filterHosts(capsets ...HostCapabilities) (hosts []RegistryHost) {\n\tfor _, host := range r.hosts {\n\t\tfor _, caps := range capsets {\n\t\t\tif host.Capabilities.Has(caps) {\n\t\t\t\thosts = append(hosts, host)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn\n}\n\nfunc (r *dockerBase) request(host RegistryHost, method string, ps ...string) *request {\n\theader := r.header.Clone()\n\tif header == nil {\n\t\theader = http.Header{}\n\t}\n\n\tfor key, value := range host.Header {\n\t\theader[key] = append(header[key], value...)\n\t}\n\tparts := append([]string{\"/\", host.Path, r.repository}, ps...)\n\tp := path.Join(parts...)\n\t// Join strips trailing slash, re-add ending \"/\" if included\n\tif len(parts) > 0 && strings.HasSuffix(parts[len(parts)-1], \"/\") {\n\t\tp = p + \"/\"\n\t}\n\treturn &request{\n\t\tmethod: method,\n\t\tpath:   p,\n\t\theader: header,\n\t\thost:   host,\n\t}\n}\n\nfunc (r *request) authorize(ctx context.Context, req *http.Request) error {\n\t// Check if has header for host\n\tif r.host.Authorizer != nil {\n\t\tif err := r.host.Authorizer.Authorize(ctx, req); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (r *request) addQuery(key, value string) (err error) {\n\tvar q url.Values\n\t// Parse query\n\tif i := strings.IndexByte(r.path, '?'); i > 0 {\n\t\tr.path = r.path[:i+1]\n\t\tq, err = url.ParseQuery(r.path[i+1:])\n\t\tif err != nil {\n\t\t\treturn\n\t\t}\n\t} else {\n\t\tr.path = r.path + \"?\"\n\t\tq = url.Values{}\n\t}\n\tq.Add(key, value)\n\n\tr.path = r.path + q.Encode()\n\n\treturn\n}\n\nfunc (r *request) addNamespace(ns string) error {\n\tif !r.host.isProxy(ns) {\n\t\treturn nil\n\t}\n\treturn r.addQuery(\"ns\", ns)\n}\n\ntype request struct {\n\tmethod string\n\tpath   string\n\theader http.Header\n\thost   RegistryHost\n\tbody   func() (io.ReadCloser, error)\n\tsize   int64\n}\n\nfunc (r *request) do(ctx context.Context) (*http.Response, error) {\n\tu := r.host.Scheme + \"://\" + r.host.Host + r.path\n\treq, err := http.NewRequestWithContext(ctx, r.method, u, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treq.Header = http.Header{} // headers need to be copied to avoid concurrent map access\n\tfor k, v := range r.header {\n\t\treq.Header[k] = v\n\t}\n\tif r.body != nil {\n\t\tbody, err := r.body()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treq.Body = body\n\t\treq.GetBody = r.body\n\t\tif r.size > 0 {\n\t\t\treq.ContentLength = r.size\n\t\t}\n\t}\n\n\tctx = log.WithLogger(ctx, log.G(ctx).WithField(\"url\", u))\n\tlog.G(ctx).WithFields(requestFields(req)).Debug(\"do request\")\n\tif err := r.authorize(ctx, req); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to authorize: %w\", err)\n\t}\n\n\tclient := &http.Client{}\n\tif r.host.Client != nil {\n\t\t*client = *r.host.Client\n\t}\n\tif client.CheckRedirect == nil {\n\t\tclient.CheckRedirect = func(req *http.Request, via []*http.Request) error {\n\t\t\tif len(via) >= 10 {\n\t\t\t\treturn errors.New(\"stopped after 10 redirects\")\n\t\t\t}\n\t\t\tif err := r.authorize(ctx, req); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to authorize redirect: %w\", err)\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\t_, httpSpan := tracing.StartSpan(\n\t\tctx,\n\t\ttracing.Name(\"remotes.docker.resolver\", \"HTTPRequest\"),\n\t)\n\tdefer httpSpan.End()\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\thttpSpan.SetStatus(err)\n\t\treturn nil, fmt.Errorf(\"failed to do request: %w\", err)\n\t}\n\thttpSpan.SetAttributes(\n\t\tattribute.Int(\"http.response.status_code\", resp.StatusCode),\n\t\tattribute.Int(\"http.status_code\", resp.StatusCode), // Deprecated: SemConv <= v1.21\n\t)\n\tlog.G(ctx).WithFields(responseFields(resp)).Debug(\"fetch response received\")\n\treturn resp, nil\n}\n\nfunc (r *request) doWithRetries(ctx context.Context, responses []*http.Response) (*http.Response, error) {\n\tresp, err := r.do(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tresponses = append(responses, resp)\n\tretry, err := r.retryRequest(ctx, responses)\n\tif err != nil {\n\t\tresp.Body.Close()\n\t\treturn nil, err\n\t}\n\tif retry {\n\t\tresp.Body.Close()\n\t\treturn r.doWithRetries(ctx, responses)\n\t}\n\treturn resp, err\n}\n\nfunc (r *request) retryRequest(ctx context.Context, responses []*http.Response) (bool, error) {\n\tif len(responses) > 5 {\n\t\treturn false, nil\n\t}\n\tlast := responses[len(responses)-1]\n\tswitch last.StatusCode {\n\tcase http.StatusUnauthorized:\n\t\tlog.G(ctx).WithField(\"header\", last.Header.Get(\"WWW-Authenticate\")).Debug(\"Unauthorized\")\n\t\tif r.host.Authorizer != nil {\n\t\t\tif err := r.host.Authorizer.AddResponses(ctx, responses); err == nil {\n\t\t\t\treturn true, nil\n\t\t\t} else if !errdefs.IsNotImplemented(err) {\n\t\t\t\treturn false, err\n\t\t\t}\n\t\t}\n\n\t\treturn false, nil\n\tcase http.StatusMethodNotAllowed:\n\t\t// Support registries which have not properly implemented the HEAD method for\n\t\t// manifests endpoint\n\t\tif r.method == http.MethodHead && strings.Contains(r.path, \"/manifests/\") {\n\t\t\tr.method = http.MethodGet\n\t\t\treturn true, nil\n\t\t}\n\tcase http.StatusRequestTimeout, http.StatusTooManyRequests:\n\t\treturn true, nil\n\t}\n\n\t// TODO: Handle 50x errors accounting for attempt history\n\treturn false, nil\n}\n\nfunc (r *request) String() string {\n\treturn r.host.Scheme + \"://\" + r.host.Host + r.path\n}\n\nfunc requestFields(req *http.Request) log.Fields {\n\tfields := map[string]interface{}{\n\t\t\"request.method\": req.Method,\n\t}\n\tfor k, vals := range req.Header {\n\t\tk = strings.ToLower(k)\n\t\tif k == \"authorization\" {\n\t\t\tcontinue\n\t\t}\n\t\tfor i, v := range vals {\n\t\t\tfield := \"request.header.\" + k\n\t\t\tif i > 0 {\n\t\t\t\tfield = fmt.Sprintf(\"%s.%d\", field, i)\n\t\t\t}\n\t\t\tfields[field] = v\n\t\t}\n\t}\n\n\treturn log.Fields(fields)\n}\n\nfunc responseFields(resp *http.Response) log.Fields {\n\tfields := map[string]interface{}{\n\t\t\"response.status\": resp.Status,\n\t}\n\tfor k, vals := range resp.Header {\n\t\tk = strings.ToLower(k)\n\t\tfor i, v := range vals {\n\t\t\tfield := \"response.header.\" + k\n\t\t\tif i > 0 {\n\t\t\t\tfield = fmt.Sprintf(\"%s.%d\", field, i)\n\t\t\t}\n\t\t\tfields[field] = v\n\t\t}\n\t}\n\n\treturn log.Fields(fields)\n}\n\n// IsLocalhost checks if the registry host is local.\nfunc IsLocalhost(host string) bool {\n\tif h, _, err := net.SplitHostPort(host); err == nil {\n\t\thost = h\n\t}\n\n\tif host == \"localhost\" {\n\t\treturn true\n\t}\n\n\tip := net.ParseIP(host)\n\treturn ip.IsLoopback()\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/resolver_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes/docker/auth\"\n\tdigest \"github.com/opencontainers/go-digest\"\n\tspecs \"github.com/opencontainers/image-spec/specs-go\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\nfunc TestHTTPResolver(t *testing.T) {\n\ts := func(h http.Handler) (string, ResolverOptions, func()) {\n\t\ts := httptest.NewServer(h)\n\n\t\toptions := ResolverOptions{}\n\t\tbase := s.URL[7:] // strip \"http://\"\n\t\treturn base, options, s.Close\n\t}\n\n\trunBasicTest(t, \"testname\", s)\n}\n\nfunc TestHTTPSResolver(t *testing.T) {\n\trunBasicTest(t, \"testname\", tlsServer)\n}\n\nfunc TestBasicResolver(t *testing.T) {\n\tbasicAuth := func(h http.Handler) (string, ResolverOptions, func()) {\n\t\t// Wrap with basic auth\n\t\twrapped := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\t\tusername, password, ok := r.BasicAuth()\n\t\t\tif !ok || username != \"user1\" || password != \"password1\" {\n\t\t\t\trw.Header().Set(\"WWW-Authenticate\", \"Basic realm=localhost\")\n\t\t\t\trw.WriteHeader(http.StatusUnauthorized)\n\t\t\t\treturn\n\t\t\t}\n\t\t\th.ServeHTTP(rw, r)\n\t\t})\n\n\t\tbase, options, close := tlsServer(wrapped)\n\t\tauthorizer := NewDockerAuthorizer(\n\t\t\tWithAuthClient(options.Client),\n\t\t\tWithAuthCreds(func(host string) (string, string, error) {\n\t\t\t\treturn \"user1\", \"password1\", nil\n\t\t\t}),\n\t\t)\n\t\toptions.Hosts = ConfigureDefaultRegistries(\n\t\t\tWithClient(options.Client),\n\t\t\tWithAuthorizer(authorizer),\n\t\t)\n\t\treturn base, options, close\n\t}\n\trunBasicTest(t, \"testname\", basicAuth)\n}\n\nfunc TestAnonymousTokenResolver(t *testing.T) {\n\tth := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\tif r.Method != http.MethodGet {\n\t\t\trw.WriteHeader(http.StatusMethodNotAllowed)\n\t\t\treturn\n\t\t}\n\t\trw.Header().Set(\"Content-Type\", \"application/json\")\n\t\trw.WriteHeader(http.StatusOK)\n\t\trw.Write([]byte(`{\"access_token\":\"perfectlyvalidopaquetoken\"}`))\n\t})\n\n\trunBasicTest(t, \"testname\", withTokenServer(th, nil))\n}\n\nfunc TestBasicAuthTokenResolver(t *testing.T) {\n\tth := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\tif r.Method != http.MethodGet {\n\t\t\trw.WriteHeader(http.StatusMethodNotAllowed)\n\t\t\treturn\n\t\t}\n\t\trw.Header().Set(\"Content-Type\", \"application/json\")\n\t\trw.WriteHeader(http.StatusOK)\n\t\tusername, password, ok := r.BasicAuth()\n\t\tif !ok || username != \"user1\" || password != \"password1\" {\n\t\t\trw.Write([]byte(`{\"access_token\":\"insufficientscope\"}`))\n\t\t} else {\n\t\t\trw.Write([]byte(`{\"access_token\":\"perfectlyvalidopaquetoken\"}`))\n\t\t}\n\t})\n\tcreds := func(string) (string, string, error) {\n\t\treturn \"user1\", \"password1\", nil\n\t}\n\n\trunBasicTest(t, \"testname\", withTokenServer(th, creds))\n}\n\nfunc TestRefreshTokenResolver(t *testing.T) {\n\tth := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\tif r.Method != http.MethodPost {\n\t\t\trw.WriteHeader(http.StatusMethodNotAllowed)\n\t\t\treturn\n\t\t}\n\t\trw.Header().Set(\"Content-Type\", \"application/json\")\n\t\trw.WriteHeader(http.StatusOK)\n\n\t\tr.ParseForm()\n\t\tif r.PostForm.Get(\"grant_type\") != \"refresh_token\" || r.PostForm.Get(\"refresh_token\") != \"somerefreshtoken\" {\n\t\t\trw.Write([]byte(`{\"access_token\":\"insufficientscope\"}`))\n\t\t} else {\n\t\t\trw.Write([]byte(`{\"access_token\":\"perfectlyvalidopaquetoken\"}`))\n\t\t}\n\t})\n\tcreds := func(string) (string, string, error) {\n\t\treturn \"\", \"somerefreshtoken\", nil\n\t}\n\n\trunBasicTest(t, \"testname\", withTokenServer(th, creds))\n}\n\nfunc TestFetchRefreshToken(t *testing.T) {\n\tf := func(t *testing.T, disablePOST bool) {\n\t\tname := \"testname\"\n\t\tif disablePOST {\n\t\t\tname += \"-disable-post\"\n\t\t}\n\t\tvar fetchedRefreshToken string\n\t\tonFetchRefreshToken := func(ctx context.Context, refreshToken string, req *http.Request) {\n\t\t\tfetchedRefreshToken = refreshToken\n\t\t}\n\t\tsrv := newRefreshTokenServer(t, name, disablePOST, onFetchRefreshToken)\n\t\trunBasicTest(t, name, srv.BasicTestFunc())\n\t\tif fetchedRefreshToken != srv.RefreshToken {\n\t\t\tt.Errorf(\"unexpected refresh token: got %q\", fetchedRefreshToken)\n\t\t}\n\t}\n\n\tt.Run(\"POST\", func(t *testing.T) {\n\t\tf(t, false)\n\t})\n\tt.Run(\"GET\", func(t *testing.T) {\n\t\tf(t, true)\n\t})\n}\n\nfunc TestPostBasicAuthTokenResolver(t *testing.T) {\n\tth := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\tif r.Method != http.MethodPost {\n\t\t\trw.WriteHeader(http.StatusMethodNotAllowed)\n\t\t\treturn\n\t\t}\n\t\trw.Header().Set(\"Content-Type\", \"application/json\")\n\t\trw.WriteHeader(http.StatusOK)\n\n\t\tr.ParseForm()\n\t\tif r.PostForm.Get(\"grant_type\") != \"password\" || r.PostForm.Get(\"username\") != \"user1\" || r.PostForm.Get(\"password\") != \"password1\" {\n\t\t\trw.Write([]byte(`{\"access_token\":\"insufficientscope\"}`))\n\t\t} else {\n\t\t\trw.Write([]byte(`{\"access_token\":\"perfectlyvalidopaquetoken\"}`))\n\t\t}\n\t})\n\tcreds := func(string) (string, string, error) {\n\t\treturn \"user1\", \"password1\", nil\n\t}\n\n\trunBasicTest(t, \"testname\", withTokenServer(th, creds))\n}\n\nfunc TestBadTokenResolver(t *testing.T) {\n\tth := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\tif r.Method != http.MethodPost {\n\t\t\trw.WriteHeader(http.StatusMethodNotAllowed)\n\t\t\treturn\n\t\t}\n\t\trw.Header().Set(\"Content-Type\", \"application/json\")\n\t\trw.WriteHeader(http.StatusOK)\n\t\trw.Write([]byte(`{\"access_token\":\"insufficientscope\"}`))\n\t})\n\tcreds := func(string) (string, string, error) {\n\t\treturn \"\", \"somerefreshtoken\", nil\n\t}\n\n\tctx := context.Background()\n\th := newContent(ocispec.MediaTypeImageManifest, []byte(\"not anything parse-able\"))\n\n\tbase, ro, close := withTokenServer(th, creds)(logHandler{t, h})\n\tdefer close()\n\n\tresolver := NewResolver(ro)\n\timage := fmt.Sprintf(\"%s/doesntmatter:sometatg\", base)\n\n\t_, _, err := resolver.Resolve(ctx, image)\n\tif err == nil {\n\t\tt.Fatal(\"Expected error getting token with inssufficient scope\")\n\t}\n\tif !errors.Is(err, ErrInvalidAuthorization) {\n\t\tt.Fatal(err)\n\t}\n}\n\nfunc TestHostFailureFallbackResolver(t *testing.T) {\n\tsf := func(h http.Handler) (string, ResolverOptions, func()) {\n\t\ts := httptest.NewServer(h)\n\t\tbase := s.URL[7:] // strip \"http://\"\n\n\t\toptions := ResolverOptions{}\n\t\tcreateHost := func(host string) RegistryHost {\n\t\t\treturn RegistryHost{\n\t\t\t\tClient: &http.Client{\n\t\t\t\t\t// Set the timeout so we timeout waiting for the non-responsive HTTP server\n\t\t\t\t\tTimeout: 500 * time.Millisecond,\n\t\t\t\t},\n\t\t\t\tHost:         host,\n\t\t\t\tScheme:       \"http\",\n\t\t\t\tPath:         \"/v2\",\n\t\t\t\tCapabilities: HostCapabilityPull | HostCapabilityResolve | HostCapabilityPush,\n\t\t\t}\n\t\t}\n\n\t\t// Create an unstarted HTTP server. We use this to generate a random port.\n\t\tnotRunning := httptest.NewUnstartedServer(nil)\n\t\tnotRunningBase := notRunning.Listener.Addr().String()\n\n\t\t// Override hosts with two hosts\n\t\toptions.Hosts = func(host string) ([]RegistryHost, error) {\n\t\t\treturn []RegistryHost{\n\t\t\t\tcreateHost(notRunningBase), // This host IS running, but with a non-responsive HTTP server\n\t\t\t\tcreateHost(base),           // This host IS running\n\t\t\t}, nil\n\t\t}\n\n\t\treturn base, options, s.Close\n\t}\n\n\trunBasicTest(t, \"testname\", sf)\n}\n\nfunc TestHostTLSFailureFallbackResolver(t *testing.T) {\n\tsf := func(h http.Handler) (string, ResolverOptions, func()) {\n\t\t// Start up two servers\n\t\tserver := httptest.NewServer(h)\n\t\thttpBase := server.URL[7:] // strip \"http://\"\n\n\t\ttlsServer := httptest.NewUnstartedServer(h)\n\t\ttlsServer.StartTLS()\n\t\thttpsBase := tlsServer.URL[8:] // strip \"https://\"\n\n\t\tcapool := x509.NewCertPool()\n\t\tcert, _ := x509.ParseCertificate(tlsServer.TLS.Certificates[0].Certificate[0])\n\t\tcapool.AddCert(cert)\n\n\t\tclient := &http.Client{\n\t\t\tTransport: &http.Transport{\n\t\t\t\tTLSClientConfig: &tls.Config{\n\t\t\t\t\tRootCAs: capool,\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\toptions := ResolverOptions{}\n\t\tcreateHost := func(host string) RegistryHost {\n\t\t\treturn RegistryHost{\n\t\t\t\tClient:       client,\n\t\t\t\tHost:         host,\n\t\t\t\tScheme:       \"https\",\n\t\t\t\tPath:         \"/v2\",\n\t\t\t\tCapabilities: HostCapabilityPull | HostCapabilityResolve | HostCapabilityPush,\n\t\t\t}\n\t\t}\n\n\t\t// Override hosts with two hosts\n\t\toptions.Hosts = func(host string) ([]RegistryHost, error) {\n\t\t\treturn []RegistryHost{\n\t\t\t\tcreateHost(httpBase),  // This host is serving plain HTTP\n\t\t\t\tcreateHost(httpsBase), // This host is serving TLS\n\t\t\t}, nil\n\t\t}\n\n\t\treturn httpBase, options, func() {\n\t\t\tserver.Close()\n\t\t\ttlsServer.Close()\n\t\t}\n\t}\n\n\trunBasicTest(t, \"testname\", sf)\n}\n\nfunc TestResolveProxy(t *testing.T) {\n\tvar (\n\t\tctx  = context.Background()\n\t\ttag  = \"latest\"\n\t\tr    = http.NewServeMux()\n\t\tname = \"testname\"\n\t\tns   = \"upstream.example.com\"\n\t)\n\n\tm := newManifest(\n\t\tnewContent(ocispec.MediaTypeImageConfig, []byte(\"1\")),\n\t\tnewContent(ocispec.MediaTypeImageLayerGzip, []byte(\"2\")),\n\t)\n\tmc := newContent(ocispec.MediaTypeImageManifest, m.OCIManifest())\n\tm.RegisterHandler(r, name)\n\tr.Handle(fmt.Sprintf(\"/v2/%s/manifests/%s\", name, tag), mc)\n\tr.Handle(fmt.Sprintf(\"/v2/%s/manifests/%s\", name, mc.Digest()), mc)\n\n\tnr := namespaceRouter{\n\t\t\"upstream.example.com\": r,\n\t}\n\n\tbase, ro, close := tlsServer(logHandler{t, nr})\n\tdefer close()\n\n\tro.Hosts = func(host string) ([]RegistryHost, error) {\n\t\treturn []RegistryHost{{\n\t\t\tClient:       ro.Client,\n\t\t\tHost:         base,\n\t\t\tScheme:       \"https\",\n\t\t\tPath:         \"/v2\",\n\t\t\tCapabilities: HostCapabilityPull | HostCapabilityResolve,\n\t\t}}, nil\n\t}\n\n\tresolver := NewResolver(ro)\n\timage := fmt.Sprintf(\"%s/%s:%s\", ns, name, tag)\n\n\t_, d, err := resolver.Resolve(ctx, image)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tf, err := resolver.Fetcher(ctx, image)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\trefs, err := testocimanifest(ctx, f, d)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(refs) != 2 {\n\t\tt.Fatalf(\"Unexpected number of references: %d, expected 2\", len(refs))\n\t}\n\n\tfor _, ref := range refs {\n\t\tif err := testFetch(ctx, f, ref); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc TestResolveProxyFallback(t *testing.T) {\n\tvar (\n\t\tctx  = context.Background()\n\t\ttag  = \"latest\"\n\t\tr    = http.NewServeMux()\n\t\tname = \"testname\"\n\t)\n\n\tm := newManifest(\n\t\tnewContent(ocispec.MediaTypeImageConfig, []byte(\"1\")),\n\t\tnewContent(ocispec.MediaTypeImageLayerGzip, []byte(\"2\")),\n\t)\n\tmc := newContent(ocispec.MediaTypeImageManifest, m.OCIManifest())\n\tm.RegisterHandler(r, name)\n\tr.Handle(fmt.Sprintf(\"/v2/%s/manifests/%s\", name, tag), mc)\n\tr.Handle(fmt.Sprintf(\"/v2/%s/manifests/%s\", name, mc.Digest()), mc)\n\n\tnr := namespaceRouter{\n\t\t\"\": r,\n\t}\n\ts := httptest.NewServer(logHandler{t, nr})\n\tdefer s.Close()\n\n\tbase := s.URL[7:] // strip \"http://\"\n\n\tro := ResolverOptions{\n\t\tHosts: func(host string) ([]RegistryHost, error) {\n\t\t\treturn []RegistryHost{\n\t\t\t\t{\n\t\t\t\t\tHost:         flipLocalhost(host),\n\t\t\t\t\tScheme:       \"http\",\n\t\t\t\t\tPath:         \"/v2\",\n\t\t\t\t\tCapabilities: HostCapabilityPull | HostCapabilityResolve,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tHost:         host,\n\t\t\t\t\tScheme:       \"http\",\n\t\t\t\t\tPath:         \"/v2\",\n\t\t\t\t\tCapabilities: HostCapabilityPull | HostCapabilityResolve | HostCapabilityPush,\n\t\t\t\t},\n\t\t\t}, nil\n\t\t},\n\t}\n\n\tresolver := NewResolver(ro)\n\timage := fmt.Sprintf(\"%s/%s:%s\", base, name, tag)\n\n\t_, d, err := resolver.Resolve(ctx, image)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tf, err := resolver.Fetcher(ctx, image)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\trefs, err := testocimanifest(ctx, f, d)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(refs) != 2 {\n\t\tt.Fatalf(\"Unexpected number of references: %d, expected 2\", len(refs))\n\t}\n\n\tfor _, ref := range refs {\n\t\tif err := testFetch(ctx, f, ref); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc flipLocalhost(host string) string {\n\tif strings.HasPrefix(host, \"127.0.0.1\") {\n\t\treturn \"localhost\" + host[9:]\n\n\t} else if strings.HasPrefix(host, \"localhost\") {\n\t\treturn \"127.0.0.1\" + host[9:]\n\t}\n\treturn host\n}\n\nfunc withTokenServer(th http.Handler, creds func(string) (string, string, error)) func(h http.Handler) (string, ResolverOptions, func()) {\n\treturn func(h http.Handler) (string, ResolverOptions, func()) {\n\t\ts := httptest.NewUnstartedServer(th)\n\t\ts.StartTLS()\n\n\t\tcert, _ := x509.ParseCertificate(s.TLS.Certificates[0].Certificate[0])\n\t\ttokenBase := s.URL + \"/token\"\n\n\t\t// Wrap with token auth\n\t\twrapped := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\t\tauth := strings.ToLower(r.Header.Get(\"Authorization\"))\n\t\t\tif auth != \"bearer perfectlyvalidopaquetoken\" {\n\t\t\t\tauthHeader := fmt.Sprintf(\"Bearer realm=%q,service=registry,scope=\\\"repository:testname:pull,pull\\\"\", tokenBase)\n\t\t\t\tif strings.HasPrefix(auth, \"bearer \") {\n\t\t\t\t\tauthHeader = authHeader + \",error=\" + auth[7:]\n\t\t\t\t}\n\t\t\t\trw.Header().Set(\"WWW-Authenticate\", authHeader)\n\t\t\t\trw.WriteHeader(http.StatusUnauthorized)\n\t\t\t\treturn\n\t\t\t}\n\t\t\th.ServeHTTP(rw, r)\n\t\t})\n\n\t\tbase, options, close := tlsServer(wrapped)\n\t\toptions.Hosts = ConfigureDefaultRegistries(\n\t\t\tWithClient(options.Client),\n\t\t\tWithAuthorizer(NewDockerAuthorizer(\n\t\t\t\tWithAuthClient(options.Client),\n\t\t\t\tWithAuthCreds(creds),\n\t\t\t)),\n\t\t)\n\t\toptions.Client.Transport.(*http.Transport).TLSClientConfig.RootCAs.AddCert(cert)\n\t\treturn base, options, func() {\n\t\t\ts.Close()\n\t\t\tclose()\n\t\t}\n\t}\n}\n\nfunc tlsServer(h http.Handler) (string, ResolverOptions, func()) {\n\ts := httptest.NewUnstartedServer(h)\n\ts.StartTLS()\n\n\tcapool := x509.NewCertPool()\n\tcert, _ := x509.ParseCertificate(s.TLS.Certificates[0].Certificate[0])\n\tcapool.AddCert(cert)\n\n\tclient := &http.Client{\n\t\tTransport: &http.Transport{\n\t\t\tTLSClientConfig: &tls.Config{\n\t\t\t\tRootCAs: capool,\n\t\t\t},\n\t\t},\n\t}\n\toptions := ResolverOptions{\n\t\tHosts: ConfigureDefaultRegistries(WithClient(client)),\n\t\t// Set deprecated field for tests to use for configuration\n\t\tClient: client,\n\t}\n\tbase := s.URL[8:] // strip \"https://\"\n\treturn base, options, s.Close\n}\n\ntype logHandler struct {\n\tt       *testing.T\n\thandler http.Handler\n}\n\nfunc (h logHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {\n\th.handler.ServeHTTP(rw, r)\n}\n\ntype namespaceRouter map[string]http.Handler\n\nfunc (nr namespaceRouter) ServeHTTP(rw http.ResponseWriter, r *http.Request) {\n\th, ok := nr[r.URL.Query().Get(\"ns\")]\n\tif !ok {\n\t\trw.WriteHeader(http.StatusNotFound)\n\t\treturn\n\t}\n\th.ServeHTTP(rw, r)\n}\n\nfunc runBasicTest(t *testing.T, name string, sf func(h http.Handler) (string, ResolverOptions, func())) {\n\tvar (\n\t\tctx = context.Background()\n\t\ttag = \"latest\"\n\t\tr   = http.NewServeMux()\n\t)\n\n\tm := newManifest(\n\t\tnewContent(ocispec.MediaTypeImageConfig, []byte(\"1\")),\n\t\tnewContent(ocispec.MediaTypeImageLayerGzip, []byte(\"2\")),\n\t)\n\tmc := newContent(ocispec.MediaTypeImageManifest, m.OCIManifest())\n\tm.RegisterHandler(r, name)\n\tr.Handle(fmt.Sprintf(\"/v2/%s/manifests/%s\", name, tag), mc)\n\tr.Handle(fmt.Sprintf(\"/v2/%s/manifests/%s\", name, mc.Digest()), mc)\n\n\tbase, ro, close := sf(logHandler{t, r})\n\tdefer close()\n\n\tresolver := NewResolver(ro)\n\timage := fmt.Sprintf(\"%s/%s:%s\", base, name, tag)\n\n\t_, d, err := resolver.Resolve(ctx, image)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tf, err := resolver.Fetcher(ctx, image)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\trefs, err := testocimanifest(ctx, f, d)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(refs) != 2 {\n\t\tt.Fatalf(\"Unexpected number of references: %d, expected 2\", len(refs))\n\t}\n\n\tfor _, ref := range refs {\n\t\tif err := testFetch(ctx, f, ref); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc testFetch(ctx context.Context, f remotes.Fetcher, desc ocispec.Descriptor) error {\n\tr, err := f.Fetch(ctx, desc)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdgstr := desc.Digest.Algorithm().Digester()\n\tio.Copy(dgstr.Hash(), r)\n\tif dgstr.Digest() != desc.Digest {\n\t\treturn fmt.Errorf(\"content mismatch: %s != %s\", dgstr.Digest(), desc.Digest)\n\t}\n\n\tfByDigest, ok := f.(remotes.FetcherByDigest)\n\tif !ok {\n\t\treturn fmt.Errorf(\"fetcher %T does not implement FetcherByDigest\", f)\n\t}\n\tr2, desc2, err := fByDigest.FetchByDigest(ctx, desc.Digest)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"FetcherByDigest: faild to fetch %v: %w\", desc.Digest, err)\n\t}\n\tif desc2.Size != desc.Size {\n\t\tr2b, err := io.ReadAll(r2)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"FetcherByDigest: size mismatch: %d != %d (content: %v)\", desc2.Size, desc.Size, err)\n\t\t}\n\t\treturn fmt.Errorf(\"FetcherByDigest: size mismatch: %d != %d (content: %q)\", desc2.Size, desc.Size, string(r2b))\n\t}\n\tdgstr2 := desc.Digest.Algorithm().Digester()\n\tif _, err = io.Copy(dgstr2.Hash(), r2); err != nil {\n\t\treturn fmt.Errorf(\"FetcherByDigest: faild to copy: %w\", err)\n\t}\n\tif dgstr2.Digest() != desc.Digest {\n\t\treturn fmt.Errorf(\"FetcherByDigest: content mismatch: %s != %s\", dgstr2.Digest(), desc.Digest)\n\t}\n\treturn nil\n}\n\nfunc testocimanifest(ctx context.Context, f remotes.Fetcher, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {\n\tr, err := f.Fetch(ctx, desc)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to fetch %s: %w\", desc.Digest, err)\n\t}\n\tp, err := io.ReadAll(r)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif dgst := desc.Digest.Algorithm().FromBytes(p); dgst != desc.Digest {\n\t\treturn nil, fmt.Errorf(\"digest mismatch: %s != %s\", dgst, desc.Digest)\n\t}\n\n\tvar manifest ocispec.Manifest\n\tif err := json.Unmarshal(p, &manifest); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar descs []ocispec.Descriptor\n\n\tdescs = append(descs, manifest.Config)\n\tdescs = append(descs, manifest.Layers...)\n\n\treturn descs, nil\n}\n\ntype testContent struct {\n\tmediaType string\n\tcontent   []byte\n}\n\nfunc newContent(mediaType string, b []byte) testContent {\n\treturn testContent{\n\t\tmediaType: mediaType,\n\t\tcontent:   b,\n\t}\n}\n\nfunc (tc testContent) Descriptor() ocispec.Descriptor {\n\treturn ocispec.Descriptor{\n\t\tMediaType: tc.mediaType,\n\t\tDigest:    digest.FromBytes(tc.content),\n\t\tSize:      int64(len(tc.content)),\n\t}\n}\n\nfunc (tc testContent) Digest() digest.Digest {\n\treturn digest.FromBytes(tc.content)\n}\n\nfunc (tc testContent) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tw.Header().Add(\"Content-Type\", tc.mediaType)\n\tw.Header().Add(\"Content-Length\", strconv.Itoa(len(tc.content)))\n\tw.Header().Add(\"Docker-Content-Digest\", tc.Digest().String())\n\tw.WriteHeader(http.StatusOK)\n\tw.Write(tc.content)\n}\n\ntype testManifest struct {\n\tconfig     testContent\n\treferences []testContent\n}\n\nfunc newManifest(config testContent, refs ...testContent) testManifest {\n\treturn testManifest{\n\t\tconfig:     config,\n\t\treferences: refs,\n\t}\n}\n\nfunc (m testManifest) OCIManifest() []byte {\n\tmanifest := ocispec.Manifest{\n\t\tVersioned: specs.Versioned{\n\t\t\tSchemaVersion: 1,\n\t\t},\n\t\tConfig: m.config.Descriptor(),\n\t\tLayers: make([]ocispec.Descriptor, len(m.references)),\n\t}\n\tfor i, c := range m.references {\n\t\tmanifest.Layers[i] = c.Descriptor()\n\t}\n\tb, _ := json.Marshal(manifest)\n\treturn b\n}\n\nfunc (m testManifest) RegisterHandler(r *http.ServeMux, name string) {\n\tfor _, c := range append(m.references, m.config) {\n\t\tr.Handle(fmt.Sprintf(\"/v2/%s/blobs/%s\", name, c.Digest()), c)\n\t}\n}\n\nfunc newRefreshTokenServer(t testing.TB, name string, disablePOST bool, onFetchRefreshToken OnFetchRefreshToken) *refreshTokenServer {\n\treturn &refreshTokenServer{\n\t\tT:                   t,\n\t\tName:                name,\n\t\tDisablePOST:         disablePOST,\n\t\tOnFetchRefreshToken: onFetchRefreshToken,\n\t\tAccessToken:         \"testAccessToken-\" + name,\n\t\tRefreshToken:        \"testRefreshToken-\" + name,\n\t\tUsername:            \"testUser-\" + name,\n\t\tPassword:            \"testPassword-\" + name,\n\t}\n}\n\ntype refreshTokenServer struct {\n\tT                   testing.TB\n\tName                string\n\tDisablePOST         bool\n\tOnFetchRefreshToken OnFetchRefreshToken\n\tAccessToken         string\n\tRefreshToken        string\n\tUsername            string\n\tPassword            string\n}\n\nfunc (srv *refreshTokenServer) isValidAuthorizationHeader(s string) bool {\n\tfields := strings.Fields(s)\n\treturn len(fields) == 2 && strings.ToLower(fields[0]) == \"bearer\" && (fields[1] == srv.RefreshToken || fields[1] == srv.AccessToken)\n}\n\nfunc (srv *refreshTokenServer) BasicTestFunc() func(h http.Handler) (string, ResolverOptions, func()) {\n\tt := srv.T\n\treturn func(h http.Handler) (string, ResolverOptions, func()) {\n\t\twrapped := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {\n\t\t\tif r.URL.Path != \"/token\" {\n\t\t\t\tif !srv.isValidAuthorizationHeader(r.Header.Get(\"Authorization\")) {\n\t\t\t\t\trealm := fmt.Sprintf(\"https://%s/token\", r.Host)\n\t\t\t\t\twwwAuthenticateHeader := fmt.Sprintf(\"Bearer realm=%q,service=registry,scope=\\\"repository:%s:pull\\\"\", realm, srv.Name)\n\t\t\t\t\trw.Header().Set(\"WWW-Authenticate\", wwwAuthenticateHeader)\n\t\t\t\t\trw.WriteHeader(http.StatusUnauthorized)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\th.ServeHTTP(rw, r)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tswitch r.Method {\n\t\t\tcase http.MethodGet: // https://docs.docker.com/registry/spec/auth/token/#requesting-a-token\n\t\t\t\tu, p, ok := r.BasicAuth()\n\t\t\t\tif !ok || u != srv.Username || p != srv.Password {\n\t\t\t\t\trw.WriteHeader(http.StatusForbidden)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tvar resp auth.FetchTokenResponse\n\t\t\t\tresp.Token = srv.AccessToken\n\t\t\t\tresp.AccessToken = srv.AccessToken // alias of Token\n\t\t\t\tquery := r.URL.Query()\n\t\t\t\tswitch query.Get(\"offline_token\") {\n\t\t\t\tcase \"true\":\n\t\t\t\t\tresp.RefreshToken = srv.RefreshToken\n\t\t\t\tcase \"false\", \"\":\n\t\t\t\tdefault:\n\t\t\t\t\trw.WriteHeader(http.StatusBadRequest)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tb, err := json.Marshal(resp)\n\t\t\t\tif err != nil {\n\t\t\t\t\trw.WriteHeader(http.StatusInternalServerError)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\trw.WriteHeader(http.StatusOK)\n\t\t\t\trw.Header().Set(\"Content-Type\", \"application/json\")\n\t\t\t\tt.Logf(\"GET mode: returning JSON %q, for query %+v\", string(b), query)\n\t\t\t\trw.Write(b)\n\t\t\tcase http.MethodPost: // https://docs.docker.com/registry/spec/auth/oauth/#getting-a-token\n\t\t\t\tif srv.DisablePOST {\n\t\t\t\t\trw.WriteHeader(http.StatusMethodNotAllowed)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tr.ParseForm()\n\t\t\t\tpf := r.PostForm\n\t\t\t\tif pf.Get(\"grant_type\") != \"password\" {\n\t\t\t\t\trw.WriteHeader(http.StatusBadRequest)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif pf.Get(\"username\") != srv.Username || pf.Get(\"password\") != srv.Password {\n\t\t\t\t\trw.WriteHeader(http.StatusForbidden)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tvar resp auth.OAuthTokenResponse\n\t\t\t\tresp.AccessToken = srv.AccessToken\n\t\t\t\tswitch pf.Get(\"access_type\") {\n\t\t\t\tcase \"offline\":\n\t\t\t\t\tresp.RefreshToken = srv.RefreshToken\n\t\t\t\tcase \"online\", \"\":\n\t\t\t\tdefault:\n\t\t\t\t\trw.WriteHeader(http.StatusBadRequest)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tb, err := json.Marshal(resp)\n\t\t\t\tif err != nil {\n\t\t\t\t\trw.WriteHeader(http.StatusInternalServerError)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\trw.WriteHeader(http.StatusOK)\n\t\t\t\trw.Header().Set(\"Content-Type\", \"application/json\")\n\t\t\t\tt.Logf(\"POST mode: returning JSON %q, for form %+v\", string(b), pf)\n\t\t\t\trw.Write(b)\n\t\t\tdefault:\n\t\t\t\trw.WriteHeader(http.StatusMethodNotAllowed)\n\t\t\t\treturn\n\t\t\t}\n\t\t})\n\n\t\tbase, options, close := tlsServer(wrapped)\n\t\tauthorizer := NewDockerAuthorizer(\n\t\t\tWithAuthClient(options.Client),\n\t\t\tWithAuthCreds(func(string) (string, string, error) {\n\t\t\t\treturn srv.Username, srv.Password, nil\n\t\t\t}),\n\t\t\tWithFetchRefreshToken(srv.OnFetchRefreshToken),\n\t\t)\n\t\toptions.Hosts = ConfigureDefaultRegistries(\n\t\t\tWithClient(options.Client),\n\t\t\tWithAuthorizer(authorizer),\n\t\t)\n\t\treturn base, options, close\n\t}\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/schema1/converter.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\n// Package schema1 provides a converter to fetch an image formatted in Docker Image Manifest v2, Schema 1.\n//\n// Deprecated: use images formatted in Docker Image Manifest v2, Schema 2, or OCI Image Spec v1.\npackage schema1\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/containerd/v2/pkg/archive/compression\"\n\t\"github.com/containerd/containerd/v2/pkg/labels\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes\"\n\tdigest \"github.com/opencontainers/go-digest\"\n\tspecs \"github.com/opencontainers/image-spec/specs-go\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"golang.org/x/sync/errgroup\"\n)\n\nconst (\n\tmanifestSizeLimit            = 8e6 // 8MB\n\tlabelDockerSchema1EmptyLayer = \"containerd.io/docker.schema1.empty-layer\"\n)\n\ntype blobState struct {\n\tdiffID digest.Digest\n\tempty  bool\n}\n\n// Converter converts schema1 manifests to schema2 on fetch\ntype Converter struct {\n\tcontentStore content.Store\n\tfetcher      remotes.Fetcher\n\n\tpulledManifest *manifest\n\n\tmu         sync.Mutex\n\tblobMap    map[digest.Digest]blobState\n\tlayerBlobs map[digest.Digest]ocispec.Descriptor\n}\n\n// NewConverter returns a new converter\nfunc NewConverter(contentStore content.Store, fetcher remotes.Fetcher) *Converter {\n\treturn &Converter{\n\t\tcontentStore: contentStore,\n\t\tfetcher:      fetcher,\n\t\tblobMap:      map[digest.Digest]blobState{},\n\t\tlayerBlobs:   map[digest.Digest]ocispec.Descriptor{},\n\t}\n}\n\n// Handle fetching descriptors for a docker media type\nfunc (c *Converter) Handle(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {\n\tswitch desc.MediaType {\n\tcase images.MediaTypeDockerSchema1Manifest:\n\t\tif err := c.fetchManifest(ctx, desc); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tm := c.pulledManifest\n\t\tif len(m.FSLayers) != len(m.History) {\n\t\t\treturn nil, errors.New(\"invalid schema 1 manifest, history and layer mismatch\")\n\t\t}\n\t\tdescs := make([]ocispec.Descriptor, 0, len(c.pulledManifest.FSLayers))\n\n\t\tfor i := range m.FSLayers {\n\t\t\tif _, ok := c.blobMap[c.pulledManifest.FSLayers[i].BlobSum]; !ok {\n\t\t\t\tempty, err := isEmptyLayer([]byte(m.History[i].V1Compatibility))\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\n\t\t\t\t// Do no attempt to download a known empty blob\n\t\t\t\tif !empty {\n\t\t\t\t\tdescs = append([]ocispec.Descriptor{\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tMediaType: images.MediaTypeDockerSchema2LayerGzip,\n\t\t\t\t\t\t\tDigest:    c.pulledManifest.FSLayers[i].BlobSum,\n\t\t\t\t\t\t\tSize:      -1,\n\t\t\t\t\t\t},\n\t\t\t\t\t}, descs...)\n\t\t\t\t}\n\t\t\t\tc.blobMap[c.pulledManifest.FSLayers[i].BlobSum] = blobState{\n\t\t\t\t\tempty: empty,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn descs, nil\n\tcase images.MediaTypeDockerSchema2LayerGzip:\n\t\tif c.pulledManifest == nil {\n\t\t\treturn nil, errors.New(\"manifest required for schema 1 blob pull\")\n\t\t}\n\t\treturn nil, c.fetchBlob(ctx, desc)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"%v not support for schema 1 manifests\", desc.MediaType)\n\t}\n}\n\n// ConvertOptions provides options on converting a docker schema1 manifest.\ntype ConvertOptions struct {\n\t// ManifestMediaType specifies the media type of the manifest OCI descriptor.\n\tManifestMediaType string\n\n\t// ConfigMediaType specifies the media type of the manifest config OCI\n\t// descriptor.\n\tConfigMediaType string\n}\n\n// ConvertOpt allows configuring a convert operation.\ntype ConvertOpt func(context.Context, *ConvertOptions) error\n\n// UseDockerSchema2 is used to indicate that a schema1 manifest should be\n// converted into the media types for a docker schema2 manifest.\nfunc UseDockerSchema2() ConvertOpt {\n\treturn func(ctx context.Context, o *ConvertOptions) error {\n\t\to.ManifestMediaType = images.MediaTypeDockerSchema2Manifest\n\t\to.ConfigMediaType = images.MediaTypeDockerSchema2Config\n\t\treturn nil\n\t}\n}\n\n// Convert a docker manifest to an OCI descriptor\nfunc (c *Converter) Convert(ctx context.Context, opts ...ConvertOpt) (ocispec.Descriptor, error) {\n\tco := ConvertOptions{\n\t\tManifestMediaType: ocispec.MediaTypeImageManifest,\n\t\tConfigMediaType:   ocispec.MediaTypeImageConfig,\n\t}\n\tfor _, opt := range opts {\n\t\tif err := opt(ctx, &co); err != nil {\n\t\t\treturn ocispec.Descriptor{}, err\n\t\t}\n\t}\n\n\thistory, diffIDs, err := c.schema1ManifestHistory()\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"schema 1 conversion failed: %w\", err)\n\t}\n\n\tvar img ocispec.Image\n\tif err := json.Unmarshal([]byte(c.pulledManifest.History[0].V1Compatibility), &img); err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to unmarshal image from schema 1 history: %w\", err)\n\t}\n\n\timg.History = history\n\timg.RootFS = ocispec.RootFS{\n\t\tType:    \"layers\",\n\t\tDiffIDs: diffIDs,\n\t}\n\n\tb, err := json.MarshalIndent(img, \"\", \"   \")\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to marshal image: %w\", err)\n\t}\n\n\tconfig := ocispec.Descriptor{\n\t\tMediaType: co.ConfigMediaType,\n\t\tDigest:    digest.Canonical.FromBytes(b),\n\t\tSize:      int64(len(b)),\n\t}\n\n\tlayers := make([]ocispec.Descriptor, len(diffIDs))\n\tfor i, diffID := range diffIDs {\n\t\tlayers[i] = c.layerBlobs[diffID]\n\t}\n\n\tmanifest := ocispec.Manifest{\n\t\tVersioned: specs.Versioned{\n\t\t\tSchemaVersion: 2,\n\t\t},\n\t\tConfig: config,\n\t\tLayers: layers,\n\t}\n\n\tmb, err := json.MarshalIndent(manifest, \"\", \"   \")\n\tif err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to marshal image: %w\", err)\n\t}\n\n\tdesc := ocispec.Descriptor{\n\t\tMediaType: co.ManifestMediaType,\n\t\tDigest:    digest.Canonical.FromBytes(mb),\n\t\tSize:      int64(len(mb)),\n\t}\n\n\tlabels := map[string]string{}\n\tlabels[\"containerd.io/gc.ref.content.0\"] = manifest.Config.Digest.String()\n\tfor i, ch := range manifest.Layers {\n\t\tlabels[fmt.Sprintf(\"containerd.io/gc.ref.content.%d\", i+1)] = ch.Digest.String()\n\t}\n\n\tref := remotes.MakeRefKey(ctx, desc)\n\tif err := content.WriteBlob(ctx, c.contentStore, ref, bytes.NewReader(mb), desc, content.WithLabels(labels)); err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to write image manifest: %w\", err)\n\t}\n\n\tref = remotes.MakeRefKey(ctx, config)\n\tif err := content.WriteBlob(ctx, c.contentStore, ref, bytes.NewReader(b), config); err != nil {\n\t\treturn ocispec.Descriptor{}, fmt.Errorf(\"failed to write image config: %w\", err)\n\t}\n\n\treturn desc, nil\n}\n\n// ReadStripSignature reads in a schema1 manifest and returns a byte array\n// with the \"signatures\" field stripped\nfunc ReadStripSignature(schema1Blob io.Reader) ([]byte, error) {\n\tb, err := io.ReadAll(io.LimitReader(schema1Blob, manifestSizeLimit)) // limit to 8MB\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn stripSignature(b)\n}\n\nfunc (c *Converter) fetchManifest(ctx context.Context, desc ocispec.Descriptor) error {\n\tlog.G(ctx).Debug(\"fetch schema 1\")\n\n\trc, err := c.fetcher.Fetch(ctx, desc)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tb, err := ReadStripSignature(rc)\n\trc.Close()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar m manifest\n\tif err := json.Unmarshal(b, &m); err != nil {\n\t\treturn err\n\t}\n\tif len(m.Manifests) != 0 || len(m.Layers) != 0 {\n\t\treturn errors.New(\"converter: expected schema1 document but found extra keys\")\n\t}\n\tc.pulledManifest = &m\n\n\treturn nil\n}\n\nfunc (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) error {\n\tlog.G(ctx).Debug(\"fetch blob\")\n\n\tvar (\n\t\tref            = remotes.MakeRefKey(ctx, desc)\n\t\tcalc           = newBlobStateCalculator()\n\t\tcompressMethod = compression.Gzip\n\t)\n\n\t// size may be unknown, set to zero for content ingest\n\tingestDesc := desc\n\tif ingestDesc.Size == -1 {\n\t\tingestDesc.Size = 0\n\t}\n\n\tcw, err := content.OpenWriter(ctx, c.contentStore, content.WithRef(ref), content.WithDescriptor(ingestDesc))\n\tif err != nil {\n\t\tif !errdefs.IsAlreadyExists(err) {\n\t\t\treturn err\n\t\t}\n\n\t\treuse, err := c.reuseLabelBlobState(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif reuse {\n\t\t\treturn nil\n\t\t}\n\n\t\tra, err := c.contentStore.ReaderAt(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer ra.Close()\n\n\t\tr, err := compression.DecompressStream(content.NewReader(ra))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tcompressMethod = r.GetCompression()\n\t\t_, err = io.Copy(calc, r)\n\t\tr.Close()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tdefer cw.Close()\n\n\t\trc, err := c.fetcher.Fetch(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tdefer rc.Close()\n\n\t\teg, _ := errgroup.WithContext(ctx)\n\t\tpr, pw := io.Pipe()\n\n\t\teg.Go(func() error {\n\t\t\tr, err := compression.DecompressStream(pr)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tcompressMethod = r.GetCompression()\n\t\t\t_, err = io.Copy(calc, r)\n\t\t\tr.Close()\n\t\t\tpr.CloseWithError(err)\n\t\t\treturn err\n\t\t})\n\n\t\teg.Go(func() error {\n\t\t\tdefer pw.Close()\n\n\t\t\treturn content.Copy(ctx, cw, io.TeeReader(rc, pw), ingestDesc.Size, ingestDesc.Digest)\n\t\t})\n\n\t\tif err := eg.Wait(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\tif desc.Size == -1 {\n\t\tinfo, err := c.contentStore.Info(ctx, desc.Digest)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to get blob info: %w\", err)\n\t\t}\n\t\tdesc.Size = info.Size\n\t}\n\n\tif compressMethod == compression.Uncompressed {\n\t\tlog.G(ctx).WithField(\"id\", desc.Digest).Debugf(\"changed media type for uncompressed schema1 layer blob\")\n\t\tdesc.MediaType = images.MediaTypeDockerSchema2Layer\n\t}\n\n\tstate := calc.State()\n\n\tcinfo := content.Info{\n\t\tDigest: desc.Digest,\n\t\tLabels: map[string]string{\n\t\t\tlabels.LabelUncompressed:     state.diffID.String(),\n\t\t\tlabelDockerSchema1EmptyLayer: strconv.FormatBool(state.empty),\n\t\t},\n\t}\n\n\tif _, err := c.contentStore.Update(ctx, cinfo, \"labels.\"+labels.LabelUncompressed, fmt.Sprintf(\"labels.%s\", labelDockerSchema1EmptyLayer)); err != nil {\n\t\treturn fmt.Errorf(\"failed to update uncompressed label: %w\", err)\n\t}\n\n\tc.mu.Lock()\n\tc.blobMap[desc.Digest] = state\n\tc.layerBlobs[state.diffID] = desc\n\tc.mu.Unlock()\n\n\treturn nil\n}\n\nfunc (c *Converter) reuseLabelBlobState(ctx context.Context, desc ocispec.Descriptor) (bool, error) {\n\tcinfo, err := c.contentStore.Info(ctx, desc.Digest)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"failed to get blob info: %w\", err)\n\t}\n\tdesc.Size = cinfo.Size\n\n\tdiffID, ok := cinfo.Labels[labels.LabelUncompressed]\n\tif !ok {\n\t\treturn false, nil\n\t}\n\n\temptyVal, ok := cinfo.Labels[labelDockerSchema1EmptyLayer]\n\tif !ok {\n\t\treturn false, nil\n\t}\n\n\tisEmpty, err := strconv.ParseBool(emptyVal)\n\tif err != nil {\n\t\tlog.G(ctx).WithField(\"id\", desc.Digest).Warnf(\"failed to parse bool from label %s: %v\", labelDockerSchema1EmptyLayer, isEmpty)\n\t\treturn false, nil\n\t}\n\n\tbState := blobState{empty: isEmpty}\n\n\tif bState.diffID, err = digest.Parse(diffID); err != nil {\n\t\tlog.G(ctx).WithField(\"id\", desc.Digest).Warnf(\"failed to parse digest from label %s: %v\", labels.LabelUncompressed, diffID)\n\t\treturn false, nil\n\t}\n\n\t// NOTE: there is no need to read header to get compression method\n\t// because there are only two kinds of methods.\n\tif bState.diffID == desc.Digest {\n\t\tdesc.MediaType = images.MediaTypeDockerSchema2Layer\n\t} else {\n\t\tdesc.MediaType = images.MediaTypeDockerSchema2LayerGzip\n\t}\n\n\tc.mu.Lock()\n\tc.blobMap[desc.Digest] = bState\n\tc.layerBlobs[bState.diffID] = desc\n\tc.mu.Unlock()\n\treturn true, nil\n}\n\nfunc (c *Converter) schema1ManifestHistory() ([]ocispec.History, []digest.Digest, error) {\n\tif c.pulledManifest == nil {\n\t\treturn nil, nil, errors.New(\"missing schema 1 manifest for conversion\")\n\t}\n\tm := *c.pulledManifest\n\n\tif len(m.History) == 0 {\n\t\treturn nil, nil, errors.New(\"no history\")\n\t}\n\n\thistory := make([]ocispec.History, len(m.History))\n\tdiffIDs := []digest.Digest{}\n\tfor i := range m.History {\n\t\tvar h v1History\n\t\tif err := json.Unmarshal([]byte(m.History[i].V1Compatibility), &h); err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to unmarshal history: %w\", err)\n\t\t}\n\n\t\tblobSum := m.FSLayers[i].BlobSum\n\n\t\tstate := c.blobMap[blobSum]\n\n\t\thistory[len(history)-i-1] = ocispec.History{\n\t\t\tAuthor:     h.Author,\n\t\t\tComment:    h.Comment,\n\t\t\tCreated:    &h.Created,\n\t\t\tCreatedBy:  strings.Join(h.ContainerConfig.Cmd, \" \"),\n\t\t\tEmptyLayer: state.empty,\n\t\t}\n\n\t\tif !state.empty {\n\t\t\tdiffIDs = append([]digest.Digest{state.diffID}, diffIDs...)\n\n\t\t}\n\t}\n\n\treturn history, diffIDs, nil\n}\n\ntype fsLayer struct {\n\tBlobSum digest.Digest `json:\"blobSum\"`\n}\n\ntype history struct {\n\tV1Compatibility string `json:\"v1Compatibility\"`\n}\n\ntype manifest struct {\n\tFSLayers  []fsLayer       `json:\"fsLayers\"`\n\tHistory   []history       `json:\"history\"`\n\tLayers    json.RawMessage `json:\"layers,omitempty\"`    // OCI manifest\n\tManifests json.RawMessage `json:\"manifests,omitempty\"` // OCI index\n}\n\ntype v1History struct {\n\tAuthor          string    `json:\"author,omitempty\"`\n\tCreated         time.Time `json:\"created\"`\n\tComment         string    `json:\"comment,omitempty\"`\n\tThrowAway       *bool     `json:\"throwaway,omitempty\"`\n\tSize            *int      `json:\"Size,omitempty\"` // used before ThrowAway field\n\tContainerConfig struct {\n\t\tCmd []string `json:\"Cmd,omitempty\"`\n\t} `json:\"container_config,omitempty\"`\n}\n\n// isEmptyLayer returns whether the v1 compatibility history describes an\n// empty layer. A return value of true indicates the layer is empty,\n// however false does not indicate non-empty.\nfunc isEmptyLayer(compatHistory []byte) (bool, error) {\n\tvar h v1History\n\tif err := json.Unmarshal(compatHistory, &h); err != nil {\n\t\treturn false, err\n\t}\n\n\tif h.ThrowAway != nil {\n\t\treturn *h.ThrowAway, nil\n\t}\n\tif h.Size != nil {\n\t\treturn *h.Size == 0, nil\n\t}\n\n\t// If no `Size` or `throwaway` field is given, then\n\t// it cannot be determined whether the layer is empty\n\t// from the history, return false\n\treturn false, nil\n}\n\ntype signature struct {\n\tSignatures []jsParsedSignature `json:\"signatures\"`\n}\n\ntype jsParsedSignature struct {\n\tProtected string `json:\"protected\"`\n}\n\ntype protectedBlock struct {\n\tLength int    `json:\"formatLength\"`\n\tTail   string `json:\"formatTail\"`\n}\n\n// joseBase64UrlDecode decodes the given string using the standard base64 url\n// decoder but first adds the appropriate number of trailing '=' characters in\n// accordance with the jose specification.\n// http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-31#section-2\nfunc joseBase64UrlDecode(s string) ([]byte, error) {\n\tswitch len(s) % 4 {\n\tcase 0:\n\tcase 2:\n\t\ts += \"==\"\n\tcase 3:\n\t\ts += \"=\"\n\tdefault:\n\t\treturn nil, errors.New(\"illegal base64url string\")\n\t}\n\treturn base64.URLEncoding.DecodeString(s)\n}\n\nfunc stripSignature(b []byte) ([]byte, error) {\n\tvar sig signature\n\tif err := json.Unmarshal(b, &sig); err != nil {\n\t\treturn nil, err\n\t}\n\tif len(sig.Signatures) == 0 {\n\t\treturn nil, errors.New(\"no signatures\")\n\t}\n\tpb, err := joseBase64UrlDecode(sig.Signatures[0].Protected)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not decode %s: %w\", sig.Signatures[0].Protected, err)\n\t}\n\n\tvar protected protectedBlock\n\tif err := json.Unmarshal(pb, &protected); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif protected.Length > len(b) {\n\t\treturn nil, errors.New(\"invalid protected length block\")\n\t}\n\n\ttail, err := joseBase64UrlDecode(protected.Tail)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid tail base 64 value: %w\", err)\n\t}\n\n\treturn append(b[:protected.Length], tail...), nil\n}\n\ntype blobStateCalculator struct {\n\tempty    bool\n\tdigester digest.Digester\n}\n\nfunc newBlobStateCalculator() *blobStateCalculator {\n\treturn &blobStateCalculator{\n\t\tempty:    true,\n\t\tdigester: digest.Canonical.Digester(),\n\t}\n}\n\nfunc (c *blobStateCalculator) Write(p []byte) (int, error) {\n\tif c.empty {\n\t\tfor _, b := range p {\n\t\t\tif b != 0x00 {\n\t\t\t\tc.empty = false\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn c.digester.Hash().Write(p)\n}\n\nfunc (c *blobStateCalculator) State() blobState {\n\treturn blobState{\n\t\tempty:  c.empty,\n\t\tdiffID: c.digester.Digest(),\n\t}\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/scope.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/containerd/containerd/v2/pkg/reference\"\n)\n\n// RepositoryScope returns a repository scope string such as \"repository:foo/bar:pull\"\n// for \"host/foo/bar:baz\".\n// When push is true, both pull and push are added to the scope.\nfunc RepositoryScope(refspec reference.Spec, push bool) (string, error) {\n\tu, err := url.Parse(\"dummy://\" + refspec.Locator)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\ts := \"repository:\" + strings.TrimPrefix(u.Path, \"/\") + \":pull\"\n\tif push {\n\t\ts += \",push\"\n\t}\n\treturn s, nil\n}\n\n// tokenScopesKey is used for the key for context.WithValue().\n// value: []string (e.g. {\"registry:foo/bar:pull\"})\ntype tokenScopesKey struct{}\n\n// ContextWithRepositoryScope returns a context with tokenScopesKey{} and the repository scope value.\nfunc ContextWithRepositoryScope(ctx context.Context, refspec reference.Spec, push bool) (context.Context, error) {\n\ts, err := RepositoryScope(refspec, push)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn WithScope(ctx, s), nil\n}\n\n// WithScope appends a custom registry auth scope to the context.\nfunc WithScope(ctx context.Context, scope string) context.Context {\n\tvar scopes []string\n\tif v := ctx.Value(tokenScopesKey{}); v != nil {\n\t\tscopes = v.([]string)\n\t\tscopes = append(scopes, scope)\n\t} else {\n\t\tscopes = []string{scope}\n\t}\n\treturn context.WithValue(ctx, tokenScopesKey{}, scopes)\n}\n\n// ContextWithAppendPullRepositoryScope is used to append repository pull\n// scope into existing scopes indexed by the tokenScopesKey{}.\nfunc ContextWithAppendPullRepositoryScope(ctx context.Context, repo string) context.Context {\n\treturn WithScope(ctx, fmt.Sprintf(\"repository:%s:pull\", repo))\n}\n\n// GetTokenScopes returns deduplicated and sorted scopes from ctx.Value(tokenScopesKey{}) and common scopes.\nfunc GetTokenScopes(ctx context.Context, common []string) []string {\n\tscopes := []string{}\n\tif x := ctx.Value(tokenScopesKey{}); x != nil {\n\t\tscopes = append(scopes, x.([]string)...)\n\t}\n\n\tscopes = append(scopes, common...)\n\tsort.Strings(scopes)\n\n\tif len(scopes) == 0 {\n\t\treturn scopes\n\t}\n\n\tl := 0\n\tfor idx := 1; idx < len(scopes); idx++ {\n\t\t// Note: this comparison is unaware of the scope grammar (https://docs.docker.com/registry/spec/auth/scope/)\n\t\t// So, \"repository:foo/bar:pull,push\" != \"repository:foo/bar:push,pull\", although semantically they are equal.\n\t\tif scopes[l] == scopes[idx] {\n\t\t\tcontinue\n\t\t}\n\n\t\tl++\n\t\tscopes[l] = scopes[idx]\n\t}\n\treturn scopes[:l+1]\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/scope_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/containerd/containerd/v2/pkg/reference\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestRepositoryScope(t *testing.T) {\n\ttestCases := []struct {\n\t\trefspec  reference.Spec\n\t\tpush     bool\n\t\texpected string\n\t}{\n\t\t{\n\t\t\trefspec: reference.Spec{\n\t\t\t\tLocator: \"host/foo/bar\",\n\t\t\t\tObject:  \"ignored\",\n\t\t\t},\n\t\t\tpush:     false,\n\t\t\texpected: \"repository:foo/bar:pull\",\n\t\t},\n\t\t{\n\t\t\trefspec: reference.Spec{\n\t\t\t\tLocator: \"host:4242/foo/bar\",\n\t\t\t\tObject:  \"ignored\",\n\t\t\t},\n\t\t\tpush:     true,\n\t\t\texpected: \"repository:foo/bar:pull,push\",\n\t\t},\n\t}\n\tfor _, x := range testCases {\n\t\tt.Run(x.refspec.String(), func(t *testing.T) {\n\t\t\tactual, err := RepositoryScope(x.refspec, x.push)\n\t\t\tassert.NoError(t, err)\n\t\t\tassert.Equal(t, x.expected, actual)\n\t\t})\n\t}\n}\n\nfunc TestGetTokenScopes(t *testing.T) {\n\ttestCases := []struct {\n\t\tscopesInCtx  []string\n\t\tcommonScopes []string\n\t\texpected     []string\n\t}{\n\t\t{\n\t\t\tscopesInCtx:  []string{},\n\t\t\tcommonScopes: []string{},\n\t\t\texpected:     []string{},\n\t\t},\n\t\t{\n\t\t\tscopesInCtx:  []string{},\n\t\t\tcommonScopes: []string{\"repository:foo/bar:pull\"},\n\t\t\texpected:     []string{\"repository:foo/bar:pull\"},\n\t\t},\n\t\t{\n\t\t\tscopesInCtx:  []string{\"repository:foo/bar:pull,push\"},\n\t\t\tcommonScopes: []string{},\n\t\t\texpected:     []string{\"repository:foo/bar:pull,push\"},\n\t\t},\n\t\t{\n\t\t\tscopesInCtx:  []string{\"repository:foo/bar:pull\"},\n\t\t\tcommonScopes: []string{\"repository:foo/bar:pull\"},\n\t\t\texpected:     []string{\"repository:foo/bar:pull\"},\n\t\t},\n\t\t{\n\t\t\tscopesInCtx:  []string{\"repository:foo/bar:pull\"},\n\t\t\tcommonScopes: []string{\"repository:foo/bar:pull,push\"},\n\t\t\texpected:     []string{\"repository:foo/bar:pull\", \"repository:foo/bar:pull,push\"},\n\t\t},\n\t\t{\n\t\t\tscopesInCtx:  []string{\"repository:foo/bar:pull\"},\n\t\t\tcommonScopes: []string{\"repository:foo/bar:pull,push\", \"repository:foo/bar:pull\"},\n\t\t\texpected:     []string{\"repository:foo/bar:pull\", \"repository:foo/bar:pull,push\"},\n\t\t},\n\t}\n\tfor _, tc := range testCases {\n\t\tctx := context.WithValue(context.TODO(), tokenScopesKey{}, tc.scopesInCtx)\n\t\tactual := GetTokenScopes(ctx, tc.commonScopes)\n\t\tassert.Equal(t, tc.expected, actual)\n\t}\n}\n\nfunc TestCustomScope(t *testing.T) {\n\tscope := \"whatever:foo/bar:pull\"\n\tctx := WithScope(context.Background(), scope)\n\tctx = ContextWithAppendPullRepositoryScope(ctx, \"foo/bar\")\n\n\tscopes := GetTokenScopes(ctx, []string{})\n\tassert.Equal(t, []string{\"repository:foo/bar:pull\", scope}, scopes)\n}\n"
  },
  {
    "path": "pkg/remote/remotes/docker/status.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage docker\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/moby/locker\"\n)\n\n// Status of a content operation\ntype Status struct {\n\tcontent.Status\n\n\tCommitted bool\n\n\t// ErrClosed contains error encountered on close.\n\tErrClosed error\n\n\t// UploadUUID is used by the Docker registry to reference blob uploads\n\tUploadUUID string\n}\n\n// StatusTracker to track status of operations\ntype StatusTracker interface {\n\tGetStatus(string) (Status, error)\n\tSetStatus(string, Status)\n}\n\n// StatusTrackLocker to track status of operations with lock\ntype StatusTrackLocker interface {\n\tStatusTracker\n\tLock(string)\n\tUnlock(string)\n}\n\ntype memoryStatusTracker struct {\n\tstatuses map[string]Status\n\tm        sync.Mutex\n\tlocker   *locker.Locker\n}\n\n// NewInMemoryTracker returns a StatusTracker that tracks content status in-memory\nfunc NewInMemoryTracker() StatusTrackLocker {\n\treturn &memoryStatusTracker{\n\t\tstatuses: map[string]Status{},\n\t\tlocker:   locker.New(),\n\t}\n}\n\nfunc (t *memoryStatusTracker) GetStatus(ref string) (Status, error) {\n\tt.m.Lock()\n\tdefer t.m.Unlock()\n\tstatus, ok := t.statuses[ref]\n\tif !ok {\n\t\treturn Status{}, fmt.Errorf(\"status for ref %v: %w\", ref, errdefs.ErrNotFound)\n\t}\n\treturn status, nil\n}\n\nfunc (t *memoryStatusTracker) SetStatus(ref string, status Status) {\n\tt.m.Lock()\n\tt.statuses[ref] = status\n\tt.m.Unlock()\n}\n\nfunc (t *memoryStatusTracker) Lock(ref string) {\n\tt.locker.Lock(ref)\n}\n\nfunc (t *memoryStatusTracker) Unlock(ref string) {\n\tt.locker.Unlock(ref)\n}\n"
  },
  {
    "path": "pkg/remote/remotes/errors/errors.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage errors\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nvar _ error = ErrUnexpectedStatus{}\n\n// ErrUnexpectedStatus is returned if a registry API request returned with unexpected HTTP status\ntype ErrUnexpectedStatus struct {\n\tStatus                    string\n\tStatusCode                int\n\tBody                      []byte\n\tRequestURL, RequestMethod string\n}\n\nfunc (e ErrUnexpectedStatus) Error() string {\n\treturn fmt.Sprintf(\"unexpected status from %s request to %s: %s\", e.RequestMethod, e.RequestURL, e.Status)\n}\n\n// NewUnexpectedStatusErr creates an ErrUnexpectedStatus from HTTP response\nfunc NewUnexpectedStatusErr(resp *http.Response) error {\n\tvar b []byte\n\tif resp.Body != nil {\n\t\tb, _ = io.ReadAll(io.LimitReader(resp.Body, 64000)) // 64KB\n\t}\n\terr := ErrUnexpectedStatus{\n\t\tBody:          b,\n\t\tStatus:        resp.Status,\n\t\tStatusCode:    resp.StatusCode,\n\t\tRequestMethod: resp.Request.Method,\n\t}\n\tif resp.Request.URL != nil {\n\t\terr.RequestURL = resp.Request.URL.String()\n\t}\n\treturn err\n}\n"
  },
  {
    "path": "pkg/remote/remotes/handlers.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage remotes\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/containerd/v2/pkg/labels\"\n\t\"github.com/containerd/errdefs\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/platforms\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"golang.org/x/sync/semaphore\"\n)\n\ntype refKeyPrefix struct{}\n\n// WithMediaTypeKeyPrefix adds a custom key prefix for a media type which is used when storing\n// data in the content store from the FetchHandler.\n//\n// Used in `MakeRefKey` to determine what the key prefix should be.\nfunc WithMediaTypeKeyPrefix(ctx context.Context, mediaType, prefix string) context.Context {\n\tvar values map[string]string\n\tif v := ctx.Value(refKeyPrefix{}); v != nil {\n\t\tvalues = v.(map[string]string)\n\t} else {\n\t\tvalues = make(map[string]string)\n\t}\n\n\tvalues[mediaType] = prefix\n\treturn context.WithValue(ctx, refKeyPrefix{}, values)\n}\n\n// MakeRefKey returns a unique reference for the descriptor. This reference can be\n// used to lookup ongoing processes related to the descriptor. This function\n// may look to the context to namespace the reference appropriately.\nfunc MakeRefKey(ctx context.Context, desc ocispec.Descriptor) string {\n\tkey := desc.Digest.String()\n\tif desc.Annotations != nil {\n\t\tif name, ok := desc.Annotations[ocispec.AnnotationRefName]; ok {\n\t\t\tkey = fmt.Sprintf(\"%s@%s\", name, desc.Digest.String())\n\t\t}\n\t}\n\n\tif v := ctx.Value(refKeyPrefix{}); v != nil {\n\t\tvalues := v.(map[string]string)\n\t\tif prefix := values[desc.MediaType]; prefix != \"\" {\n\t\t\treturn prefix + \"-\" + key\n\t\t}\n\t}\n\n\tswitch mt := desc.MediaType; {\n\tcase mt == images.MediaTypeDockerSchema2Manifest || mt == ocispec.MediaTypeImageManifest:\n\t\treturn \"manifest-\" + key\n\tcase mt == images.MediaTypeDockerSchema2ManifestList || mt == ocispec.MediaTypeImageIndex:\n\t\treturn \"index-\" + key\n\tcase images.IsLayerType(mt):\n\t\treturn \"layer-\" + key\n\tcase images.IsKnownConfig(mt):\n\t\treturn \"config-\" + key\n\tdefault:\n\t\tlog.G(ctx).Warnf(\"reference for unknown type: %s\", mt)\n\t\treturn \"unknown-\" + key\n\t}\n}\n\n// FetchHandler returns a handler that will fetch all content into the ingester\n// discovered in a call to Dispatch. Use with ChildrenHandler to do a full\n// recursive fetch.\nfunc FetchHandler(ingester content.Ingester, fetcher Fetcher) images.HandlerFunc {\n\treturn func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) {\n\t\tctx = log.WithLogger(ctx, log.G(ctx).WithFields(log.Fields{\n\t\t\t\"digest\":    desc.Digest,\n\t\t\t\"mediatype\": desc.MediaType,\n\t\t\t\"size\":      desc.Size,\n\t\t}))\n\n\t\tswitch desc.MediaType {\n\t\tcase images.MediaTypeDockerSchema1Manifest:\n\t\t\treturn nil, fmt.Errorf(\"%v not supported\", desc.MediaType)\n\t\tdefault:\n\t\t\terr := Fetch(ctx, ingester, fetcher, desc)\n\t\t\tif errdefs.IsAlreadyExists(err) {\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t}\n}\n\n// Fetch fetches the given digest into the provided ingester\nfunc Fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc ocispec.Descriptor) error {\n\tlog.G(ctx).Debug(\"fetch\")\n\n\tcw, err := content.OpenWriter(ctx, ingester, content.WithRef(MakeRefKey(ctx, desc)), content.WithDescriptor(desc))\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cw.Close()\n\n\tws, err := cw.Status()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif desc.Size == 0 {\n\t\t// most likely a poorly configured registry/web front end which responded with no\n\t\t// Content-Length header; unable (not to mention useless) to commit a 0-length entry\n\t\t// into the content store. Error out here otherwise the error sent back is confusing\n\t\treturn fmt.Errorf(\"unable to fetch descriptor (%s) which reports content size of zero: %w\", desc.Digest, errdefs.ErrInvalidArgument)\n\t}\n\tif ws.Offset == desc.Size {\n\t\t// If writer is already complete, commit and return\n\t\terr := cw.Commit(ctx, desc.Size, desc.Digest)\n\t\tif err != nil && !errdefs.IsAlreadyExists(err) {\n\t\t\treturn fmt.Errorf(\"failed commit on ref %q: %w\", ws.Ref, err)\n\t\t}\n\t\treturn err\n\t}\n\n\tif desc.Size == int64(len(desc.Data)) {\n\t\treturn content.Copy(ctx, cw, bytes.NewReader(desc.Data), desc.Size, desc.Digest)\n\t}\n\n\trc, err := fetcher.Fetch(ctx, desc)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer rc.Close()\n\n\treturn content.Copy(ctx, cw, rc, desc.Size, desc.Digest)\n}\n\n// PushHandler returns a handler that will push all content from the provider\n// using a writer from the pusher.\nfunc PushHandler(pusher Pusher, provider content.Provider) images.HandlerFunc {\n\treturn func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {\n\t\tctx = log.WithLogger(ctx, log.G(ctx).WithFields(log.Fields{\n\t\t\t\"digest\":    desc.Digest,\n\t\t\t\"mediatype\": desc.MediaType,\n\t\t\t\"size\":      desc.Size,\n\t\t}))\n\n\t\terr := push(ctx, provider, pusher, desc)\n\t\treturn nil, err\n\t}\n}\n\nfunc push(ctx context.Context, provider content.Provider, pusher Pusher, desc ocispec.Descriptor) error {\n\tlog.G(ctx).Debug(\"push\")\n\n\tvar (\n\t\tcw  content.Writer\n\t\terr error\n\t)\n\tif cs, ok := pusher.(content.Ingester); ok {\n\t\tcw, err = content.OpenWriter(ctx, cs, content.WithRef(MakeRefKey(ctx, desc)), content.WithDescriptor(desc))\n\t} else {\n\t\tcw, err = pusher.Push(ctx, desc)\n\t}\n\tif err != nil {\n\t\tif !errdefs.IsAlreadyExists(err) {\n\t\t\treturn err\n\t\t}\n\n\t\treturn nil\n\t}\n\tdefer cw.Close()\n\n\tra, err := provider.ReaderAt(ctx, desc)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer ra.Close()\n\n\trd := io.NewSectionReader(ra, 0, desc.Size)\n\treturn content.Copy(ctx, cw, rd, desc.Size, desc.Digest)\n}\n\n// PushContent pushes content specified by the descriptor from the provider.\n//\n// Base handlers can be provided which will be called before any push specific\n// handlers.\n//\n// If the passed in content.Provider is also a content.Manager then this will\n// also annotate the distribution sources in the manager.\nfunc PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, store content.Provider, limiter *semaphore.Weighted, platform platforms.MatchComparer, wrapper func(h images.Handler) images.Handler) error {\n\n\tvar m sync.Mutex\n\tmanifests := []ocispec.Descriptor{}\n\tindexStack := []ocispec.Descriptor{}\n\n\tfilterHandler := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {\n\t\tswitch desc.MediaType {\n\t\tcase images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:\n\t\t\tm.Lock()\n\t\t\tmanifests = append(manifests, desc)\n\t\t\tm.Unlock()\n\t\t\treturn nil, images.ErrStopHandler\n\t\tcase images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:\n\t\t\tm.Lock()\n\t\t\tindexStack = append(indexStack, desc)\n\t\t\tm.Unlock()\n\t\t\treturn nil, images.ErrStopHandler\n\t\tdefault:\n\t\t\treturn nil, nil\n\t\t}\n\t})\n\n\tpushHandler := PushHandler(pusher, store)\n\n\tplatformFilterhandler := images.FilterPlatforms(images.ChildrenHandler(store), platform)\n\n\tvar handler images.Handler\n\tif m, ok := store.(content.Manager); ok {\n\t\tannotateHandler := annotateDistributionSourceHandler(platformFilterhandler, m)\n\t\thandler = images.Handlers(annotateHandler, filterHandler, pushHandler)\n\t} else {\n\t\thandler = images.Handlers(platformFilterhandler, filterHandler, pushHandler)\n\t}\n\n\tif wrapper != nil {\n\t\thandler = wrapper(handler)\n\t}\n\n\tif err := images.Dispatch(ctx, handler, limiter, desc); err != nil {\n\t\treturn err\n\t}\n\n\tif err := images.Dispatch(ctx, pushHandler, limiter, manifests...); err != nil {\n\t\treturn err\n\t}\n\n\t// Iterate in reverse order as seen, parent always uploaded after child\n\tfor i := len(indexStack) - 1; i >= 0; i-- {\n\t\terr := images.Dispatch(ctx, pushHandler, limiter, indexStack[i])\n\t\tif err != nil {\n\t\t\t// TODO(estesp): until we have a more complete method for index push, we need to report\n\t\t\t// missing dependencies in an index/manifest list by sensing the \"400 Bad Request\"\n\t\t\t// as a marker for this problem\n\t\t\tif errors.Unwrap(err) != nil && strings.Contains(errors.Unwrap(err).Error(), \"400 Bad Request\") {\n\t\t\t\treturn fmt.Errorf(\"manifest list/index references to blobs and/or manifests are missing in your target registry: %w\", err)\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// SkipNonDistributableBlobs returns a handler that skips blobs that have a media type that is \"non-distributeable\".\n// An example of this kind of content would be a Windows base layer, which is not supposed to be redistributed.\n//\n// This is based on the media type of the content:\n//   - application/vnd.oci.image.layer.nondistributable\n//   - application/vnd.docker.image.rootfs.foreign\nfunc SkipNonDistributableBlobs(f images.HandlerFunc) images.HandlerFunc {\n\treturn func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {\n\t\tif images.IsNonDistributable(desc.MediaType) {\n\t\t\tlog.G(ctx).WithField(\"digest\", desc.Digest).WithField(\"mediatype\", desc.MediaType).Debug(\"Skipping non-distributable blob\")\n\t\t\treturn nil, images.ErrSkipDesc\n\t\t}\n\n\t\tif images.IsLayerType(desc.MediaType) {\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tchildren, err := f(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif len(children) == 0 {\n\t\t\treturn nil, nil\n\t\t}\n\n\t\tout := make([]ocispec.Descriptor, 0, len(children))\n\t\tfor _, child := range children {\n\t\t\tif !images.IsNonDistributable(child.MediaType) {\n\t\t\t\tout = append(out, child)\n\t\t\t} else {\n\t\t\t\tlog.G(ctx).WithField(\"digest\", child.Digest).WithField(\"mediatype\", child.MediaType).Debug(\"Skipping non-distributable blob\")\n\t\t\t}\n\t\t}\n\t\treturn out, nil\n\t}\n}\n\n// FilterManifestByPlatformHandler allows Handler to handle non-target\n// platform's manifest and configuration data.\nfunc FilterManifestByPlatformHandler(f images.HandlerFunc, m platforms.Matcher) images.HandlerFunc {\n\treturn func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {\n\t\tchildren, err := f(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// no platform information\n\t\tif desc.Platform == nil || m == nil {\n\t\t\treturn children, nil\n\t\t}\n\n\t\tvar descs []ocispec.Descriptor\n\t\tswitch desc.MediaType {\n\t\tcase images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest:\n\t\t\tif m.Match(*desc.Platform) {\n\t\t\t\tdescs = children\n\t\t\t} else {\n\t\t\t\tfor _, child := range children {\n\t\t\t\t\tif child.MediaType == images.MediaTypeDockerSchema2Config ||\n\t\t\t\t\t\tchild.MediaType == ocispec.MediaTypeImageConfig {\n\n\t\t\t\t\t\tdescs = append(descs, child)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tdefault:\n\t\t\tdescs = children\n\t\t}\n\t\treturn descs, nil\n\t}\n}\n\n// annotateDistributionSourceHandler add distribution source label into\n// annotation of config or blob descriptor.\nfunc annotateDistributionSourceHandler(f images.HandlerFunc, manager content.Manager) images.HandlerFunc {\n\treturn func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {\n\t\tchildren, err := f(ctx, desc)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// only add distribution source for the config or blob data descriptor\n\t\tswitch desc.MediaType {\n\t\tcase images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest,\n\t\t\timages.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:\n\t\tdefault:\n\t\t\treturn children, nil\n\t\t}\n\n\t\tfor i := range children {\n\t\t\tchild := children[i]\n\n\t\t\tinfo, err := manager.Info(ctx, child.Digest)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\tfor k, v := range info.Labels {\n\t\t\t\tif !strings.HasPrefix(k, labels.LabelDistributionSource+\".\") {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tif child.Annotations == nil {\n\t\t\t\t\tchild.Annotations = map[string]string{}\n\t\t\t\t}\n\t\t\t\tchild.Annotations[k] = v\n\t\t\t}\n\n\t\t\tchildren[i] = child\n\t\t}\n\t\treturn children, nil\n\t}\n}\n"
  },
  {
    "path": "pkg/remote/remotes/handlers_test.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage remotes\n\nimport (\n\t\"context\"\n\t_ \"crypto/sha256\"\n\t\"encoding/json\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/core/images\"\n\t\"github.com/containerd/containerd/v2/plugins/content/local\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\nfunc TestContextCustomKeyPrefix(t *testing.T) {\n\tctx := context.Background()\n\tcmt := \"testing/custom.media.type\"\n\tctx = WithMediaTypeKeyPrefix(ctx, images.MediaTypeDockerSchema2Layer, \"bananas\")\n\tctx = WithMediaTypeKeyPrefix(ctx, cmt, \"apples\")\n\n\t// makes sure that even though we've supplied some custom handling, the built-in still works\n\tt.Run(\"normal supported case\", func(t *testing.T) {\n\t\tdesc := ocispec.Descriptor{MediaType: ocispec.MediaTypeImageLayer}\n\t\texpected := \"layer-\"\n\n\t\tactual := MakeRefKey(ctx, desc)\n\t\tif actual != expected {\n\t\t\tt.Fatalf(\"unexpected ref key, expected %s, got: %s\", expected, actual)\n\t\t}\n\t})\n\n\tt.Run(\"unknown media type\", func(t *testing.T) {\n\t\tdesc := ocispec.Descriptor{MediaType: \"we.dont.know.what.this.is\"}\n\t\texpected := \"unknown-\"\n\n\t\tactual := MakeRefKey(ctx, desc)\n\t\tif actual != expected {\n\t\t\tt.Fatalf(\"unexpected ref key, expected %s, got: %s\", expected, actual)\n\t\t}\n\t})\n\n\tt.Run(\"overwrite supported media type\", func(t *testing.T) {\n\t\tdesc := ocispec.Descriptor{MediaType: images.MediaTypeDockerSchema2Layer}\n\t\texpected := \"bananas-\"\n\n\t\tactual := MakeRefKey(ctx, desc)\n\t\tif actual != expected {\n\t\t\tt.Fatalf(\"unexpected ref key, expected %s, got: %s\", expected, actual)\n\t\t}\n\t})\n\n\tt.Run(\"custom media type\", func(t *testing.T) {\n\t\tdesc := ocispec.Descriptor{MediaType: cmt}\n\t\texpected := \"apples-\"\n\n\t\tactual := MakeRefKey(ctx, desc)\n\t\tif actual != expected {\n\t\t\tt.Fatalf(\"unexpected ref key, expected %s, got: %s\", expected, actual)\n\t\t}\n\t})\n}\n\nfunc TestSkipNonDistributableBlobs(t *testing.T) {\n\tctx := context.Background()\n\n\tout, err := SkipNonDistributableBlobs(images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {\n\t\treturn []ocispec.Descriptor{\n\t\t\t{MediaType: images.MediaTypeDockerSchema2Layer, Digest: \"test:1\"},\n\t\t\t{MediaType: images.MediaTypeDockerSchema2LayerForeign, Digest: \"test:2\"},\n\t\t\t{MediaType: images.MediaTypeDockerSchema2LayerForeignGzip, Digest: \"test:3\"},\n\t\t\t{MediaType: ocispec.MediaTypeImageLayerNonDistributable, Digest: \"test:4\"},\n\t\t\t{MediaType: ocispec.MediaTypeImageLayerNonDistributableGzip, Digest: \"test:5\"},\n\t\t\t{MediaType: ocispec.MediaTypeImageLayerNonDistributableZstd, Digest: \"test:6\"},\n\t\t}, nil\n\t}))(ctx, ocispec.Descriptor{MediaType: images.MediaTypeDockerSchema2Manifest})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(out) != 1 {\n\t\tt.Fatalf(\"unexpected number of descriptors returned: %d\", len(out))\n\t}\n\tif out[0].Digest != \"test:1\" {\n\t\tt.Fatalf(\"unexpected digest returned: %s\", out[0].Digest)\n\t}\n\n\tdir := t.TempDir()\n\tcs, err := local.NewLabeledStore(dir, newMemoryLabelStore())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\twrite := func(i interface{}, ref string) digest.Digest {\n\t\tt.Helper()\n\n\t\tdata, err := json.Marshal(i)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tw, err := cs.Writer(ctx, content.WithRef(ref))\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tdefer w.Close()\n\n\t\tdgst := digest.SHA256.FromBytes(data)\n\n\t\tn, err := w.Write(data)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tif err := w.Commit(ctx, int64(n), dgst); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\treturn dgst\n\t}\n\n\tconfigDigest := write(ocispec.ImageConfig{}, \"config\")\n\n\tmanifest := ocispec.Manifest{\n\t\tConfig:    ocispec.Descriptor{Digest: configDigest, MediaType: ocispec.MediaTypeImageConfig},\n\t\tMediaType: ocispec.MediaTypeImageManifest,\n\t\tLayers: []ocispec.Descriptor{\n\t\t\t{MediaType: images.MediaTypeDockerSchema2Layer, Digest: \"test:1\"},\n\t\t\t{MediaType: images.MediaTypeDockerSchema2LayerForeign, Digest: \"test:2\"},\n\t\t\t{MediaType: images.MediaTypeDockerSchema2LayerForeignGzip, Digest: \"test:3\"},\n\t\t\t{MediaType: ocispec.MediaTypeImageLayerNonDistributable, Digest: \"test:4\"},\n\t\t\t{MediaType: ocispec.MediaTypeImageLayerNonDistributableGzip, Digest: \"test:5\"},\n\t\t\t{MediaType: ocispec.MediaTypeImageLayerNonDistributableZstd, Digest: \"test:6\"},\n\t\t},\n\t}\n\n\tmanifestDigest := write(manifest, \"manifest\")\n\n\tout, err = SkipNonDistributableBlobs(images.ChildrenHandler(cs))(ctx, ocispec.Descriptor{MediaType: manifest.MediaType, Digest: manifestDigest})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(out) != 2 {\n\t\tt.Fatalf(\"unexpected number of descriptors returned: %v\", out)\n\t}\n\n\tif out[0].Digest != configDigest {\n\t\tt.Fatalf(\"unexpected digest returned: %v\", out[0])\n\t}\n\tif out[1].Digest != manifest.Layers[0].Digest {\n\t\tt.Fatalf(\"unexpected digest returned: %v\", out[1])\n\t}\n}\n\ntype memoryLabelStore struct {\n\tl      sync.Mutex\n\tlabels map[digest.Digest]map[string]string\n}\n\nfunc newMemoryLabelStore() local.LabelStore {\n\treturn &memoryLabelStore{\n\t\tlabels: map[digest.Digest]map[string]string{},\n\t}\n}\n\nfunc (mls *memoryLabelStore) Get(d digest.Digest) (map[string]string, error) {\n\tmls.l.Lock()\n\tlabels := mls.labels[d]\n\tmls.l.Unlock()\n\n\treturn labels, nil\n}\n\nfunc (mls *memoryLabelStore) Set(d digest.Digest, labels map[string]string) error {\n\tmls.l.Lock()\n\tmls.labels[d] = labels\n\tmls.l.Unlock()\n\n\treturn nil\n}\n\nfunc (mls *memoryLabelStore) Update(d digest.Digest, update map[string]string) (map[string]string, error) {\n\tmls.l.Lock()\n\tlabels, ok := mls.labels[d]\n\tif !ok {\n\t\tlabels = map[string]string{}\n\t}\n\tfor k, v := range update {\n\t\tif v == \"\" {\n\t\t\tdelete(labels, k)\n\t\t} else {\n\t\t\tlabels[k] = v\n\t\t}\n\t}\n\tmls.labels[d] = labels\n\tmls.l.Unlock()\n\n\treturn labels, nil\n}\n"
  },
  {
    "path": "pkg/remote/remotes/resolver.go",
    "content": "/*\n   Copyright The containerd Authors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\n\npackage remotes\n\nimport (\n\t\"context\"\n\t\"io\"\n\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\n// Resolver provides remotes based on a locator.\ntype Resolver interface {\n\t// Resolve attempts to resolve the reference into a name and descriptor.\n\t//\n\t// The argument `ref` should be a scheme-less URI representing the remote.\n\t// Structurally, it has a host and path. The \"host\" can be used to directly\n\t// reference a specific host or be matched against a specific handler.\n\t//\n\t// The returned name should be used to identify the referenced entity.\n\t// Depending on the remote namespace, this may be immutable or mutable.\n\t// While the name may differ from ref, it should itself be a valid ref.\n\t//\n\t// If the resolution fails, an error will be returned.\n\tResolve(ctx context.Context, ref string) (name string, desc ocispec.Descriptor, err error)\n\n\t// Fetcher returns a new fetcher for the provided reference.\n\t// All content fetched from the returned fetcher will be\n\t// from the namespace referred to by ref.\n\tFetcher(ctx context.Context, ref string) (Fetcher, error)\n\n\t// Pusher returns a new pusher for the provided reference\n\t// The returned Pusher should satisfy content.Ingester and concurrent attempts\n\t// to push the same blob using the Ingester API should result in ErrUnavailable.\n\tPusher(ctx context.Context, ref string) (Pusher, error)\n}\n\n// Fetcher fetches content.\n// A fetcher implementation may implement the FetcherByDigest interface too.\ntype Fetcher interface {\n\t// Fetch the resource identified by the descriptor.\n\tFetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error)\n}\n\n// FetcherByDigest fetches content by the digest.\ntype FetcherByDigest interface {\n\t// FetchByDigest fetches the resource identified by the digest.\n\t//\n\t// FetcherByDigest usually returns an incomplete descriptor.\n\t// Typically, the media type is always set to \"application/octet-stream\",\n\t// and the annotations are unset.\n\tFetchByDigest(ctx context.Context, dgst digest.Digest) (io.ReadCloser, ocispec.Descriptor, error)\n}\n\ntype ReferrersFetcher interface {\n\tFetchReferrers(ctx context.Context, dgst digest.Digest, artifactTypes ...string) (io.ReadCloser, ocispec.Descriptor, error)\n}\n\n// Pusher pushes content\ntype Pusher interface {\n\t// Push returns a content writer for the given resource identified\n\t// by the descriptor.\n\tPush(ctx context.Context, d ocispec.Descriptor) (content.Writer, error)\n}\n\n// FetcherFunc allows package users to implement a Fetcher with just a\n// function.\ntype FetcherFunc func(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error)\n\n// Fetch content\nfunc (fn FetcherFunc) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.ReadCloser, error) {\n\treturn fn(ctx, desc)\n}\n\n// PusherFunc allows package users to implement a Pusher with just a\n// function.\ntype PusherFunc func(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error)\n\n// Push content\nfunc (fn PusherFunc) Push(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error) {\n\treturn fn(ctx, desc)\n}\n"
  },
  {
    "path": "pkg/remote/unpack.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage remote\n\nimport (\n\t\"archive/tar\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/containerd/containerd/v2/pkg/archive/compression\"\n)\n\n// Unpack unpacks the file named `source` in tar stream\n// and write into `target` path.\nfunc Unpack(reader io.Reader, source, target string) error {\n\trdr, err := compression.DecompressStream(reader)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer rdr.Close()\n\n\tfound := false\n\ttr := tar.NewReader(rdr)\n\tfor {\n\t\thdr, err := tr.Next()\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t\tif hdr.Name == source {\n\t\t\tfile, err := os.Create(target)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tdefer file.Close()\n\t\t\tif _, err := io.Copy(file, tr); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfound = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif !found {\n\t\treturn fmt.Errorf(\"not found file %s in tar\", source)\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/resolve/resolver.go",
    "content": "/*\n * Copyright (c) 2021. Alibaba Cloud. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage resolve\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/transport\"\n\tdistribution \"github.com/distribution/reference\"\n\t\"github.com/google/go-containerregistry/pkg/name\"\n\tretryablehttp \"github.com/hashicorp/go-retryablehttp\"\n\t\"github.com/pkg/errors\"\n)\n\ntype Resolver struct {\n\tres transport.Resolve\n}\n\nfunc NewResolver() *Resolver {\n\tresolver := Resolver{\n\t\tres: transport.NewPool(),\n\t}\n\treturn &resolver\n}\n\nfunc (r *Resolver) Resolve(ref, digest string, labels map[string]string) (io.ReadCloser, error) {\n\tnamed, err := distribution.ParseDockerRef(ref)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed parse docker ref %s\", ref)\n\t}\n\thost := distribution.Domain(named)\n\tsref := fmt.Sprintf(\"%s/%s\", host, distribution.Path(named))\n\tnref, err := name.ParseReference(sref)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to parse ref %q (%q)\", sref, digest)\n\t}\n\tkeychain := auth.GetRegistryKeyChain(ref, labels)\n\n\tvar tr http.RoundTripper\n\turl, tr, err := r.res.Resolve(nref, digest, keychain)\n\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to create authn transport %v\", keychain)\n\t}\n\n\treq, err := retryablehttp.NewRequest(\"GET\", url, nil)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to new http get %s\", url)\n\t}\n\n\tclient := newRetryHTTPClient(tr)\n\tres, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to http get %s\", url)\n\t}\n\n\tif res.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to GET request with code %d\", res.StatusCode)\n\t}\n\treturn res.Body, nil\n}\n\nfunc newRetryHTTPClient(tr http.RoundTripper) *retryablehttp.Client {\n\tretryClient := retryablehttp.NewClient()\n\tretryClient.HTTPClient.Transport = tr\n\tretryClient.Logger = nil\n\treturn retryClient\n}\n"
  },
  {
    "path": "pkg/signature/signature.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage signature\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/signer\"\n)\n\ntype Verifier struct {\n\tsigner *signer.Signer\n\tforce  bool\n}\n\nfunc NewVerifier(publicKeyFile string, validateSignature bool) (*Verifier, error) {\n\tres := &Verifier{\n\t\tforce: validateSignature,\n\t}\n\tif !validateSignature {\n\t\treturn res, nil\n\t}\n\tif publicKeyFile == \"\" {\n\t\treturn nil, errors.New(\"publicKeyFile is required\")\n\t}\n\tif _, err := os.Stat(publicKeyFile); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to find publicKeyFile %q\", publicKeyFile)\n\t}\n\tpublicKeyByte, err := os.ReadFile(publicKeyFile)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to read from publicKeyFile %q\", publicKeyFile)\n\t}\n\tsign, err := signer.New(publicKeyByte)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to initialize signer\")\n\t}\n\tres.signer = sign\n\treturn res, nil\n}\n\nfunc (v *Verifier) Verify(label map[string]string, bootstrapFile string) error {\n\tsignature, err := getFromLabel(label)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif signature == nil {\n\t\tif v.force {\n\t\t\treturn errors.New(\"bootstrap signature is required when force validation\")\n\t\t}\n\t\treturn nil\n\t}\n\n\tif v.signer == nil {\n\t\treturn nil\n\t}\n\tf, err := os.Open(bootstrapFile)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer f.Close()\n\treturn v.signer.Verify(f, signature)\n}\n\nfunc getFromLabel(labels map[string]string) ([]byte, error) {\n\tif s, ok := labels[label.NydusSignature]; ok {\n\t\tres, err := base64.StdEncoding.DecodeString(s)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn res, nil\n\t}\n\treturn nil, nil\n}\n\n// func Verify(label map[string]string, bootstrapFile, publicKey string, force bool) error {\n// \tsignature, err := getFromLabel(label)\n// \tif err != nil {\n// \t\treturn err\n// \t}\n// \t// if we found signature on image manifest, we should verify it\n// \tif signature == nil {\n// \t\tif force {\n// \t\t\treturn errors.New(\"bootstrap signature is required when force validation\")\n// \t\t}\n// \t\treturn nil\n// \t}\n//\n// \tpublicKeyByte, err := ioutil.ReadFile(publicKey)\n// \tif err != nil {\n// \t\treturn err\n// \t}\n// \tsign, err := signer.New(publicKeyByte)\n// \tif err != nil {\n// \t\treturn err\n// \t}\n// \tf, err := os.Open(bootstrapFile)\n// \tif err != nil {\n// \t\treturn err\n// \t}\n// \tdefer f.Close()\n// \treturn sign.Verify(f, signature)\n// }\n"
  },
  {
    "path": "pkg/snapshot/storage.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage snapshot\n\nimport (\n\t\"context\"\n\n\t\"github.com/containerd/containerd/v2/core/snapshots\"\n\t\"github.com/containerd/containerd/v2/core/snapshots/storage\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/pkg/errors\"\n)\n\ntype WalkFunc = func(id string, info snapshots.Info) bool\n\nfunc GetSnapshotInfo(ctx context.Context, ms *storage.MetaStore, key string) (string, snapshots.Info, snapshots.Usage, error) {\n\tctx, t, err := ms.TransactionContext(ctx, false)\n\tif err != nil {\n\t\treturn \"\", snapshots.Info{}, snapshots.Usage{}, err\n\t}\n\n\tdefer func() {\n\t\tif err := t.Rollback(); err != nil {\n\t\t\tlog.L.WithError(err).Errorf(\"Rollback traction %s\", key)\n\t\t}\n\t}()\n\n\tid, info, usage, err := storage.GetInfo(ctx, key)\n\tif err != nil {\n\t\treturn \"\", snapshots.Info{}, snapshots.Usage{}, err\n\t}\n\n\treturn id, info, usage, nil\n}\n\nfunc GetSnapshot(ctx context.Context, ms *storage.MetaStore, key string) (*storage.Snapshot, error) {\n\tctx, t, err := ms.TransactionContext(ctx, false)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdefer func() {\n\t\tif err := t.Rollback(); err != nil {\n\t\t\tlog.L.WithError(err).Errorf(\"Rollback traction %s\", key)\n\t\t}\n\t}()\n\n\ts, err := storage.GetSnapshot(ctx, key)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"get snapshot\")\n\t}\n\n\treturn &s, nil\n}\n\n// Iterate all the parents of a  snapshot specified by `key`\n// Stop the iteration once callback `fn` is invoked successfully and return current iterated snapshot\nfunc IterateParentSnapshots(ctx context.Context, ms *storage.MetaStore, key string, fn WalkFunc) (string, snapshots.Info, error) {\n\tctx, t, err := ms.TransactionContext(ctx, false)\n\tif err != nil {\n\t\treturn \"\", snapshots.Info{}, err\n\t}\n\n\tdefer func() {\n\t\tif err := t.Rollback(); err != nil {\n\t\t\tlog.L.WithError(err).Errorf(\"Rollback transaction %s\", key)\n\t\t}\n\t}()\n\n\tfor cKey := key; cKey != \"\"; {\n\t\tid, info, _, err := storage.GetInfo(ctx, cKey)\n\t\tif err != nil {\n\t\t\tlog.L.WithError(err).Warnf(\"failed to get snapshot info of %q\", cKey)\n\t\t\treturn \"\", snapshots.Info{}, err\n\t\t}\n\n\t\tif fn(id, info) {\n\t\t\treturn id, info, nil\n\t\t}\n\n\t\tcKey = info.Parent\n\t}\n\n\treturn \"\", snapshots.Info{}, errdefs.ErrNotFound\n}\n\nfunc UpdateSnapshotInfo(ctx context.Context, ms *storage.MetaStore, info snapshots.Info, fieldPaths ...string) (snapshots.Info, error) {\n\tctx, t, err := ms.TransactionContext(ctx, true)\n\tif err != nil {\n\t\treturn snapshots.Info{}, err\n\t}\n\tinfo, err = storage.UpdateInfo(ctx, info, fieldPaths...)\n\tif err != nil {\n\t\tif rerr := t.Rollback(); rerr != nil {\n\t\t\tlog.L.WithError(rerr).Errorf(\"update snapshot info\")\n\t\t}\n\t\treturn snapshots.Info{}, err\n\t}\n\tif err := t.Commit(); err != nil {\n\t\treturn snapshots.Info{}, err\n\t}\n\treturn info, nil\n}\n"
  },
  {
    "path": "pkg/stargz/resolver.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage stargz\n\nimport (\n\t\"archive/tar\"\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/transport\"\n\t\"github.com/containerd/stargz-snapshotter/estargz\"\n\tdistribution \"github.com/distribution/reference\"\n\t\"github.com/google/go-containerregistry/pkg/authn\"\n\t\"github.com/google/go-containerregistry/pkg/name\"\n\t\"github.com/pkg/errors\"\n)\n\nconst httpTimeout = 15 * time.Second\n\nconst (\n\tFooterSize  = 47\n\tTocFileName = \"stargz.index.json\"\n)\n\ntype Resolver struct {\n\tres transport.Resolve\n}\n\nfunc NewResolver() *Resolver {\n\tresolver := Resolver{\n\t\tres: transport.NewPool(),\n\t}\n\treturn &resolver\n}\n\ntype Blob struct {\n\tref    string\n\tdigest string\n\tsr     *io.SectionReader\n}\n\n// getTocOffset get toc offset from stargz footer\nfunc (bb *Blob) GetTocOffset() (int64, error) {\n\ttocOffset, _, err := estargz.OpenFooter(bb.sr)\n\tif err != nil {\n\t\treturn 0, errors.Wrap(err, \"open stargz blob footer\")\n\t}\n\n\treturn tocOffset, nil\n}\n\n// ReadToc read stargz toc content from blob\nfunc (bb *Blob) ReadToc() (io.Reader, error) {\n\tstart := time.Now()\n\tdefer func() {\n\t\tduration := time.Since(start)\n\t\tlog.L.Infof(\"read toc duration %d\", duration.Milliseconds())\n\t}()\n\n\ttocOffset, err := bb.GetTocOffset()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttocBuf := make([]byte, bb.sr.Size()-tocOffset-FooterSize)\n\t_, err = bb.sr.ReadAt(tocBuf, tocOffset)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tzr, err := gzip.NewReader(bytes.NewReader(tocBuf))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tzr.Multistream(false)\n\ttr := tar.NewReader(zr)\n\th, err := tr.Next()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif h.Name != TocFileName {\n\t\treturn nil, fmt.Errorf(\"failed to find toc from image %s blob %s\", bb.ref, bb.digest)\n\t}\n\tvar buf bytes.Buffer\n\t_, err = buf.ReadFrom(tr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &buf, nil\n}\n\nfunc (bb *Blob) GetDigest() string {\n\treturn bb.digest\n}\n\nfunc (bb *Blob) GetImageReference() string {\n\treturn bb.ref\n}\n\nfunc (r *Resolver) GetBlob(ref, digest string, keychain authn.Keychain) (*Blob, error) {\n\tstart := time.Now()\n\tdefer func() {\n\t\tduration := time.Since(start)\n\t\tlog.L.Infof(\"get blob duration %d\", duration.Milliseconds())\n\t}()\n\n\tsr, err := r.resolve(ref, digest, keychain)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &Blob{\n\t\tref:    ref,\n\t\tdigest: digest,\n\t\tsr:     sr,\n\t}, nil\n}\n\ntype readerAtFunc func([]byte, int64) (int, error)\n\nfunc (f readerAtFunc) ReadAt(p []byte, offset int64) (int, error) { return f(p, offset) }\n\n// parseFooter extract toc offset from footer\nfunc parseFooter(p []byte) (tocOffset int64, ok bool) {\n\tif len(p) != 47 {\n\t\treturn 0, false\n\t}\n\tzr, err := gzip.NewReader(bytes.NewReader(p))\n\tif err != nil {\n\t\treturn 0, false\n\t}\n\textra := zr.Extra\n\tif len(extra) != 16+len(\"STARGZ\") {\n\t\treturn 0, false\n\t}\n\tif string(extra[16:]) != \"STARGZ\" {\n\t\treturn 0, false\n\t}\n\ttocOffset, err = strconv.ParseInt(string(extra[:16]), 16, 64)\n\treturn tocOffset, err == nil\n}\n\nfunc (r *Resolver) resolve(ref, digest string, keychain authn.Keychain) (*io.SectionReader, error) {\n\tnamed, err := distribution.ParseDockerRef(ref)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\thost := distribution.Domain(named)\n\tsref := fmt.Sprintf(\"%s/%s\", host, distribution.Path(named))\n\tnref, err := name.ParseReference(sref)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to parse ref %q (%q)\", sref, digest)\n\t}\n\n\turl, tr, err := r.res.Resolve(nref, digest, keychain)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to resolve reference of %q, %q\", nref, digest)\n\t}\n\n\tsize, err := getSize(url, tr)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to get size from url %s\", url)\n\t}\n\tlog.L.Infof(\"get size %d\", size)\n\n\tsr := io.NewSectionReader(readerAtFunc(func(b []byte, offset int64) (int, error) {\n\t\tlength := len(b)\n\t\tctx, cancel := context.WithTimeout(context.Background(), httpTimeout)\n\t\tdefer cancel()\n\t\treq, err := http.NewRequestWithContext(ctx, \"GET\", url, nil)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\treq.Close = false\n\t\tr := fmt.Sprintf(\"bytes=%d-%d\", offset, offset+int64(length)-1)\n\t\treq.Header.Set(\"Range\", r)\n\t\tres, err := tr.RoundTrip(req)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\tdefer func() {\n\t\t\tif _, err := io.Copy(io.Discard, res.Body); err != nil {\n\t\t\t\tlog.L.Errorf(\"failed to copy %s\", err)\n\t\t\t}\n\t\t\tres.Body.Close()\n\t\t}()\n\t\tif res.StatusCode/100 != 2 {\n\t\t\treturn 0, fmt.Errorf(\"failed to HEAD request with code %d\", res.StatusCode)\n\t\t}\n\t\treturn io.ReadFull(res.Body, b)\n\t}), 0, size)\n\n\treturn sr, nil\n}\n\nfunc getSize(url string, tr http.RoundTripper) (int64, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), httpTimeout)\n\tdefer cancel()\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", url, nil)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treq.Close = false\n\treq.Header.Set(\"Range\", \"bytes=0-0\")\n\tres, err := tr.RoundTrip(req)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tdefer func() {\n\t\tif _, err := io.Copy(io.Discard, res.Body); err != nil {\n\t\t\tlog.L.Errorf(\"failed to copy %s\", err)\n\t\t}\n\t\tres.Body.Close()\n\t}()\n\tif res.StatusCode/100 != 2 {\n\t\treturn 0, fmt.Errorf(\"failed to HEAD request with code %d\", res.StatusCode)\n\t}\n\tcontentRange := res.Header.Get(\"Content-Range\")\n\ttotalSize := strings.Split(contentRange, \"/\")[1]\n\treturn strconv.ParseInt(totalSize, 10, 64)\n}\n"
  },
  {
    "path": "pkg/stargz/resolver_test.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage stargz\n\nimport (\n\t\"archive/tar\"\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/google/go-containerregistry/pkg/authn\"\n\t\"github.com/google/go-containerregistry/pkg/name\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n)\n\nfunc TestResolver_resolve(t *testing.T) {\n\n\tresolver := Resolver{\n\t\tres: &MockResolver{},\n\t}\n\tkeychain, err := auth.FromBase64(\"dGVzdDp0ZXN0Cg==\")\n\trequire.Nil(t, err)\n\tsr, err := resolver.resolve(\"example.com/test/myserver:latest-stargz\", \"sha256:mock\", keychain)\n\trequire.Nil(t, err)\n\tsize := sr.Size()\n\tvar b [47]byte\n\tn, err := sr.ReadAt(b[:], size-47)\n\tassert.Nil(t, err)\n\tassert.Equal(t, 47, n)\n\ttocOffset, ok := parseFooter(b[:])\n\tassert.True(t, ok)\n\tfmt.Printf(\"tocoffset %d\", tocOffset)\n\ttocTargz := make([]byte, size-tocOffset-47)\n\t_, err = sr.ReadAt(tocTargz, tocOffset)\n\tassert.Nil(t, err)\n\tzr, err := gzip.NewReader(bytes.NewReader(tocTargz))\n\tassert.Nil(t, err)\n\tzr.Multistream(false)\n\ttr := tar.NewReader(zr)\n\th, err := tr.Next()\n\tassert.Nil(t, err)\n\tassert.Equal(t, \"stargz.index.json\", h.Name)\n}\n\ntype MockResolver struct {\n}\n\nfunc (res *MockResolver) Resolve(_ name.Reference, _ string, _ authn.Keychain) (string, http.RoundTripper, error) {\n\treturn \"http://oss.com/v2/test/myserver/blobs/sha256:mock\", &mockRoundTripper{}, nil\n}\n\ntype mockRoundTripper struct{}\n\nfunc (tr *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {\n\turl := req.URL.String()\n\tif url == \"https://example.com/v2/\" {\n\t\treturn &http.Response{\n\t\t\tStatusCode: http.StatusOK,\n\t\t\tBody:       io.NopCloser(bytes.NewReader([]byte{})),\n\t\t}, nil\n\t}\n\tif url == \"https://example.com/v2/test/myserver/blobs/sha256:mock\" {\n\t\theader := make(http.Header)\n\t\theader.Add(\"Location\", \"http://oss.com/v2/test/myserver/blobs/sha256:mock\")\n\t\treturn &http.Response{\n\t\t\tStatusCode: http.StatusMovedPermanently,\n\t\t\tHeader:     header,\n\t\t\tBody:       io.NopCloser(bytes.NewReader([]byte{})),\n\t\t}, nil\n\t}\n\tif url == \"http://oss.com/v2/test/myserver/blobs/sha256:mock\" {\n\t\trangeHeader := req.Header.Get(\"Range\")\n\t\t// get length\n\t\tif rangeHeader == \"bytes=0-0\" {\n\t\t\theader := make(http.Header)\n\t\t\theader.Add(\"Content-Range\", \"bytes 0-0/24613186\")\n\t\t\treturn &http.Response{\n\t\t\t\tStatusCode: http.StatusPartialContent,\n\t\t\t\tHeader:     header,\n\t\t\t\tBody:       io.NopCloser(bytes.NewReader([]byte{})),\n\t\t\t}, nil\n\t\t}\n\t\t// get footer\n\t\tif rangeHeader == \"bytes=24613139-24613185\" {\n\t\t\tfooter, _ := os.ReadFile(\"testdata/stargzfooter.bin\")\n\t\t\treturn &http.Response{\n\t\t\t\tStatusCode: http.StatusPartialContent,\n\t\t\t\tBody:       io.NopCloser(bytes.NewReader(footer)),\n\t\t\t}, nil\n\t\t}\n\t\tif rangeHeader == \"bytes=24442675-24613138\" {\n\t\t\ttoc, _ := os.ReadFile(\"testdata/stargztoc.bin\")\n\t\t\treturn &http.Response{\n\t\t\t\tStatusCode: http.StatusPartialContent,\n\t\t\t\tBody:       io.NopCloser(bytes.NewReader(toc)),\n\t\t\t}, nil\n\t\t}\n\t}\n\n\treturn &http.Response{\n\t\tStatusCode: 200,\n\t}, nil\n}\n"
  },
  {
    "path": "pkg/stargz/testdata/config/nydus.json",
    "content": "{\n  \"device\": {\n    \"backend\": {\n      \"type\": \"registry\",\n      \"config\": {\n        \"auth\": \"\",\n        \"timeout\": 5,\n        \"connect_timeout\": 5,\n        \"retry_limit\": 0\n      }\n    },\n    \"cache\": {\n      \"type\": \"blobcache\",\n      \"config\": {\n        \"work_dir\": \"\"\n      }\n    }\n  },\n  \"mode\": \"direct\",\n  \"digest_validate\": true,\n  \"iostats_files\": true,\n  \"enable_xattr\": true,\n  \"amplify_io\": 1048576,\n  \"fs_prefetch\": {\n    \"enable\": true,\n    \"threads_count\": 10,\n    \"merging_size\": 131072\n  }\n}\n"
  },
  {
    "path": "pkg/stargz/testdata/stargz.index.json",
    "content": "{\n\t\"version\": 1,\n\t\"entries\": [\n\t\t{\n\t\t\t\"name\": \"bin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/bash\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1099016,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 123,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3f0bc167fa8ef1f7a38452a5fd16d077ed8ef657bb81cdce5af9537ca96e8345\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/cat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35688,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 557313,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f1e77796eaa4f465ff57128d4a66b3aaebc1c1c9812a015bc2726da949886f6c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/chgrp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 64424,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 574029,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:48774490af3d77e3e7a03f1b0dc06676db9b06866422847d49423297a19a96fe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/chmod\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60296,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 604734,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a514b561e2007d38c8ea158ff62243db30dae741a95fc1da35165ce55b58bcad\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/chown\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 64456,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 634251,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:066d6564f9a97370e347d2b792e2d6d4c8e2705ff2ce8b437a0c402202cd4908\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/cp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130504,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 666106,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e0ba82626269bd1f2d71761ef299508f6a85954721c921f07992ec5563e1f437\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/dash\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 117208,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 729890,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e803088e7938b328b0511957dcd0dd7b5600ec1940010c64dbd3814e3d75495f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/date\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 105448,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 788656,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f4c8f40e23e7825a2d6c018adb06de6be4172a252f6ac0241abef92b1b5b192f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/dd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 76816,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 839666,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:71dcc2044f22e9575881502576f648c8fccb1327126d067a7db0a3d83fa04ac3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/df\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 85688,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 876584,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5c2810e81a1dda76573e378e3468a54594c0322a1def87951d090b084a18918d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/dir\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130736,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 919547,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a42642d5bad1f3a79817513a06646b98b129de7d1df64ef7a6a1aea5e917cc44\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/dmesg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 73032,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 981644,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc00594e32cc8c667f3695ff1db64ac7cc7c6ecdc9e007389b3e8ee2050cb7e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/dnsdomainname\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-07-03T19:26:17Z\",\n\t\t\t\"linkName\": \"hostname\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/domainname\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-07-03T19:26:17Z\",\n\t\t\t\"linkName\": \"hostname\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/echo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1010882,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:615183f74a4f135160e2323720678396454266d17647874816f2843714bad102\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/egrep\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 28,\n\t\t\t\"modtime\": \"2017-01-23T18:18:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1025997,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f7c621ae0ceb26a76802743830bc469288996f64342901ae5292950ff713e981\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/false\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1026120,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:127ae383b59b92a437692c9dd0095800bb40347b8a8488358c595c76d85e29ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/fgrep\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 28,\n\t\t\t\"modtime\": \"2017-01-23T18:18:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1039843,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5c8b1486de899cdd010d3cacde94579999cb82d0be9ec8c131b1b56886cfd36b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/findmnt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 62072,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1039969,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ecbf8f39f78385c8dfb35b5495471aa4144ab3c3169e89465419d3c5ba5aae27\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/grep\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 215360,\n\t\t\t\"modtime\": \"2017-01-23T18:18:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1066887,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5772e5f9aea26318c6ab587d38988013d7127531ee185984fec45874c4379596\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/gunzip\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2301,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1169811,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:091abe52520c96a75cf7d4ff38796fc878cd62c3a75a3fd8161aa3df1e26bebd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/gzexe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5927,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1171050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6de8254cfd49543097ae946c303602ffd5899b2c88ec27cfcd86d786f95a1e92\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/gzip\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 102408,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1173484,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3b7dea216f49346ddd68c471deefa345d5cdfb9d21da0942909d47e39d23b23d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/hostname\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18992,\n\t\t\t\"modtime\": \"2016-07-03T19:26:17Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1228033,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f3187f6c1d9951dc45c8a3dd4579e9e1a24037156cc1126724c18be50a1c8348\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/ln\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56240,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1234279,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2af73dbb7990bc6d3a21aaa386d400b96ccd4df2ff4c0751e786c6c1dc9c0e65\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/login\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 52632,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1261422,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:07369ff7775bc32fb0e4c977e132a442bf94c68454ddea08a3d02912c4ccb30f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/ls\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130736,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1282844,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a0e06b5a72fed6c106391cf0162dbee1750c047640117bfea2234857055216a0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/lsblk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 81376,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1344940,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3f9a7fb1e45651b0b0b4609e3b4597282efeef3f777bb75a986edec97dfcf7cf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/mkdir\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 81032,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1381190,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:46254c850ec5d828557ef58c958e793ad96b948161c8378fd4954c3632b560f8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/mknod\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 68648,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1420908,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:02d68294caac9d375456f35e26c99d17abb27cce90abb31ecb346a26fc7b56e9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/mktemp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43912,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1454052,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ec6d01605f2a1d0518003dfc0822e9d7f75eafa337a5e4d575db0d98b8325a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/more\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39752,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1473855,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8f448b9780748ae395fefb8abb09a4f94eaba1796996880979c15a2f970c3fa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/mount\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 44304,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 35309,\n\t\t\t\"offset\": 1493006,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4df3d21877d09f670bc6c0a9021fecf0b0faa4434f8383ea048cbf1528f32910\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/mountpoint\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14840,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1509324,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a5640eba9a1104278409564b771b53276a5f0f48692052a7dcf76a70f9f80ad3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/mv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 126416,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1514148,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a9c0bbf66cff9f6870a3fa58c7182afb1020ff99282a6e48c82a75931d638b21\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/nisdomainname\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-07-03T19:26:17Z\",\n\t\t\t\"linkName\": \"hostname\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/pidof\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-12T21:55:39Z\",\n\t\t\t\"linkName\": \"/sbin/killall5\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/pwd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35656,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1577351,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d27a17c6a7ded3550c37d49e6fd8875a86641a01e18f76c297e43ee65d0a1297\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/rbash\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"linkName\": \"bash\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/readlink\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43816,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1593217,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:539ab7e307835455c670f725fafb9831df823ea59e64d11967b9bc43f7dec749\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/rm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 64424,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1613850,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:661eba5491e486bb9308dc6fcfd65aaa790471ea5f6bf1b5f775672cd982389e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/rmdir\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43816,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1645395,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d02f44490836b4f010e17cc2197921ebf0e58cbca0f206609b59fbd52cbca9d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/run-parts\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19288,\n\t\t\t\"modtime\": \"2017-04-02T17:10:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1665557,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a37652fd9ee165d666902bd4e7a3967969dc6fc7ff0d7f017fab3260c93967e9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/sed\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 105808,\n\t\t\t\"modtime\": \"2017-02-04T15:16:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1673379,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ab8fbc38bf9f67c706d7d422a4ef4c051eb5c4c21579037f4d184ebf189f5e79\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/sh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"linkName\": \"dash\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/sh.distrib\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"linkName\": \"dash\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/sleep\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35592,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1727499,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:196bce40af413a2188c4ca548db12d710334af5523a0d5e4f2e9bedeb987c39c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/stty\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 76680,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1742845,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:52fe1b6ffec2a667b411c5b131d86c8fa444bbbcacf3bcbaf43745141bd66321\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/su\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 40536,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 35309,\n\t\t\t\"offset\": 1775410,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0c1d3341d124b09395a959f2674da1d775703e66c285ed309031c2b8cc77f75e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/sync\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31496,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1791921,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94e555750f59f1ddf60451ffd1902d520a786751f71894b3bce2e75a9ac4d841\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/tailf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23232,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1806686,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc2d8a0225c79247fb2d539a2d854210bcbd3512ccb45c526ac67c9f71995407\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/tar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 416896,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 1817371,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a216ed63dced5ea5ea949c4f11ee78a7f7aa715de76cb87498940a3433e5b3d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/tempfile\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10680,\n\t\t\t\"modtime\": \"2017-04-02T17:10:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2021609,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6702e5b02aaa841832ddc9cfc6cbb6333b2d03ca88839d2cd8dcedaae4e07b8d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/touch\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 93160,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2025161,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:952786e16e51f9ee059472abc0d8f1ec9e237af253e09fe49a975445aaaec589\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/true\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2070363,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5a2de760cb026c9749bf515dd1ad258b3c8b554fb4ba4bc2fd33f99ae834e472\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/umount\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31720,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 35309,\n\t\t\t\"offset\": 2084085,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4c90ff10f6b7dc1c61e06166792f90954ca4071c4cb43942b991ffd5e1eeee3b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/uname\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35592,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2095736,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6eb9b55fc05a8938ac49c78d336f8f8669195db70756b9ff3cb9d31e6107c95b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/uncompress\",\n\t\t\t\"type\": \"hardlink\",\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"linkName\": \"bin/gunzip\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/vdir\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130736,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2110686,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b42f70b011e4069795a55ee63719c9e6ed533ed356073eab38092ca92bb6bd9a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/wdctl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2172779,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:657b50892f2acf5a3c1b0af2ced09a9cf7f70c1537c86fce5552a9936f55102d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/which\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 946,\n\t\t\t\"modtime\": \"2017-04-02T17:10:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2186759,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7bdde142dc5cb004ab82f55adba0c56fc78430a6f6b23afd33be491d4c7c238b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/ypdomainname\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-07-03T19:26:17Z\",\n\t\t\t\"linkName\": \"hostname\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/zcat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1937,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2187365,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aaf7b2c7036c2597450e109198ea7b5870c164591e2501b1891a3e767dfc0e00\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/zcmp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1777,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2188438,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ae3c2b73273b7d953d432b10c50612011cb0bd0f245220d8ec10a5a47239d86d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/zdiff\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5764,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2189446,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:97f3993ead63a1ce0f6a48cda92d6655ffe210242fe057b8803506b57c99b7bc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/zegrep\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 140,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2191473,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:da2da96324108bbe297a75e8ebfcb2400959bffcdaa4c88b797c4d0ce0c94c50\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/zfgrep\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 140,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2191669,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b9711301d3ab42575597d8a1c015f49fddba9a7ea9934e11d38b9ff5248503a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/zforce\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2131,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2191867,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6936c9aa8e17781410f286bb1cbc35b5548ea4e7604c1379dc8e159d91a0193d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/zgrep\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5938,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2193069,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1cab9ec4e390ceba0ddd47e7d4537527df5c1991c5b35208a29005e1494b408d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/zless\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2037,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2195544,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:14dc8106ec64c9e2a7c9430e1d0bef170aaad0f5f7f683c1c1810b466cdf5079\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/zmore\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1910,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2196723,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f66077e5cc686ee33c99149972abdfd3a36d3e125cc4b42c215a0d2701eeaf6e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"bin/znew\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5047,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2197786,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01764d96697b060b2a449769073b7cf2df61b5cb604937e39dd7a47017e92ee0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"boot/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"dev/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/.pwd.lock\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33152,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/adduser.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2981,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2200038,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ccdc9675d7bd39c3cc79c2a5d6938f2562dd4062350dbed3058c1faee48b353e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/README\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 100,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2201526,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:100fc671b65c94241e6013d3a7332a1f5d1a97e0324e37f4ff4851fec607497e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/awk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/usr/bin/mawk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/awk.1.gz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/usr/share/man/man1/mawk.1.gz\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/builtins.7.gz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/usr/share/man/man7/bash-builtins.7.gz\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/nawk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/usr/bin/mawk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/nawk.1.gz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/usr/share/man/man1/mawk.1.gz\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/pager\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/bin/more\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/pager.1.gz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/usr/share/man/man1/more.1.gz\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/rmt\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/usr/sbin/rmt-tar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/alternatives/rmt.8.gz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/usr/share/man/man8/rmt-tar.8.gz\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/apt.conf.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/apt.conf.d/01autoremove\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 769,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2201963,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:295419b57259cb583b726064b66ffcd3b625999c637905fdc63e06432afcf752\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/apt.conf.d/70debconf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 182,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2202387,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:db749e19baf3b72ca2c157c70c52522cae23d94bc8b2dc5793fd43d427445367\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/apt.conf.d/docker-autoremove-suggests\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 754,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2202646,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:84cb100b000873f25f677cf23ab51f841eb490264fa496361591d6071aebf0f4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/apt.conf.d/docker-clean\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1175,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2203183,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:484f60f8d215bf22008b5fe7dd8484350d7abd44655ea79accee79ce11976c81\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/apt.conf.d/docker-gzip-indexes\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 481,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2203874,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9da4604fbac169caa47e787b4d85c8e06c887603878afa2a61f39fd551a41359\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/apt.conf.d/docker-no-languages\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 269,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2204295,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a7fea31d968796bf459a439279abdf8d45f5e3f68bbaa9e09dbd9e7f3bd831f6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/preferences.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/sources.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 168,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2204630,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5c58eef9e4b1520d146082c7781f775f3fe1bd7d2749a7f7d8db21bd2a9b4ae5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/sources.list.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/trusted.gpg.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/trusted.gpg.d/debian-archive-jessie-automatic.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5138,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2204887,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d03faac2548c2e653d8fbfdb4088f5ef7b7633cca6a1afa8a67c4df3f445e19f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/trusted.gpg.d/debian-archive-jessie-security-automatic.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5147,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2210121,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4691fd79441853a23cbd6fc991983cba296280159dfce0ef70508d064bd4c898\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/trusted.gpg.d/debian-archive-jessie-stable.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2775,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2215357,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bcc458a220eb49df0cc61da109c815bdb2db17c5712f5734e5ebc4e28f0ce7a4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/trusted.gpg.d/debian-archive-stretch-automatic.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7483,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2218333,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1f1c4eba7c74aa485a0da3b170dd0b3d5ea4d5ada4ec9201a2616ec0a3f4130b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/trusted.gpg.d/debian-archive-stretch-security-automatic.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7492,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2225734,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1eb9ab7a15f18580d449658ff1ba432d06b0a6ac7e0937f933c831cd5ef36d62\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/trusted.gpg.d/debian-archive-stretch-stable.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2275,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2233132,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4d221cb762e470f73d3200d30354b5c39f28c4a1d1d1c2bc01a81a0eac427d7f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/trusted.gpg.d/debian-archive-wheezy-automatic.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3780,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2235599,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:13b45eb5716c72be9831bb1a9e18672ad23f3f41884df63fa42b09eb7d8d30ae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/apt/trusted.gpg.d/debian-archive-wheezy-stable.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2851,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2239517,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9637cd12bf4cd1f33a24a714dbcaa76bfb1dd5de5c94ae0e9b621616e2d15e34\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/bash.bashrc\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1863,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2242516,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5638e43ea1289e856d5fbbc80f96d1e2cf249c04976870fa5481278e081a0163\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/bindresvport.blacklist\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 367,\n\t\t\t\"modtime\": \"2017-04-09T21:28:38Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2243473,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:63229551ffc257f56e3df60ca97e1f2963f3ab2128ce27a0f398b4418fa454d0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/cron.daily/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/cron.daily/apt-compat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1474,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2243845,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8eeae3a9df22621d51062e4dadfc5c63b49732b38a37b5d4e52c99c2237e5767\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/cron.daily/dpkg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1597,\n\t\t\t\"modtime\": \"2018-06-26T02:48:17Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2244691,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c08441d2782fbde6e06a6f27cf84ae647efb67b5305919e739431b19f284ec95\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/cron.daily/passwd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 249,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2245528,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:777a9112ee093d8683645b031eb6cfeb9ce77274f40575c48ff2054ea24114d1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/debconf.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2969,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2245764,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fe7e76d4162e80e0bc8c24bc638c56ae92c07a80db750cbf0a87e0904e143f4e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/debian_version\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2247154,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:02da5eaddc974610c7221b297e33005e32beead4b2d6371e8625a5ed1494033f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/default/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/default/hwclock\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 657,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2247299,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:827cf5c033ba11433d2b4087ec1e36e82766eab39ceed8e7f8f09d983d2d8235\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/default/nss\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1756,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2247771,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:836614e9d4d501d0af43087c9c9300365a38d53f24f845efcf0b2ad8194cbaa0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/default/useradd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1118,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2248690,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:03b603de7e8c7a8192902d827edea1891360bd094cf2c810669af13aee823c70\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/deluser.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 604,\n\t\t\t\"modtime\": \"2016-06-26T20:00:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2249396,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:946e0f11a8997bf41dbafca1f6f5a4bedf46746c91801ca4f2e90dd0172f06b6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/dpkg/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/dpkg/dpkg.cfg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 446,\n\t\t\t\"modtime\": \"2014-11-28T01:08:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2249890,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fead43b89af3ea5691c48f32d7fe1ba0f7ab229fb5d230f612d76fe8e6f5a015\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/dpkg/dpkg.cfg.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/dpkg/dpkg.cfg.d/docker\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3543,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2250297,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5493667488dbf55f6aff36bac8c35362faa45803b4d350af959a76a5aaf2dda1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/dpkg/dpkg.cfg.d/docker-apt-speedup\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 259,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2251381,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ab3af717d57cbbea36555833dc1ae031fa46750b879199ec579ee00be9aa0124\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/dpkg/origins/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/dpkg/origins/debian\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 82,\n\t\t\t\"modtime\": \"2009-02-02T23:06:58Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2251704,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:50f35af8ac4a5df3690991a4b428fa49d56580b0020fcc6e38283b3b1b2e6c74\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/dpkg/origins/default\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"debian\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/environment\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/fstab\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 37,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2251928,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a6b093c9916c6c54e5d634d3689f1a0132e14cce0b8e50ff445da8e85acfbd17\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/gai.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2584,\n\t\t\t\"modtime\": \"2016-08-02T02:01:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2252062,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:76a5771adee7b9f36c7ae66eae78d72f325557500269107f2d98a7e3560a1808\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/group\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 446,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2253248,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:639aef8980b6ea2ea640187f4117523b4ade4b7289a5f8b3ef8ad7bb1a731fa7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/group-\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 446,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33152,\n\t\t\t\"offset\": 2253598,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cfde4574c857edbfbd31667000d75d07efe6bc61f22063693010dee2a912450b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/gshadow\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 374,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33184,\n\t\t\t\"gid\": 42,\n\t\t\t\"offset\": 2253956,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9f095e317e25ddd4a4bc3b58d5aaa08e20bbe8a0e42ca745b0e6ba6d17d61a34\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/host.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 9,\n\t\t\t\"modtime\": \"2006-08-07T17:14:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2254224,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:380f5fe21d755923b44203b58ca3c8b9681c485d152bd5d7e3914f67d821d32a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/hostname\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2254330,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:411eb208674138b8ce7624993e678f6b1d8a39c6f2bc4156e10d9466e0c71d2b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/init.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/init.d/hwclock.sh\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3809,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2254481,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a919f9434b681974a2f1d4120af10c0527b30e8cda6fdec1dea1eee3077b6609\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/issue\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2256157,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3836ea85d67769580f775bb6c2e547b8f1167b00810f00f54bd9ff31fbb5ca12\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/issue.net\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2256283,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:202afaaf205a231b5cc398d1b78caf8d2d476d108d9ba47c62d3c5105acebe1d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/kernel/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/kernel/postinst.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/kernel/postinst.d/apt-auto-removal\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2903,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2256468,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:64fef575566fd0ab647200ed6849156d07432997d22c65a06694c8852bdb7255\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/ld.so.cache\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5912,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2257911,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1b041de9bcd1a26dce46de0dd5b29ad0cfc11991925102bc1ac66bad20a4e372\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/ld.so.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 34,\n\t\t\t\"modtime\": \"2017-04-09T21:28:38Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2259376,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d4b198c463418b493208485def26a6f4c57279467b9dfa491b70433cedb602e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/ld.so.conf.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/ld.so.conf.d/libc.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 44,\n\t\t\t\"modtime\": \"2016-03-20T23:45:12Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2259532,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:90d4c7e43e7661cd116010eb9f50ad5817e43162df344bd1ad10898851b15d41\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/ld.so.conf.d/x86_64-linux-gnu.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 68,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2259690,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:54ad1c27463ba4c81f7cf9f58621e34ab679c760692ac046845940390fb4e612\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/libaudit.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 191,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2259840,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d48318c90620fde96cb6a8e6eb1eb64663b21200f9d1d053f9e3b4fce24a2543\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/localtime\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/usr/share/zoneinfo/Etc/UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/login.defs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10477,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2260119,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ff7cf6759ea81d72c51ab879e751c23bb4aa73307b737743aae9f034a314e7b6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/logrotate.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/logrotate.d/apt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2264687,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fcc2510172fd914ca22762c4b2dc43d36152e65becf8e84abec59f7652da5e3f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/logrotate.d/dpkg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 232,\n\t\t\t\"modtime\": \"2018-06-26T02:48:17Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2264867,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a65183e9cf4e0d9c655514495e204b437baef0717c8207639c2d60d6d7a801c2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/machine-id\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 33,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2265064,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7dcaeff856e487b63782f158ad6de51af878a00135068cecba7c9d4ba0df41a9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/mke2fs.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 973,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2265192,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:437ffd423945a6427ebb62de923667aea851fc05c79be7428eecea14a024f35e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/motd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 286,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2265645,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a378977155fb42bb006496321cbe31f74cbda803c3f6ca590f30e76d1afad921\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/nsswitch.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 497,\n\t\t\t\"modtime\": \"2017-12-31T12:12:42Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2265946,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e241e67d7b5c15a5ace818d89277507b5ded8b49688b7a4431afb3b1041a3759\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/opt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/os-release\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"linkName\": \"../usr/lib/os-release\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 552,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2266374,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8aa7f3472ec88a24a572d6ffd9748ce3da223fba3b2545098eaaae768b6408c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/chfn\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 384,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2266702,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d66a095a330d7e20d0bbb56a4cb28a4b1bfc92e8a5a5e9bfc3d0a51c5e3d7170\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/chpasswd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 92,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2267039,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f3f96229e82bf41a7fd3ec12e697b3465235d96bb1e44c39ba91157425a36082\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/chsh\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 581,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2267222,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0101e7e589ce40435c5a8709888225400a78ab6be86dfc5fef86ee23ba5338ad\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/common-account\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1208,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2267648,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa8a63d72e79399b6c51ebe4e9f828c954145a799eb4b8f3224724f51cbb9fac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/common-auth\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1221,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2268373,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:df3ed820b414b7163bd61b623e6b7e5896d541f9df392240606a23aa4f421d4a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/common-password\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1440,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2269107,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ede17d3b24602a774a51fde44a5afd536f73eb3da65f948926ab7952b474d3b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/common-session\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1156,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2269931,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6dc1d9be5915053dec2ac18f1c0b6b3389b3f0ed74383dde4a46dec81edefe68\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/common-session-noninteractive\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1154,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2270623,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d137251095e22fca44fcc5c993699e46446673a085dab8238de6a670fb3cc7f2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/login\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4945,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2271302,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:42e1e68613a5e0d2942ceeb8b5a4544341bde732fed47630108a163545359f6d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/newusers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 92,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2273285,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:26e75ce7c9066801b8db380ff9d8ba58a5e8cf2de5fb38ffd1db5ba62c85acef\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/other\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 520,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2273468,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d13078e71d3351ef7f63a7265ddb50b710a2598b9febc78810fbb0130a02695a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/passwd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 92,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2273845,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:87696fad1046d6b33b6d3407bb419980987331b4dcd8905f7a6041bced90c51d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/runuser\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 143,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2274030,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2d430cb6628248953568010427d663f3305856f3cb055955c2239bea226c5280\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/runuser-l\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 138,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2274230,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:be9329a8b26e3cfd4af879fe60900f646f8188f3fbe491688f23d4d8b491c5b1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/pam.d/su\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2257,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2274416,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f7cac62fbcd50f9931d09a9190fc3ec390fd48fb5b8bec57e0996a7246856b12\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/passwd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 919,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2275504,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f3df8ec25c77cb0e445aab589c5fef4d77868f875fa742c0d42fccb9e1a50754\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/passwd-\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 919,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33152,\n\t\t\t\"offset\": 2275953,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f3df8ec25c77cb0e445aab589c5fef4d77868f875fa742c0d42fccb9e1a50754\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/profile\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 767,\n\t\t\t\"modtime\": \"2016-03-04T11:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2276404,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b8ffd2c97588047e1cea84b7dfdb68bfde167e2957f667ca2b6ab2929feb4f49\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/profile.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rc0.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rc0.d/K01hwclock.sh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"../init.d/hwclock.sh\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rc1.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rc2.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rc3.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rc4.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rc5.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rc6.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rc6.d/K01hwclock.sh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"../init.d/hwclock.sh\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rcS.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rcS.d/S01hwclock.sh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"../init.d/hwclock.sh\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/resolv.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 104,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2277035,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a535ac16b8fe54e9e1afbb474c4c19fd8faeddbac8b1e1c17f8f52191ce84f96\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/rmt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 268,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2277208,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0bdd822a1df82458bdf623d6869f9d0817f6e66f517366a67a4770dbbe714dd2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/securetty\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4179,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2277489,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:49310071ed72eb85aa785d2934051a9ca846f91a474b7fb9b76290444f6b16df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/access.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4620,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2279287,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb2d5cbb78756240990da65ce40431a0ccb4f09746868c6a874234ba5fb42f2b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/group.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3635,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2281174,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41df4bc646811997d0390c6d37d839d2aef4a9a1a940c44ee1a798a9dc1ac864\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/limits.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2150,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2282877,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69ff0dea1ee42bc6eda9077627610d3181e6fa82a9a3d03e36f20d35c3dbab9e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/limits.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/namespace.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1440,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2283786,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0c3045ba5071b8375fde6165d4e4db9b69f49af5d2525cecd2bca1cb7538552\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/namespace.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/namespace.init\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1016,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2284546,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2d76094c06f10839c566ef64bde5624c325aeab7991e7f5d776c5310e8f41932\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/opasswd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33152,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/pam_env.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2972,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2285163,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ff4956721a3f53e56e25ffffde62fe4fa0267e5dd94c3411def12de50322fb8f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/sepermit.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 419,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2286669,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:885ec2a43042ad88d7f849e5e1cbef4e34e58229764a84a927c0e09cd7d47d70\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/security/time.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2179,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2286990,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6802adfc8efc6168f87e98e960fa7d15e516a295fef7a6472ef5359527e886ff\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/selinux/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/selinux/semanage.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2041,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2288206,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:80464fb793459392ffbf1e79e57df3247a7b2fe413854f2c155848a0b8c6004f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/shadow\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 501,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33184,\n\t\t\t\"gid\": 42,\n\t\t\t\"offset\": 2289342,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1845e019de82ee247c38d602bd78dd32c53b156789869c53e447399f362d824\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/shadow-\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 501,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33152,\n\t\t\t\"offset\": 2289547,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1845e019de82ee247c38d602bd78dd32c53b156789869c53e447399f362d824\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/shells\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 73,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2289752,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ddbebd60d26dd772114734225c89b80ef95f3cffa69031ae2b6aaeda791c4652\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/skel/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/skel/.bash_logout\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 220,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2289933,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:26882b79471c25f945c970f8233d8ce29d54e9d5eedcd2884f88affa84a18f56\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/skel/.bashrc\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3526,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2290189,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:afae8986f549c6403410e029f9cce7983311512d04b1f02af02e4ce0af0dd2bf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/skel/.profile\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 675,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2291873,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:86512cad76131783f5dae4346ddc3fb39f6f7c0f74b3039bff70ca4015ade034\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/staff-group-for-usr-local\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 771,\n\t\t\t\"modtime\": \"2012-06-09T10:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2292362,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:64a482506f00572df1d4909a347d6f4fa8e6ce23686b7f058bfbd650ec0658ce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/subgid\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/subuid\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/systemd/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/systemd/system/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/systemd/system/timers.target.wants/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/systemd/system/timers.target.wants/apt-daily-upgrade.timer\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/lib/systemd/system/apt-daily-upgrade.timer\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/systemd/system/timers.target.wants/apt-daily.timer\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/lib/systemd/system/apt-daily.timer\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/terminfo/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/terminfo/README\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 212,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2293065,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cfc3399b782bb0ecb14b9727dbd5ffd82ef774d473f6c47c39e621f8f4850603\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/timezone\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2293303,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f0dcac7b1d721d2f68937a71f0229b4c4f88564fd711339951528889913cd85d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/update-motd.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"etc/update-motd.d/10-uname\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23,\n\t\t\t\"modtime\": \"2017-04-04T12:00:00Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2293453,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1dca09550a75048731bbd17f17e027cc71ae50a86e0d911a8b3813e88d9b5ab6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"home/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/init/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/init/init-d-script\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5643,\n\t\t\t\"modtime\": \"2017-02-12T21:55:39Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2293643,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:31c2f323e3ea8d633880fd46f35954e2e91139c254c887c17cb06add05ef20e0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/init/vars.sh\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1212,\n\t\t\t\"modtime\": \"2017-02-12T21:55:39Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2295656,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:49d734860b46c62805fc29a67b9d61210113b6eac2409e4ffd5cf14589f4f0a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/lsb/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/lsb/init-functions\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 11510,\n\t\t\t\"modtime\": \"2016-11-25T15:00:10Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2296440,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1ca0a1b8aa2acd634075589ef49172d6125e8f7cada2069b8576fc090c953eb5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/lsb/init-functions.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/lsb/init-functions.d/20-left-info-blocks\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1088,\n\t\t\t\"modtime\": \"2014-08-28T23:04:48Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2300293,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:10997f92734d15a0a49c153f47cbd11553a2f3d8132f7191e6676a69444f8810\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/systemd/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/systemd/system/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/systemd/system/apt-daily-upgrade.service\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 238,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2300807,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8e4b846bd3da8819c6c4101556742239234e2cb3f670418fdbfe33606b2c5ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/systemd/system/apt-daily-upgrade.timer\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 184,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2301099,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b804d7bab8eb41202384f9270e25d5383346ace8b3d7c4f5029c150638d77bcd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/systemd/system/apt-daily.service\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 225,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2301356,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aaec2cdb7384fc2f5c75105e9daf6b3f5dae507ab6bfe1ea2fb7fbb8ff112c7f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/systemd/system/apt-daily.timer\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 156,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2301626,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0075e974af4e3a94757e219ba50ccb8348d4d1a8834d938f6cc9b1f4fd1db4e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/E/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/E/Eterm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2267,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2301908,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:599e0a90f89a32e077f51ec8a86540680e4ae1faf99c539bc357a693b892cd6d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/E/Eterm-color\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"Eterm\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/a/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/a/ansi\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1481,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2303240,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:93ec8cb9beb0c898ebc7dda0f670de31addb605be9005735228680d592cff657\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/c/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/c/cons25\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1502,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2303991,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:acd69b88fbc9045037b562dd67c876e88cc5d2616af20b9ca6c41d33ee335606\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/c/cons25-debian\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1519,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2304827,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0437ef75abb06ca00a0ca444a8aa7402276b7217a20330217c84b59fdd8e0b4f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/c/cygwin\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1518,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2305668,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1a9b75481dba09d8f73b9b13f39d52db026bfc7ae8eb4de1d250388756445dbc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/d/dumb\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 308,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2306487,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:123c85a2812a517d967db5f31660db0e6aded4a0b95ed943c5ab435368e7a25c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/h/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/h/hurd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1570,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2306686,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d5dc00724a04eb3b030addab6914380521d40f416818943171070ec64c623607\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/l/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/l/linux\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1788,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2307548,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b864e16853fe9aa36a43abd59a3d349026a993a74bc9775880cafb1c9bb6675e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/m/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/m/mach\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 617,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2308528,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ecd31c58040e5908eb434514e67620b2e4be538655126f427155760b273c7e9b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/m/mach-bold\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 652,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2308967,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4e4400e3ad4df2dbbf90920860c540cd72552ca71a24b556a0b6ba62fa091b84\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/m/mach-color\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1095,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2309431,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5caa825bd606e26c8b6c55a3206eccfea525e788f74da5e7cb48cc713db52239\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/m/mach-gnu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1056,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2309925,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:99372cd399478be723230692595362004df345dee6c4145e4d109113a2357717\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/m/mach-gnu-color\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1318,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2310545,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e1c62541670d0e10fe46daabce8ce95d9fd77115a68106e5eb2c2a7647e40a13\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/p/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/p/pcansi\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1198,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2311246,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ecda9662049c96ee0a574f40cfb8950b0198b508b5b72a3de05774eb3cb3f34e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/r/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/r/rxvt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2078,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2311812,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb5b104f26f34e48f9ca6b5626b1f2247f82548b198ae28aa0524b2bdc345557\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/r/rxvt-basic\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2034,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2313001,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:43f20d35ddc7766d030e99d0b850a439e6d97a257aea86ae61bc52b76131d5c1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/r/rxvt-m\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"rxvt-basic\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/r/rxvt-unicode\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2508,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2314190,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:280165734528e93ec7c770524e8ce3a3d29dcf5ca5696dacd093d1eb5ce3460a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/s/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/s/screen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1594,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2315571,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2354bf40efa7c42d938abc9091da7dcfd80b2fc35bbeef6e16ae2e77ffa6a28c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/s/screen-256color\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1912,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2316442,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:15c3d76efa9475f696ca7f73a22dbe0e91a3cc1d2f316d347577042c6534b154\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/s/screen-256color-bce\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1924,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2317434,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a12dcef9fcf27bb68948d692ada56b088ff9c00e902c292447e3edd4ac349a2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/s/screen-bce\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1590,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2318437,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:479d4fc2e09e17723741a8f69f79dc59f539e28be6fd1dbe9853a54675c8ac71\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/s/screen-s\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1612,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2319302,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:93b4fd80b4159ee730b1881d747d7d173bfd69de3eb6b5325dec66e4f61c2dc8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/s/screen-w\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1594,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2320187,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a80c790b6f86666214cf9189f67581502a4cf74b8d1ce8001d3bba7ce82221e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/s/sun\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1004,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2321051,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:02e392161cb23f49a8fb1ba2f1a6583e013c0c26672f58c5eaca828db3b19914\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/v/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/v/vt100\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1194,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2321583,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c919070d5dd70856abcda7993ec63680e0a30b997693926301a2049b419d3fb9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/v/vt102\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1188,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2322290,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5af8abfb4747049ccde158eee68a8b8138528ece70fddf31b5c85afbdc03dd67\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/v/vt220\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1377,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2322998,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:75a4723bfcdcd22756366838f1d65233f386d7592b019740c8ca5b578e9a5857\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/v/vt52\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 470,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2323827,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d8e7d40be89fe71e5d2582caa5168fe53ed85d9063e0ccf42e5c53f4d17b069\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/w/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/w/wsvt25\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1597,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2324150,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:28d3410e6b83a3b78a41f108098ac8772a3af3ee2b627b9f9bb4b19b363a5be3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/w/wsvt25m\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1607,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2325046,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18c85db3b0ef0ab15b7eb8dc4ac6ea14a37d851628220c8bb61e2edfa4f81683\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/xterm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3360,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2325980,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c51120adbae844f9bb500711c753335bb3235192e54dff4f576bf56d23c51a9b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/xterm-256color\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3430,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2327737,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c820689eed8803db2741a0c0832eb9049ab38ce65670b0ce305ca286f15f921\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/xterm-color\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1569,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2329533,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0b270450c7498756c0e99cfb24341e68f7443344adcf1656e30a0333e48f550f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/xterm-debian\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"xterm\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/xterm-mono\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1515,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2330325,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:183c527a8cbec5b5fef3eb8c28473a0530317eea7d01150eec74c01a214fef59\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/xterm-r5\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1301,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2331036,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:82098ec067be6189e91e8264278bb85fe3b7bfdeaa3754be301313be140522ca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/xterm-r6\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1491,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2331654,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ee12fe6d2d8e1d0b83d1042fe8a38f1aed6fd73e2c7316e6db5ec5b061b09ef8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/xterm-vt220\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2316,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2332359,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bbb3183473a03823612e1bdfa6d4ba7207b36f37b688cf45f217345064f9bb4c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/terminfo/x/xterm-xfree86\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2265,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2333528,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2c5638bcc74b380e8d70032c88a5920b116bfd5d3ef84168e9b52a0c217c9a9a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/udev/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/udev/hwclock-set\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 776,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2334755,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bec691723c892b77efe3c718846c2f320b4218d6448c8cf71d663e3be8396564\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/udev/rules.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/udev/rules.d/85-hwclock.rules\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 204,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2335252,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a65b7d818578fa91ebc00d086964c0528fa28d0ca04c54f11009c6c375f3e158\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/ld-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 153288,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2335549,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1e73928ade92803c17729c193954735d3ca8d22e228cd95da4cb0c6ed8996df6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/ld-linux-x86-64.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"ld-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libBrokenLocale-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6304,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2415597,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d4743e9fdefe3c995545d378713d7bd8c756d554513a74e9e6413b8941ad1b19\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libBrokenLocale.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libBrokenLocale-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libSegFault.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18736,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2417375,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:23d3c4e5a8cd6ebf20fb62bca2b5bacd9282dae432eb0eadafccaaf17d9e3ab0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libacl.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-02-06T22:10:44Z\",\n\t\t\t\"linkName\": \"libacl.so.1.1.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libacl.so.1.1.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35488,\n\t\t\t\"modtime\": \"2016-02-06T22:10:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2423409,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b9c9311dbc806b487e098f844b06b68070b8681cbd4f71511f29647c188e9f1d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libanl-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15024,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2439331,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c7575604b8072decb9046118d5e650111428db5cece0aac60fc280a2c2f051a9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libanl.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libanl-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libattr.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2014-09-08T07:27:07Z\",\n\t\t\t\"linkName\": \"libattr.so.1.1.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libattr.so.1.1.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18832,\n\t\t\t\"modtime\": \"2014-09-08T07:27:07Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2445552,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:290a147cfa1c559e27bddef432a125c91f6ba8d3bad33555d125afe2748949aa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libaudit.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"linkName\": \"libaudit.so.1.0.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libaudit.so.1.0.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 120752,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2453677,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:11f89d5e0d0f069eeba5210970669602983da5a0f136a108d5011bb3f96e5119\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libblkid.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"libblkid.so.1.1.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libblkid.so.1.1.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 283464,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2497883,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:95780e2f163855c81b56c94c3e40266d7d1b9cfaa472b0d7d252e90d9b6c3a23\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libbz2.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-01-29T18:30:31Z\",\n\t\t\t\"linkName\": \"libbz2.so.1.0.4\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libbz2.so.1.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-01-29T18:30:31Z\",\n\t\t\t\"linkName\": \"libbz2.so.1.0.4\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libbz2.so.1.0.4\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 66992,\n\t\t\t\"modtime\": \"2017-01-29T18:30:31Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 2625921,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9ebec8ea0b22a7e53f4b24d3e543120454eb228af53fa641eafba6f5e3824cb2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libc-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1689360,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 2657158,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b2c8bf64c2cafdce5cb263cc100749b5e6b3e4783eef2fff16ae1b4bc5633e16\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libc.so.6\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libc-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libcap-ng.so.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-07-03T19:04:40Z\",\n\t\t\t\"linkName\": \"libcap-ng.so.0.0.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libcap-ng.so.0.0.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22944,\n\t\t\t\"modtime\": \"2016-07-03T19:04:40Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3402905,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d6f690e38dee69b10da966bfbf594345328f57993453a0e5606a950216d8e783\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libcidn-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 190888,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3411878,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0f04fd41040235d4aff6bca686da46d8fed6bdf78b6011496fed4f40cd6b8bb1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libcidn.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libcidn-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libcom_err.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"libcom_err.so.2.1\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libcom_err.so.2.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14248,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3472898,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d4be0a20cba38d6c62e06ccd45b2142f8fa798227d6a0a41ce98689940b611a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libcrypt-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39256,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3478207,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f52cec1c11e6d0023332a319ba9b7544450bd252a5b1d4853cf8095de9c13407\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libcrypt.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libcrypt-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libdl-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14640,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3496376,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:91a225e90a28326285fac19ea582e32bf02bbc081d6be78df6326cef8e97eee9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libdl.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libdl-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libe2p.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"libe2p.so.2.3\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libe2p.so.2.3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 32264,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3501377,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dc040f0ec8112483eb1f26986ca459f15fe45d4ec12b20cfdd8877dde0aa8717\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libext2fs.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"libext2fs.so.2.4\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libext2fs.so.2.4\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 331536,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3514555,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fb1d8fb387e6f452eafac6f1b428b38edb8c124d0302daed21bc3f111fd359c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libfdisk.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"libfdisk.so.1.1.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libfdisk.so.1.1.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 381000,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3674215,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d1bc0b9de54b9b1400ad86ff1ec9133801ba8dfe228be0b038485d6cb6a27b77\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libgcc_s.so.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 92584,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3845933,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41124e5da0f8d4ee3368868846bebc6bb8953edea57b1c481cf03f72bbc81e46\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libgcrypt.so.20\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-06-15T09:58:05Z\",\n\t\t\t\"linkName\": \"libgcrypt.so.20.1.6\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libgcrypt.so.20.1.6\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1112184,\n\t\t\t\"modtime\": \"2018-06-15T09:58:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 3889670,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:594967450ccdcbb04408bb8904dadef96ae2c9ec2ef1594a897e84c4af5cc1b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libgpg-error.so.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-01-18T16:27:10Z\",\n\t\t\t\"linkName\": \"libgpg-error.so.0.21.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libgpg-error.so.0.21.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 79936,\n\t\t\t\"modtime\": \"2017-01-18T16:27:10Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 4347769,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:24781f22c712ea9e073df0e72fac6d720d14f5e7bb7ae0f9729af188aadb038d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/liblzma.so.5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-10-08T13:11:19Z\",\n\t\t\t\"linkName\": \"liblzma.so.5.2.2\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/liblzma.so.5.2.2\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 154376,\n\t\t\t\"modtime\": \"2016-10-08T13:11:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 4383258,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5b8415cf12090162ee1086681eb2183c509962ffafed315225780a49aa35a205\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libm-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1063328,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 4465352,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:289922c95eeb611a45fe25aa04e445244095406837408629d4bbc8365dd85b94\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libm.so.6\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libm-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libmemusage.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18808,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5197320,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0a4f0bc7c7aaeda9cd9e406f2a7711b9b58fac67a02c00add2a5cad505ce698d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libmount.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"libmount.so.1.1.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libmount.so.1.1.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 313096,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5204144,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:52742396b967444df7b701ed146637800950fa7e3f144d77e850d6a0052286c1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libmvec-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 170464,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5345904,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e8f744c1124445b8d71d510288887424f2a0e681fc327babb78d9520fe8015c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libmvec.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libmvec-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libncursesw.so.5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"libncursesw.so.5.9\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libncursesw.so.5.9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 194480,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5442329,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e07d728762a9d3db0a3f914241133a0273b644c980476c5cae884f6198514cc4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnsl-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 89064,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5533494,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c27427576c4c2a418b1751e1a1b0b433d44e160be90955af78f8c95ad3d99ebc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnsl.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libnsl-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_compat-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31616,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5573691,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b20464e41de918df0a4d6a3654d6d4c7126a4691d640eea68e56512f2ee50b93\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_compat.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libnss_compat-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_dns-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22928,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5587677,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c825dd0cf1e0fa3d1c6027fe98ef37ef160ee05463a72bac5752af304e9299c8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_dns.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libnss_dns-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_files-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47632,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5598262,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05e233e28d802968e27b3e4524f15813052f38fac4a53dff5bccee49cc3bcf77\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_files.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libnss_files-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_hesiod-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18880,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5616060,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:96093b7999357700ccacfa9ad5b6bc17e8fba3db65fb01009eb46940b215afe5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_hesiod.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libnss_hesiod-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_nis-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47688,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5624293,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8ba7bbfb7eba66e468c8349e1d55e52d3156b7c0dc67c8f22b24501f56d0f915\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_nis.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libnss_nis-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_nisplus-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 51736,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5644935,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c05d785888d0a7e72d6ccc12d245ccfc72b5ffa9797d266a7d749d117d87e84d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libnss_nisplus.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libnss_nisplus-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpam.so.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"linkName\": \"libpam.so.0.83.1\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpam.so.0.83.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56016,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5667737,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:010b0a9d601fc5f020fbcea4e94fe406d15ed687b503f58d7aee4b5f6b436dd6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpam_misc.so.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"linkName\": \"libpam_misc.so.0.82.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpam_misc.so.0.82.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14640,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5692744,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cfa4eb5810c55bc5b3335531f0d5d1a8aacf8829983e22a55cc03dd91cf46b91\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpamc.so.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"linkName\": \"libpamc.so.0.82.1\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpamc.so.0.82.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14640,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5698007,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:143e37de8cb78d3d42f8ce5dd077026378c58e1aabca523039df185f6b83ef10\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpcprofile.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6328,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5703762,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3bf9a695f6ae82d14513ce4d620a62210d939579f725e68c6ee57771473bf09c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpcre.so.3\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-03-21T22:03:19Z\",\n\t\t\t\"linkName\": \"libpcre.so.3.13.3\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpcre.so.3.13.3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 468920,\n\t\t\t\"modtime\": \"2017-03-21T22:03:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5705959,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8e472c698a67150907281f8ef307f1b4df3f32e8a993f4943abd8182898b7b17\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpthread-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 135440,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 5886295,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d54f396d38b23c1111e8912fbbb518404efa0af34f66249634bbcde601e41b1c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libpthread.so.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libpthread-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libresolv-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 84848,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5940730,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4163c78a92525c3a541fc77988452a8ed5e9c7769f6414267fd0148a3514507f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libresolv.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libresolv-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/librt-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31744,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5983664,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:df94214b7c10737895d7a46236eff917ad66687551b8ba3906f134e672b22380\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/librt.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"librt-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libselinux.so.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 155400,\n\t\t\t\"modtime\": \"2017-09-24T15:30:16Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 5997619,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3f284c04405d5f7f8015347718f31c0e6239886a7d5c02a2a1c6a4f408e8323e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libsepol.so.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 623320,\n\t\t\t\"modtime\": \"2016-12-03T23:19:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6072745,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e1c8fb50dc88214875a37f46e21e486f1e092b00e3ad830889020c14e3a297cb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libsmartcols.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"libsmartcols.so.1.1.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libsmartcols.so.1.1.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 168040,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6342649,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6e723c7a681e702b349b2cd25949313e3e6c9d3aea240d5ccf445023d6592d16\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libss.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"libss.so.2.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libss.so.2.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26544,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6418718,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:225f7393cfdee69acf4ba224b9ac1686a52c2bb8473dbf588aea74d84863d7c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libsystemd.so.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"linkName\": \"libsystemd.so.0.17.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libsystemd.so.0.17.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 557552,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6428928,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:99c33261698212db4bef7bf5069641f963433ab92f3e87f8d1bf1103eabc1832\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libthread_db-1.0.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35744,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6681851,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:004d1374cc5a50f86616fb3047f18b099ad35b2eb8d563faaa63f872c28e50e3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libthread_db.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libthread_db-1.0.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libtinfo.so.5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"libtinfo.so.5.9\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libtinfo.so.5.9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 170776,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6695310,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:33626a82c73c983b4bd872e80cd9d8965eb6d985ac82d53fa1d3a21ccd4a2c27\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libudev.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"linkName\": \"libudev.so.1.6.5\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libudev.so.1.6.5\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 131344,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6759287,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7dd6fd6e3d6bfedc594900e40f9ba638144d4ba474de8a922501f5d19ab97a98\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libutil-2.24.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10688,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6818192,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05d83744f7cc822e5f0cb7053f439f04318bb017b176b132ced2b19e5833ab24\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libutil.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"libutil-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libuuid.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"libuuid.so.1.3.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libuuid.so.1.3.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19008,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6822485,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d7a0fbf91d6863b57af26dd5199c2a27a2d1691b189fb9bebcabfb6e573324a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libz.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-01-29T17:22:23Z\",\n\t\t\t\"linkName\": \"libz.so.1.2.8\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/libz.so.1.2.8\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 105088,\n\t\t\t\"modtime\": \"2017-01-29T17:22:23Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6830261,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7fd423a008f108094d410797edabbd5e3f28ec3110b0ee98fa7dee2b2c0426e3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_access.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18680,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6887318,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:741b9d0308461abade6ca1ca9a5c12f68ae6e8e60bfc2c5114eeac658040886b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_debug.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10376,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6894624,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ce1931f2608dc6b14204d3a883f5f54663d53163cc465fc0be38411493672dd3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_deny.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6000,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6897618,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a22d25e07a233c0a410f215a9276fcc7c1d0996ce5d6a8354220dd241759e768\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_echo.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10336,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6899273,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0df400110557b2acc88b3cf4f7e4e467100a79940a86304921e7658690f74915\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_env.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14536,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6902605,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01fd00b9dec9fc67ad9fc5f3ee2b0fb67d5578bfddc1fc6aa1d6f8108974eb75\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_exec.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14728,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6909166,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1faa12207908abbd20e26bc5bd660b227204126f961c65b095588f962c3bb886\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_faildelay.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10368,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6914974,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ce49ccfdad0e09bd00861c3d1a527e9214689a70e49791ada68273ba4ef09ccd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_filter.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14576,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6917932,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a3342745265703a761e19453c77cef5576c09b010cd3eeebf04df6b871234e54\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_ftp.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10304,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6923870,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b6fff572ca79d68c3079de5531730ebe229244593ed012619fe557c719502945\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_group.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14616,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6926757,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a55044f05f249a7bdaff776f5bbf367878910a1c8bb6166241a6b99f0c86dfae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_issue.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10448,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6932891,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fb5f07a6e14baf75d91f3414077a34be5bb8df4fdec1b8c825a631b0c6ffea10\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_keyinit.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10344,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6937095,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5a69822d86f9a9c08640479fe827cd041f0b28ad1948e3ea9d39199d5dc7c31a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_lastlog.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14560,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6940594,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94bc347d76d327016475c084a06654eeb16121aec0ff126c267ddfd63fabaeeb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_limits.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22944,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6947032,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ac02e973a5c9e2e2bb5f2f2061b3629f54993ba4302f80dff6a1ccf8636893c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_listfile.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10384,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6956584,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:54cefeadd3e76f9ea910689356f90941894692b33166466ff6a6ba8a6768430d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_localuser.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10312,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6960925,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b0d353746e2325d6adc1393fad9a40f2e99746b0d925974e46f96d2466c6c87b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_loginuid.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10392,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6963675,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:976ed19a2598c14d89261041083d5b79598652d5d523b9a0270cf810be71a91f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_mail.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10376,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6967126,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:82a5741ea520b1ebc626dc0908f2a7597ec0a2237c4d2074d119d8fcb02a063f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_mkhomedir.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10376,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6971797,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:73fbb80cb6b9148628fe7a4b78bb9d24958856338f7916cd5726d6b889687bf7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_motd.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10360,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6975182,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:311d8406f3e0ff395b92fc9fbfc87ccfcea7951b3cb96ee04d560dbd00fe1e9d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_namespace.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39720,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6977918,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:51921e28f0808e3f784b886bc5cfc1cb9eb5e6ef6fc01f719c9befe92807e9a1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_nologin.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10328,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6995679,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ff14b70ef4bed07e3b8418e32f3263e67fc4b97ab867a632bf5ef51d36861ce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_permit.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6168,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 6998548,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:125d4284c78f6afb87ecb34601b75d599125156f581a06976930c960e962c1e6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_pwhistory.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14664,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7000544,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9d0433c3cf7dff5334ca9feab51c2c959bef02f328bd1a6ecac1c7f83137116c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_rhosts.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10296,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7006689,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ff008965f47c629c01acdeeca39430a64ba5eeee423569e76f49af30cd938036\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_rootok.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10368,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7009385,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:659c269828c5fedf40139f7f50edc268192deec5b18ab37640c8d02e974b3ed1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_securetty.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10368,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7012344,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ada92bbe998f2c513721676dc3ad5624f4968f33c202cb137387b706b6ffb899\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_selinux.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18800,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7016176,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cc0e5a04e98404c89b5417f7db0d15924b37d0f24661a929860be2a302950ae0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_sepermit.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14624,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7024413,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:84722b688949aefcb8d5d093a7253ab794a3af787b8eed1abd6df5bb1e63c929\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_shells.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6216,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7029970,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e8130cb3fac5f8bb3af5fc799765591cbcd4f257c16ec36adde8e2e9afd8c269\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_stress.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14456,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7032470,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e5968c6d25951ad2b75857e0f7952d2e070937afe23bba64f4f9692967e46093\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_succeed_if.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14496,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7038360,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:800bcedbc816683381ec819c0b063260afadfc20547072b6fdfa34fe59f374fb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_tally.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14536,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7043619,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5e4a5d92cca63d8d48d282200d73d6c7bc2e951176799c6f5b6924d11cff28e7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_tally2.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14576,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7049672,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e4022de4f38434e19c4d7df37a64009cba2dbe4937616935b8547c7d4e8056d6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_time.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14584,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7056004,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:db7a38c09c845b85283618f8c5569f98de10475c6bb1f32fc21eae961e9acf6f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_timestamp.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18816,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7061595,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:220f806a68e43085e93f1041a1c30c31f5fb5c40967ccab3e60f0d5f6006240a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_tty_audit.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10360,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7070244,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2c0b59ae3374776f52ecbb8359646bc1660a9e90e00fd6a524181788af655927\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_umask.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10432,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7074204,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa93ee352ded717297820567c4060a511768322790f7b227284f8d6e77478a4e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_unix.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60336,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7077930,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:af89f5fbafa92beaa31acb1197efa72562ec0b5f633f3ed29211dfeb4e4bfa36\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_userdb.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14512,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7104104,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1b52f6baa4b37fa10c83acf9dab51cdb5cadcf26016a8926159460e4d11c3a0f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_warn.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6168,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7109253,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:579b9dd418f75343d13c850ade1166f5de83dd97cfa99bf04e2a79c0b544c479\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_wheel.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10320,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7111509,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3eb1b65ad1db5dcdbca14e261651021463b40f2988dbb3a90dde4a9dc884f42b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib/x86_64-linux-gnu/security/pam_xauth.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18992,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7114599,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7cf30ba8872ef595352d1e0ce316d0ba78476a57bda0dc4eaed265b9432a56e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib64/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"lib64/ld-linux-x86-64.so.2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"linkName\": \"/lib/x86_64-linux-gnu/ld-2.24.so\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"media/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"mnt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"opt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"proc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"root/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16832,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"root/.bashrc\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 570,\n\t\t\t\"modtime\": \"2010-01-31T11:52:26Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7122808,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41f1685d04031d88891dea1cd02d5154f8aa841119001a72017b0e7158159e23\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"root/.profile\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 148,\n\t\t\t\"modtime\": \"2015-08-17T15:30:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 7123253,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:74bc92bcf960bfb62b22aa65370cdd1cd37739baa4eab9b240d72692c898ef1f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"run/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"run/lock/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17407,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"run/utmp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33204,\n\t\t\t\"gid\": 43,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/agetty\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 57680,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7123549,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6adcf14685980ef53a00b82359ade7cb3373f620e7bbe3e9100f5cb2ed53a5a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/badblocks\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26632,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7148884,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6c22b8ac432d81bf31b3f443dbb2acc284a16ce094b95a61825752dee26c4c1c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/blkdiscard\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27264,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7161409,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ef233f2d7a23b1676923be2e0c55310cc648096b4ce268eb92454c02856f33d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/blkid\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 85408,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7172442,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b39bc5aa694d02a547bbe02a749ceb0fc141bc2956be48ac19d9056ca320c163\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/blockdev\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35624,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7211380,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7d832c9473c9718bf6a1d40f8cc6d61ab20c00f44dfb712d05c80dac22e3461c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/cfdisk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 90472,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7227436,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d3202ac1ca49497e274acdd85f85857a36d2299d47465e2bf2a0d92e0ceb57c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/chcpu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23128,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7267991,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:85f7dae37c72adafd7db37f7bcfba4d6355f2203d5b1a656ee5c347c5a14a6e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/ctrlaltdel\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19032,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7277888,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bf5470d36f33cfac7e6d701cf2ce612a871c395300f99d19483cd44b743914af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/debugfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 218624,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7285732,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:453270d361f09f1a18159e97710d81e924fdb9d7ee55326f033a861dd4d8e618\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/dumpe2fs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26704,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7378324,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2e0450a263144ebef2fa6682593b70c49c096a02555d93ea45f2620b6588c0db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/e2fsck\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 305696,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7389192,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5fe40e84f2369007c7102486a087ed8fd77df64354e2977de0c9316f050df99d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/e2image\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 34896,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7527447,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5bd6c8600fa8decb1057bf9feb055dfb93432a34161fbfcff4c06c588e91217b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/e2label\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"tune2fs\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/e2undo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18504,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7541953,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:78cf9a8072c1bd7295ccf39004203762468a3bdab1f154245892995b386ebb7a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fdisk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 118056,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7548613,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3cd2d0f2b7a9507e7d85cba7b07a149ce9fdf281d245853e5ea80c88e1a37c82\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/findfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10568,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7599475,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6627f4b74b0834856bc7c75b3df1a572b4e521405913847c9165121f56f78b19\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fsck\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 48328,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7602969,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fe5c55b3131424db749416881d406f69a909738f82a8cfe755179e82f9f0e255\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fsck.cramfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35680,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7624273,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0ce71a2e669b3d146d603e72b853d8acc736246653c0e60ac008d3653b66e604\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fsck.ext2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"e2fsck\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fsck.ext3\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"e2fsck\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fsck.ext4\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"e2fsck\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fsck.minix\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 85088,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7640929,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:11a4a0da6c5136844f52674889dcf3a346469f5c06f952a6e11b653558d4f439\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fsfreeze\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10680,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7679365,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:19c8eb6b70d539642ba85ecdeb101926bff94585c3640d206f62797f01e4b7c1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fstab-decode\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6352,\n\t\t\t\"modtime\": \"2017-02-12T21:55:39Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7683720,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2ffad77e711447254ed284248d3ba09af3a1448a29651080c1623ed243049c34\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/fstrim\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43992,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7686161,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2069a7cd4120fd53a7105dce987ab07c2428dc85cc16eaebfc7e6ce925cc615e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/getty\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"agetty\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/hwclock\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 64528,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7704830,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:deb501e34bd14fd38f60af8f4409fb53655845033f77bba564edc9d7f42e3b13\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/initctl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 253,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7734039,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:62d14f76b1641895a5ae24a7ea65eb26dd46dadb5ffd9ca356856530ebb822e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/installkernel\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2638,\n\t\t\t\"modtime\": \"2017-04-02T17:10:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7734314,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ab0bedb106c10aa2c2ce88ca6bb9db1a973854049b36a9961a532c4496051815\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/isosize\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23160,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7735645,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:12d7d7cdfeb659bf7f652f9b0cbb6bd24b179b390ecb9222df3cd163eab63997\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/killall5\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23224,\n\t\t\t\"modtime\": \"2017-02-12T21:55:39Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7745675,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a00fc547beaadb6ecb7496a8aa9e79c05c27e45a452fa179977d722de86daa90\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/ldconfig\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 881912,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 7755155,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3285f67cbc98d087914ca23f176377383a40351bd36d92f988643b9f048d19c6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/logsave\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10240,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8145697,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1dbb0bc743b753ff4fd705853d6943b7b8188c46ea28aa75ca0df2e8c22247a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/losetup\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 81120,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8149804,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:68fa149ce22fb59c02ab0ec40ce05b9ea80d08056bf41cc8b386e287f7102d24\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mke2fs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 125248,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8186566,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9ced556c67781a6b31069438b3b9d5b499077dbd566317d4485d86a5256806fe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mkfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10664,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8243659,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69dc955885b589730049a14d6caafff16f0370951bab247a491fc37497138486\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mkfs.bfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31400,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8248092,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9fb75647f280ab27b35c95f021a55545d6372c8e46f4b58ca2c0c77ceeff85ce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mkfs.cramfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35456,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8260743,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e13447f68e32306467bf895234bf673fead8e633ce30c195d6d3f1db4469b6e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mkfs.ext2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"mke2fs\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mkfs.ext3\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"mke2fs\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mkfs.ext4\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"linkName\": \"mke2fs\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mkfs.minix\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 81016,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8278232,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:53b162d90a37217a12257d77ec8239b956e7784603ab1a269753e96592e0e3d4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mkhomedir_helper\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18848,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8315583,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:83450062779f8461cec78e65ce86265d6eff1875935ea1b3b9219af3261e0a94\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/mkswap\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 81144,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8320055,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cd1950bdb7206435290914fb502c1bbd67776ec4f609bbf4d840bc93954a757d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/pam_tally\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10592,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8355762,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0f2e66063fecae11a818631269b535d57b75c1ed6d9ae02c42455fd17291e0e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/pam_tally2\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14776,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8360230,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:96e3830159176453765f5cccc56c53df9869c47750ae5783ba058dfdb6e4f59d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/pivot_root\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10640,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8365639,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:857da20329f563fff5253f774fc47615a2ba9ac236aefb06178d2a6bc3cf92af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/raw\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14784,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8369059,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:802c354e5487c50f1083fd1d14342d077c220234e41219c798e9bc288e8cd8b1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/resize2fs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 59464,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8374050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e3ef18176cfb7fe20a71c285ce425603ecb9c60a828e41e71c8d00656ba2cd1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/runuser\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31816,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8400304,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:440a23508224db42e4315796a4f8cbb88c613cd4735ea634de2b4eaaf6be3b2b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/sfdisk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 106656,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8413762,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:754823d46d2538d9eeb5f9859a989a6e757eace3b2e036334b2fb05a044a846a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/shadowconfig\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 885,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8460396,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e456ba3088c0cb498ba86d9ce496273138e9cfe523feeb1a7e7083aae349dded\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/start-stop-daemon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31848,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8460821,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a8b2eaf2a3a97f5bcafe7ff1b84dc2157510ca38356b54c91f037d89f286fc10\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/sulogin\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 44208,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8474664,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e0855820d16f2bc3f054c7e1be69c79800a9c96e6538b7fdc286e317a2bdbec4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/swaplabel\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14848,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8495674,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c87ea0de1cb075f4d811137106811c53af315eb89286f99d4fec05142c671af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/swapoff\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19104,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8500908,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dcae8e64c12b6efb0de4ddfbb96ba7133fc3a2c109dac31b272b42ba95e55961\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/swapon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 48488,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8507986,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41683c62a58c1a5a718678d8bc38f69dd19e2ed19635dd8056126aafd57bda4c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/switch_root\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14800,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8528257,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:faea48ed6d9dafed493aa055914886c4b5bc6557af5d22242c9609816e5bfec0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/tune2fs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 100608,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8533221,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0879be617e4b224d9a560376ff1a3897d2f989f8ddd6a6bda090496cc10ee24a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/unix_chkpwd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35592,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 34285,\n\t\t\t\"gid\": 42,\n\t\t\t\"offset\": 8578992,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2a80b648171dbdc98e867fb9fd54c5f03509a4eb475ee6e3c53b6f03908edb1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/unix_update\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35528,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8593770,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b15b766a76d7f947906478c52e9b6144585499cc3304e2bdffbadeadea8bba7b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/wipefs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31536,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8608004,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bfb983f08b7ac1ba294bab99e8162600b07f73eb4a89e69214390c3b6dd349cc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sbin/zramctl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 93512,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8622200,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:367402816b433cd360b6038d50dc849736de44f4df104295907cb319ef6f3fce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"srv/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"sys/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"tmp/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17407,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/[\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 52008,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8664038,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d204b3e80ec8a1004e4fdb3a6a4f908ec5f267c0a28449cb95af9e1b69f2e572\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/addpart\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23072,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8688508,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:412862f7dad64eb66e614d87cecf30359bda3896be474a54aada5c5d241af679\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/apt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14424,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8697489,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bf44404ddc8b2c0a38dfb3e1a9e6425d2ab8d8760b1a267d759b6b7db1e8da91\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/apt-cache\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 80032,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8702450,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e181fc48fa88009dab8c35cfe8f01fdf3958ecd92281e95aedbe0dd5910214cf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/apt-cdrom\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22688,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8737321,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9c694896977ab9e2ba656267c588970547ff76ebaf636b418fac3ef934effcbb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/apt-config\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22616,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8746221,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d122c30960616a613c979f9df23776eb226613badcb6d1af69b2ee0c516051ab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/apt-get\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43168,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8755464,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:61e6dc14f653378466cfbc9504b3e34eeb6911878ae93a7477a6570ec169d241\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/apt-key\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26269,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8772706,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:945c55192dfc8dd7d55bd4f332943d3fd7107a64878512bdc26c2ddf0b044ff0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/apt-mark\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43168,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8780858,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bd5e981cdfaa500cb9753e62369e94c599f041c96c4c2f12c25f12cee0f0b5ef\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/arch\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35592,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8799713,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e5895e2f65d872985b5a0c18e5b195fa1b94a8f6cd40e91e597d711b2e17bfd1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/awk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/etc/alternatives/awk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/b2sum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56200,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8814671,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2ab02e2d0f12f71322da010a896b8937b6bb18427b2899e3b2e2ce214c38b1b2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/base32\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39720,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8839271,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:40513e3c1d21c68a756fd4c14bfaa6ce686e61d242981c07b3f412d488504b20\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/base64\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39720,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8857666,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ec4ba544c021045e3272a4bfd195fb2f047b27f61a45fe20f1f672a24637281f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/basename\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8875974,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b79987e26f5937e8a8122541488ef2e57eb2f0f68636fddc00db04c46c888558\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/bashbug\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7120,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8890872,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2bf2c1619c223b4a5041b8319c275a0fbb0798114d320a4a58eff23f0b3a445b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/captoinfo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"tic\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/catchsegv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3302,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8894112,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8d4b393b1004e0e15bc9d7db1c83692d5e441551c9f254d0976210c4f9d49069\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/chage\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 71856,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 34285,\n\t\t\t\"gid\": 42,\n\t\t\t\"offset\": 8895804,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1b4cdc81efd9aba0b4d3dd5a18c34f4573b3260074c785a2ec3494b3b7c73a18\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/chattr\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14336,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8924236,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:503f92590d4a6a65e284f5ad70606a2c3e80680a3b5439753b99341104145807\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/chcon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 64520,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8928860,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:68642e97d0d27f8f136c5893c885d8b590a9b1573c0f97dee223120da5b5fe3d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/chfn\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 50040,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 35309,\n\t\t\t\"offset\": 8960141,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c25505dbc0c17abb8d1bf59e64020c3ee0ca3ad4ccefe3a90480fa95cb574843\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/chrt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31496,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 8981024,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f235546564c11de25611b61a607af7811220885f16cac017d8f9607d3089e2bf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/chsh\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 40504,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 35309,\n\t\t\t\"offset\": 8994743,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ef5f2f8a8460950fa1a37736c226cdcc435d7bcf85e15ab90830ce445423b3d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/cksum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35592,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9011530,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:42b99d097670fab6cffa6b619276c5c0912912576759d22ee6af10c7bfc12e46\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/clear\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6136,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9027982,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0efd2a25ce5ded9cc58e7d1913cbd2bc61f0d7dfacf73bea2138e1fe1f7f4070\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/clear_console\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10552,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9030096,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8bff03727bb906a63497467f0e2352486613fa900e26df2a4091f950d3dfa9db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/cmp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43768,\n\t\t\t\"modtime\": \"2017-01-09T22:55:10Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9034088,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ab79ce775431d53706e8986609129837341a9c44b2599302e44307d02f4be312\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/comm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39720,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9055725,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:590005cf6262bc933fd5f15d29616a7405a801c246c49a724a407540e81001ec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/csplit\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 48072,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9073796,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a0f6057870475b80a03ee78071dfd22df815b8ef6955a26e1021e59cddbbf84d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/cut\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43880,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9096748,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b69c459f0d6a3e85e7368f594d4e0bf622250cc57a13ff6c389de90fac84611e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/deb-systemd-helper\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 20142,\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9116708,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:10b3c17c0f82dbf2e29ca3a8b353237fd198999c541599a5b48f44a00b180020\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/deb-systemd-invoke\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4507,\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9123064,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e96ed9793cf4bdeb41fe5990323d76b7b33cd950c53828b395e517377f9127f4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/debconf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2859,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9125100,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d365d13eb1dff880be7361e4043d25875075776445d4edd1eb4fb1e451a2e41a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/debconf-apt-progress\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 11541,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9126558,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:93fb257df4185cc6b83858bdae3c7aec0a4f759a848c743a0b0fd7c7091cf34b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/debconf-communicate\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 608,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9129978,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:705b8ce793f999f21bf2f20348b390738a139116c9e483fb39165a508fde4d27\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/debconf-copydb\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1719,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9130436,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:085ff55904c81115d8d65f8862f0a5ad393e062da3047762e4d9cd4f5ba761f4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/debconf-escape\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 647,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9131309,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6c17a536ca0fcefa24a7d37f7eaebc02e774415b3160836918cff6cecdef807d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/debconf-set-selections\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2935,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9131786,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8085a988bb9850fd9a3405c8a1f8e643c197811f6edf53dfc5ad20ef85040224\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/debconf-show\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1827,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9133035,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9dd0bfe9a51d92af868012a32a8190b83a6f4b0834385d12033732b24ee2ceca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/delpart\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23072,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9133931,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e5ebb3ec95a1cfb3cfea4356e1b5b356f052270bb3f29b41ae169cfab13eefd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/diff\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 146824,\n\t\t\t\"modtime\": \"2017-01-09T22:55:10Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9142851,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f580a4abfc32cf085085e532b9d12477cb955879a4482cc2281e201ff3749343\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/diff3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60360,\n\t\t\t\"modtime\": \"2017-01-09T22:55:10Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9214889,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ceb327f5400a38a7e85021dddf454ed114c61c8472d703b8e61031c5ff20cba4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dircolors\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43792,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9244499,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f735068729c48d617ddc88845342a191f46b5306ae2e358925f0d6ea71497175\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dirname\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9265069,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a1a02e1267047c0a568b7f97c28ea351331e9a6aa035ec84fc6c85be0d1254f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dpkg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 293376,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9279590,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f59b2bde8f707858160374c6d2c7929bc82737af4ec27a027c0e6c7f40902d04\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dpkg-deb\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 149856,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9410564,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a66f16b41551031cbee4f129339043770ad7d4eaf32f3842d672170c8acadb1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dpkg-divert\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 141728,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9476405,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c05f47fc6dbbc5109d2ceb9833ac1d751ed6203373a2a7b04dd00972d3768c8d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dpkg-maintscript-helper\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19030,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9539989,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7183c0a85c8b309d97d6a9713b58fa4cfbbb2287404c1741f781f56b0c829a23\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dpkg-query\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 149912,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9544415,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:be6a64db2186874046a857578c6927ca09c82f2b0f28d33be035c25a6177cd78\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dpkg-split\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 117080,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9611851,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fdcc92761a3390f7a5cd2a9e906daf8ffb5f50eeb3eb7ba781224fcf18ef401a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dpkg-statoverride\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 71936,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9665324,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f1f690ef016f4e17b0aa8df4ebbe303dd908c24ef3475418abecc774be00c22e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/dpkg-trigger\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 67848,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9696355,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d1eb6b4ef3af26b32852e8d2beda588fc1f5ad8713bbd58c63d4f20cd5853aa8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/du\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 105640,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9725993,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:62c8fd7bcf8cb3fe6426105f997aa5334b4a5a99bbea189506571fe305d34447\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/env\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31496,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9778101,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9e41c33c216856b3f975d8442e782e78497d157b2aa099189a7c8c44ce069b03\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/expand\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35624,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9792776,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2357a0c300183ddda4b593ad4ecf639c6e8e0353ba13af1b980420ecd3d0df77\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/expiry\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22808,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 34285,\n\t\t\t\"gid\": 42,\n\t\t\t\"offset\": 9808891,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e7e79217ef4aab5c4e1fc12ab6487333e1398572d0b62e57341ed9bac78a0f27\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/expr\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43848,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9818087,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:824957efaf21e1e78bee63a4da3ee2d9ad64f8ee8b0a03d6d88b2e254c65c259\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/factor\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 76680,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9837814,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d86bcbd395838672f0bde8b3cfb5c049028e925ffa94eb02ca684d0188f8931f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/faillog\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18728,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9880668,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b1386c2f119271d3c3771a9b9d37975f695c44fa84fca4d7e1460a5c9a8747c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/fallocate\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27280,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9887976,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9101a2ce5c3936bde40dce3b92116b8cdc1b9adfd3553f45aff9048e1c4d4812\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/find\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 221768,\n\t\t\t\"modtime\": \"2017-02-18T15:37:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 9899287,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:97c94127488a66250e93cf93f475258910992f160e222166aa5c2a7890410b62\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/flock\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27432,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10003466,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a711e2146884827b952e586809a51522f4aadc27396d0e23a1f22dab91ab4843\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/fmt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39720,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10015776,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e13ee863ebaf2e03d0390430c42236c8f07a3c204fc4ae225b8a48d98a18fb1f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/fold\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35624,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10035417,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dd7b3f381567876171d71316d5dc5a56b096b5cac07d0eca22c1ba0f880744ae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/getconf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22904,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10051803,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bb1ed5c8b5f0df1aa51624ddb6996ed0e70cfe85d07189384a4e4f6cee7032dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/getent\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23872,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10059112,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4cb3a246795c58c1134e0b6ce2abfb4db667b6d517b687a8a782ce369f1ede7f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/getopt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14840,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10068699,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:73c12040481a67e5a4be643d6fb0438383e20bf03a15bd08973150463ed7d394\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/gpasswd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 75792,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 35309,\n\t\t\t\"offset\": 10075055,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d92f083fc7a6638ee7a3203e7e55de3bf0e539e3f5849e8cb5644a12f1d65698\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/gpgv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 420496,\n\t\t\t\"modtime\": \"2018-06-08T18:12:24Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10106103,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0948d08c3939b9060186cf5cc5337f1c4ac6752bda5b80c5bdb2fd1c4a517886\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/groups\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35624,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10321770,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:acc452e8dab94df9262cd81258c97fbf0f319418bd90c33ecc3a5cbdf72a20bf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/head\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43848,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10337294,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a6469ce6901c72f2d80b27e637998d0894adfa5468b812d74aca74e6f2837153\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/hostid\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10357448,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d436a899df1651fa756a3dc8af940333c331315c10e55642d06f4e211798ac5b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/i386\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"setarch\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/iconv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56328,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10371529,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2139423a0d8c34211eee59501ac82f6420a08aeaf4d4118b87c9551fecee6aa0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/id\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43944,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10397042,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a88307cf73282e6b7aa985eccb065711323674e1484a8754103b7254d058baa6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/infocmp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 59464,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10416302,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ebb18b167aa6b5c798174adb9b5e706ba65b37dbe3a6ac8b56f387db11c595d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/infotocap\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"tic\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/install\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 138864,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10444204,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:51522c627f0a50ef871c35c81b8a4f1d153e4cc7e2df8357abf3681693af72d8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/ionice\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27304,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10512302,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0b23a47f4e71dc982bad25d3284e61f42b29ee2d99a413c89ee41a57c3dfccdb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/ipcmk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27416,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10523063,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:734a8697d86f4689634039981c11637d69856738a5d27c3c08338b3883a2adab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/ipcrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27264,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10533925,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ddaf50c3a72c430630693ce22f3c489feff0b9fefd0deb58eec8dab46a04f1c7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/ipcs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 52008,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10545492,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b1ff7436abc1fed72b616367f7aae26632bbf2ac81591888dd987a5c7f909d00\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/ischroot\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10552,\n\t\t\t\"modtime\": \"2017-04-02T17:10:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10567108,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:70a15af1786a0de15ea8fc910b203d38b98790ae43df5efdd24534a51f358b47\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/join\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47976,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10570592,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:97469b77f991fce4f29ffaed18dac01e5d8b7559aab02d87a39580244599a03c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/last\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43880,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10592860,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1dd54f2f90d9ba5d7b60c8a0e458606a6e38dbcda4c02dd7123402ff3c640358\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/lastb\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"last\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/lastlog\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18504,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10612362,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:57eb32f4479e2b6c49780d6b6bb7c84bd96c1c8b28565d97d8e45eeab2138e91\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/ldd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5395,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10619060,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8fe75b6fdfdb63c4cb7710f4599a240a8e9d74b49f7b4354f00852afbb815a8d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/line\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10648,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10621531,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:53c72b327830b2a6a769336fff7a957976127f3be818fa13b76023eccbf5f8ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/link\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10624948,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ad85507f80593524834b45e173e6c7d25edef521b09388890cb2237480b0972c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/linux32\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"setarch\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/linux64\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"setarch\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/locale\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 38824,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10639221,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8014cd1cc08fe903a26756458680e5b3d5cdda67e77f35b35553ba2366b1bf8d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/localedef\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 302784,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10654128,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7897c88201f7e4b01a8f37578c79375e0d013005d3729bde488b3ca12826dc40\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/logger\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 44472,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10787530,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b39fdf305c3a2778a1c016ca4551d468707492597e5e8886cf6ecf0039f4f62c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/logname\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10808065,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a58a0693abd829aeb1da6f21723bdc9f27a23f2ee5e7b8b9e493a56144d5808e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/lsattr\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10240,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10822124,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0098d84be8685553ffb2e2a07aebb771e1ce6fc9362a549a0b1e9c8c8e199d4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/lscpu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 64712,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10825931,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a9509ab607c61d6bcba57ca47556b8cbbec51d75d1a8c9b083a9e92f79140c29\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/lsipc\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 72824,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10854951,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e5806384fb3b1d5c58521098a382a534a909de3f892ef6f28135ecdc29826946\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/lslocks\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 36008,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10885523,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5353616c18ffc2a8e0e60f5c02edad6e4448484d70a5c47d9621f5ed0cf00a66\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/lslogins\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60696,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10900854,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ffb8b19b306970bde5485c3bcee17303a7615287ce4d688b16edb9ed034827a5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/lsns\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39800,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10927568,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:17501abd11ecc79d079aac38ba9ebff3bc3f152c76983f90686abe714c69d26b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/mawk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 121976,\n\t\t\t\"modtime\": \"2012-03-23T20:15:00Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 10945121,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3f791f82e19d9723c55fe3fb70e85a19c1663e5b76936293fe75070667a42cba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/mcookie\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31528,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11005973,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3b0404268fc5504d4e9bd525a1848ccb92b6a81915f2756575531e6297864872\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/md5sum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43880,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11019661,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:08c9ecb479710c1a5f548bf48b722c7ef03054a1741116ae0794df49a5fbb9d4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/md5sum.textutils\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"linkName\": \"md5sum\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/mesg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10704,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11041129,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:92c01c7ebdbbf0a99a01dff02ee410ba617217ae9eeabe30745f9e82b0429593\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/mkfifo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 64552,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11045233,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6128655aea11b8cd2b24737829c22a3849d3ba76f2ed2c272c44989a595b43c9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/namei\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27296,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11076521,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d687cece51a5f5dec3f16e9471fbc069601e31a922e419aa5bb6f46848d2aec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/nawk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/etc/alternatives/nawk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/newgrp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 40312,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 35309,\n\t\t\t\"offset\": 11088866,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6fe1acc3cde9a01dd79aea6295ade4f77a6bb409f16a8fc0e807f7b26a9ad7f7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/nice\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35592,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11104827,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:02174675c94855def605d70484e0c5a9d41b97ca4d9188ed1f2e702147122068\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/nl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39848,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11120628,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8fa1c7f0a5b967d98e52f57641b3ab7a60a2e30b6dd3e59c1ec02f7e43d536e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/nohup\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35624,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11139298,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a5834965b06e51bfbcb33014d6bf4710b658a4d66840f27d38508ea9b539ca4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/nproc\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35624,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11155576,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:404890e77c1e568eff323f84b85705d509c87e9e9e3ce2d67fd45dbcd946abf1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/nsenter\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31688,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11171258,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d89feb89c37c671d6eea65992a70a5ef85f390f8e0e9bc3005f53a90a767ce4d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/numfmt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60328,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11183908,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bcd656bdcb3dd092b8cd04a40491857d5b044efbb6411c372ab155519da35c39\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/od\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 68520,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11212554,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:68d5ef1443988c44a6a9159bcf5eda795978946e659e90c281d09e4f29742e84\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/pager\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/etc/alternatives/pager\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/partx\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 85640,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11244752,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:65f2986421a88eecdcb04485e359f3c09f48374c74f728c1a156b86a75cec20c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/passwd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 59680,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 35309,\n\t\t\t\"offset\": 11282891,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1e22ec1a89d852c8429353ea8bb416e83f5b5eefdbceabd26df81e019bc8f1a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/paste\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35624,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11305777,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ebfd11891eaf4bf1714e6368a543c70b49bb141ba9f42f49913ad899792b3352\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/pathchk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31496,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11322087,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2e44afffe8aeaca8c8377f5f26498f6a14d296d97a6c3c3a91c8fd6442bf54ea\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/perl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2021960,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 11337229,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d1a8fc5e7ee0803534d6ac82d69293969a6ce78f20f201d7ddb175ad67b0da66\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/perl5.24.1\",\n\t\t\t\"type\": \"hardlink\",\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"linkName\": \"usr/bin/perl\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/pg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39824,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12240511,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e779778855282c0cb23bd2d23734537fe24761f7d15e2657114fadc77dc62e4a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/pinky\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39880,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12260132,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bd141bf418442f9ba531d33f7cb745e0abf1f1e1e27f798a03d97b46efb85399\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/pldd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14920,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12277950,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d31f258fbf6377e98c9ffa230938692851303aed1b16763d28c04dcf2b5cc73e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/pr\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 76808,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12284291,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e46076a45a96c94edc03b37b5f1e02584adb923202a403af38b214f80e05d5c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/printenv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12320488,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:40b3aa6167ac603d66811e1361b6ca8504f4d0502ba33a304af23f9c5c4c3640\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/printf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 52008,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12334770,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8ccb2aa21eae8183c2a456c22938f8f2fad5f5a8a599091e8bd4c3e147a245de\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/prlimit\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 32136,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12359026,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1c2bb9d71566f9503d007356cb588347a79f4a452684f2f7e08b378206b573c9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/ptx\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 72712,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12373085,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2e52751b9d00810563e72af922413a61560ee26050add0289a9f3d5f705e397f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/realpath\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47944,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12408010,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:47bb43b6a5b8e17deb9e88f9b7969043196805aedcf4c9853ed89c67909a78ad\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/rename.ul\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14824,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12429787,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cef334521baa2145e7b86d4386b7df1a65ccb83178ca215617c6e8dd0655b75e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/renice\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10608,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12434769,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b082856233958a9c9e442c33d029aec9f7c6453e3d2d748c43da904925607393\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/reset\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"tset\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/resizepart\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39792,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12439364,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:08a76a3919d9a3c73c8ca880d1c22176db459a43fed3eba8a6f8dd0e504dac0e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/rev\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10704,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12456239,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:369b529387fb569d8547e1862849f4ddcd18ce83a106a7c4649eba53df24679c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/rgrep\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 30,\n\t\t\t\"modtime\": \"2016-11-28T21:59:51Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12460356,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0a8dd42a068115f058ae57f9f6347e1ef0ae2ffea89bf658b132974246577748\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/runcon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35688,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12460484,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:596b31f310c95629556e2c5fdc8d81ab224546b58cc4813a814b91ca5e18ebd2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/savelog\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10469,\n\t\t\t\"modtime\": \"2017-04-02T17:10:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12476468,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b5a489fb4c7a5e1240384e25ac3ff8de31e0456a3439fd7ad0ae28fda777c5db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/script\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23272,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12480189,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0159b8f03fe657f228f1a43559560332dda855e2eee2840d2c4ba48c3345d4f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/scriptreplay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23168,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12490349,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1be86c1360ddfac0d4b01829dedf1f8b65900ed5dd279dfbec58e88ab408b235\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sdiff\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 52072,\n\t\t\t\"modtime\": \"2017-01-09T22:55:10Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12500871,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:146843c271e78b0736e78fc3ffd0bb45ca7c49c03c70c85ea57f91dad0e9a0e7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/select-editor\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1215,\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12524172,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41184f27a957f4a6091f9e9959a3888323059c3a97c273ae0a6c3bc98bfc4fd2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sensible-browser\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1138,\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12524817,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:535567fc55d7b0e4a893b2c0e27306848115c1a68f4e70a0730005a52df7da2d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sensible-editor\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1109,\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12525289,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e0c6affda06feb37dfe1342d7062bb9110c3e84709e461ac8632ade024d70aac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sensible-pager\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 288,\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12525822,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0a691103beee994a548bf309f201a42f3756311a3fdefd93df7c633afbe7052f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/seq\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47944,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12526085,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:775eae051ea6ceb32f30651279aa482f780f0dcc6bd73e0fa06579d89f88e031\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/setarch\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19184,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12549367,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1e5f4eca6af935fa2458c9947ed0f727a8d04e6fcc7252acc08c040ccf40b4d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/setsid\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10696,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12555490,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fe4630dc8f7c730d74825519c9119dd8becee95e526575607be1c212938bfdde\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/setterm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39608,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12559504,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7f4270fcb6ea0734cbcfc81076c4047047d7d6a8a4ee20e9edc76e469dad658f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sg\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"linkName\": \"newgrp\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sha1sum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47976,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12576304,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bdfb66ff9f531063976ccecd408857c52cc4dbf5f7db36724877d332a331f482\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sha224sum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56168,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12599391,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bf49bc5ae0f5057a1a7d6568f34573015185c2b127ff466e5314a1a97f396164\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sha256sum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56168,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12626948,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:355dc2076bf6973fdba060a8a8a98eaa8a04d6a49cdd11bc563dfcb9d650f305\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sha384sum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60264,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12654510,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c483a60f508e8bee6102250371a4f11ca9d2665e8d8c2d386ad67b1352c3492b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sha512sum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60264,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12685023,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e7443c21507f7a316189c7af20aa4e7c358b0fcce4d183f22e7df623359ffd39\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/shred\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60424,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12715542,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3693d8c295f3bacd02c57cfdd0ad7b392864585ed61871d88b1fe77e7c8a2909\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/shuf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56232,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12744060,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:88f6ead25d1a76f00e7d328d22b9088381f04c74638638a863e12f39faa5e5ce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sort\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 110096,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12770058,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bb7b7d5d1d8824b053fb59a5e95d753069231ae21a483ba4fa86a4c98559b748\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/split\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56712,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12825908,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e6c4f385cc62429ee05d25c137e9f631be98012bac82e21b98b9513e245cf7e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/stat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 85096,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12851880,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dfe514438c4c69953459973a11aa85d26f6cb7754f85c9bc0a86b21e7275c094\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/stdbuf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47944,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12893340,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:270c6288a4675c11c5b4aa488987b330a323beb33d8f220f44d41f085e0d2cbe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/sum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39760,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12915966,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:27acd7e71844d21ac757361f299fcdf2271ff52086b0133c2fe48c171ab40052\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tabs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14328,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12935370,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cbd146a258bb40422a779b98672625fd0e4324371bfeb9493ad3cbd74d40cd83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tac\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39752,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12940795,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:27541a3a4f5bb50a9be46940ad7d2e5970bf164f57bed59a79cb8229a08d5f01\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tail\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 68584,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12958437,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6d64e365ae41c6e0b72fdce23aef6e914dcfafcb3f8e91c018152e64a48c85f7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/taskset\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31488,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 12991834,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8f1457e2b893dcc8c248afd23756e33449712ea7b955fcfcdc99e67c94ddd0e7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tee\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35656,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13005738,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d606a9ee3ec8d9f6a70eebf6d2cf69c0024f335dcd4dfd9deb45b9de869c0925\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/test\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47912,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13022316,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:db96ecffc6850632a463c8776f2e37ecdf92d081deb9ae8148084876b8afcd38\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tic\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 79984,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13045523,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f64a36b9119e7c8bf0b022d7b3dd3eb30f59b99720753122d7564a3af8496f3c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/timeout\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 40296,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13081511,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:48e7c70ff117a19a2155175d117f5d482deecff2627c0ea1dc2a903c38a00a3f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/toe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14328,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13099764,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5385b0117f1af117a549f38bfccbd2d665b3433800140a3049acc04d514e23da\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/touch\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/bin/touch\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tput\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18456,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13105589,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a984aac02449d9f7b8c3fb6800db7631419497c777fdfb5cdd6a81a5614cd89e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tr\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47912,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13113172,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:885bc7a63fbd80c7046f923dd6d840095817bcabbef1ada0c7ed259ec3497ea4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/truncate\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39688,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13135745,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94a38366047ebdf3ac56b2768c4391ac242a444d1b10a2152ff7493a0d33db3f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tset\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22528,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13153113,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dbb3fceb4c20598113231d21d01c1c18835b1920a8678a07c375ccda52776d27\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tsort\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35592,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13162552,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ccd07efef4bc2b9383284f5d2c45ef292f3d7327ab9ad9b3e91bd7604d68b76\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tty\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31496,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13179745,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8265e9a3914b6e62563cefbec2bd668d1d1cb79ca6d2c7297e63a18d8525f77d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/tzselect\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15183,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13193742,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:098968d62a5ca72aa895c08f7ddd0d3fa34f94e8951279b64e09563c4a0aec2e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/unexpand\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35656,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13199746,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:11a5a98d238c3da9ffb5db16cf3e80fc6827989fff8dc3041a3227e175b544c8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/uniq\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43880,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13216131,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7022bae3d35b33308300ad93113a65891562560cbc6f65ab1e1f1d931b67cc85\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/unlink\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13236836,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eceee77777b3852ed4c2e29123a97b9d7c087ee1c8d1c8793a0850578cdb7705\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/unshare\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19272,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13250963,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:256157e769562d513e2efbc478b1aa714964f105c401c1b10a9ed5a64fa6cab7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/update-alternatives\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47112,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13258678,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5284d89c9db30387c306ea730834c95a0f970cda37b94ed58a244abac4242dec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/users\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31528,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13279216,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d342c8f899a264011068f44a8a2abbe5da7d0cb1c6153758033dea0676d849a7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/utmpdump\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23256,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13294291,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d7a8b32dad8560f1d8a29aa44d81d8279c2c7116e8bae0f3059c8f3be93a122c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/wall\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27448,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 34285,\n\t\t\t\"gid\": 5,\n\t\t\t\"offset\": 13304152,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a2c7e6645b55c65905227f696f94731947a8fb2bfc128b3791816869e409c1b5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/wc\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43888,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13316715,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d566e182f833e3e0365cc35dc2e4c78007a4d4409a1b931b85b5b3bed7c64ebe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/whereis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27744,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13337559,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0ffa3486644df8ca05d5e4114a92c105e97a6e714c533516ca7770a86a59652b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/which\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/bin/which\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/who\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 52168,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13348087,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:36312f62a0eb6d337ee41859d3a7c00e905357397c59d5813e8a48b13fb6d7ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/whoami\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31496,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13372822,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:370dbe69b3aa202cbd31f1f597ff30b9bfa9023e37dafc610b3e4008e9375227\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/x86_64\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"linkName\": \"setarch\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/xargs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 67800,\n\t\t\t\"modtime\": \"2017-02-18T15:37:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13387042,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:efcdba7cbbf91d82113f64453ab11c0e64245a963e67b032b8f084ec30d22531\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/yes\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31464,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13419643,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d07b3d1897e68927efcb012bba09d57e39a50e61ee5256ebe37fe919f2645313\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/bin/zdump\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14768,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13434180,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7597033749fadd103a24b3a278ffba55ea762ad2f43baea7e645380370c3a422\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/games/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/include/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/apt-helper\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26784,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13441022,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8ca18a42645e85626aabff7cd9320ccb9b3e09a94b4628ca76f9e99aefeb2b13\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/apt.systemd.daily\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15416,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13452294,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:100c73ca198b46cd60314fe2caa9c26fe7eb8573539c10358c85df58487db262\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/bzip2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"linkName\": \"store\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/cdrom\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 34976,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13456996,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8767d67d18e09afaf19fb0c836ef761c5fc50c709a888bb1748e47db382f7560\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/copy\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18592,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13470455,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d90b02abf40ff63071505eb84ede4cfd50c401f98748001c43a179c87eb9b669\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/file\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18592,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13476895,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b30f5e92352e011facc307c4b13c959218c64e0cc396def475f16ac48697052\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/ftp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 63744,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13483905,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0fad9076801625d64e863ae4200e1b53b5af493c0536c19d4b7a20c21f911902\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/gpgv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 55456,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13510659,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:02b85554325276116efdd59b6be7066cfcb4dd6d715d407a8ac90d6f0ddf3f0f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/gzip\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"linkName\": \"store\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/http\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 112808,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13532943,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:63a27ce8eee65a0c6f91fadfd05feb7d2767181620739c042eea11e22e23b9b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/lzma\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"linkName\": \"store\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/mirror\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 137448,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13582418,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5f5183db0600db27a2b2dab6158144529406d58987cc2f816d62e662883271ab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/rred\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47264,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13642317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:005da2aa6d732ed000d00138eb744d6a0aeea1346440178739b106d4e0bfec85\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/rsh\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 30896,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13661946,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9aa728dbcee13b6ea052300e707e95f805e1ed70ff1778da8e377eb3513ff2bf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/ssh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"linkName\": \"rsh\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/store\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22688,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13674700,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:181be8323b9885182006036cfc7f9aaf2bd73dfa89985923b20e82d9a3b72737\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/methods/xz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"linkName\": \"store\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/planners/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/planners/dump\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"linkName\": \"../solvers/dump\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/solvers/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/apt/solvers/dump\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18520,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13683482,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f79e93a0ce641b06284933c1f5c46d1b69610b9d1fc170ba4172480027324107\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/dpkg/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/dpkg/methods/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/dpkg/methods/apt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/dpkg/methods/apt/desc.apt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 567,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 13690116,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4035a2ca99d6d473f6e9a0af7b39d395bfe47e48b3a9993488fc2fae139145f8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/dpkg/methods/apt/install\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2861,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13690562,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:810da1fcf97636219401c67e891a04a7a4f01b2a0d73fd60bf3bbbdfb3775f76\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/dpkg/methods/apt/names\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 13691901,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0a636de469385b41ea06f639a389c523946ec7f023fe2a12c0adf8300e2a82ad\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/dpkg/methods/apt/setup\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7728,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13692053,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c645a091943f61ff46847973d000cbf1817623a86e1ede412f97f437aa1eb56a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/dpkg/methods/apt/update\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1242,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 13694442,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:605ae19f87289e8d4cdb80028dd071c4b3ea0e2e46da9ad697b6bd739ba4c6b3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/gcc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/gcc/x86_64-linux-gnu/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/gcc/x86_64-linux-gnu/6/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/gcc/x86_64-linux-gnu/6.3.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"linkName\": \"6\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_ADDRESS\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 131,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 13695330,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e56fdac7f4d70bdb7517a9a3c98bbfefef52fcfb082d3a49c26eec93fd8f9d9d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_COLLATE\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1515838,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 13695537,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:821d59144c41906337b31ca68dec0e38bcc91b9a532d06050c6aedbf00587472\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_CTYPE\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 198372,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14383146,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4826e6c02b3df039a8aa8fbddacdc060f7d697438e7b525483c44c4d4d7e949f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_IDENTIFICATION\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 243,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14405493,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0a1272e17344d4e4d9ac8b783181721cd4a9faae87890793561261e47c7eedd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_MEASUREMENT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14405720,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bb14a6f2cbd5092a755e8f272079822d3e842620dd4542a8dfa1e5e72fc6115b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_MESSAGES/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_MESSAGES/SYS_LC_MESSAGES\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 48,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14405898,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f9ad02f1d8eba721d4cbd50c365b5c681c39aec008f90bfc2be2dc80bfbaddcb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_MONETARY\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 270,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14406061,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b453edb3c67a2b0f326d045ce72a5cd0ffde75fcfe31e47edd1c2d802bb18b6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_NAME\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 62,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14406322,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:14507aad9f806112e464b9ca94c93b2e4d759ddc612b5f87922d7cac7170697d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_NUMERIC\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 50,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14406486,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f5976e6b3e6b24dfe03caad6a5b98d894d8110d8bd15507e690fd60fd3e04ab2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_PAPER\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 34,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14406640,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cde048b81e2a026517cc707c906aebbd50f5ee3957b6f0c1c04699dffcb7c015\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_TELEPHONE\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14406790,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f4caf0d12844219b65ba42edc7ec2f5ac1b2fc36a3c88c28887457275daca1ee\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/locale/C.UTF-8/LC_TIME\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2498,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14406947,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a61ddf48d8afc6d3aa93effb63cc55033c4ab9e42a4dbed2be1e385b5f6f7451\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/mime/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/mime/packages/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/mime/packages/sensible-utils\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 97,\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14407873,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e9d9b4e7782deb0509bb543620c597710bda659a3045bfce55b28c632f201f2a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/mime/packages/tar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 327,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14408061,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:31deef64d49013a02645bcd32e43d108d12ebb89a93034fb35947c7c576397c8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/mime/packages/util-linux\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 90,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14408260,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8c2a3124292211ce117712858ad06a036675a7f7d8f578e5b84267b1196c1665\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/os-release\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 236,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14408414,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b4c8c0cfed0dc1f1b4f6f34fe29539d7177c343624de2ec59c86c762615597a6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/python2.7/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/python2.7/dist-packages/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/python2.7/dist-packages/debconf.py\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5971,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14408720,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6d43e8fb8ce8e97cb0462912d224ee912c56e9453bd52bd6fb0cdfec0b27d575\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/python3/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/python3/dist-packages/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/python3/dist-packages/debconf.py\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5971,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14411248,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6d43e8fb8ce8e97cb0462912d224ee912c56e9453bd52bd6fb0cdfec0b27d575\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/tar/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/tmpfiles.d/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/tmpfiles.d/passwd.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 239,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14413781,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1a3b927102b44454eb4c47e4fe659de2f5283f364ba27408329a54d4ad47e310\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/audit/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/audit/sotruss-lib.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10512,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14414075,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d3b259d2cdfddf10191a34b45491fe65b62ba40ab7354baabab6a49729f8a972\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/coreutils/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6208,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14418024,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8a9a76f2bf31a771caaef396959e0499600db824c6fd10074d2b5d2f310ef3e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ANSI_X3.110.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22696,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14420506,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:52262e2d0a7f214cc2245cff3961f378543e0d39c6d4417ba30c9f2e49c1df9a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ARMSCII-8.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14428237,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ae82c1d28f62461266e9cda0cc26c4645b440747c5ca989d7a04051fbf3a6b73\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ASMO_449.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14432539,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0807e5512dcf1ae8672b10d01c191bed90ec3776d984fe1e7173ca3d2a46639c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/BIG5.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 88232,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14436989,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0a81b5d9ade3c77d046913fb43921df3a07cb580e4846bea244c88cfc49242bd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/BIG5HKSCS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 235688,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14501902,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:088d26cae29c1089532420dce6af0c0834ddbf2027e9a9afbe1b15babeab6326\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/BRF.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14599125,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d2eb65850ad018518ea8e7ae4c50f847cdda4cdfc7420b6822898342ab3ead23\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP10007.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14603462,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d25df0bc6be89a0422849cad6efaf8e3c3666eaf0be6efa73a0d7d1cab90df7a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1125.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14608398,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a96ddfac1fd5bb74ea4a8c19a887225894890762e291196c27b3346472402b0e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1250.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14613378,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c761e88cad960d05daa141ab51c03fae9189d49967ee1afde72e5e2543257b3c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1251.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14618353,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8470d189bf9c79a768cab14e380114e1634200bcf5c1b7cd45de0b4aa411ef4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1252.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14623308,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f4742d917fafa59406fdeabe074b69a986bfc11e1af5c2337035f465b0431648\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1253.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14628249,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ebc48f981c92999a5e72516c02bed94d8526575bdc6bd52458cd07644acff61d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1254.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14633150,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c91b07b46724dd2a2e4113a96d0111a99da10b5122d2d4158f43a5b0a80ddd83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1255.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14504,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14638095,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:050f26ec19bc43127b0f1d669818c6d9f0bb0b76259291bca38747d1e9b34f34\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1256.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14645317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9083224cce4afa3cb1bf1b7ff1ea16b8e085e9664d46043c57063946e9c3c98a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1257.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14650361,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ff6585ff708bf5e82fbc25fe25f0e7e4c32db17d04b9784c25b0b6e050e79657\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP1258.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14512,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14655334,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c194a2a2ac90d7c9156b215e92e100d8311f5442e85e5ece08e0773b03214bf1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP737.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14663380,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8eac0e2ad46c543422ed7672850fac763fe58dc28a14a4a82ad0605a0850dfa4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP770.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14668423,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3fb2446b1b6483defec27db9793c0156498cea296d512e1a0bb799d1f175c751\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP771.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14673540,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4281251137e534c30c61ba1a897c758ad61ee7dfe39d5863e44b96917c806ce3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP772.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14678534,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:512ebd920245e0401557704cd7f2bea935d0471e6a41d4d95d9a7963aa6b4994\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP773.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14683587,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb607d2235d078938530c1939d1216db8e78c74c77ae0547de9e8cb0a2e4427e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP774.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14688605,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:70ecf1712bf970a9215527626c2d5c6276e1cb448212755038d019ddb2709be0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP775.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14693692,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:61ae97e8aa5c5d703ed36945ecf7f0a8e591bf61dd584bfbd51ec5bed4235a73\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CP932.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 96424,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14698751,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6f626fa00093a081100e122fcebf717df97ed310c48e11f369c838a01686f7ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CSN_369103.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14740144,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2bc8813d57c2b440c2917aa89b9e409c52fc46a659c14ca91fe3a7bcef7ae279\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/CWI.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14745042,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6adb325cf1a72086f60d31d01e81243b8b40fbcad35a1e35f1a27a477b267ad0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/DEC-MCS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14750111,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f0aaf44d6cafe56fb90c09c7d1a0dca359f375895de8493522e68649f1ad998e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-AT-DE-A.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14754955,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3d44f8769af83450b7b75d3f9b69621f27833af117daf2b2bd927dce856fed8d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-AT-DE.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14759385,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:44b682d782826047e399de9272a2cdfc3437d8221f036ecba701473827935148\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-CA-FR.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14763835,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a9b9c635be74120334387edb3e0a0f622aa9fd7c3d58c04c5571ef29640ae54e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-DK-NO-A.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14768362,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5a8dd91fe6988b4141191d94ef30b37e49351cac989b276cb5e9a717e9546ca8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-DK-NO.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14772792,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:64df1cc8d7c8746ec30347c4b4800777af8c347ecfc66e3ff7b93df8c70d7d0a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-ES-A.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14777239,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e8e45fa922d6c98a1c515ab7e3a3a8a582c95d383ae63cd0e962e6f060625ed4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-ES-S.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14781794,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:88f6ab75e922f12e226b9d0fe92c4a0ac4df64f63dd1d482287db69b638d13c9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-ES.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14786227,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b98e70cfd597501422b69559e7bc448ed6d4f5302953406e68e064ed840dfdf8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-FI-SE-A.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14790805,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f020cfdd4d521d4520a87299908e65f7d6b906452252900b5aa5a673789cd656\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-FI-SE.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14795234,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ffb39c7296bdee62e96d7cd05c4a58073e66aecedd6bf70bbc9ca6d429d7dcb2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-FR.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14799676,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8f03bf1c63291b5bf1d97a041025b91c22c2fc0d930ad38d4eb730f67c790ca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-IS-FRISS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14804118,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ffc94a955ae58f68e83baf656c3c6b375851e301ff4b5f9fb7610e606a108705\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-IT.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14808669,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0cb0f62f17f0bda72a19a2327de4692c8fce54eac0b5f05a875d4516d46fe65e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-PT.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14813101,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:423fa5915f65e0b3865c8e864c57d3c5c828515dc142a2985da5773f3572c1ab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-UK.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14817543,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a4e3458fba6edf9a883d5dc4f909b6ed2fc0d8836bb6df2b6fd8e04e89e4077\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EBCDIC-US.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14822100,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0f3a1b38dca122467b74a7a75af0f77f26bf13ea4c328a94d2197343acb194af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ECMA-CYRILLIC.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14826536,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:073232e33584358d25014f6e1b8c2d502c7bed0413cdabe4f3780f66ff073269\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EUC-CN.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18600,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14831401,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4f11c781a92eb325d435cb71767224d7e6c3cb87f948d1b73f4729ce7c3c26bc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EUC-JISX0213.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14504,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14839196,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7123e1baba3fa0da4b59aba823aff32464d7a9debb950bdd2f2d934f638cccd8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EUC-JP-MS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 88232,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14846580,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2f4418c4976ddd63cd367d60f2e0ed53624b6bee43e6d68320b8ce51c47835af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EUC-JP.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14504,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14885819,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9fc8079f6369e76c7ac57330cd90e636f8e9db2f1bd40b189a650409f1d84d29\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EUC-KR.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14504,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14892604,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:047e570c03fb7dc3f12a42776f3d14f3b4751aaf9cdd19feaabf67429f11c3b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/EUC-TW.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22696,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14898948,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:10e457260126d17f57ad318e53c35cc0138b0e1385e4c0b8c32a5bffe12e9d99\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GB18030.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 178344,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 14909184,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:facce5fb00a24c8a6c405e08a2076775fa706a665c5b17b0847e2e289649e3f6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GBBIG5.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 55456,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15065887,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69311d0fbb67b61a6f4da8a77559b5c649f7baf8d9377fddd5637235b7552b39\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GBGBK.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15099011,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:490382cef8df9d193c080356fb8fbd686bdd3175f1daf0ba902ea58ef758423f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GBK.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 112808,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15103715,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1cad89450d971726751f89feb19d40373513de10cffe0065e20d4b354f587e4b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GEORGIAN-ACADEMY.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15195138,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:645d761630fc542d42c8121c84504f16d01484ffeff9dc355416b00a30e43f52\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GEORGIAN-PS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15200078,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d7636579114a2eba5f995bff71ff91bd6f2f03308f271a9b356673661a47277a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GOST_19768-74.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15205024,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c44a7f287143a6fb190f01ca1488485e81f7ed9fad8f8b81aaaf0c1820d72ed1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GREEK-CCITT.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15209845,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e5a26ab830be4dcdebe57cc422518ed2f2c4dd5275b9441c34af4b5df0d621f4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GREEK7-OLD.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15214317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c15f04d0267a44780eddf824781d343e25f879d071532bec5feea8332d99c110\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/GREEK7.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15218842,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4904f214e0f8bda99b02b4721f51943a068c6394c677eb26dbb4f65d94d87f71\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/HP-GREEK8.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15223317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8ab569cbc017a53dd32af34d62f7d88ff1d3898fadea71e62eb6ffc7889c3a3b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/HP-ROMAN8.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15228105,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3f5d0340f0ce36889d978675a59504e65ad70a1afe4d625a63055628650ff72c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/HP-ROMAN9.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15233029,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:54bb72b18c528c95b09a4290dd5da78c86c884865bc14590221ecc788dcf4924\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/HP-THAI8.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15237958,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:130909152ac8794e8fe8b4ec538fd608e3e6b6d13f66a4b892e25c0a9225c398\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/HP-TURKISH8.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15242829,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c7fc4f586144a96fa7de6cc71a6a5445fe80da2cbad80aa7101421a7e1639146\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM037.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15247743,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ffa677531c2da9a1bf845f2839cc4044aba8e1039de4a01600d4f548b7d57888\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM038.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15252485,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a01d54b7e0eb7a8aa35d8152e92a5c44bfd3d61e31ab3a8fa9cb5cebd10a7dd1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1004.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15256912,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:da5a574d13f503b0d81e78d414dcc1a139b04923d239fbcbfa3f097129147ae5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1008.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15261823,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5573b22026ba9d681b076fb7b7039cd521e1891f19a7cd5bebd9010fa767ee7b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1008_420.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6304,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15266876,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c77c2618443efe3604bcc2b3430d81610af1dbd3de34abffe3240b84276fb653\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1025.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15269808,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d3f1c1d482362ddea8c36d7bbc9ed2dbf4be212155ecc654cc287efa7e2079c7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1026.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15274665,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:db2d4454948890403012e477944c933aef8760781485b9074e15a555d0a6a315\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1046.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15279560,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:af4e25d6a109a75ea583bb16bc6f7baf836c25019cde02adecbeac0b116a0881\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1047.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15284718,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a689bcda087e85aed9ac1b09e2b8fc7eca93f1d3be9555f8e5fb3c4e0c5ce108\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1097.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15289460,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4fc795da190f3eb93324a9ad223481ea599ff5478d8629552e9d50a51220c78a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1112.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15294514,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ec977f45a23bfa21197e42502acb11c17666275b488b956e0240540e47088f74\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1122.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15299413,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0357639fdbdde937f46feb178b768c0135a176aad0f2d2c9936fafdffd8c615a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1123.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15304248,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:65632ea53e05173632a3d0dcae26bf0c1d2e0b8a3340a0111a9ab2e5f9d7bf7c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1124.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15309113,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:db992833af0f46a736af4a988167be258272c958225c9f5abe3ecc2bef6e0e58\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1129.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15313977,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:24f9a845bc9caf06ac136b345c8945b975d870415fb17481992d4c216140b71c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1130.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15318861,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a8fb0798d47c5826b4eddbfb8eda589f3bed0d13c51d2c4a54634829586a8ddd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1132.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15323742,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d2a3fd0bee2d819027bcff4e19b989652dc064c4df22b1cba328548bf5acc47f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1133.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15328571,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0a813aacf57c8d5e844f57bafddd48166fb24464486d7eb8f574e109fc0393df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1137.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15333396,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c2ccad4af98d6fd4fd6fba34af927eb0bbacaaf0ed19873bd057f39a27256a53\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1140.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15338298,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ba4d8304f773b6b875d3fc632b24a264b97489f76fac2d040b117e96b86a5f92\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1141.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15343128,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:783877472678337e9e9f3111e0408f0591fab7bf0879926164cb2752cecfb5df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1142.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15347956,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:edbb8c88aab7ec11323f067da638af465b762bd6fcd48753858ab87c0fbde1d0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1143.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15352782,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3d785fa4bd087becac09242fd4cbe91d19d6d992ba24e372db9f9bf5ba9a47d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1144.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15357608,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a44afd8f7d7509e91517da5c7bfcc00212ebcb5b021cd3f8297cc0a97850ad8d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1145.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15362434,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:93ac0ff644b41571b707d3f78be9c22e39ebe7735a6caf9266d83f6847b86cab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1146.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15367261,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:132c94776db1d54d57da406e50e8a02bfdb681ff3f3c9d4b716a2b9345f4b4b9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1147.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15372088,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cd372c049f87498c44cca93829d2e5129675b2d23b4acef1e010cbc959c5830f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1148.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15376915,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a4dc2316705e8c0c49ce32c381bfc339c232fd26514bd0a5280e474e691712c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1149.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15381741,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:98155f7777984365e0ce63e51d0ab7cd19f4184fa09a10c85edd757c16a7523e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1153.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15386569,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c9ffb0622e8512f6ecdfe1f10ba710f0c3ca47e8867886d21c2b06d3a44eb2af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1154.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15391473,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8b38fa5d3035cca9e8f70da21ab5d0a09eaf02692dabe4ed5908ac74bfdc3b7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1155.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15396332,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8bacc4b9c6c33fe729ab68223a5bb263c6734179db8df3cc6793f34377d2588b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1156.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15401174,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa551c5c91eb06f4181855e890e7b12b7063308d841894a2226d7da041a70062\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1157.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15406080,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6d613439d5fd1cffab59037098eef8132a2ef81105a9f20cf45679dd8272006f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1158.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15410923,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:315953061208acef9f8e36c4707723e33c1a82ee5648e743a5ebf2756a776917\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1160.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15415794,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8aee39f57a5a2e37263bd515a2ce9dc0996d8f627a8bbedb26a4403caa5c39f6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1161.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15420629,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:61a596be406a3ed50b3b5968388ceb1a889471fcceeeb1575408fa3ac7011e3e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1162.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15425413,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4420dcd49007c9cd0e59ba80b90096b1652d2e2d8a8bfc7a99ba678141af583b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1163.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15430305,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fce604a2be8f9975a159d9601bcf8e5ccdd43460e160ecfdd03172a65fded28e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1164.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15435199,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0dfed478ecbc38b59bd59cdf70ff4344b2088d65696901bf3bc92837bb2c7e9e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1166.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15440084,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a0e9df4edae2676f8ec5b4f5b9f29bb3ea2202a9d2ba8f4484163b37f6aa9096\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1167.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15445006,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:13799e0bb916470fdf9a785df825ea8d8cc7fc748cab754c690080fb7943fec4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM12712.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15450020,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e7b96feddd55908724a0f76348bd6b790ee46aa5cf217bc4688078f2b814c11e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1364.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 149664,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15454873,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5eae3691cf2b1c728cbdeac9483db62b43359baada0f708d7118d0d7cbfd8376\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1371.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129184,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15541041,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6fddb19ff2a399ea3734a21f091e2f75de7334ef813a00e8bdc9bf222cbdfd12\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1388.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 174240,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15628179,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8d7e4a59d4578c6320c588f9a3965121154eb3a1401fcfc909edc3761cf2d50\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1390.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 231584,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15755302,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c45c11a5a89eccbf3bbc5da8212e38b23c43d623ec54fe9e8580c8b3825ebce2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM1399.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 231584,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15864185,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69d1ed3af9406cd96f05b4767de1e1844aad4c016fdf3ee25ca341d96ecb1a2d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM16804.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15973069,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:174471be37f87afb1ff2a2dc5d89ca168fac9eba1c2a7f085a88f79c23de61f6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM256.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15978116,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2fd6c744c678b54bea45ac4480281529a532dd6612ae16a46b3789642950cfae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM273.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15983014,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94d110b50d0fedefcc97863e11923467eaebfc82d0e8360d37a142b6c4a3a5d1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM274.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15987881,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a7a6242291c4cbb59097b0e6f032db96b84e01e20e62859da02687c1edb024e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM275.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15992310,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ea6e9264226e60b9b2a7a3cf0bc36fb3c7d7268b98a6771d4bec1bbf3aebfd8c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM277.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 15996747,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:07f666cb4198dd56ef05a560686b93cecb7869ec3d937e73a63b26ec72d16356\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM278.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16001614,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:421e5ae26d0d6680f222df26e118a624da3468d5ee8ab4f594c19dffedf15eac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM280.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16006483,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5e82dfed5e52f1b370fe5b9b4512e5a21750178dde3cd33c72d8fe4b211a6c3e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM281.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16011351,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b836097e81bce60b77c581eb02b22a36eab47385f982d4e681ad994e4e8a3911\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM284.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16015905,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b5d14e21dd1a4334988c9a7d05026461243032eb28a58be8e6c593076f7b7dd6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM285.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16020773,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fcd0cce71970b57ea8f5b514edb87a67dff8881d5f8ebb507053eabe46e1f066\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM290.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16025642,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8ff364f710e0fe5da17b6fb110f46c2f69bdaec817b3f5be30bd0f9fa13da1b6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM297.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16030394,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ac311a9b154b833e687e6da68b5852377826e6a3807108db5d5008ab8cb99a5b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM420.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16035265,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bdf124d4625d421740fd4a87c32b1c33c61fc510afad4d22733e90068cff00ae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM423.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16040216,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9c9aa740bfa804752c55e6f5e4900b607d080e87dee22db7a6d4fa1d1e21e37b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM424.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16044984,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f1709bc66bacb52d1ee29baadb87dfc54413500c5a2e8f2722ed7586a07471b7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM437.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16049769,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f5c1a7ff03ce11bfeefcb84dfcb4d076996dc92826c362390643ef61f5d1be77\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM4517.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16054811,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:637fe4b15c525d9189b7ff8327a6b36f5e85b065473d14b12bd40c7c6d3c5195\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM4899.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16059867,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:38d72ffc9cf63da58fdd2e8098d6f7107e9bc7a1ffe69ce7f15e1284032cbf7b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM4909.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16064487,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:096bafbf84ae0a11c205c69be664d8b25d7c03b9601413c9c56709d110a9fc0b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM4971.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16069397,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aabed2c3014ca5ef9ba2343aded8d9b7be4b97b5c8c861ae5df478f146cec2d8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM500.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16074305,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5e7ea1eb91ae67e152ccaf54d91a805d79aec6dfda5440c6440204d2dd2d2f02\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM5347.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16079051,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f7794f33f4f549cd7b900a9e0d124c8d8ee45ed5e72bffbf58b99636574c0dc3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM803.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16083969,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:12e63f232b6d2c473e1b8e16ee34f718de0ae57753bfb78b148c4220baf5fde0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM850.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16088531,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bff40bb4f70daf445f86fc7badb76e7bef76e03d904209f804ce4c003b21ace9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM851.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16093511,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2246a0b9995ced61e360318c07f7bf3fb3de6a71ee6a3037f3455c93e9c52aa2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM852.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16098541,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94bd3f4c26c97659c7efdd4e5eb22c76ea74bebd4a483aa88e87eda89438f1df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM855.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16103581,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d69adcb0986a7b7bb42c5e8eac260ce795700f86f01058bdf6706d5786e672dc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM856.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16108593,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:716fc1d1f5d59170ae615480b329b93fc17a3ccf65b1bff0193d36fbeb426ac4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM857.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16113784,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ee104d20dce0e3d24e81386c8279bd10fbb44896749734c62cded74ad85593c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM860.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16118759,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b90781183dc19b7bb0be4aa3a698149961c6082948d6875940ba9e4b27021ebd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM861.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16123831,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6a524114517e8b549bbc4e541f992394904ede309b0dea264ff0c9be51ba3317\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM862.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16128868,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:65a3cf8294db774a0b1f92e147e1f765945181fff298d1e157913ac5da9c09dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM863.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16133935,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:44f3abc411039df838412e683539ad909fb5bc5d1ff9684d9f24ede26fe866b8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM864.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16138969,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8bf8472ce956e06b5d1d7e4189b3b1b1d9460393fcacd169f9881fbe926b583b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM865.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16144043,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4c4d90e3d7c6d7578e31d6bb02f3b433955e2c2adf6080d7888a8ed09daef79b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM866.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16149081,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:55ae4862b9143fe249143ba2f49cbab7bfbff2f16a04e139d5a69e1ea5fa5945\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM866NAV.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16154069,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1ad140369291ad4b4c9ed5a99c09647ca1d7024267226f535e32aa6120e9c626\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM868.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16159042,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:37947f8351375fe599584fcab7808373f9ff9dabbd8e76889818fe7e977c7acb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM869.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16164066,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41d75ca56cfef68b22f0203a8dcab4ef6b94ac6884c00531e40a06e1abe7f878\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM870.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16169050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4171f7ad9654ee4544810afb91c29222062dd454991fbf734d8f0fd2c32206b5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM871.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16173771,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:781755c6a791c3bbc367e1f77d68a47b911a075bcf2b6870149553900e611eaf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM874.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16178514,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3b47f8c7c57e01afa84d534ce3a84740bf4f6f5949f33868cc6b631a160d8708\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM875.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16183333,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:de05a012df560caa790bfbd539a6facafe236146a47aa1086c6f284985d2d4db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM880.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16188228,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e1bf245408a0e9c5b4080480818c4d9c03919dc9a9216744bf7fb42c8ff5aeb2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM891.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16193103,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8460de36522083da985248fc15b924c3dbe7cbb7608ba15bb3b0b77d228b8367\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM901.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16197397,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:945e714b987eec68188cdf64585bea4cd22ae324715c3bd17246a33c16aa7880\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM902.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16202547,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ac939c532a0033b92774d6b211ed90ac688f219988649549e38ac13d9bc233e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM903.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16207641,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:59c6612d1820088464c63be822e84d685e8034a01c51d0fb722e8f08dba6d789\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM9030.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16211931,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1bcfb795581ebaeed2fc544cf8160d82e4ea773c48b21b33fc6d7c6692a777d0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM904.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16216757,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a1cc3d93256ed9456365a2c01a8a5cc9839b31d0590180b0cf9ccf1c1fce6669\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM905.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16221066,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:171f80601fa0f39d5fcacbb48ee8221e8a1a194910f9ad98339c873f34b1b120\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM9066.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16225815,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:98dc687de3d0354f1224275324e3b80cbfbc47ea789e9f57924efe92a35bc830\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM918.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16230592,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5908006ffeb6461a7586c6f7be52d01a1449dde53ef874866387d7bf5edc41dc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM921.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16235488,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5dd97299d93e5bfd2e8171e73b4230176555cf1ac088b5f704bc628efe55d8b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM922.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16240389,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ee548a7a8ff7579dcda62cb4fba3d2b88f45bc603fcad99e11719ca96928f4d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM930.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 108792,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16245492,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:de5b3714b8c22e51c6e2f82287b0609b036da9c81e51d1f3dfc5759899f6fa25\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM932.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 71848,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16326736,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e341b0d949b294e2af29882efa2c177ebedc1061dbdd8def17448ba28e86d2f4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM933.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 125176,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16386443,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:63647654e0331c4c95ad7989ebea843bc023583c462a50139e20a9dfaf881942\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM935.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 88312,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16485478,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:22c972c25479bc47fbed3c1d4d7c50446f9dba07caea37254f3b259f1b4346bf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM937.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 112808,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16554275,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:61b08c43ad98438cfda2db99a1b3c68e0e88f82b5a14433563fb8662994e519d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM939.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 108792,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16641205,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7f131860e5285f14114020bc4cd70a42ee1e94ce7aeec5f36a395d65094fe513\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM943.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 71848,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16722354,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5a2930c6e3412a012bec7d42e4e214fa4904d1d0117496ce7a3bb480c46e6e67\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IBM9448.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16782497,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:546743fef1081d17e538c4f00759378aa7fcfe8ad3024edd6bff5f60a819f4ea\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/IEC_P27-1.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16787777,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:913aba8336287510c2330d2f7bc614563b932586d282ff17ca08588cedb8b2d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/INIS-8.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16792818,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7dea555becddc9e970a514b4787407289ed4e031d046b9c7644b655bcd265976\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/INIS-CYRILLIC.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16797155,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8bdc14dff70504bc689a02df98bee665bfb58e233a3785fe793e29e454b40f11\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/INIS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16801663,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:816a7e39ad8aa48a8cc520d5e0339a4a5f3ac6c1d14b03c6e7456c044cf11dd5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISIRI-3342.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16805997,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dda2bd62ba2860068ce89d2cf20e12220a24687ec71b8bc07380ae6b7b85203c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO-2022-CN-EXT.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39088,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16810860,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e025193c38c4a257c6bc6cbbcfc76636ca73a09c9139b0626430ad27ff795513\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO-2022-CN.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 34984,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16829575,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:65f8fdb4fa806278d1c8a6e5479cf0935b38c0ac5ef9f803f413db124beed643\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO-2022-JP-3.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26792,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16844919,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f3bcfe27bb653b69949f0d6446544cd721f998dd56917d7e563097088d381afe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO-2022-JP.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43208,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16857314,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1a299788585bfd0f94ef83bc91170f6e4d8deff92153ab01f269be57e6ff153d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO-2022-KR.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14504,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16877102,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:32dd52a49870d3495a86d9594cea8fb8093f2bd4aff8648b530ccf5043b5562c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO-IR-197.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16883964,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cbb8b3adfc2e13b87e0e8ef29c430d5fc8d2f33cbaefdf96a0a549aa4044dc60\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO-IR-209.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16888927,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8d8b34e4aa48e0b44836ebb35206743cc6d390da28d4ddf64c4ce880213ffd34\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO646.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18704,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16893904,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:625a226500b5f6c8ce49a86987decce222f543c22253560bd09949ce22fde3c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-1.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16903072,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:46727b1a93dd243dfb0429fcbb477bfdbd6b415daa00acfba60434f9283faaac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-10.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16906849,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:851f0221d15a6c0e2da791226a6612184105741aa1ef006dda3b655308d91512\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-11.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16911763,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dba2a8a403fab6f5f12ad1fe136f3fcde328339b61a7910b1de37c837bf545d3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-13.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16916633,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b8f450dcf883cd8c998a8755fcbead27e8a72a80d6728d231c41d728c3893277\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-14.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16921539,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:38998a00cb4eb2dbf7b2103ac1ba1c253b6d2bf604f8c2ff90569704e2d224c2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-15.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16926468,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c011d6da2ccc5cc2679d32d38b7722527aca659c6c3f449d9c9e73b499bd5a01\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-16.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16931317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e41455363ef0515ff562b97ea50a0bf52f833d56b8a56d9f2adb53315438155\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-2.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16936226,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5515c694f7211d21914cb5b20c7533d712b0ab8b3509e4eeb7ef89884fec632c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-3.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16940961,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2d0c5d71deb6725dc7b6c5b64785cfd67bfef0f29089f8e263e90968ca8c544a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-4.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16945727,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b495bfa75a310c1795456ba1d0599299f80fee44cc62264809e52981dcc700d7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-5.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16950466,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:12dd7d7541d9b049169eb3047adcb274f0a4a0e66fea7206421caed761260e0f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-6.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14504,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16955330,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:553da67d94b5f224c7e687433ded076d6732cde209d6224e76522296230665ff\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-7.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16959999,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eb496fdaedbc8b165c45a4b9fe86a698fd423ad2b5b44503571c81b66e6f16b9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-8.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16964920,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ae95477c13c51f9efcb543114ce0ccac531f42588b286d84ac69778a45409681\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-9.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16969714,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6e6628a4f0a818d3eef3f22ef8fb119e0f3cae87852997124158135d948f37b8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO8859-9E.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16974408,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d575123ca67fb2e29c1fb632b0e42d31fd90bea935673f782e9047b0d6ec1c4d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO_10367-BOX.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16979336,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9f7e623d1a813d7499f13eda918130d8b4b6865f7fb44f88eecb9e82a7d33780\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO_11548-1.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16984078,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:99a44f668b7d38c97c2792319b325963f28c47b3677db18a41e8fe4e7a4d9fa3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO_2033.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16987856,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:26cffd10435270376d9dc677847bafd6eb1c7ea08b0534162798feed6547a1d2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO_5427-EXT.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16992024,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0b8cc43ca2ff904d2c67eadd907b9e235055336e4f0b31cd5c413d53ae2754bc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO_5427.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 16996339,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:346d9e98132068c292ab331c0f1a7291df75b727b2c5c713c4470aa70a95301d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO_5428.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17000793,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa3a53e36ea0e51b216cb0c128a3ec2746099f9b1799d36b3d2ffa78bbb50844\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO_6937-2.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22696,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17005266,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:917eec307f0419b0eb5626a3ce06a06c6b2cde5bfb07eee33e690351b5d2bf2c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/ISO_6937.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22696,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17013126,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7bdf85fceef907f3f107f180ee1c8035df2a4a6f8ea081c470d8ef69d3b4104e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/JOHAB.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18600,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17021010,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:49f1473027e1f4a77cb488a480a2416c2da50817e4ce504382bffbd628020b56\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/KOI-8.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17029049,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3e7a16200475dd0f5b4efc87d4d7b76d69d74418d3b8a5ea6a9b1103885ef543\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/KOI8-R.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17033579,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3734f0fce1d3cea25057e64a3040067c2b4a75095a844b0014533f58eae0caab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/KOI8-RU.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17038579,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c4bcab695d57c38718e0e0f2bcd54ec8d0c8d5c4ab6b3bdd435b0ae47bba59e3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/KOI8-T.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17043587,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:79c497aebaaa188ebc8e112fa86c1c52510e1ff8acf5020a413289cfde47103d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/KOI8-U.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17048509,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6c0fee532eef0f23262c6f5f40dd7bd0e75f3348c444600dd22974f1efbb869f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/LATIN-GREEK-1.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17053521,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bfbafee63147fa484f5d99d50185b8650dc654d0261e30d557caa04f086ee04e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/LATIN-GREEK.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17057977,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d9886ec5ac307b7d6dcdde296d9776ff03742108fc9edde3a7edf5cfb6a4edd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/MAC-CENTRALEUROPE.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17062446,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7b5342684ef8b8d3b96bb77796d922eee2d86f51bd4dc3e2f6be99c94d4c89c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/MAC-IS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17067418,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1cda7799bf65f03fdce63d58f62ff3d3ee232381a936d27dd7ffb2bdd2640e12\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/MAC-SAMI.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17072464,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7e59bc0bcef532ac1921dabe599d97cf51ac48bc96ba94cd16e3332b34010088\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/MAC-UK.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17077453,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e1e6608ed00aa7edd17536a89b55772415b69698d74b0e7ac56bff88ddae7d0a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/MACINTOSH.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17082395,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bb17f05e20edcb5a297536325145fb8fb8944df8ed3e2b304fd9a3f7d70d6daa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/MIK.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17087461,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1182feb2279704ac8908682559744389a8a643378d6937eb68f78b2ba213ee7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/NATS-DANO.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17092524,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bf1cf46fc38c6797ed76283e8d7167dc0db37e7b19988a6dd1021006bd05f371\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/NATS-SEFI.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17097005,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05c0ce52f879990be8e84ee6fd13cd1056b3ba371769017b9d4739447342891c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/PT154.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17101473,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bccaa42a9d9707c53b6646385a5dd19f6498bfe11048a51812d1e576dc6d2577\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/RK1048.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17106400,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d49391cc45f31a755e61a9200df1f574bb6f2e8be75808b95c54a427f80e0c63\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/SAMI-WS2.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17111410,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0dafadac4c42a811741e0cd8c7e2fde3ec62ef1dbab88b93bb0d4b0b2c7c116\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/SHIFT_JISX0213.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18600,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17116379,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ce1c56c87b70ae86f4e8740beb57bf0856842ee16aa681f7c1fab2f3c6ce055a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/SJIS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 96424,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17124377,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b4dd8bf37ed58cb46c1e62348e7731bcc49a3345646fa0d448e1764276a16203\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/T.61.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18600,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17163270,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3e420f16235289e9ca17826b421ef9ec9db680fe943fbd159ff7cb48e340cd99\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/TCVN5712-1.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14512,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17170395,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6b6c6e685c14292a607b93d809350c567e2a4e3a1548c6bb7b0b80a424163f61\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/TIS-620.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17177861,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:640a340021b4d554c98cff37bcb5b9e15346398e3af69629ff6b3366a04a1392\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/TSCII.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18600,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17182612,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a12de9b3f86bd3f60a14ecbd5b8736b8889da21d467eb2509a6baa47c9181a4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/UHC.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 71848,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17191613,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:87745f69d98339a80a94319c170c349e80b4d82ea2da5396f32e92f9b6baf687\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/UNICODE.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10424,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17239936,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a56a8d04dfc075211652c6d262025496610816f21c50f24a94dd44e3b464998\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/UTF-16.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14528,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17244247,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:968f95cc06ad1abccf4a9d085bc56c4bcb63dfa2a7d89772702ed33c8d7fdeca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/UTF-32.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10432,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17250022,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f1c221602b45ccc3050a416128510f555017047673d13e56af123a1435717fa0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/UTF-7.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18608,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17254582,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d69f39af22d64a34517529b6335756ce362daa89c9d90e36865950405ecf789c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/VISCII.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17263074,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:441f95483f53007c5934b27a02980cb5e3c9a00f8d10600207cf66a84ced2098\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/gconv-modules\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56095,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17267992,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6f90f42555e1f390e26b6090186384cf4131bba167c331b58e8d7b13f86b7b45\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26258,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17277397,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eef49f11d96d1ff44e461f9ef1dfbd9a70f02ab5dbaec1cc302527a775c62fe4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/libCNS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 468984,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17288862,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fbc708c917e17da80bbc83b4d1cbfd47d511c17085ef18e8c0241a83ce8ee5dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/libGB.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 67576,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17580006,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:015d06af82091920aa60f2b9e06ae8b18ad45488917f270a956ebd11c7d67674\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/libISOIR165.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 59384,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17614076,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3aed87fc8c51a7f5de1921639de2c02499b1075852c98c23a95827bc40e5b667\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/libJIS.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 100344,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17654497,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a329c58c5692ae5fb1a3d900a14226def7afbeae9293a352291f963d9d167fcd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/libJISX0213.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 120824,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17721680,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d4c0867d87e8d3b67cbaf3d16d9e0febbc4c889ea99312b06628641004027ec2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/gconv/libKSC.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47096,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17773967,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a162aa2fce5ab2a500d13c461d90c772dea2e3134f01c788908de538584cb626\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libapt-pkg.so.5.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"linkName\": \"libapt-pkg.so.5.0.1\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libapt-pkg.so.5.0.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1776872,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 17813375,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c90b5b1173c7e515a7fefee77c5d9b8d0fef4e4ca49b89e806061fb0b30f6088\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libapt-private.so.0.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"linkName\": \"libapt-private.so.0.0.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libapt-private.so.0.0.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 378968,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 18584843,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5b38fedfa8f8a38929bb9fdfa5bc65a15610457b53a662f50f7ec6dca23e2fce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libdb-5.3.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1827512,\n\t\t\t\"modtime\": \"2017-09-24T07:14:53Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 18743676,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d14b28c8e96a50f8532cc26eb8c6e9f49db92fbe9cd35389a3926599c92a12c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libdebconfclient.so.0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-04-03T05:58:27Z\",\n\t\t\t\"linkName\": \"libdebconfclient.so.0.0.0\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libdebconfclient.so.0.0.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10360,\n\t\t\t\"modtime\": \"2017-04-03T05:58:27Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 19590542,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a2a1f22356ddcffcf35745f744dfeabdee3147653226ab168f994d832fad2638\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libformw.so.5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"libformw.so.5.9\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libformw.so.5.9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 68840,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 19593588,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc08c8a92dab40a2bdefe2524665db90e03cd483a173d7ca643deaf9deb45461\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/liblz4.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-02-17T15:27:54Z\",\n\t\t\t\"linkName\": \"liblz4.so.1.7.1\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/liblz4.so.1.7.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 72024,\n\t\t\t\"modtime\": \"2016-02-17T15:27:54Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 19624444,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:89bfd1003b37b293626a7800b34eab1b1d665465960d6955fd151eda316d14a1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libmenuw.so.5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"libmenuw.so.5.9\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libmenuw.so.5.9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35088,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 19658643,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:00069d616f3a56330f24e452e3950fc374fc5f380d46a71d4eea516cdfb46933\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libpanelw.so.5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"libpanelw.so.5.9\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libpanelw.so.5.9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14184,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 19673786,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b59bd2358da7fbe2f4c9a3df20781c72a00dd271fc93243363d566f3b862252c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libpcreposix.so.3\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-03-21T22:03:19Z\",\n\t\t\t\"linkName\": \"libpcreposix.so.3.13.3\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libpcreposix.so.3.13.3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10128,\n\t\t\t\"modtime\": \"2017-03-21T22:03:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 19679391,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:20ab25eb5624d2f2046c5a960f9b430cd5d2d26bb6d06659d2ba5ec99c33dcd6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libsemanage.so.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 248032,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 19682805,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a49abba01c68d4b5ee596db8bb5d1df4f7fc8eabf7650dcb87f54acd7572d824\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libstdc++.so.6\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"linkName\": \"libstdc++.so.6.0.22\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1566168,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 19780945,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4376550db3d4404d019fab791ad0795ec76ded3fc969248c11ec6d775f614860\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libtic.so.5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"libtic.so.5.9\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libtic.so.5.9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 59400,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20271814,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c75698c2c3fe73c1eb5cda96578cf74aebd9d9115e5094cd17d2d14fc21cac89\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libustr-1.0.so.1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-11-23T19:59:34Z\",\n\t\t\t\"linkName\": \"libustr-1.0.so.1.0.4\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/libustr-1.0.so.1.0.4\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 215040,\n\t\t\t\"modtime\": \"2016-11-23T19:59:34Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20301589,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:95f03fca5815ca2181d1323e140aa73f89842dd3792efc836dc1ca7bab1b27f8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/AutoLoader.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5487,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20380419,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:750ee369fbf3c34f72a823ca261d33a89bba98ad1d4a967f4f89e19b122eaabf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Carp/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Carp/Heavy.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 773,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20382632,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d5ac9b22f0e3e5632a1ce0945adedacbcfd02f4409d60437e908604f4857fb58\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Carp.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 20138,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20383195,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa19d9299eb23a422f3d8220e06e434ea4e6b3154226d8ec8ba84cb3904060d4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Config.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3331,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20390093,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2f1a1c4013c19ebf4260c6b6e5f0039145f54409411fd140b4f153e641d7fad2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Config_git.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 409,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20391666,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:09c5e2ee35ee18d9043d95273f1cd37bc82e80567fd1372a1eb134c809c39504\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Config_heavy.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 50645,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20391977,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0ecaa7f841191eed99ec3daaa84d891eb68125d1f357f337160a630dea100d12\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Cwd.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18542,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20407426,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e707f6c9273736f137eed9710aa2eec7edf582f86813abc8820fb982c4bf101\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/DynaLoader.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10453,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20414075,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:877b793ad9ae57d997c22aa505862f0a44221764b12201a2bc8634260ac7fffc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Errno.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4884,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20418413,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fb0e2878b7d240e5d4a74509a19ae2fff14ffe23ab3a69494c41a916ab915443\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Exporter/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Exporter/Heavy.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6406,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20420798,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a05d2fb4ade7016e108d8b8cdb25b8426b232560be0874755b198fc5be0fee1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Exporter.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2367,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20423386,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b9db7ff262f5d5bcc8ac7c827b0453c7e514c3cb1dd6a30fad96a25de2a76991\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Fcntl.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2156,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20424559,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:293ad7b0904fa32bf79bda796dd2244e799bb6b42450c910ef8f54d2edf076ee\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/File/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/File/Basename.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5429,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20425726,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9aeea43fda475ea4e2b75633b2e25528f45b2510c7df4809449fbf938de58bd8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/File/Glob.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1837,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20427698,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ad3a5d01dbdaea75fe6a46ab66146583d71ba0fff3b7b91dce67409a2d6e5f84\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/File/Path.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18490,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20428654,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:83defe5b5d9de11983c36de5507cefbf71822786fcd05d4549b4d3ab083f654a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/File/Spec/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/File/Spec/Unix.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10014,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20433898,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9be5591be0deed683c85b784c13d7706aaf156301da775975bc529fc31fb7ddd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/File/Spec.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 622,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20437583,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fd864e0a9be904138992c9174a9f51524d38599ad6b1d584fa8ef723c652c3dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/File/Temp.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 46927,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20438022,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f83f5e969b8ba4cb9de0302624d1df4220f1ad8c5e20f83acb9967d474516fb2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/FileHandle.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2105,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20452671,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:54211db845a110f16d8f3630e2cd2d258f2e47078a1e5261b0eae18a0a5d6cd5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Getopt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Getopt/Long.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43321,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20453804,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0a9a40e9df4b4c1a5aa260ab5fc9affa4cae13a8070fc52aea6768d276434fb9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Hash/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Hash/Util.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7580,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20466581,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:983dc4ad312e28882bc90465167f4a19e03dd4c27ecae615190cdbc26aa0fc82\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/File.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1666,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20468833,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:79263664dcd2997530dd5d941fbccc1470d4c66b8ae82c02fd96290513c39d14\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/Handle.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8235,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20469704,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fb4a9ff170e5a74ded4c42c539f6d5ce8999761b394830d39e6d3f152ab73b69\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/Pipe.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3425,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20472376,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:45f66014a6b374dbbbcc0325c79024b7d8bb22b41c8c7dc855e4394cebfe7c26\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/Seekable.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 686,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20473786,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a8ac552be340a0b593516d44eb34ca695676e46d2492f2651efeb6ada7f22103\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/Select.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4359,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20474271,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:09c61eed565460a2edee326be3eb5391ce55c0e3c53ec74c831a87646decf955\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/INET.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7474,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20476044,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4ff429519f3b93fb5e6ae2e42127b75cc5f37b6978de5885fd8251f7489057f9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/IP.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 20427,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20478446,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:866b9e45195fabae560e69cb445142d8e2aa902825c54b183fe5463137b7aa9a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/Socket/UNIX.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1375,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20484519,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1555039d56f24fccc3b829dcd40b87c1aa04b22e37b228e903ce12fb9bd0d58e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO/Socket.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 9455,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20485297,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1074f21b6d6a5e43e8c4363cb7ca4847a32e24f373d10ada9dfd3c93bad2d9c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IO.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 472,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20488603,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3d851a18125f4ad6f9d4d9aa8be00a33ce924b3965f0381fd8e74ac1507f68c6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IPC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IPC/Open2.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 816,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20489092,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6500142ce04d79ddb58102de7bdf1427c49a9d1be04f6c908027b6240a0e6303\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/IPC/Open3.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 9053,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20489716,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2d4aa629476d90f663ebff57af566044f9cb134f4eef1699516dc13c227cdb83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/List/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/List/Util.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1078,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20493539,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d9f7992c477f3cce159a5477927380e304cca7cb4cc99abf9e520bff652ffab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/POSIX.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19879,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20494294,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9d3f00c0ad31d9bc8875d19f0703490b39bc4ff8c36de3864269fd30708165a7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Scalar/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Scalar/Util.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1410,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20502130,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3b04edbbe4a7f38411c5081ab10c79f538e7c08dd7b4866d63f60492a2d09be6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/SelectSaver.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 344,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20502957,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f6f2b9bf40423e54466311866dc9f67a1318396d2d162cf84722e28d715a0ca9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Socket.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 13554,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20503310,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:535d67a90adfaab5f799eea70bf57859da660a0c99fd4777384d7e85123d0b8c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Symbol.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2099,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20508323,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b2ba240a38118df64bb369c770ae6476502a71097ba53f65fe435d82deafd94d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Text/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Text/ParseWords.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4480,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20509533,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa7484ce8671e27adbb65f24d19d376882e84edab8da3ea91d144fefc6906184\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Text/Tabs.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1702,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20511107,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa167b69c997b88b575b3a98013421745b41c3681b0a6a7433f17c1da19f8f25\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Text/Wrap.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2922,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20512058,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d63777a317a5631dcfb6b0ea4ae5f782d2e718ff31b9f091ac03962a997fc095\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Tie/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/Tie/Hash.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2037,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20513449,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e81ae4e495e961af321beac6695b5d43870418739901785a6b90c742f2d39d42\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/XSLoader.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3899,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20514378,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7d50e4be2f9f14462e63858a7e2582e3e7eb7ecef4d7f2c8e74634abf71b987d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/attributes.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3018,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20516162,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:67b321a13ffc51ace70061b9d2a079e1775fd7b915c27a3176cc40c7fab5a9e6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/Cwd/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/Cwd/Cwd.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18704,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20517619,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ec2714a435c774dba95b03f798b37f13cee4041449dfbc1c131c1234ff2bd0df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/Fcntl/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/Fcntl/Fcntl.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18688,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20524515,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ea8785c9591bb2c1d35e125a1b7c92fa14c01e3558004ecfd85d6ba0cf932bdf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/File/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/File/Glob/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/File/Glob/Glob.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27176,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20531138,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a11a966a7961d77dc8b882e35c0424f6a938a8931e6ad8994298f19292e6772\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/Hash/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/Hash/Util/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/Hash/Util/Util.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14544,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20543995,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c4f6fe1e6a3f629d31afeb9f4b27d3f83a68f7efaf9e4fa29aa143cf728d38de\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/IO/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/IO/IO.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18768,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20550050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:11b53111335419d0c238e35d067fc2eca5d7b8c0ecf98570b0d6b5a537980870\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/List/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/List/Util/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/List/Util/Util.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47696,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20557011,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:73c3c43ebc0f93b27345edfd7795f4fdeeb9004d3a30e51dd0a33046282f619e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/POSIX/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/POSIX/POSIX.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 106128,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20577193,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aeb85d4a9ea24a5350c0e68574d7b343aceea965eb733125bd2c3710bd924797\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/Socket/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/Socket/Socket.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43464,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20614367,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:503d657ab8a95d1979f74bdcce8796f06f32d49f7a8631815e07e53a0073845c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/attributes/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/attributes/attributes.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10408,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20630016,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4031753d1e50bc3e256e64af263c0ae58f9080219869fd6b3fd0e2e383b43427\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/re/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/auto/re/re.so\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 495120,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20634547,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2aeebf7edb04019dcfefaa326d6d779766d3b5da6ec6633807bd569fbcf5dd85\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/base.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8931,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20858830,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:394447d984af9973eef7ce0628625cfad98ec778f3ed81a467f0b8c6ed2fd1a1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/bytes.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 447,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20862319,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb05c506666da8af731d6470f1d5824c794461e1d5a6a4fd0ec9a78d1589e574\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/bytes_heavy.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 758,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20862684,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c7def62cbf7d031c4fe319e414117043f2a273885bff93bd18e11935d00a6677\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/constant.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5737,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20863007,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5decbf923c0f5f065147a7a1a89fd351a26d5d5efd8799ba4ee992a1d00cd837\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/feature.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4313,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20865364,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:79baab039d05935885bb984532dbfeed64e4fd5b238a6c6cdce38b92524bad92\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/fields.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5022,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20866841,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:47de715abc8377a925a04ca8e0f68f80957c075fd0cddb2400724968c22c08ef\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/integer.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 172,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20868888,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1c387bfbc4bcb4046e7372c534372c7150315499bc5641328d5c3c1c1ad50373\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/lib.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2284,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20869115,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6636e89a2107d3d76574e41f6535aee9d740700c892fe1f0179f015356d9ba4e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/locale.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3421,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20870148,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d584f47f71a525301511965b4a245933e9a936f94406b6bcd1c78e7fe63a7b6f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/overload.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4466,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20871537,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6eb2a643d33cb9ad8c265e890836c4c9a7bf3be53efa9a75e6bf8a99704f927d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/overloading.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 964,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20873372,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5387b33943963d2e47f05b3f37926f2d454f9ded33ca857e56ffb33b3adb999d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/parent.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 479,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20873905,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ce8f47c371967107564fdb66a00c46303213f8f6e7c933e19ed856af79af758\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/re.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8639,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20874317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7aec46a23600f1c35b9037a0ffefb061bf064e4954b4e35f4eeb39d22b46c8e3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/strict.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1606,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20877274,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3f100533c2abc1cd0b20060bfe71372c28443b13356fd5604133a69e844fc88b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/Heavy.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129498,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20878088,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cac1f06d7853a8dd1f6b8b59c3341758cbf59dd48c11c47ef1c1982a09d7fd4e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Age.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17925,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20905776,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:799fc2db4cef7d7dda3548341210a8682ee71a2f4added92776b9991c65620b3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7925,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20913050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:172a214478d317cb35788e97fa81a574ed0ffd9ac3abe5fb42119973fad512c3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bmg.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5118,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20916542,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6d45b0fb96dc56845f3c1444b2d92fa7029f6d0f06aa807725d94708e6de1030\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bpb.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2125,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20919036,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:495995c6eb2b997756c2b2f91071b2f9a2e3a0cafd63a69e9f6f347af868ce05\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Bpt.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1692,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20920165,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bdbc4054229d801ca6824d97da7cd8b618437a3587eee430578b870c1f55d4eb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Cf.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15381,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20921046,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:54a8ed05ddd618f1fa3bcbb38843656be0d9665870513e0f7a2565b26f589d9f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Digit.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5673,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20926472,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb144fe271026cc6d95fbc440569557c8ab031e5f20697e2024af502680b0c49\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Ea.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2980,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20928828,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d1c2abec486552afa3e054d3a04c051337f8a2baf2ad28af3ade507dec6f5bb2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Fold.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22741,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20930384,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5ab3a81e3d6fb8c22832d335e3c621a35f084f21d045f2d9ab4ce3c13b85ca6e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/GCB.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17439,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20938364,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d7c93cd1e83dc9729c54cd49fdc39b3f7aeb10e0f010bab7957a4df4510b206\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Gc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31753,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20944222,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c7ac42570c6443b79837db38e7b28400def99821d69533222e13456640c0d9dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Hst.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 9998,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20956677,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:023125f07cd4d45f40c3970bbaae4649dd7749f2ce60afb5065446426a606a83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/InPC.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7712,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20960205,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4ed0cf7f0e9344d0359c962b30fee48084b5e1554a52c85fc7f5265e7ebf71fb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/InSC.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 13326,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20963031,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2442f91af082912354e8047ba1f2ce6c261de8bf48591749e9405f9d242fa8d4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Isc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 798,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20967132,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6a774b0bbaa651dbdb6c76d01689c0c5b45258b7cdab8d6b33e8e8e2fa07f151\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Jg.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3112,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20967713,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a7b09acc2d7518a722dabe81efd8fe4a3f50f633da21709d89d38a8f3ce574a4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Jt.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4702,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20969363,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:db6d2fdf3147500d04a81c1e3912dfaa0b90d07047f6ca54b7e29b463368029c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Lb.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 29045,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20971709,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d85bf398ecf6f2e50e8d3e7b8dca3f6d011133b50b25e0f20fe9eda8e3511939\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Lc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8187,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20983312,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:07164c5cdd6a9a387080628aa79b8bee7f330937391b6245b8504a3efd7a1d3f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Lower.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15524,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20987466,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0215cd96047e1d95cab34a25177d117b886b83ca778abefda7e246f84ea10df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFCQC.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1751,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20994145,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8b3c568799d0d1b374373948f3084efd18881070e6deaac8ec3a09a2ddd10232\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFDQC.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2920,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20995181,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6763a26a0fbf79445cff82309d495738d81b6d6383617683a57f61b3812fb17b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFKCCF.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 398291,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 20996710,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bfecad5f99d94c2f4a2b4963ebe2750fa9908b15cb4efe7c438eb6c80a3d200c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFKCQC.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3714,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21055779,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9b80985800cfef4f1501f705642040f7190fe032b318320a280f4ff35562891a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NFKDQC.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4719,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21057625,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5f65d6e6d9e3fe8083d0ac3020a2b1a862247fa49e5ced277c7958d8255fd920\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Na1.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 63563,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21059896,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:63b774155c56a83a978a6694c58f9b57de8eb0f8fa8e06236126eef9aec97841\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/NameAlia.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 13366,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21073969,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b03da714d8dfc017d7bd2f2677061d395d23e923e014c65385d4f19c16374b75\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Nt.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4211,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21077590,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fea2fae1f19a464744e165bba3bf0547d4551a54205d9e10dad4457ec19e67a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Nv.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7517,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21079264,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2a2360e18d5df4d2b10ad5217bbbb2a60e2a4bb3e7407bdc134786898c7e2c75\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/PerlDeci.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1621,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21082547,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:97866947d1ede559eb516bf4d4460b401381fde6777562b49f1120f0d6013652\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/SB.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31093,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21083542,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:28e91b6b63b070bc0cc7d50c32334165c63035d77c8e68077c5cbccc0c930371\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Sc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15111,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21092862,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:914389449d1c7e8c20e857efc1f7d130c18624671aff6f857cb0c8091a85e6e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Scx.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17831,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21098657,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc69aa26dd8227544693047e64023804b49fbbdbb1afa52179196f086db42a5c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Tc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 11534,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21105089,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:288caee21b8c0d7aa9fedaa79e5f09a0aaa3e507cc12aa260273b077e694c642\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Title.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18899,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21110011,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:880c552b5da95595385f8888449619180af41fcf361d02b648f0c0acd5b59e71\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Uc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15206,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21117499,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b6fce17927c7bbfcd067efad997c748bd0419638854e7720d6646d9aa3624c2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/Upper.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22274,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21122931,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:60fa685cc003713e98ab17fe1ccfdf4b6ff8f4c15f530785a4bc343293a38fb9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/WB.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15165,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21130821,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5535f07a25badcb4ad08550577676c465be9e0a4ebb52e1de914a8ce4429a647\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/_PerlLB.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 28370,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21135917,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:09d95c10092034783830776b1632d968fe5970a2c9cf0a8ab320d1e22dca0c05\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/To/_PerlWB.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15388,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21144183,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b1cd7ef951a18bff13baa2e3aef1ae8772e298362fccb86829e58461a6e995f5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/NA.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7663,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21149388,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:895666b9e5c02a149077dd4632bad174ac718c2eb73c0ab0d4c0f0183b1a9bba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V11.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3447,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21152814,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:631458895694ee09d4b5e7a1658c7e8f9dcd7e20773a561e7d8de1ec8e871e42\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V20.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 841,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21154539,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d9fb6634cb4582e18366ecacf6f6a82244f6fb3a092b1f7a9d08a21e05224f7f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V30.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1709,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21155161,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9fb591eb2efddaac5e714e4f932debd58f1a8abd0ed686cf37f493db1365984d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V31.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 978,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21156189,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:85654494a8650e805227daaec6d25205b0d2d89d5dc722b5a567b7449e44ba7b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V32.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1115,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21156832,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:39ec1432799ed310f2b97a0e697d4b2f06b1a463a5de819f887e0ffb5e235a47\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V40.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1325,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21157581,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d3c689b3ba921e05f55cc2f701f7ba910c1d91875edf5ba61d21008477fb06f9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V41.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1429,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21158431,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fde400c6deaaa41ffb42a52cc4e4a99b290fd5f12392d707107b6f55f21994a9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V50.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 870,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21159315,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e5590ee9f1837c84b6e47dd318d952ceb83d729f096df7919d6d1bd6e1030e71\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V51.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1459,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21159960,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a03248090f3d9dbde0be80a89cb12131035acf9381a6e11a0ba02330d382b138\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V52.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1539,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21160860,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:46e9e09a71988fa10555ab1a452624424f0627c849c0341e1a47b8bb5452317b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V60.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1815,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21161778,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b4266095222ffa94a519336edb457a9c4d8a820dcbf4b3783a81d033aebdb1ff\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V61.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1625,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21162757,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f77c3582d514dc07e2fd26130801864a5b034145ffd22d20df0e71d902fb736b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V70.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2213,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21163654,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:696ac2fb6561e7598f89790b1dd2559ca33d380d01a1e72039a3afc12df3a9e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Age/V80.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1213,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21164825,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d065d94198e8268c26a48c173636c6a22b97e2c615883f8f7dc48e0572bbaf0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Alpha/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Alpha/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7378,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21165629,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:153ecfab205c8ebe3e525e9bde6913d1640c06dd7b2fa7432d8545e798ce6368\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/AL.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 708,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21169000,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:51b28b80d650595eed708e3f67154a1587d55aaa11143f6674d4678cfc5bdefc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/AN.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 542,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21169562,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a45e2cf93b810b43af4f6d60e642e4e88c6894ebb05580ebb016194ef5dcb6fc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/B.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 526,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21170033,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18b1b9e230759a28efbc814575412350931491980dc48c3c0c9e4d0bc29e67ce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/BN.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 882,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21170494,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94cfe9fcb8120c1054db0a9151767423f6efe1f1b77c70129c21c69ade604667\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/CS.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 618,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21171132,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:895fb05bab16084ded08df473a119fb89f207fbcaf90598d0c90ea4451880e25\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/EN.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 614,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21171641,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4278188bd2e78e736d4d53e61dfbdc8bf1f8bb342e2efb4b4909502c6c76d098\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/ES.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 580,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21172159,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:930e8c3072267904ed75d0a2b2945018096b1d091bca696a32987812467cfccf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/ET.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 714,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21172649,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2257544aa2fac4acbdf791327a2fe45990f0f4d33cdc6489b2212d4dee92a39d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/L.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4913,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21173209,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:52adbf5dc0da2d5d721eadf3282a290611eec86bda5d2eb1be7c1b11c9eed969\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/NSM.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3351,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21175512,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:40b12bf6ab2ca1c3c1610530a9b64a2d3c40ca7b204c1c15e8bdbdc9509acc7a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/ON.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2436,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21177135,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:394079cd6f91f9b3dbb943b526b2cf57129ea244f048b33d5a9e834daf7c84fd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/R.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 838,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21178455,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e4887c1576cac2abb7788747bca6ff8eba0287ba436699cc56a5808451095b89\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bc/WS.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 554,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21179069,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e9326135605b27c28f29a3ebc70b8a6e60ce49439b65d8f022eae0840c03ad7a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/BidiC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/BidiC/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21179579,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:95b0b0cbd67c31a3c6576d5ae664956d685a9d74c3e05cee58a34ca33c673e06\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/BidiM/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/BidiM/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1717,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21180077,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:153d2c916858765de9b42d64392328010f666b7f06bf8666c1424b1e3be79769\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Blk/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Blk/NB.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1025,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21181075,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:98710c03108d5b8ddd049c49a5c54ea46030d365b8919d6e5df441cd11683228\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/C.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1177,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21181831,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01271a108ff293e54e3144751dfc207edf4c57e9c42ff5f72267b468908f1591\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/N.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 800,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21182545,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:21dab8af5f812d52bdf968459e49c740fb4661400bb7ae449db24c7dc5d39a91\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Bpt/O.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1177,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21183145,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d2f892a7cd36f3f588205261a6f47471fb3f83477a90923014b2d17dd20a2f2d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CE/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CE/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 846,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21183880,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c36c6982a245f4ca4e162574511ee721fc264eb4a21742bce44a00b433ce13ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CI/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CI/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4241,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21184516,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a265bd13d34abb29313b7987de58e14c44d35b35387f511593d010c3b1c5ec1d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWCF/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWCF/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6490,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21186542,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a28dd0229822f0e85a3c00462cb32e780534f2f16af181997fcfc6a3bebc1bc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWCM/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWCM/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1593,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21189631,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d50b98c979b8b22ad5bfc1feaabb4e1ec33bd8d0389ad7afe9b512d2ac32be0d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWKCF/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWKCF/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8994,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21190648,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8bd002f770064e710d41cd11ea343b92d2d536e76aa9b341fe3bce7f7e58bb5d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWL/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWL/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6374,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21194854,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:88ad9c96eda907f2eb3a7b30373015a29be5950279d6c3927a5c571844159de7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWT/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWT/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6532,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21197888,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:abe8a77955ed2930198261b9741bdb4729acd6d853b9f2d224a92c28e65def65\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWU/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CWU/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6524,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21200982,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:13b16e9e72a8b6f7c8d102292042ba80ba3aaa13d96880f63f9b74655b5a8a05\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Cased/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Cased/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1937,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21204072,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cd8039d00559b55e7d6984e64b62d7baf9f8cd0f756228eada0ced86b60bcc53\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/A.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1551,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21205189,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7767a020409dad0f6d805f1adf3c17c362da3eaea55d6961db978f446bfbca66\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/AR.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 525,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21206102,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4af81b6bbfb9cf07817d5358f6af328c6b697f2cbe4376ec6781d70d231011d7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/ATAR.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 535,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21206571,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a68565ea04fe17f76e245a90d84d011bf45b9dd209e2234212693a6f1baf6642\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/B.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1211,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21207036,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:847b4e8706ad7ebc9bb1c438fa3fe6f0926eac8c72fb281e87c21d08e61f4391\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/BR.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 531,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21207826,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bfad8077a9404ab7c48861b119912ab5e47cb403bc67c2f358f9dd34718f7ed6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/DB.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 523,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21208289,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9e90c185c7c234e6fee15d4967661500f12b628114818720726ca90c22b9c1ec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/NK.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 710,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21208751,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b48f6419b3f652d85c3b11f9ddc4936271f4db389d11b92557af6a96f6f119f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/NR.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2149,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21209304,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f4a6ad8520f85deea7a999166e055d235f35aeb0081ff42e5376255444cf345f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/OV.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 610,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21210468,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1ebb46d59960672a29f9045e3a2046cb93e827f58fcf8abff252a1d7c563d364\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ccc/VR.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 942,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21210977,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa750cfd0df25a10b0967b28690de1ba5993cb2a448f2d147ffc56080c16859a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CompEx/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/CompEx/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1259,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21211670,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:362b71e73a3b072425f5889dd64e4fdc08c93b0c002d91089ab31a36754bf68a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/DI/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/DI/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 678,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21212474,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:582eb22ce663ac2cb933b20f6a1f07628d86118008d611ddf44194b2d5674755\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dash/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dash/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 718,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21213052,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a6aada6ff63c45d487a58fa5b16e5ff15feb253b5db7ae93178eaecbf101fbf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dep/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dep/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 586,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21213637,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ff21ef6a2e5398dcaf1f20ffef0310f0ab60cb3c28018cefdf7a1b2b83b073a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dia/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dia/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2061,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21214164,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f0696b99052d6493f9760f1755ef8f8e137480f4fb90de1ee0b60192e6de0bc7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Com.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1249,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21215342,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6517d7369068ddf4621da7a984430011d831c9cb2f4c8a0e859bb3f938060199\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Enc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 586,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21216156,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2d57420e36706e61b846baf1f831f0a8c265dadf3e928595641f59af61488681\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Fin.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1847,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21216651,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c76ba4201f2c128223c5d10779cf0b6b643fc3429d759847f12c49cfd67a745a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Font.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1379,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21217580,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:634e71167318263a480c83e8288105d0a588b6c33d680cf82bb791f4a09eaf9c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Init.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1391,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21218333,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a4e9f05f11e1f2f5c8c72010d59e5eab18051769ec32d7c307e030271719671e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Iso.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1667,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21219121,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cd0458d5589485eca6c394f28c91636a50e587fbfc652a1348ead4dd459521e9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Med.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1139,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21219995,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fce9c154d14ac6bd407150ed9e99b5c5640c60026a61d8d656baa569b69da0e2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Nar.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 562,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21220678,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:531d4f55728f8dd5b78b1738c2e7cd45bfbcefde93d1f2f22730a59c24cde560\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Nb.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 538,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21221151,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e429db6cf47bfa4a78882fb401e05b37edc9ac8c2fc39c533e8d5a68b7949a6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/NonCanon.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2657,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21221622,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1945b1fc2a60d15018317eacde9cd20e0e1499fbc6c906a85ec682bee21dfa84\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Sqr.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 606,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21222963,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b45c60ee1e042ed6eb2e9dd216a07e2cd361bace92b05bee522b90fecf76bdce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Sub.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 531,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21223466,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6ed0dd870aed3f0db2749513931412e06b161fcd6e1c75f987c557e17da9ba2e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Sup.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 738,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21223935,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8f90ebc3abf2cf6935c377d8ad362a1b454807fb9f86eb6c3c63ebfb44a0e43b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Dt/Vert.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21224515,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eacc5f27dc0f5299b611fa9add6d92f47ddb80dc5f8d8faa6a09c4357ad33da1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/A.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2152,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21225014,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7dd3d1b8becf26d4673b9de63f045a21b26a30c1cff0c1e029fe41c9f949d44f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/H.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 572,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21226253,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e29e29e6c6e70eed775d55bb5b62b1cbb442cf9e2b145bac5323799028764bf8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/N.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2613,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21226733,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:00c916dfbc363c8b6d78559da963bf63d891b9df6634449309b5f905f30d6825\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/Na.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 553,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21228158,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9068ab08b300c75c8ceca277b1ef6e6268b2cdfa7de15176f6f8989463cf8a47\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ea/W.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 896,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21228640,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eddb361861195dce0801db83acfce1fb7ea7c286a9d73765799e35df4a2ec3de\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ext/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ext/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 776,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21229309,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0b98dd664962ed3dba4143d1a23d85265709c2b79c50b547a28ac2afc43c153c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/CN.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 717,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21229924,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:46a2b8690ebfbf7ecb3b7819097259cf2d6c03953495a9e7c3d28b59192d911d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/EX.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3581,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21230501,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c4152337f9173e8719f9b4b257f0ba7998ddb54900e52966edbbc3632fd07c13\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/LV.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5279,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21232206,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c4568a86bc16057955da044c097ff34a5e8a17f7d0005324ad15284b78468ef3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/LVT.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5279,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21234411,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:90aea35d7a172c8b53a3fe1b10c919a9b02c7e489fe46b84ee4ffc4e3a79fc72\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/SM.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1929,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21236616,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb496af4f93e7144e07e9b15755de6497d8fc0e892de6bde46ffcf4797f3a248\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GCB/XX.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3296,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21237652,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a4a41055bf7da9f924c4fbdbb58b075fd4af6afe1e96889a9971b3f1f7de010\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/C.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21239319,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1b684544c72a4779455627f4d813423a0ca5dc6312c509b366f9dc6a03758dfd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Cf.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 680,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21242693,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e789aae540f2927b3db679c559591cf4e5ff8401b60df1937315d292ade44405\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Cn.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7523,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21243241,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:38cb532eb185268bf9ce967c557a1af01b6db11398a755ca514d7aca4d4ada05\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/L.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6716,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21246603,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7b658b5727e3819db80c229aa3b3dcfc392751045c3b4bfb9a1b2125b06df149\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/LC.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1849,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21249648,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1cc2bbb0394ae80d1d686401c9ae623e34b4f8f537594e5501afa169e6828f72\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Ll.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6928,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21250691,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c464c9d51cf75d1a7d3123e0c81dde4f3446175a814053b1ec196a8927d6f960\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Lm.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1091,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21253975,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c5becb57eedfbf023e5a36a95a5a67aeac1dec28fce67729a0cd8a4b71d6fa86\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Lo.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5375,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21254712,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9c49eea5bc50f051fb58329f23e9675cc01887328f93d29fa0540f727b95d939\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Lu.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6866,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21257215,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa0731e935c0c4ae87db490249f22768933051e24ff8fb3adfd8dc692576f949\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/M.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3065,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21260451,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b69ebc1803fdef3b03df749ee254f466f80d26bc3010734759312043bcc46580\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Mc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2085,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21261986,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a9a2e66cc09f7e006b0294a27d9fe0b1022c6a3232cd53789f22dda89ce751d6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Me.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 542,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21263093,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:abbdd8849b43e36186134ba648f58e9f7ccd789683837f543b7004b9c5f678b8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Mn.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3391,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21263563,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d10d8ee92ceb362c2ba777eab53b6857bfbf1c02b8cd95b558d3ecfbee5e3c26\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/N.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1731,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21265199,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1dc44fa3a7704c2d629b43720749f90790e49127b5a5cc94b848fe76a767399b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Nd.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1043,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21266224,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:63dac7016953581540a2538710b0c4318ec2b9fc3acfca829e69ca737f8e49af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Nl.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 628,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21266959,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:016a472ab6cc5b30ae7cc6551f94b63b473ea4c6b73ea282db39c5d649552868\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/No.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1149,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21267476,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:822dd7912d7229f9f14013f318e2a1ea135fd57e6be75f108ba665d313f6a8f8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/P.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2229,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21268244,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:371b7f97bad43659b45c06c5935c55d427df4bb8c488672fc78f1982b3391c36\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pd.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 678,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21269455,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ad65ae09d8cb997364c099b590b3c28ef4a8db23ec0526278051b6a3208d432b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pe.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1321,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21269993,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7615e72e7e374f966d60f68243e039dea6c567b3a9be817b40c5b3d8838938aa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pf.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 600,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21270747,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:753f0b70a76c59d123209a9ef95ca3793b8d99a1a7b6bf59bff11fedc5bf3b14\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Pi.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 610,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21271241,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8c45405effca58ee2d3a4fbf1a38a8236a8076a2de9aba13bb48393c8a667468\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Po.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2197,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21271741,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:58800da8ee0bb4a638eca93796b087a9dfe35012888a45571f2cecd211356b19\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Ps.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1353,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21272922,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b34ec254d4e43c5752e2226811eed8c99a41073aa72e6fd8e0b7a1563da414f5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/S.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2934,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21273684,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d5ce890e481dff7a947a98d7d7c76f2e7907e472f81cb7c9d5f84dd71782faae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Sc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 666,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21275182,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:08d139cf2fd09d29efc97db42f745d90d2bc0a7601f2fb92a43f42eb356f70cd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Sk.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 772,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21275719,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa1fded45460df446896a9545016c9159a610265a1e32fa9df2d8b40c1381b8f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Sm.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1191,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21276321,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:164ceffc29dd40a6cfd9ba9332d3a4831a99987e8d2a6c2cdd441b338656d926\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/So.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2468,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21277089,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6d251b99654781e7e7ec057f316a0a1eb51497f3fbc3be442a1d61bc125ef346\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Z.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 566,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21278364,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2eab52cc23eb22532a256bf16b3ce41de6ee59dc35289113be6a8d2a804d9f84\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Gc/Zs.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 556,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21278852,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:58055a6143a100243cc3e9ed7cbdf794b4a2fff5a5fea630238823f492c6eb0c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GrBase/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/GrBase/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8947,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21279366,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:790ad94d6a1e74542fa78f2a31e760c96ab9d767018c0a1c6f64f33200f0ffb4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hex/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hex/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 545,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21283331,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:21cc921c64c5201357a67823af77d2b6a19acabe9cefc238ad8938adf058e05b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hst/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hst/NA.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21283837,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5fc815fa3b720f3de4e4d61db293e6abb336d413aebdf60b9b4c507566c2d3ef\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hyphen/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Hyphen/T.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 594,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21284347,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:db11dd24449811de8c6717ebf0ce58d3e68f05d280f18b8d5816ae313b072d5f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IDC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IDC/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7786,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21284880,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:988886312785a308c02e30225a6f72e3109dc0acc30b89ac0169bbebe8ed7b7c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IDS/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/IDS/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6730,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21288422,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b0e8a0ac8dfa48e844a0a40a043aa11198a1564895ef9df692ebc50c226ed5e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ideo/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Ideo/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 644,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21291508,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b9a3f4b14ad1df197900ccd1f6e40fdb030486c1cf11e1cfb4ae4d2c632f3bac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/2_0.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3746,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21292070,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:13f6d56ca5be2fcc4826008e757ea3250f99bd6135926db97001bd25d9608109\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/2_1.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3746,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21293931,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3e9efcf7212fe4e7a64db95b2a03d7b420f1cd07013bd3ccca2ccdc9a72f4e7d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/3_0.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4350,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21295794,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0c46b7bde68599a3b1954a0eb362cf190294381a30127a7968a92c92e42be8a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/3_1.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4802,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21297911,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a82015a87e5674584856f531e4143deeb2ede5c72b9b106f08fd72ce6159a39b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/3_2.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4740,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21300214,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01217f692d41f64cf3e72eaa4efafaef4a8ffc8f3289e8d944d8dbd20dec2ce0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/4_0.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4924,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21302486,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b0d564073aae2946b46181dc7f7352e2f2a18b96c7570f0e5c8d980813a7912e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/4_1.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5170,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21304829,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e69aa31c985304dbd9691fecc2e8eae34c2424c867e65a3d60f023fcdb5b10b9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/5_0.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5298,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21307271,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fd2ee1e5d66198cf658a0bbb582b37f29f13f247b299c5380f168c98a776afaf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/5_1.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5490,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21309760,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f0166a4d8804a9e22594eec9c4ef7b17e4c1363f57e30dfa8cac6cd110a77ba6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/5_2.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6002,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21312330,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:02fe6fae9f32062930bf45f7dbd669f9f321fa6543f6c8ee93483fefacd62904\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_0.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6261,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21315100,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9dd477413e652a76542f7d038d7fdd4f7236179b61c33040b1ff78850c4361e3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_1.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6759,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21317977,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:04c5ae4eb50ebf723ac3db094a8d42b56eeba5ed8adc5d5a0833509afb9ffe2c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_2.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6759,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21321037,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ab1d7d9b60dd8903cae87e7918b121b8c9fa4ce2a60324cf3ccd174ac8ce9789\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/6_3.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6759,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21324098,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d6d7ed8d5392f036d48104c22ccf3fb71c9a0a5a99b49599554818ff0125e8b2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/7_0.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7515,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21327162,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:923bb6a9d109b0da8a3cac2d6a1b442f9fd932ef0804a3867f9e7646365e1d0a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/In/8_0.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7665,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21330521,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6e3ad837e82daa5f3ec302a18814ce9f6662b5de63d557e75ff8153fda240395\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Bottom.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1699,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21333992,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:468da8bf6dfba6e473f2972b251691aff4c6f0e3e7f2d2c08441c6e76c70566c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Left.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 902,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21334962,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c6dc18df59e6636c97eedeec3fd68ac87b9fe3c9949c6be0d848a69c2482fa12\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/LeftAndR.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 628,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21335602,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4550e724c609641a8ac46c39d0ed5bd150aff8baf8300693321f92123c02b842\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/NA.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2311,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21336118,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b6feb9c1b0413d1da65ee9a47ace8183300edf33ecb6bb51022dbd0a001a0f73\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Overstru.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 533,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21337345,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a78146108cfd6325943bfa19174f77476accd0f7a2a662f5acd052e371d92b4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Right.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1981,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21337816,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4e3b2907207137d39f00dcdfb4e9de5d6990068a0f8a2ebe32a1150e9300ae4e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/Top.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2125,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21338873,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:630fc5fc51a6d904805f10a558983948b9a0bb3f5f785b0843897e58d278ce3d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndBo.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 552,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21340018,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f1afb1d74d21ae82b54c28ac2c4266f33cfeab3de1e10e8b9db7e6b9716eda7c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndL2.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 531,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21340500,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a0f38b4d2a324af133bfdc80cba6e71a4b12504d516d698a0afefd27aa028dc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndLe.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 554,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21340977,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3d33132e3c015dab8fca9eeaec0779e29cab54fd50443ac1d4b613a302482b85\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/TopAndRi.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 584,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21341459,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:75f7ba0cd02d1d35e55cc1a752bda119c86525e228849f6b07d895486c2fb3a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InPC/VisualOr.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 566,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21341955,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ed0c5935a1cda0e566a66e4568d2caba1f227952c22b93e37a4cdf34c276707\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Avagraha.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 626,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21342472,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f72d20989594d3e67120d0be23e41d7aa7c035ad751ba8c72634368e7360cac0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Bindu.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 892,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21342993,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d2f8b73a98b0cdee98c1bf27fc6466d7c4befa157ed16e469b2fd72030937451\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Cantilla.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 576,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21343640,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1dd353f8f78fff54c57d1dd7e972f709ba595ae55d97f374e06f41165591fdf3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona2.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 608,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21344135,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f5384d0716886b40810a8342cb7c8437229b7b5d98ee83ea953fe7951fc5f29c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona3.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 586,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21344656,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4c807a57b2b975117eb16ac10789e0de5af30f597c79957062279adab01afd2a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona4.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 586,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21345157,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4c5f334957a5abf4cad68467b86087af42a926e518c4480080822a6b96fd6b1b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona5.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 562,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21345658,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2efd67da131f00815609e67de866cc43760fccde62d46414855bf5399b31ac53\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consona6.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 531,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21346150,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7050f2f53849a374b0f2af1ec7de9ecd1d48f1d537b8c52a899dd4ca9ecf9552\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Consonan.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2019,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21346620,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5339e1b16056a13163fc91a699698cc9708952648ac828f1f7e5a7652a2da8b1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Invisibl.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 566,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21347738,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9e2be1b50e53e515a745b2c595ab7186e590f9e74917e602bd9c14b8408250da\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Nukta.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 722,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21348226,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ad89d93922400e9011557a23689ed306877926358f8fa2e9eb79b6092f9c725b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Number.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 918,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21348791,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f037c0204cb21032219cb0a78893a2aa2857a01e2d09d15e430564f99ffd834b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Other.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3459,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21349466,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5b0c6ebd2b4fa552ea5799e784af2b49d9116eb2196eaa28f41b075ebe96fee5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/PureKill.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 652,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21351189,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:75421328514596cfafcc7de3ff352d428137c2d6d8e38250625fb0f49f4696f0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Syllable.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 618,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21351727,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cead1ea4a4fe43635e01bce4b9fc348abef77d318e3713498e125f7548516714\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/ToneMark.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 650,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21352246,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b75f698a239534cbab48e902e8bb88c9f1ca298de111e7c5ed2346757155e5c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Virama.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 732,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21352779,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0da894d458c455ba17371f79be3244c4c97b823e2943b699393857300affeaca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Visarga.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 796,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21353352,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a87513f8a1d92e4f8a8ac566b700322d47f36b9ac10f70f0468f01fe23cc6a4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/Vowel.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 548,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21353956,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d468fa92702a4e0f60574c696863cca6561ab504fa31062ab2cf19e096b76e65\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/VowelDep.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1625,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21354436,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d33a82fec0243216a80c828c8032de7d45df1bd8156e936406911527c59e8f5e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/InSC/VowelInd.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1241,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21355390,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:84a3f31938cd83f47d9383d92cae715d5d608e97e0c31f6a3477ee2bd1f9ec10\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Ain.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 540,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21356218,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f24016b9d14d5ed0291379def4ea1de1dab8aa0daeeca3785e790377048bfb21\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Alef.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21356690,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f4b11ee075b7873457c9899e1f7be563c4787cd0128277cd1fe80192086fcb6f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Beh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21357162,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a251179bbb302b9ff9b437f1bad999c7287026cee7403079202dcf38250f7e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Dal.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 540,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21357638,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:56947fd737c7f13b8376e6702eb5f26e6296a5b99a04565a6880ec2025d74ea7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/FarsiYeh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21358114,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5dc68c9a2b5f3544d5df69f5571d284ae453244ff58d1a64de0efbb1b8a22323\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Feh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21358580,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ae53d8e50eaa7b8787692e3589b38ca28db44bc5542c0cd499dd8581642f5bf5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Gaf.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21359048,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e4e395972574b5ab0668dc6a4f210a7dfbb03f06b04a08ade566d5474a6216e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Hah.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 570,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21359522,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d14cced32f4055d4ac13cf8d92b6be4fdcdc1c9b1674ec2ec9f46384239dc4ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Kaf.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21360010,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:87bfeee9af881a4d1357a6a08cc239b7e22d0b7df7e6f543fe83bf744c3cffe9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Lam.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21360478,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e43f4f9917b7243e1673aeb509e0c063a56718d1e1d998fbdc05da0aa33ea7e6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/NoJoinin.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 714,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21360948,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a12c205a59adfa5912d715e3313fbb00a35952d9a9f4c79b1463267c79d0ca69\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Qaf.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21361502,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d5f83fc3feeb39fad902ccae85624b39d6afb82504930dd3239ef71e0095822e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Reh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 570,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21361964,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:264d7bee09393a22317c8583efda0c39c886997c8839ed5c2beed124d1369fc8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Sad.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21362454,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e51b935f2bcb554b10978d7236af8a127b2760c0ce33376de6af82c9314df086\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Seen.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 560,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21362923,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b3127bc9cd8f5b8c005e9b3235ecda61da74279beae78d560cbd7de1b4b7627d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Waw.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 560,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21363403,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:920dcab0a75a0cbb76488df491ae59bdfc7bde9641cc858d7662aec79f2a94dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jg/Yeh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 560,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21363885,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:76e8ea7d2005c5a1eefac0d1b20e58f09df82db8d61c7891c780eac65446f83b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/C.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21364397,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:65fa3c06bb480760cf92b70a8e4472aa9768f6b25785f3fc766f3900015327f7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/D.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1047,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21364857,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6b7ac3e4cbfdd06d82a7486db53310fc013bec3a8e075126f4f3e309985c1abe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/R.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1021,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21365548,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a2cb7c3e73e46c497012713f475252c94893a6a1060f6349eb136a356bc2db56\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/T.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3527,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21366210,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d332613820c49cbf11b5704ed9c4540b7ec73f4b822f94f9da42aed0010c95b5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Jt/U.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3715,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21367906,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e4d9ca5f6e99a834259c84c9fae537399938892687b735fd24965f360280a799\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/AI.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1581,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21369711,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b11022673f7f67894f2decc01c1c48b7979ed84edc80ee1e260312d0c91f6367\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/AL.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8299,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21370654,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9844fcc9be847140cd01ffb3ea9af682a28215faa9078140cdf143f69d4bee9f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/BA.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1436,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21374369,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:201498aad9193c088657a784984d18f4fb4375457addd1206b0871e1737a9694\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/BB.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 652,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21375228,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bd32e12c3a73321d3ee2caf733d70c574f2443798d38a3f834d33430170aad83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/CJ.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 790,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21375765,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:42c7825541dc6610e017372d3a8efb1ca40e9f902f7b753dc41cc795e950835b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/CL.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1453,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21376323,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9103ed646347e80f105a396fb40da96c67987d228006afbec4f9a8a142996888\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/CM.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2913,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21377123,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bff75a24686a2f41fd0584ca0591fbc5f305f51fb6d5393120240eea6e5d87e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/EX.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 734,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21378606,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:20a5578ef22b824b1d46f57c7975a9988de472db0923e14da1114eda5a127d9e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/GL.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 594,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21379172,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fbfd4d27e4263cbcedd2ab51a0565064e497b26e150f1aef9da80bc5bd563d19\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/ID.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1997,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21379674,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0fcbb793a7a08737f7cdc8cd292a32e5394850852e49382a281577a829c6160\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/IN.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 533,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21380723,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05939a3120788239583c7041e285cfb294a7d86e9fa8551c36b16cc45a7289ed\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/IS.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 580,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21381187,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6dab652d9ca506eec3a81522f0264dd939c145d3340f96a20517d45c875f8e2a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/NS.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 678,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21381678,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:316b077ed0564abd6ed7751171e36beca2e14cfac602472fbb676b8483a58f6f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/OP.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1441,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21382208,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:15bea04086658d18d80ce78c654cc87f72eb3c9776e4ac555ee2b6aa5981107d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/PO.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21383011,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:30e78aaf87f8f2e91f79f63c244b8d77ee976000fa38f6b095119c23481a2b94\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/PR.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 702,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21383562,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:93e20a79854fe08ed2aece340eb63149e65e4c3916add2d554a2d125c43972bc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/QU.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 620,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21384121,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6baa2930012d73c927e385f3b9181c8ec08a8092ad5e80338ba6413fa4a928b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/SA.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 926,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21384637,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fbac2fd92d95af1bd7960f50252247040c8f1da99eaad06fea8703a90d3b31a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lb/XX.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7404,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21385293,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5e4a09109f7eddad90eaddf7ec155f28c2ea3543ea9693894cf679cd66a9d93c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lower/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Lower/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6986,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21388636,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2fd2550c8dd707f916b5608dc6adbd5a25a41ca1cb0556461f8daebec81d3732\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Math/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Math/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2093,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21391966,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:659033c57408a43fcd825c8233d423b70d51d17aa126582a99e394da31104392\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFCQC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFCQC/M.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 894,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21393083,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:35b860728ea7e0d195e3ff942c26df489663e927b6207e9df4b210a42e7ada2d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFCQC/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1641,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21393741,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:310eb93664b58c215224857f99291667c99d6be09702efcfefaf972e6b7ab4db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFDQC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFDQC/N.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2885,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21394726,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:abaa7ba35e14c3bad73e74789f290c325ff1625bd31d61ccda3c5042abcf56e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFDQC/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2887,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21396206,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3c29d7fad1c6929e8b0e7e8ab6104be050eb47b24e6126b8c4afbf6cd6b3f3a7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKCQC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKCQC/N.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3321,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21397718,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fe77c77030f1e1e99698aefa57fb2cf5b8e8eccf23bf9565b542650b9e7e2fcd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKCQC/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3691,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21399334,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1f5fab3008efa3c5b53190bdf969ea1f547baeabe9a41e4c9b790ca84a6fcf93\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKDQC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKDQC/N.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4791,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21401145,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e0f895808e8339727f0b5744779e2103ab91ebc74dc77734352667e575ff0669\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/NFKDQC/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4793,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21403408,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8bed0812bc523847488a63a7c3aae16aa5caa8f4474b11bc2fa8173d4608a544\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/Di.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 702,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21405695,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3c278d93de413ca5e0210b4ed4ad791223c18ea02ac9ccc923482b9d09d38980\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/None.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2629,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21406252,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:56de36761d9a9cfd088c85e561b6081759f8e2bc77ee7b175882ffeb41a33274\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nt/Nu.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2149,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21407619,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:beca0b577b03dca5c3e976bc219c662bbe60c40f1667d0389fbdb11008c2afd5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/0.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1257,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21408787,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d59f895d8d9db1e3ba2f030543fc3c58f29781dfd67bdfa3894cf2c97618c1d0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1787,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21409578,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ee1c6cc39b46109853103c6c93e8f19166e59d89e02b87d5977c5eee269e0900\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/10.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1062,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21410585,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:be3afd12ad8c3b06f8e210c273fe03b12fa43e7ad71cc72c72f9e76148897c6a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/100.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 828,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21411284,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:062447e211a0753dc7b8d69aca1bb364937d1065b74768bc0338831b56ed776f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1000.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 710,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21411886,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7f61ec9f997bae10ad53eba48eddf2416ad833f761564e1f77aafa90ff06d748\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/10000.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 594,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21412442,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fbe03cac66a477c30ba70339e69ad16997456727d28ae3fd1e1edd049a3e6352\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/11.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21412940,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:10c0beb58714c1a2d12a98ba86666ad288872cf1a3a28e53c986477b13d2255f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/12.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21413416,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7e19666dbe9e7cff6581f954c1b90842312aecfd9c137e2109947e7f986bd6b2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/13.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21413890,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b09047105c8f53ebf6f559362f0af14470a3b21e4e7794fa441a432d7c5019d2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/14.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21414352,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:799cef8b8010ef2aa1edc5ec0da21261031f1942917b9e9f9252efc812a8d913\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/15.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21414815,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:80e45d74c4701efe80e6305a0965114dae16bd82a7d0dfde5d4f32bdac25d81a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/16.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 540,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21415277,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5207764dac87e97fdcf4787cad1966721e636ff768c984dfb69f1f7444463bee\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/17.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 540,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21415746,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18c61339544aab80adf0219e8e46046c35d188766f17996993e26b3f6e617f19\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/18.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 540,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21416214,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:825518e61f5b329281357fbc566496484a3ee5b27bf65a83dcb86ba65e8a16a4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/19.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 540,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21416685,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fd7a996d357f74ef65d6d9e174293dd9b2b62e1fc8b0f231c761baf67d1059c7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_2.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 624,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21417156,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2aaf91c335a92bc9014f5342abd9565cf90a28610455bd4ba8471f66c27db2fa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_3.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 560,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21417673,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:71cfd371216fa9290dc38b17ec5a9f810acf1a8988bbb974aeca18ae03205134\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_4.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 612,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21418151,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f3aa2dc45272ea33a70f9eb387faf24f1a521db91dfecc1229a914a896584b03\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/1_8.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 544,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21418657,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:90d84e969a919182cbb641336f84927bb38827287027c0a0f0da3e8231ad1d93\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/2.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1789,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21419132,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:400d0cf0f66474b868ef996e910c4dc33486cdff13c2dd436bde843fc7841439\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/20.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 842,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21420124,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:26cb5831d1afaf01f35e659269bd4455b124df20d7eb12a114516b2a9a4da22b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/200.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 537,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21420733,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:748a077ee40368a52770dc192fe6ddde19d7161061c621c64228f56fbf180342\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/2_3.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 572,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21421199,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ea4dc781c6de8fd29ad1b3d3884c3a8d9a4df1a1ae458fae80915d4bb3d7a0c6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1771,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21421682,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a169a6edc2d01accc73b423afe0a4cbc165a79de17f3da89dcb90619bc6c76f9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/30.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 672,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21422679,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e82e4c2aa63e7bdfcd08eff764bb40cad93a2ff06de84a8f6df03496b79a5205\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/300.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21423214,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c975e4a9b2cfec95d561f3fcb33018472b139e787a614a52d38b9ebdce94f7ad\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/3_4.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 564,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21423688,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:59e611a9c7d9a6113998ddc4081599b7f1b8bfca865df319c3c64c346e456b44\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/4.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1703,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21424171,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:86f8e4e022f5063e8916dcafdf0d948f9d3e9c949d49eb15a5adddc4f11b87e7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/40.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 674,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21425131,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:606184715fc996afb0a828ddfaed5cb76207645a780757cb1055df956f9c910c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/400.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 537,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21425669,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d7a72efd682759fc95fb185033e24f78039ae948aaf7a499f9939b4c8ad4b0c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/5.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1723,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21426135,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d91aae3728260a7bd81a57f286e6ecec5757eb92e9391e78cea83a44d6487281\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/50.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 760,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21427113,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8979e1564d8d627864464b1c82808503e831a9e8dafd55f6dda8d5409debd92\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/500.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 606,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21427686,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e084754ed9e32f713f5b5e66288dd33c1c81c59680b0fe59c4b048d71d451a15\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/5000.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 560,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21428187,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:67b3570ce87591ac940ac05127d6fe4cd86bdcb3bab1f1a5a45ae8d48e645e47\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/50000.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 548,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21428665,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:43ceac5194c4b6c13063e1bacf84965db8fc070ca441ab784eeb28e8d38ed17a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/6.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1577,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21429135,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4f3861e2b7418ce50ea92ab959cb1cbefd9a0e4ae87a9775a4d4793dd5e4aaa1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/60.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 610,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21430053,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9056982a2e7a716fce6862af087423dbd076e6522b20857d5a5cbce35e303cee\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/600.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 537,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21430560,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:31ab8a3d4a609401735014ac484ab69125f20e57cc72075ba26149106d5eb957\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/7.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1543,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21431026,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d88d19bd34873be079c39de0e6c15a9738850d6895fc882db01610d89486b59b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/70.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 610,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21431944,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a4eea7e7052640fd72bd5c91eb7b59b70804c89a384f53eb67d6d7abb2cf014b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/700.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 537,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21432453,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5576ee77c26a8d03997339628698136e995b6868e6e8da37e6c2e3bdecfb1a0c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/8.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1505,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21432919,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d865096d0036aa6bc3b8c418bffbe31bfceff0e438ec1689be161333245d2c00\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/80.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 598,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21433806,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c008bbe4be4c267926deb9c1f80ac6675958042db9b02f4eab7da592a52c3f50\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/800.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 537,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21434310,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:34117ef3e064aaeed5c77798891de425b93f3493454d43388222a8dd17906429\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/9.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1531,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21434776,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0021379b5504a82adb2eb8292ca703b5bac28d67ed2764202476ad89526db1e9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/90.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 598,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21435681,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d107b601802e681fcc8102c0360127dfc691b3a301ea27050b1b6dfed632f906\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Nv/900.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21436183,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2553e3e7f5fafcee581b2dd9e769b51501b4731ff721f8a4e987a4f39c3e5d58\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/PatSyn/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/PatSyn/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 747,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21436691,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7f8b03f8f1438356ca96901ffd41d91499bea0b8401eac571cb29261abaa711c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Alnum.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7714,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21437317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9952517b0c62af4389521abaf62d3f77d595f3ffa0b19a4e27390ba92610cc8c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Assigned.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7525,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21440807,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a4fc3da22c19db3eb90d62a430d70f94845ef607485015e3829da58ac88d08a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Blank.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 561,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21444177,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6caa50b959c6f4371ec7a8ff725912b6a9485ceab430a2a9d74e17379db8755d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Graph.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7574,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21444667,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d635200d45c7c73eab08976c3a06c4ee07d4dd09f2e9d519a05c34f1b66b818b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/PerlWord.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 514,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21448060,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b77ce2917f3475d0cbca36f6fcbe815012fef84ef399ef9cca93105f07d577d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/PosixPun.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 515,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21448523,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2fcf2c1b20a2cf64bf2d8ae307e88f7e73a630e092f3f53c531c0d4d2eb60483\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Print.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7544,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21448985,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7050e54f3f298bddbcdfe968001ac0c47cf9970e5a7935acee6b4b7cea9e929e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/SpacePer.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 579,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21452371,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:290b77398af470f5a01ae7c5adfaf1bcb07923be2bca3714ebe75753c140c48d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Title.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 582,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21452864,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c253dd153be8fe8a5801253eb6481afcb77db713d8f610438ca48442f6075cb6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/Word.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7842,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21453369,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1a1cc4d2d8e4ba131156d73913dfc69be0a7356248788439afb7dff8ea42280a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/XPosixPu.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2197,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21456911,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e26a1dd90019c5aab86075ad71a2cb5f3e8ccdd351ab1f1f587bd2e66b56b164\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlAny.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1673,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21458109,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fee75cd5ad55c4c63be21af06b5fb660423e00e818bfbd2ebe51fe05136605df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlCh2.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7896,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21459137,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ad559d235f4ad82d1e76a7bdfe5bdd1f8fe81e6ae46a219d505945c65c4ea72d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlCha.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6788,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21462706,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a8988e8ae2dd1e436489caba1a27a9656c39ca9e92a4882c009a2f6de955fba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlFol.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 772,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21465780,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5108f098c6e2d5784eb1f5c257db5a86c7a03dbd4e9665f4c03a8f1830f48cb1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlIDC.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7870,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21466365,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5316fa69c266fa288c4822ead5fe7a992be767c5a590f4c6be7af568560d8f11\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlIDS.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6830,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21469916,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:607494d403c1ec2bb6e3bb337779829df1cc146a816a4be29c6a9ba1f9ef19fc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlNch.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 742,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21473011,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5838b0621e3cb7ca2c504a6d84c340c204a109f0196e49b5753ca7b476a8802c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlPat.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21473583,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:82bb1d0597b2a672b6c7f758ea8ee3b455c0b838335a78e4c6caf928a78bf21e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlPr2.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 602,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21474050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1a6f866d8d1d7959aa1c516dc9e2f897fdea0979ac8a4ae72ede7cc914ebc77b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlPro.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 594,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21474567,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c66d8b2697b4c70f21e26079140360c36135ad4ff40f06220f71d9168202964\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Perl/_PerlQuo.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 880,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21475077,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:77ed1efcc69728561207468b1633d4eb689b5b52fe1b1c67cf580ee461384650\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/QMark/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/QMark/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 622,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21475767,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb3ab30d546abbb3adb5bcec8f5d87e03971aa26cac99751b30131a4e522c541\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/AT.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21476317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8b3f0b56cc1ca8ee4c761f2f97708e8488e2bc3663030b405d221502d6b581a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/CL.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 962,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21476782,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d142d8538c03b5c1f92bd79bd0788afbcf0df2f4fc31a1f4331f268ea62e359\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/EX.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3087,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21477450,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cacbd9e5476b94620ad8fd69bb61c78eeafcb81025961cea5ca835abc2f27945\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/FO.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 690,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21479003,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:66981228c363ee5ded673fc92d223eaffa3f04125cddbec3697ce26a91e358cb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/LE.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5607,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21479555,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:695c41da6f692fd87bd7dc442d14583021a8e8d88be6a5c58afc30d7f44279b8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/LO.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6978,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21482153,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7fdbc639de5654f060468fd16c3b81e28dd423130b719b927d8fe3b093ed1b50\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/NU.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1041,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21485451,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:021d9f558b33d16cebba51f98f508b8312a7c281736a2ff87b0451e703dc51b2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/SC.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 694,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21486184,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:552575e253a94f8201b781e7ce63ebe61297a31223d72695407a2195109e9742\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/ST.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1173,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21486726,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b74f0863978c79d6d0274bde0cb8ef806da132f2d707311e7530ac3f9ec96d25\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/Sp.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 567,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21487477,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f79d66f8d7ea24ddd3799fc847bfac9a89681e0a4c2dfd5be626a680aba329c1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/UP.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6958,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21487969,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0ef1d8351b9ed81b1849112bab416fb7b34e54ab0db3b894697899eb71ac83a7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SB/XX.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8583,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21491241,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a612aa0ebcf3a22e857a4b6da1b787d96d154f13916c0aec1d0e5b46b9248323\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SD/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/SD/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 842,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21495129,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:79830cc7a53e501897ed8ac651e1144c52ae1296c75bae0c59f3ba64b8e09725\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/STerm/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/STerm/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1203,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21495759,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1a2401619db14c43424d2859f389995dc07c28574cc2ec9ae553adbb6480e621\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Arab.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1183,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21496550,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:391e6e7828216774af135c7db740773bf09a654a371848fbd058c65a57e6645c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Armn.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 552,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21497272,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dc53d34785f52f46ad7b070bbee2b5bfd29659d8c3404b45d75eea5e0a779e1c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Beng.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 630,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21497750,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9d880049f3d8aa0de59fff5e0b00b0f2eed60c75f41d7793855d3895923edccd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Cham.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 537,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21498267,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5090d5f71d3ebc95537aab6d7f8a9a9718d868ed2f70d0f168daac292965f793\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Cprt.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 562,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21498730,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:677f13ec7877273622ff8452af3556fa95b6eb26ff8277e5770fed2af32f83d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Cyrl.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 566,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21499205,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:71208af01e306dff25877689ac0c93dd1c73421060f7ea5ddbe2c456a464959a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Deva.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 531,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21499693,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1fa5bef570ad8ca7776e6b43fb8cad5922c7a415cf79e8ff5499130c607c79e0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Dupl.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 560,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21500158,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5d62fbf32fa26c241f8e6fbc5886168de8ac180c62f5e099b25275efe96b0e4c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Ethi.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 838,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21500629,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f442e3c03c2e5bf4e4cff85fea65895e3dd30b3a8d8897ccf5876d543721357b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Geor.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 576,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21501229,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5cd28f74fa815920c263618885f86cb12a522eb5c20e752ef68e7ee07e0fecdd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gran.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21501716,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:627ef9311d3318708c1d1e969fbbd759012b60ae1137165ae2fa675e57a44d4a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Grek.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 840,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21502233,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ba3ee2c1a1243596b4c674f19c862b794cb39f437789dfd581a65fbcd740bc51\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Gujr.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 630,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21502858,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:606ab94e81f5d4fdfaa8d06df3ca7a76880b864ac9b457de14ace9ef971b58e6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Guru.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 650,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21503373,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:81005b5c2ea47842b1c641758b7159435ab42cdfdd9b3b59f3c6446ff491614c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Han.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21503890,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:03730121b80a9be3287176180ac9af84c037bb55315e6d20dc32bef95f4c0172\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Hang.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 656,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21504442,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e7074414982df58297d3be0ffafbf8151a392cf9685961ae390c0d748dfdbe74\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Hebr.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 592,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21504974,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:95eda2aab9fa22213c9f0670fab3ce7898bb4968fa0749aa4bafb1458fbe906d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Hira.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 541,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21505465,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f4a6388261e150b9582ae97adde0196558ab29cf9aaffb8e6ac1419d785aa98d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Hmng.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21505937,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:025d3ed22ce8b000246b516faef397e8cbc6325d87d10e2fe46bdbd8b8aded7d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Kana.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 588,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21506407,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:370e75d471e839252b932ad9c692847e29b6e8ff6b37672aa9edf78c304d45c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Khar.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 586,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21506904,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:abde89231e73224c436c23c41863e463b5ddc0309f984dc2c7976b7257939aaa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Khmr.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21507389,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:557b71c15ae04706c5b2e3cf62d0f0dd117ccdf798f7f44109405f5ff30f8e99\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Knda.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 630,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21507856,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:424843eea932b69369654447ad0954df298ee8490fdab5a44d9ac8489083c51d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Lana.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 540,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21508367,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ee52439efb562c59d288b90995590a46aa413d112a1e4a9f2718f0b47ed9b57c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Lao.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21508838,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0061ceac406c2a7dfd5cabead0df79fd3c271de81259c35cb1cad786d1d4d98f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Latn.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 801,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21509362,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa65fa55c01ad33641ae16773d397266e557275150c9297b3e22a1c408563242\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Limb.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 540,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21509978,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:76f8749d6cb28af3362f19954ac816a4a62a6eb0884bac2281a2c41d9c889705\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Linb.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 574,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21510445,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c3ce24b3f422fdbeb65a76caa35a8ef562f2d8f903c6300af8a8c024fabfec73\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Mlym.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 600,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21510927,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:38aa93ada735f156fd8c1d1344d8acba18193574987e3b3dfcb2c6b506d028a9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Mong.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21511430,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:40db11e81fd26763bae5d0c38cdba267e6234c9783bc8ae26894b9964631068b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Mult.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21511904,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bb5e9949b1f091314c524ba997f053697da005a46973046a88890f3cfb44c1ab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Orya.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 630,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21512374,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b121f8cb42bb658146b2a83f51c74b42464376e9b0451b344067f35e723019b8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Sinh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 622,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21512885,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1520c9231481722f778117aa4b80385ef3864d74fe8a7d2d9e5ae1eb11013e1c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Talu.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21513399,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c9bc81c423d40136bd98ce46a2bc93e77e0a486269f5403169d9f5ab15650b83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Taml.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 650,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21513861,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:63e80f0800761f549a1f22c9b40a44a9efba5ea36557d10afc92ad321a1af6df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Telu.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 620,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21514382,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a9809ee1dd684d7f274340480239376911d01438763b2dcee24635a09d95f454\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Tibt.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 560,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21514892,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:34f03fe6ebecf64c53a6337df7d1fb81555d6bd91fa7da3f09a6fd1ed047b37d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Xsux.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 537,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21515378,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:326756f86813e33faab4db12d459add1418300d5c03b888c734e1ea95fc90290\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Zinh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 790,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21515850,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6ffc0b229edff63e248bb867894b1841209a0bbbdb5acef54f07fc457bee6f33\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Zyyy.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2417,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21516447,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bf1d7c65f2be5a71a43c5b712ec5b74231f792d282936df11a75e63d46917cf3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Sc/Zzzz.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7492,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21517702,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aef97d8558d5eca3edc325992d61ec229ad72c20ce142c06c182103372e4110d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Arab.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1145,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21521084,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6fe86c9c031605dc818bb6a9fb35aa206da84cce9befac7c5675f66def073342\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Armn.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 552,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21521792,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8104bbaab001aaff455371ba6ba7d4ec8be75ea8bca2291e6f53bb018a3ad8c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Beng.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 650,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21522270,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f6b09a7f2773d738fecf42eba0ed8ecb69bf44f7a297e3e7ff03c239c9ebdbab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Bopo.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 726,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21522795,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4d84e492592330f3afc443c10b145d23b89ab83a4edbfa14226def74e8984243\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cakm.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 533,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21523350,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1024f84347f2bfaacd98b372330c72948ffa6fb37592e0386e0a83879a8f1bea\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Copt.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 534,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21523824,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:81926afb1a8b5fdeb65d82b4e5c72a57acdccc3bf5e1c90e41963f02a696b766\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cprt.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 598,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21524298,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b0f8205991529c307461b5624b2ed0fcd7a19138439ea33b3bd48ca203754875\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Cyrl.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 556,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21524790,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ade9d8f1e4a8831d77d5acb967b07967e332d869a0a6d5674b4333e2f955abc3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Deva.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 554,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21525274,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c2a8adc4eaf7cb7e68e6ed8e65b76019b5b6d8d76cc73a39a110ef7c832786d6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Dupl.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 560,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21525754,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5815a61fc51923241fc94eefc15df6c75df4b9618a7aa4aa7a9eb29793a658fc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Geor.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 586,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21526227,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1824c8df685eeeb654bfb2b909fe1b2e2402362645c3c7e0b2023e57e5918f21\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Glag.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 535,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21526723,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a5e9b2059e7af774f3c7fb6e745964cf4ae1d13e9aab87930c02e067448bfd96\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gran.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 770,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21527192,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e4863cbc11c2641691ee9feec52be7ff57419b665da9f00fc9958243097ef581\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Grek.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 856,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21527761,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:453bd840cd2d2d7707e9d46e43d4bda59547feb83c4d7a6d2a7b6dcdea4f9592\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Gujr.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 662,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21528399,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f001bbab220d35ccb9b34c59b8dff27679875cbebd579287332dab6b0f5244e2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Guru.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 682,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21528933,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:201226ee4d7744d62bc277f6c91605d6089279be4050b8692e9c045dd612fe79\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Han.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 862,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21529469,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1dbb87fdab60f31731ca377da46da55bbc3c447b490d9bd525dcfc20620c311d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hang.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 836,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21530099,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2a883383f42b37a0aca4c031601fa4c692034f9796237e53e3efc2703e624534\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Hira.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 782,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21530703,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b0915643b0657a726fec45094508f0187bca5c62d9f53d11e9540c67ab8ba2ae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Kana.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 756,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21531279,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d6bcf7da353acdd5e9a838aba68ffa73077a5cd67a8f0a2f8479cfcc9c9510aa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Knda.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21531851,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aab06d08de88e4e006480c31f71c74b2caa2fd40b0cd642c40550a723d05a884\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Latn.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 851,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21532386,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ef74e04ab1fc951cd7b386640df48f54f393cb33a2b2caff3eb20b2a9f7535c8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Limb.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 550,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21533027,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94f401e7b8f7427cc3eb6c380151a384678cba6c3b81c51a15e0aba18281861e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Linb.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 610,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21533502,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:819681fdf147c367160322000e3a10aceab7ae0f70db24160ea56f22ceaca7f2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mlym.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 630,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21534001,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a6c2c6ad8bf6c4815eedeffefcbe97f6bfa8570ece0b155160d3193693b0a88\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mong.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21534522,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2173e35e7fc77ae45b7766c3e2b50abf45425d2a0cc3581983ba156b45812dfc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mult.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 560,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21534991,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:97324117263a39a06e1a3c1316c87f40c9dc5548ad048e3d3fe2140a0da4a90c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Mymr.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 535,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21535466,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:27c0e0c7503416ad0f75d333d716c53a21deed0f9be28714813824c14d9a7143\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Orya.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 650,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21535940,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b5d8725e96463b4813fae097ae1a729f33fd83b67789294fa460fe28bc4372c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Phlp.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 535,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21536467,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ebe6ef500aa24950d10667482969d9aef942d2d56c1f3997ecb3d01b102563ad\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Shrd.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 564,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21536932,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6b80a96df206302d6c2fec2eef8c86b9485263011e895cb0a64150cf58fda411\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Sind.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 535,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21537413,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d6935b15d4f1ed7c247eb259942edfecd2995d987243064580d1164f3b1e0389\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Sinh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 632,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21537879,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6eb5b894fb05bc0ea822513f50b086a1b6e6165853193d84ed7a5d0fc1602be5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Syrc.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 580,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21538400,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:791c57c89d6787c329cff0b2a2624f2cc8d621fde44eee3af0e081268e496c7b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tagb.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21538892,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b2141832862363d05881b316c18718c45e4d22521e0dcf1db2e477973415e101\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Takr.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 535,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21539358,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:271b68e19689772c67e7729a9115197c5e98a59d1183c9532320a8c8078950a4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Taml.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21539825,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2ebc5b5308aa6ecd879262949a3b692e2f9b0d28b73fee509d62a06e37b71461\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Telu.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 650,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21540367,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6516bc5e07b64daee53ae3043509486cf12d3b7adef5361351f1307391df09c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Thaa.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 564,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21540894,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:038d130ed6d6e5a837012ef3b9a9d466de9dbae8f77f099fe4848f3cdba5a63e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Tirh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 535,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21541377,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d5118ade0a294e66ddca138067da39088548bbc12150d960fb2502a1ed82a62\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Yi.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 574,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21541844,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5f568a0611b2ef374c716ae445fc62896602f0d242f2633d83efa7d498d94a9f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Zinh.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21542334,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9ad52bb42607c737a802884ed51a2a38899cd1e7651b2b4331bb8424308e71d4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Scx/Zyyy.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2151,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21542874,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1c674c07686b646a5b4640746d9b94ab71cf955d9540dfb56d4d4e9395328bb7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Term/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Term/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1473,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21544059,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2cdaf79acbaf347b062afee8411fcd64b40e21b710e6f592b65d0d87b7a7e888\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/UIdeo/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/UIdeo/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 654,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21544970,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:06089c8caabc43cdd90864cf04dda05623bd78a8ebacbdee14bac4d07f87d604\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Upper/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/Upper/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6928,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21545529,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8f05c1aaeaba2805ad712abc324c676601cf1f876ba5a83df86fb0fd0ca41e9d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/EX.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 552,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21548821,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4ea9d698b63a3cb363ed7832498a4badac62ac24a52c7d56784b886c475719b1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/FO.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 680,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21549300,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7aa80285ec594e5c8ec72caa6b91afba3e6c8ac2d179d9ee74314db19c9cc652\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/HL.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 606,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21549850,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dc84621340949f46330e6a3a5d3a25c9493f26f5ba236225db60d1ad65552aff\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/KA.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 600,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21550349,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5e4bc630ef471f37941ac7687982495aa16ca408cd6d4040652451b14eb94e3d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/LE.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5957,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21550853,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:04a789e6d81dde8c6dde9f7ad82819bda5dd4bb9cf8bf45ec3fc22594dc8af62\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/MB.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 552,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21553584,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a5cf1c45426be4afe0b186372b415c9be3cbfe6c47bd75aa7d2c74e83d4abaa7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/ML.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 576,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21554059,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ce95c41d800744b08f2a236e8c8768baa35c1b355f2f1d22ea0f787054a35399\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/MN.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 632,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21554553,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:adb85c1d377067046b950aef31786832b791113ce661a4272f437bdfe18f90d9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/NU.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1041,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21555072,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:667c6073a434ac9ba291c8d74894f8d20bf230ebf24a110ce540c04002297a3e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/WB/XX.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7978,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21555806,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:958a3765a4043eb2b27a977d845b343ac7c8f23ea83e1c1febc12fcbb46a17ed\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/XIDC/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/XIDC/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7870,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21559416,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f7c1bda1333c0e2c8d8ee1aff7a4cff506ec10ae2e37ea196899e3f1e50e0753\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/XIDS/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/unicore/lib/XIDS/Y.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6814,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21562992,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bbc41d2ee979acb3350dc9160b0a5e6ddfe135d80e35cd352fb46b30a40a65cb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/utf8.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 342,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21566068,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f206b889aca0a761b973cb3dc58763c2863f3b9429f47164d1dd57f3d041d088\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/utf8_heavy.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31615,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21566393,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dd1cea927bfb0cd3ddc6020ee822aac3745aa7723ccfbd4beb1d70a652224a4b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/vars.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1149,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21574998,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:665260cd8f2ce2ae717e29e87c8f5499b7154ac6f20a4bb8c222ee4456639aa5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/warnings/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/warnings/register.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 488,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21575707,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:962110d3faf3e55749a260d97edaf8a9d31293b0f33d2e7771663a9ef364aa94\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/lib/x86_64-linux-gnu/perl-base/warnings.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 21639,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 21576114,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6677ba2321f7c3135854ca6f6b0d8bcaaac3fcf72dd182058a03d83705f457d8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/bin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/etc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/games/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/include/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/lib/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/man\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"share/man\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/sbin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/share/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/share/man/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/local/src/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/add-shell\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 860,\n\t\t\t\"modtime\": \"2017-04-02T17:10:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21580564,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:959e8afe5754f4f09e70e95f3aa952d265e9344b0cb635663aeb4bbf70347bf3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/addgroup\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-06-26T22:55:17Z\",\n\t\t\t\"linkName\": \"adduser\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/adduser\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 34509,\n\t\t\t\"modtime\": \"2016-06-26T22:55:16Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21581154,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:90bcaa8bc2e8a547ec25f521717cfe28c7c8449144622f65b24b373055d97f86\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/chgpasswd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 59184,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21590493,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a6accd32550d5ef4be45cafb960928c94fc2dd4f4ceba3a1fa0dc2d6a6cec83a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/chpasswd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 51096,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21614137,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:47c59f3e369c234f699786c6a248c9bbbd3e77059ec9518dfb649e7b7e12de5d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/chroot\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 39816,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21634667,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:503b2a1eef247103e996f554a39cc0993874458acdea6a8a2d8a91abe266dfa5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/cpgr\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"linkName\": \"cppw\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/cppw\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 53248,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21652809,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ec0206f95e21c88c1df1a18c6a22de7e66df89f82f59630954e427ff521097a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/delgroup\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2016-06-26T22:55:17Z\",\n\t\t\t\"linkName\": \"deluser\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/deluser\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15798,\n\t\t\t\"modtime\": \"2016-06-26T22:55:16Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21673966,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:74c622e5b715f007b903281046a02b42789bd5b5a23ca402141d29551b539507\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/dpkg-preconfigure\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3604,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21679333,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:82fa48ad05b55af0aed8fe79455301af57d57bfe76f32902ba3f87189b04f55f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/dpkg-reconfigure\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4335,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21680816,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bb6b8c55f0054f73f45d65918c59b1b8cc4435d60239c96f0717491b509cf69e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/e2freefrag\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10312,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21682662,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:06851e325b694d1a54e0b706cd3dacbb522791770c1e82ac9bc103df8d66dfc2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/e4crypt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22600,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21687223,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:352d971ad3389b75059fca8a68c2bba434f5e44625c157e31148e73fd341ad60\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/e4defrag\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26616,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21696070,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9fb3b0dceaef564bf6c0c52de2398b4ae8d93f779a08b4d6d8e0fce3eef89d55\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/fdformat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31400,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21707697,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:82115367585702c576cb36c3f2a326937624394e67911d62197c54a5098535c1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/filefrag\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14352,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21720393,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a1e6e12e7c7bfec60296ab2d770fb407577e5a3f6954938935f0065418b5129\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/groupadd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 59248,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21726797,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2c74c36be4c3f0ffb3545e0e52e76b50cb52e55a7d30dfa54b56012b285b9310\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/groupdel\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 54936,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21750959,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:135dc18f16a06d1f950f6fc14cb52ed45fb447ce8043c360a86e8c7cf294d0e3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/groupmems\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 55128,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21773295,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9450933cf5092fa7360c8656168f39c00f93a58b78772ba25b6c0166d34d589d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/groupmod\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 69856,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21796121,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7a0bd57b4fa63cf06c4e2f4c274e2566301cda9345afe5de424bdd4decf2bf57\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/grpck\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 55064,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21823831,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d2e867ecab4765822b1d6d5a432ca7091be3e4392189c684570712dd674f2552\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/grpconv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 50840,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21846506,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6833fceebf2df346b988f68587c501877df463bbba0f2254f17076af3392ed99\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/grpunconv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 50840,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21866740,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:90b88dc6a4ac3352dbd8a419534c8922439cbb5c85ab6c67197591802aa4b670\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/iconvconfig\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23208,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21886856,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2c27f482761dab9ce4e634c1d3a5995082292c6c9f0eea8eaefd55ad16360ac0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/invoke-rc.d\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18110,\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21897773,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b97967909c85bb209845a7568d6e179ea1859e4761eed87edd864ae71625f79a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/ldattach\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31448,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21903781,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e2e130f7119d1991a6b611f8c29d45f4ddf58c630d5fe5cf03833e101f4e5e2d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/mklost+found\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10232,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21916527,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aaebcc49bc9e8396188d597de70fd9efdd6bdad30400a52796afa2fd61c6cc4a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/newusers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 80312,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21919174,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ca6ec91c32fd12432ab9f79eae4d58a79b07dec65e54d5ae0e524c1d7934d76d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/nologin\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6136,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21949610,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3d9563812289692aa1cb3d0c7ba193312ecfd98a34421ffdb62ed854d018c73c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/pam-auth-update\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19490,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21951688,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0edc70d5d2e46f81be6b1d5647fc54508e23630f9cb139bf6722965f21d64d3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/pam_getenv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2890,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21958701,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:982cca7d6a9afe07d7ba3fc929082ef11ed1cadb88d253f6464bfc0a19730674\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/pam_timestamp_check\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10616,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21960193,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3698a30b91c6362501b703f24664dd367b8c73a9d25a60825fcfbe29a3992577\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/policy-rc.d\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 255,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21964501,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:21a8dca0d6a52cbac52cb7a86178d973616ffb42ea08747e6ff311659ab095e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/pwck\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 51032,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21964776,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3db87b030c79facd0e66f3fce64416820580d9509c6bb4c822152027c8ff427d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/pwconv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 46840,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 21984047,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ad2df81e018de0becd84b6ba604135696e0ef9b55ef8b4c45fda13474674ce49\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/pwunconv\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 42720,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22001336,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3927d6643798b70627213deb68041a1176aa6bc001f2c35dd64e96215c5e6a37\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/readprofile\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19032,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22018269,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:53baf68d38dbc992407f89e6c4bfbfe40d70e2e322e32737c67a2d0da1c158f5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/remove-shell\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 904,\n\t\t\t\"modtime\": \"2017-04-02T17:10:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22025169,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5a15986f8fd235bccf215832a5c39070acd6c48176c73a2415a7148bed327267\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/rmt\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/etc/alternatives/rmt\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/rmt-tar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56352,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22025793,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ba1fec0831eefd0ddc86525288b27c0c0780322861d95a36b6f558c237290c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/rtcwake\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43840,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22054312,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5bcd24a767249c4585697dcd3d37219b42a9a7fda402df5d18bfa436c01cea8c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/service\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10061,\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22073569,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2727d140345fbba81c6c842d54822f2f8ee78e4c57a9b488f5ce0ff7c572e6bb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/tarcat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 936,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22076719,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4307aa7cc97a4db32a674ad32f893b251188903cafa6d5266c813fc5c9ea755e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/tunelp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27248,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22077335,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ddcafb165a85a34431f1d2989e6405f80f6df3baa9d69fceb980962e6c22fdb4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/tzconfig\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 106,\n\t\t\t\"modtime\": \"2016-01-21T17:04:38Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22088271,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:816e1759cc6a017900439acc6c85dd2293cc78948d54bf76c1f23bf16437b1fc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/update-passwd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31136,\n\t\t\t\"modtime\": \"2017-01-16T15:52:12Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22088466,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69f054530b4a1631c477d3b1096046836ac257cd9a1f8ecbdd279229cf7dd3a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/update-rc.d\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 16062,\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22101198,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7334018b606ce73b6266b4f073638f706df24ef4f1dcbebe53bb48bbb81e322e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/useradd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 122152,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22105960,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1dec582729d5dad31c8b797f8a5b3625a5e84a9f6c0a33149458ff9372066853\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/userdel\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 84472,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22155067,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5b9097e787567d9ffac2bb5e4c5e4b151c377acea6d2718751ad52e97e652131\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/usermod\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 121960,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22188064,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:43260cdabc4a9286c44b87749f5537c6ee6740c9f902fcf93bfafa7b07691fab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/vigr\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"linkName\": \"vipw\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/vipw\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 61664,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22237251,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b3632017c35f6bc85a13ffa93094059e6b3919c8b0ce9e6e6083b41f6d0c2c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/sbin/zic\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 43560,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22260567,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f0af0e819802cbc10e6855ec744a891b18e3db25c8b3ed9cfda4e5cfb77ed40e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/adduser/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/adduser/adduser.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2981,\n\t\t\t\"modtime\": \"2016-06-26T20:20:46Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22283213,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ccdc9675d7bd39c3cc79c2a5d6938f2562dd4062350dbed3058c1faee48b353e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-files/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-files/dot.bashrc\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 570,\n\t\t\t\"modtime\": \"2010-01-31T11:52:26Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22284711,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41f1685d04031d88891dea1cd02d5154f8aa841119001a72017b0e7158159e23\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-files/dot.profile\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 148,\n\t\t\t\"modtime\": \"2015-08-17T15:30:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22285167,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:74bc92bcf960bfb62b22aa65370cdd1cd37739baa4eab9b240d72692c898ef1f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-files/dot.profile.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 72,\n\t\t\t\"modtime\": \"2015-08-17T15:32:01Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22285395,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8961ee041c712c735fb05287740ab62737777bd58ce631b54b07d8083efad3bf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-files/info.dir\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 781,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22285559,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c58a258cb9c410c29486aa8fa37f4e5b738bfeedc2b8e97be1cd6cff1df28459\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-files/motd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 286,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22286147,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a378977155fb42bb006496321cbe31f74cbda803c3f6ca590f30e76d1afad921\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-files/profile\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 767,\n\t\t\t\"modtime\": \"2016-03-04T11:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22286448,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b8ffd2c97588047e1cea84b7dfdb68bfde167e2957f667ca2b6ab2929feb4f49\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-files/profile.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 607,\n\t\t\t\"modtime\": \"2016-03-04T11:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22286904,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7d09366be1eb6bd4fa6b3cf9837e87236bbb9ec5ebe4e2428fbec3f88b7ec762\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-files/staff-group-for-usr-local\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 771,\n\t\t\t\"modtime\": \"2012-06-09T10:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22287395,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:64a482506f00572df1d4909a347d6f4fa8e6ce23686b7f058bfbd650ec0658ce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-passwd/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-passwd/group.master\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 446,\n\t\t\t\"modtime\": \"2017-01-16T15:52:12Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22287950,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cfde4574c857edbfbd31667000d75d07efe6bc61f22063693010dee2a912450b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/base-passwd/passwd.master\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 877,\n\t\t\t\"modtime\": \"2017-01-16T15:52:12Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22288319,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5e66dea2e22fa69f64b4f92053bedbf8ea2550dffb95967994730b718f4eb930\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/addpart\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 447,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22288823,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:61badc8851eb6f1c153df1a07c9c2f3bffa048fbd05d1ef775384087440a08c8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/apt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7034,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22289190,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:df95a61a8b6c5e4e779919c37fb600030ea04215e4aa82e510fbd7b6b3bf55ed\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/blkdiscard\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 571,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22290932,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:42afb5f346bd7fbb967529a9fbb92f80207d9757c9e718254e0ebf6dd6e048d1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/blkid\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1395,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22291326,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e2d3fa59a351e8af1582816ace0670c72b4088caf60b6dd983cc37c3439c93b1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/blockdev\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 726,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22291897,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e33e84094c213cca2fc2e3ea06efc4a655ef4bb27ae4126943c574b98709767\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/cfdisk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 546,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22292352,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2995b77066141f0a0b67dec82d554a20909466eca6a3e8f237eb709b7f5b4c62\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/chcpu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1510,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22292738,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a33736eafd741e7929ab8c13d1484f19a0874fb5a220dac8c6e4e7d3b2dc6458\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/chrt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 920,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22293361,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1dd13080d71c8d880e628eee89e8f493c979441692ef364e01ca8c8a761d381e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/ctrlaltdel\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 335,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22293872,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:52021091a5554e9b6275cdabbf1820ccd18eff38d8b0094284ef7fb68c38f66f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/debconf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 294,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22294193,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:45a6978806b39111a579c0e7d4e85937bd6c8e20c3f6732d3ecf5fbd2344cfb0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/debconf-show\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"linkName\": \"debconf\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/delpart\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 526,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22294515,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e337b3898cacda9485085c522d9306a043146cc52c780bbcf2c65b8d366f095a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/dmesg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1056,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22294910,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4084df6fbe19ec0f23ab8793c95a03ef7e48b22b663012bb48ca94128ef3c62b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/fallocate\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 643,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22295482,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7113bc40db42905fd04f5d0d2ee1cc5bbb2646bffad8c02d4499f57809339888\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/fdformat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 414,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22295914,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc16d071c7e14848ac2f86c3456afec6b3231f72acc352177790b90a2ce3350d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/fdisk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1231,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22296293,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6c432ff454d3dded724a4d7cea8e0d4c772bea33ef16fe6ee4599eedde9f2d6f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/findmnt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3137,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22296835,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bf5c1444b07690929d34d98f220de25dfe58c9e4859b902b698fc7525ebccd86\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/flock\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 860,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22298159,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:34ace7c62e5f9dfff7729a2b7182f1353b7223203c86068f61da24723b758c9b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/fsck\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 752,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22298639,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f1a807ffd9e57c34d769a425080836eefb882a060e4c3571db2f8596d6ccdb06\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/fsck.cramfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 607,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22299063,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5c79d1606f356dd70e7d82179956c29451cbfc85ce80f04b60e72ed6d2c781b7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/fsck.minix\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 383,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22299477,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c80e2696bcb4fb7642418d3aec96f7c2931cdcfdaf245786ee3b6cded99e22fe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/fsfreeze\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 524,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22299829,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7f99f914f660697f78e57850e4e70c027e73a0aa5074a28bd3a5d25c2564b371\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/fstrim\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 677,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22300235,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9c36b670fa1b23811490e2b47b6576a4b58f38ded511ed4f3757e7b858e3700e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/getopt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 815,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22300690,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0ae50ed789c556f2abdabe09362169d385f9facf1bd05c13cf57b3f8e0078a5d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/hwclock\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 937,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22301129,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a16d3a4bf89dac8b127a08357fa278aa6741b0949f5a163e1509985afcc2191d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/ionice\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 837,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22301634,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:121f9bd6d08e331cd90ddf509b2821e9f025141f0ba30b16f201d304a3b10500\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/ipcmk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 576,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22302117,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:701db74a1133159cf159c9a182a46eb77ecdab618c52e373f432b3924d8e2707\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/ipcrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1423,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22302477,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:454731bfb20b7be1e41f5b0704536a549ebf7ee755d64bd9ef882b04ae84173d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/ipcs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 514,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22302981,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8d2fc0706082e013fdec16a7b7fcc3aadbc0c3e22f87d8a818d9aa95f364acf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/isosize\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 529,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22303373,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0afdd61db90044908eef15ef623eb9e6f4598cdfe581f20b1b812650d961f567\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/last\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 737,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22303750,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bc8f9d4188ca658f681e93797ff614bbe0cfae2386bb860735d00b278bc28ced\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/ldattach\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1263,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22304174,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:363c860122e61a3daa0b76cd8f949a81b8d82e81558f148468b0bb272af450ca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/logger\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1431,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22304860,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5f755d0b65c08ea67c0fb32a13c36f104952fb3d52a64ec139814633672c98fd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/losetup\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1657,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22305543,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6dc177c2c2677dfb5211371de83298a217f33ef6b724d0250728caa6c6842045\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/lsblk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1881,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22306352,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7d8bf9fb21ea6a53a41380105d49afe964c0d00182653ecfeb2ea1044ff442cd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/lscpu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 985,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22307246,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3d7d68b009e60e1a8c0e381aacd3e3e920f655742ac733fb42cac35ebd89dd58\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/lsipc\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1301,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22307869,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dff12d8ed515f2ad0cfbd27bb663e761fb25b3263bc02cfb0a61ddac68d38625\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/lslocks\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1176,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22308627,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fe9cdb7ee7e64deae4b7638f8fc53c585714430803c49f339128d98be4ee6907\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/lslogins\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1704,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22309333,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:713c0e99482efd5139818e6f2a3383db05a6b6f9ae2356ab7f6578e95e3c8eb7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/lsns\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1160,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22310192,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e82a2cee42be609becdfda8c1c94d4af59a85bac89741f09eb34fc6248ed7315\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/mcookie\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 502,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22310825,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94c71202101d2267e421343ca9f1e70c9884a2462e1441cdc5fd186cf834dc34\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/mesg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 412,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22311198,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:67d09288e327f405fa72009d7e85b81a70d20c5577ffb8b418b6b0de043e7fc1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/mkfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 638,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22311531,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b90a36595a7585f33e27d5028c66fecb8db2f01832240b70527aa93f9d93c486\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/mkfs.bfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 656,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22311974,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fd5315672633d2cc96166fedd130416e7ec9c37a87f8afe57dc906059a4fac04\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/mkfs.cramfs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 821,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22312383,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a33449ad64a9c1e51ad0b82fc6afbb07febd5650842fea214231f399d7f3bf4d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/mkfs.minix\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 714,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22312807,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa873021ae3d172211a649626f466efd53423970ba15d29d6f5ce4fc5d78fcc9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/mkswap\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 765,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22313230,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:55df38a11a3a5c062176af86f5218daa930a8d5883d5c31ae2062ac8da756e68\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/more\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 528,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22313662,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2a14123adff1db7144fa503b2e939d9383055e7b893a7730e146dd93c328032\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/mount\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1908,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22314034,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ed4e4eb18ffde93e069890cf183aa5d9682a4f6253db5998267196b6375b3ac6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/mountpoint\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 570,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22314884,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d882adc45a617a1d4f9f68586dc2c0e91f50045b9b864fed66af94156fed8eba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/namei\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 500,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22315289,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1519a1b96f840f476647daa9d041a7d5db2dde0d80d3c99e973b1eccff8b259d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/nsenter\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 955,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22315681,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:70f6b574d524a5e9c5453d43c3e0288fc82c7434b9183ae2474eb69e4b1299a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/partx\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1157,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22316277,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ad72aff002951a0534dc0eb986fe83ee4aaf2a439e34bdf14838654ed942d5b6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/pg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 605,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22316980,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5dc94774a322d4d6152cf69d869cc70db29a802108675539d658580242715e09\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/pivot_root\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 387,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22317376,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3fd2fed08fe53b1bdf0b344633375273ce54bdb75c65a4383f2bf29aa9868dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/prlimit\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1351,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22317717,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6e552891869727f1249d3295811069d92dfb23d1cbfe25393b7684938f016018\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/raw\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 482,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22318469,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f546700af22030dffeefaa6b13e9ebb7c24538adb0941dcb98a9d68a6426640f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/readprofile\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 679,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22318858,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:874cf09268bc51c0dd77267ef8e3d9948ff9c8c376a1b9ce911ca135b7baf9a5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/renice\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 812,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22319295,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:631231b93ab12774133788a62650ce3d818ba80b56dc7632e6b7940a565f02b7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/resizepart\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 568,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22319764,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e0692d25787a3625816b07ea00ef66cfeada23fff0016cf0a37efd95ad84b0d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/rev\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 432,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22320171,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ffab4735212694543267952b527e72f3ee4ac9b0e07d49b432db219bd26a3aae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/rtcwake\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 921,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22320527,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c3dcadb79aa4b54a8c09721acae529ad6d264c794c64068d9f0e279039267f9c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/runuser\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 864,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22321008,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cfd2d8d2f8c11b25c9c9810aeb1ce2817c17e252a8d0f1e9ee0502cf24008e75\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/script\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 667,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22321475,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4939f89fc4e6fb5577b1803562c103d8ee43648f1f87a938c6c79a67e5850492\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/scriptreplay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 592,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22321919,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:147d35e1d56387599071cb2e27eea8c345433948a478285dac280878b41a2d9d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/setarch\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 770,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22322327,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9d0a6caf10559e1c1ebec9ad0a34f80711e51da451ab67deec521e46373af12f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/setsid\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 433,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22322832,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3bcd86d1051046fb0f9c122e0db037e0688dd2cf08f74d8b803cdb4ad2cd7d08\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/setterm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2580,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22323182,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05b03c3d0766d7fb55d9b5c9bdc1dd84b837fbdd4739f1d78b4e910375e9f92d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/sfdisk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1168,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22324128,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:84c05320ee42af8c98466b2a6482a05d5a393a7b89915984c88e0c311cde8451\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/swaplabel\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 635,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22324730,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1805b9fa1953570fa4bb99339afbb25a6d701ce5a442d22b8ddabe486b46c9c9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/swapoff\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 743,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22325132,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e84478bfbcfb4eb0accf290e7b158085cb0db7f679afade1a270f7e1e731a691\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/swapon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1523,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22325552,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9eb769c80ce8bcffeb27b1b11129ee23e1ea534892df855357ce988862d30ca8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/tailf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 530,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22326307,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:217ff91e243a27ff18c0ce71505c35da7429950e5df9c8bda810e3cbd54e1395\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/taskset\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1235,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22326689,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f5d55cf1e4460be7e1121b9a7db533591994a9cb5138124903c19be05574be16\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/tunelp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1040,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22327418,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:249c5bbde4c34e5345986ddbad444ec4491a55eebb31135ea739fd750e7a8c58\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/umount\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1469,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22327943,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:49047c62c6d9536c04be599640f37b81cf658dc6849180991e757a6c849cdbec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/unshare\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 496,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22328723,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bfd6b74257cd2802fc0b2fa02e890145870eb2dd83a47e929fd52d7a70f8b520\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/utmpdump\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 475,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22329092,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69a8a5a630ce32790499b7690d033c7d73c40c861a5985ca23c4f1585fd69b48\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/wall\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 543,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22329467,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4edebafffadbeefffad804423daf697de0ff2439b903fb203a1e9570169e1100\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/wdctl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1365,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22329859,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6cc49f54ef1974fad909f827694f7bdc42e4ff9aed20bbd4dad265473f9e49db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/whereis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 535,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22330604,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2a040afc44337e73ffcb2b910180aacf09566b784f887e82255a09cc42689d50\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/wipefs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 690,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22330999,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5479d455af2977d9d5bc9dc219e21c376abc63781eaaf6c0a5336bea82648f2f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bash-completion/completions/zramctl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1213,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22331432,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a8ca02df882804e93da5cc93f24d2125637d09e49abfcc850760569a0db31768\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bug/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bug/apt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bug/apt/script\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 886,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22332138,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b2cba592c2bd6e4077dd8b732d4895c22e77f555ed51540899b9a7bc908751bb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bug/init-system-helpers/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/bug/init-system-helpers/control\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 24,\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22332689,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c0306308b3e8655628cca8238616b8750ab7003201bdd68937a4739fe087ce5c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/Apache-2.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 11358,\n\t\t\t\"modtime\": \"2004-12-19T20:30:25Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22332862,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/Artistic\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6111,\n\t\t\t\"modtime\": \"1996-12-16T02:58:50Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22336884,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b7fd9b73ea99602016a326e0b62e6646060d18febdd065ceca8bb482208c3d88\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/BSD\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1499,\n\t\t\t\"modtime\": \"1999-08-26T12:06:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22339375,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5d588eb3b157d52112afea935c88a7ff9efddc1e2d95a42c25d3b96ad9055008\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/GFDL\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"linkName\": \"GFDL-1.3\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/GFDL-1.2\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 20431,\n\t\t\t\"modtime\": \"2010-03-23T23:34:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22340330,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:56976e64523fa1e68db4e6f464f5b2cb89d7d08f54b1d012e317b8db286b3faf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/GFDL-1.3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22962,\n\t\t\t\"modtime\": \"2008-11-03T16:47:07Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22347574,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4748f03ed2dbcc14cde6ebc30799899c403e356a7465dc30fcf2b80c45fc0059\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/GPL\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"linkName\": \"GPL-3\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/GPL-1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 12632,\n\t\t\t\"modtime\": \"2010-03-23T23:34:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22355724,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d77d235e41d54594865151f4751e835c5a82322b0e87ace266567c3391a4b912\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/GPL-2\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18092,\n\t\t\t\"modtime\": \"2010-03-23T23:34:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22360744,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8177f97513213526df2cf6184d8ff986c675afb514d4e68a404010521b880643\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/GPL-3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35147,\n\t\t\t\"modtime\": \"2007-07-01T22:55:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22367652,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b165a1dcd80c7c545eb65b903\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/LGPL\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"linkName\": \"LGPL-3\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/LGPL-2\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 25383,\n\t\t\t\"modtime\": \"2010-03-25T17:29:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22379891,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b7993225104d90ddd8024fd838faf300bea5e83d91203eab98e29512acebd69c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/LGPL-2.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26530,\n\t\t\t\"modtime\": \"2010-03-23T23:34:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22388991,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dc626520dcd53a22f727af3ee42c770e56c97a64fe3adb063799d8ab032fe551\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/LGPL-3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7651,\n\t\t\t\"modtime\": \"2010-03-23T23:34:01Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22398425,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:da7eabb7bafdf7d3ae5e9f223aa5bdc1eece45ac569dc21b3b037520b4464768\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/MPL-1.1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 25755,\n\t\t\t\"modtime\": \"2017-04-03T11:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22401124,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f849fc26a7a99981611a3a370e83078deb617d12a45776d6c4cada4d338be469\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/common-licenses/MPL-2.0\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 16726,\n\t\t\t\"modtime\": \"2017-04-03T20:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22409547,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/debconf/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/debconf/confmodule\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2690,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22414952,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:640ca3222686c4d336a8a0b4721c5e54b0caba1a83e1e3409b137bea478e9a8b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/debconf/confmodule.sh\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2875,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22416201,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9bb739cea6c1f88c3282c6743a230acba64ac1d12c40a89daf12fe5f2390cb68\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/debconf/debconf.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 414,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22417708,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2ed2f1e25211c95ae120cecfff540e33a533c03bb2793504c3d692b0b034c2dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/debconf/fix_db.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2004,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22417986,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3023d816728349ffe6647f852722046631f1802737753f75517ebff0461473df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/debconf/frontend\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2452,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22418850,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4425ec2e272875006ca7dde26d1c11b79a0a3570ececcd11f65baddd4b474ae0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/debconf/transition_db.pl\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2404,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 22419970,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9dbd7e5dcf314de4f1c1f15c46c69754f9c61c6be632b7c5a6efee08df0aa798\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/debianutils/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/debianutils/shells\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 42,\n\t\t\t\"modtime\": \"2011-10-09T00:49:46Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22420954,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:184fd1ac95af5ad460ee875e9fddb4975e8720ee7d805d964c68d125573537be\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/dict/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/adduser/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/adduser/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1995,\n\t\t\t\"modtime\": \"2016-06-26T20:00:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22421163,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3e67668ed552fe3a0684e77282325d07fa8847f2575ea1e1906000de571b5c1e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/apt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/apt/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1029,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22422270,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:307e96c4b7e8170b422d86cfb04d9ae4a404e6d46755448331cdedb23cf1c3b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/base-files/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/base-files/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1228,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22422986,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cdb5461d8515002d0fe3babb764eec3877458b20f4e4bb16219f62ea953afeea\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/base-passwd/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/base-passwd/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 799,\n\t\t\t\"modtime\": \"2016-02-20T02:44:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22423766,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c33ce99cd93b1e2f5c6067be725b73099e712afe8a4d8dffeb1659642afcd22d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/bash/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/bash/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10231,\n\t\t\t\"modtime\": \"2014-03-03T21:46:18Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22424330,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:da7a8d93abf1eccdeaf326642c8ce9ed760f3a973ca46f3f69b3cf755bb81ade\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/bsdutils/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/bsdutils/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17975,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22427545,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b99c6679c1def231db02b5c30e3a552be6840021271f1e5c4cf5b7a639b0c08c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/coreutils/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/coreutils/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 12531,\n\t\t\t\"modtime\": \"2016-01-15T17:31:23Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22432395,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:350c1a60923248396acdf5aa3d20cdd5156e82648b3411bf9dff3a16b1ce9c7e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/dash/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/dash/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3101,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22434945,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c77d28679de92b8aca0b3dd400eabac91bf9f6c68171e49355888d2593a968f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/debconf/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/debconf/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2648,\n\t\t\t\"modtime\": \"2011-02-02T00:08:31Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22436654,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5210ee02334b7cadcfe497df11a9d1ebd6e8e7de8a7fa44d15ac797b591eaac5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/debian-archive-keyring/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/debian-archive-keyring/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1243,\n\t\t\t\"modtime\": \"2006-11-21T15:36:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22437912,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b32aecaae84643700a33bc9ee83fa9b36938d35aa7b61b5042092eca77ddb732\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/debianutils/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/debianutils/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8017,\n\t\t\t\"modtime\": \"2009-05-06T01:07:50Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22438695,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a8698f078cd21fc501e66d070e12cf2f23ec1eaf5841bbc87629de76858ef7a7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/diffutils/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/diffutils/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1839,\n\t\t\t\"modtime\": \"2017-01-09T21:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22442319,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6555a03a39adb6588f85a8aac4ea9f3f1cfdf93ac921ffbbc806215f77166b07\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/dpkg/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/dpkg/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7882,\n\t\t\t\"modtime\": \"2018-03-22T04:29:34Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22443295,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1a87ca75439f4e5be763913b21e9d23476b7e5c37814b9a0500c819e437f9b8f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/e2fslibs/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/e2fslibs/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3594,\n\t\t\t\"modtime\": \"2016-09-02T04:17:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22446456,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b7b391571e7253d4cf607e33e3b463895768fad264471e7774882974f834faa1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/e2fsprogs/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/e2fsprogs/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3594,\n\t\t\t\"modtime\": \"2016-09-02T04:17:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22448282,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b7b391571e7253d4cf607e33e3b463895768fad264471e7774882974f834faa1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/findutils/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/findutils/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3089,\n\t\t\t\"modtime\": \"2016-07-04T11:21:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22450112,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7b056c63abe117298b7b8fd193f96f0a324a87c1f70fa38f5d1c750abf0314fd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/gcc-6-base/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/gcc-6-base/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 30116,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22451638,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:360fb8c50734b43dea21842b5e32a97e4b0d247530b7250a86e8057af33c1bc6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/gpgv/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/gpgv/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 9804,\n\t\t\t\"modtime\": \"2018-06-08T18:12:24Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22460146,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b6003da5877b0d74ed5b82690d2d79129985a9eda068fc8913ba7cbdc0950263\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/grep/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/grep/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1806,\n\t\t\t\"modtime\": \"2016-11-28T21:59:51Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22463372,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:11638f295e8713bb780508b539e094aa9e82ae3cca8545163be3e64aec65a8e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/gzip/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/gzip/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1112,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22464469,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f9ac4a5d7a670e3891881a2cdba5fa2cd625c4d58eae4a7aa372ac00a06803bd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/hostname/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/hostname/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1146,\n\t\t\t\"modtime\": \"2013-09-06T10:04:07Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22465241,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:272c5b1c9235edc311f202b2a6abfff24ba96a47c779b4db3b97c2e60eb3e81a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/init-system-helpers/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/init-system-helpers/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3014,\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22465990,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a3ee9fffdc037227ad9461b61700323bb07e3e4be81d9da5c068ad09232e5fa5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libacl1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libacl1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 761,\n\t\t\t\"modtime\": \"2009-08-25T00:37:49Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22467575,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:26522b0fba5e435a1afcd0e3482d0aaab245d60f00b3d5b777c31457c740756b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libapt-pkg5.0/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libapt-pkg5.0/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1029,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22468117,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:307e96c4b7e8170b422d86cfb04d9ae4a404e6d46755448331cdedb23cf1c3b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libattr1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libattr1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 789,\n\t\t\t\"modtime\": \"2009-08-26T01:32:06Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22468833,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2c18722769cd1f0494668b8118ba8c9c785be759d34a85d0b1c9dd2d89f87328\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libaudit-common/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libaudit-common/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1588,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22469382,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0c90284161619a0ccd817b467be8b225d5e52ca76ed151073c4d1e8f7fe25dd7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libaudit1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libaudit1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1588,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22470319,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0c90284161619a0ccd817b467be8b225d5e52ca76ed151073c4d1e8f7fe25dd7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libblkid1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libblkid1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17975,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22471259,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b99c6679c1def231db02b5c30e3a552be6840021271f1e5c4cf5b7a639b0c08c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libbz2-1.0/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libbz2-1.0/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2499,\n\t\t\t\"modtime\": \"2017-01-29T18:30:31Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22476110,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8d2269223e3162f7253432d7790060fe0ce16b73b12700778cde19fccb776fed\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libc-bin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libc-bin/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 25465,\n\t\t\t\"modtime\": \"2018-01-14T10:39:16Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22477540,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a09cfc6ecf8fcd835ba851a1c95b256e01420982ac7acdd01fcfaa748c402f11\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libc6/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libc6/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 25465,\n\t\t\t\"modtime\": \"2018-01-14T10:39:16Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22483797,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a09cfc6ecf8fcd835ba851a1c95b256e01420982ac7acdd01fcfaa748c402f11\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libcap-ng0/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libcap-ng0/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1407,\n\t\t\t\"modtime\": \"2015-03-25T17:03:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22490056,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8cdc2d0eeeb4ed84963c58be27389b148e830ce5ec42c2598cf194721d0430ec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libcomerr2/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libcomerr2/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1154,\n\t\t\t\"modtime\": \"2009-08-13T01:39:57Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22490926,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9e3a4384b6d8d2358d44103f62bcd948328b3f8a63a1a6baa66abeb43302d581\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libdb5.3/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libdb5.3/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7517,\n\t\t\t\"modtime\": \"2017-09-24T07:14:53Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22491689,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b3bbc6fbb3f2a0e6a487e953eb8c3cc4bdb6f4150f7f51d20b1e9a3c8ef92d3d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libdebconfclient0/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libdebconfclient0/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1978,\n\t\t\t\"modtime\": \"2011-07-05T01:00:24Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22493616,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1f48252e8bd71085c67fe1f5468c67da1d2d7cc34cd8a7e9d90b9ad2df080e8e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libfdisk1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libfdisk1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17975,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22494822,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b99c6679c1def231db02b5c30e3a552be6840021271f1e5c4cf5b7a639b0c08c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libgcc1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"linkName\": \"gcc-6-base\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libgcrypt20/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libgcrypt20/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14374,\n\t\t\t\"modtime\": \"2018-06-15T09:58:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22499714,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f8f5c4ea63d81b94e29754072a6cc2fa30cc1656a9d16e0761946c9a8a594a72\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libgpg-error0/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libgpg-error0/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1154,\n\t\t\t\"modtime\": \"2017-01-18T16:22:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22505795,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:25806fa5ca76e47d4868beb59064475397ed841f15584dd9782dbd3228ff99db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/liblz4-1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/liblz4-1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3092,\n\t\t\t\"modtime\": \"2016-02-17T15:27:54Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22506575,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18abf872210b2e1640d078bd84dc3adc34086f964346d71b6002b80b03860730\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/liblzma5/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/liblzma5/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15308,\n\t\t\t\"modtime\": \"2016-10-08T13:01:46Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22508084,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:36109804b8e69c5344232598a4f064da4465683b9461662085be7d8fca29b35a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libmount1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libmount1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17975,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22513112,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b99c6679c1def231db02b5c30e3a552be6840021271f1e5c4cf5b7a639b0c08c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libncursesw5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"linkName\": \"libtinfo5\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpam-modules/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpam-modules/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3176,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22518010,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c584b7b1f37b612da7fdf3b076eb2b2c1bae72865f0699d745ae2ac7d40d13e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpam-modules-bin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpam-modules-bin/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3176,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22519765,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c584b7b1f37b612da7fdf3b076eb2b2c1bae72865f0699d745ae2ac7d40d13e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpam-runtime/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpam-runtime/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3176,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22521517,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c584b7b1f37b612da7fdf3b076eb2b2c1bae72865f0699d745ae2ac7d40d13e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpam0g/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpam0g/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3176,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22523264,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c584b7b1f37b612da7fdf3b076eb2b2c1bae72865f0699d745ae2ac7d40d13e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpcre3/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libpcre3/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2765,\n\t\t\t\"modtime\": \"2015-03-07T18:28:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22525011,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ac9276490d2fa167442ae1aae33926514ad10c8886baa40046c5e367fccc5938\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libselinux1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libselinux1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3129,\n\t\t\t\"modtime\": \"2016-11-06T17:22:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22526540,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:514ea9dc715249906df09333d9a7583b9251fc7c3c265602b53066e564fdfcdc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsemanage-common/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsemanage-common/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1828,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22528038,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1ca1d72a22e1f1d16c2d805c823723df6b8bc7c1407e5e1e5d2bdca7ff222ae9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsemanage1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsemanage1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1828,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22529020,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1ca1d72a22e1f1d16c2d805c823723df6b8bc7c1407e5e1e5d2bdca7ff222ae9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsepol1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsepol1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2071,\n\t\t\t\"modtime\": \"2016-12-03T23:19:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22530004,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bd7d13a1f53de96562c3240d9189705ebbca107d860e9b811780ef9472a21ce7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsmartcols1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsmartcols1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17975,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22531126,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b99c6679c1def231db02b5c30e3a552be6840021271f1e5c4cf5b7a639b0c08c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libss2/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libss2/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1163,\n\t\t\t\"modtime\": \"2016-09-02T04:17:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22535973,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6f717a1464301a641ac17e7301f1a1b221da802e8edf8cf4bc963721d487b146\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libstdc++6\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"linkName\": \"gcc-6-base\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsystemd0/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libsystemd0/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7776,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22536790,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:75f342d2dda6c3e10591b8dbccc4a1d4868f026d27a2afd5ed4565971f533b7f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libtinfo5/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libtinfo5/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6366,\n\t\t\t\"modtime\": \"2017-12-28T09:32:23Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22539591,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b7606456c4e97c19c54c67c1887a705b4d44e5121c48c851b256aeb65e518a4c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libudev1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libudev1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7776,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22541844,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:75f342d2dda6c3e10591b8dbccc4a1d4868f026d27a2afd5ed4565971f533b7f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libustr-1.0-1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libustr-1.0-1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5072,\n\t\t\t\"modtime\": \"2016-11-17T13:42:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22544645,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41c7b465fec47217af1aba6e39525ff8e4ed904f22e8a10175a314b11f8a34b8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libuuid1/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/libuuid1/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17975,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22546818,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b99c6679c1def231db02b5c30e3a552be6840021271f1e5c4cf5b7a639b0c08c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/login/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/login/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5153,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22551664,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:56ca9c00cdef4d69b35d2013465c539eb9e09a80fec538d0f6dc91423dbaa1d3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/lsb-base/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/lsb-base/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2648,\n\t\t\t\"modtime\": \"2014-05-27T14:13:24Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22554262,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e9ed2924c559a5fd2fd5e32f59885baee291b46dcff09c90fbc12c7aeb61c10\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/mawk/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/mawk/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1298,\n\t\t\t\"modtime\": \"2012-03-23T20:15:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22555721,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:80910bdabaf183ae4d3ffd72d9fe9066a9a1035be8e5d7dd541ddc6755d19abb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/mount/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/mount/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17975,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22556577,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b99c6679c1def231db02b5c30e3a552be6840021271f1e5c4cf5b7a639b0c08c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/multiarch-support/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/multiarch-support/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 25465,\n\t\t\t\"modtime\": \"2018-01-14T10:39:16Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22561433,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a09cfc6ecf8fcd835ba851a1c95b256e01420982ac7acdd01fcfaa748c402f11\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/ncurses-base/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/ncurses-base/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6366,\n\t\t\t\"modtime\": \"2017-12-28T09:32:23Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22567694,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b7606456c4e97c19c54c67c1887a705b4d44e5121c48c851b256aeb65e518a4c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/ncurses-bin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/ncurses-bin/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6366,\n\t\t\t\"modtime\": \"2017-12-28T09:32:23Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22569948,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b7606456c4e97c19c54c67c1887a705b4d44e5121c48c851b256aeb65e518a4c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/passwd/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/passwd/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5153,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22572201,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:56ca9c00cdef4d69b35d2013465c539eb9e09a80fec538d0f6dc91423dbaa1d3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/perl/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/perl/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 104049,\n\t\t\t\"modtime\": \"2018-06-10T17:35:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22574795,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:84302bc1e1c76708a293f348a0b2b9a0eee86eac9cc065bb73b4a28318c6fd9b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/perl-base\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"linkName\": \"perl\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/sed/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/sed/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 849,\n\t\t\t\"modtime\": \"2017-01-05T01:31:41Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22598004,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:60886b6264e9531565ccf1e31a63cd9b23f0bf4bbd7053b46aa9e6ae7622d31d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/sensible-utils/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/sensible-utils/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 694,\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22598598,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5c58dcf1d8debb43fcec08ae0cbf2f049aa5d48c567147046db48e42c2f706ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/sysvinit-utils/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/sysvinit-utils/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2199,\n\t\t\t\"modtime\": \"2017-02-12T21:55:39Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22599093,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7778a27498a3909c855d6b3ccec28dc16c67ca5d5aaba6660842cd333ffe188d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/tar/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/tar/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1486,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22600344,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9292780f2dfd11900e92ea67c7a316cf9df740b955956f87ec099a5b4f3d9136\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/tzdata/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/tzdata/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 307,\n\t\t\t\"modtime\": \"2018-05-04T18:20:29Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22601083,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b81a12912f0ea7b6c928bc57c950234a13bfeb690611bfd81b5c329b914cd8b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/util-linux/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/util-linux/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17975,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22601449,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b99c6679c1def231db02b5c30e3a552be6840021271f1e5c4cf5b7a639b0c08c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/zlib1g/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc/zlib1g/copyright\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1606,\n\t\t\t\"modtime\": \"2013-05-03T15:30:15Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22606295,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bcf07f8f2414e28405b35fee95fb14569e926a7d4e99cc4a5db2fe1a0d1aca56\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc-base/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc-base/findutils\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 323,\n\t\t\t\"modtime\": \"2014-04-13T14:12:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22607266,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:83026123456c2f7c1cc44196701180752a65423ade28344ef277cf577b12faa6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/doc-base/users-and-groups\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 423,\n\t\t\t\"modtime\": \"2016-02-20T02:44:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22607568,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:159902a0284dbbcc039824ebab914948f8a803280fa2b67742b8f7fd40c50250\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/dpkg/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/dpkg/abitable\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 362,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22607923,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c9ed655f391a2dffdfee2070e9c4bd1f502ffff17d19abff21ba492ab643c919\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/dpkg/cputable\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1971,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22608231,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:88d770b7e95d793c6250285c4d901365487c44e460a8ebdd4895685f7613d104\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/dpkg/ostable\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2000,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22609080,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:49b8a094236fd9f06463afab94d49956cf6fba363ec14d75da6ae3310214ca42\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/dpkg/tupletable\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1361,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22609851,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d8311834400bd4c74bcdc764968d13c44b5ac8745a9d06068c2209c51401b826\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gcc-6/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gcc-6/python/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gcc-6/python/libstdcxx/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gcc-6/python/libstdcxx/__init__.py\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22610429,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gcc-6/python/libstdcxx/v6/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gcc-6/python/libstdcxx/v6/__init__.py\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1161,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22610594,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:78a3a4acc2b1b08db8f766d251b6f4d009e84663022dfee9ce2c66efd54bcb77\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gcc-6/python/libstdcxx/v6/printers.py\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 55953,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22611282,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8d290e0fd40318fcbaf0dae5a8e17a45a94be40b6c0285a75fdd3f30b412e65b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gcc-6/python/libstdcxx/v6/xmethods.py\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 26822,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22622344,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ea30e5690abecb7808b4cb9dbe36afc3922cde4f982b5f64e1888a339880b1c9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gdb/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gdb/auto-load/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gdb/auto-load/usr/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gdb/auto-load/usr/lib/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22-gdb.py\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2389,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22626081,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6957a1cadd8485b585a3821f167b8867893b5fc4ce7639c4b843901746858cdd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/info/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/keyrings/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/keyrings/debian-archive-keyring.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 36941,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22627405,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:350902b7289c1db8ffc28749772723a195dcd5ee42bbc43d2f57e59d5b06b08f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/keyrings/debian-archive-removed-keys.gpg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17538,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22662459,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ac8b1500ec8cd69c437ff1b23a2b47f60cc740573cdae02a42abe342890faa09\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/libc-bin/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/libc-bin/nsswitch.conf\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 497,\n\t\t\t\"modtime\": \"2017-12-31T12:12:42Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22678696,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e241e67d7b5c15a5ace818d89277507b5ded8b49688b7a4431afb3b1041a3759\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/lintian/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/lintian/overrides/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/locale/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/man/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/menu/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/menu/bash\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 194,\n\t\t\t\"modtime\": \"2013-10-23T12:41:22Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22679157,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1e862c7883df7a31e995769e90b4e6b87399a70f2cad6b2ce95fd865975286aa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/menu/dash\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 108,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22679353,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8bdff923cdb32fc55c80c70546c344e22444dfdccdea6280d9c4c6fa25c7c38\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/misc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-account\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1175,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22679605,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8657819f898333b2ff09e8bb4fcc6ffabb02acd015411d0ec89f28a70e672537\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-account.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 107,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22680317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8e2e9985399c29f44638f97acc1b71f9b2b946cfedb21ead16a54cd12c25992a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-auth\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1194,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22680502,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:940827d13f472a45ebd38cca4c4b2f91b7fc22f08a266a9e987222e88df4cc9b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-auth.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 159,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22681223,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9dfd7b4897f508b7e327e7a511c7d097551d7063145b411e266aa91f2c0c1d57\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-password\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1416,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22681432,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa54ac2f7b8f18c22c1a73dc63d471bfd2694686686fd244d02cd774772dc911\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-password.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 357,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22682250,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5f44a9db909d4ec8cc580261a4674f9a609ad5e7a776a7896087b738e9581b38\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-session\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1127,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22682543,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b1413e5c9105ebdaec6be4eee00535552331a09c5f6206006e8c280374b5a2df\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-session-noninteractive\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1139,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22683232,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ac763203bc998dde4c1ddbdf0c572be2afa61e3f59d82194a51f7b3a5d11f7f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-session-noninteractive.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 46,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22683911,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c4e029edf22d18a793db84b3092d36b88ddfacc5e361b785364e4756755b10e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam/common-session.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 174,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22684065,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b80d0e21fd90493886ba1dd4a4fbacf283e6ffc07815469a0ccb130f2e5d156b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam-configs/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pam-configs/unix\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 682,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22684316,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5b434421d10875a53932e967eddc9b885ea42bd9f1360600af04248e8d42be74\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/AutoSelect.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1833,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22684716,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05d14126837c8b32b3f6a96c204d0946521827cfe7629e6f6060f698ab6788e3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Base.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 499,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22685564,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:66ddc0f2cb2cae1e92bce9f5ae48cc82aea652a9ade8ab86cf9a1a3093e1f3e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Client/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Client/ConfModule.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3900,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22686015,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7d1b308c40b249d160ca49488f5ef1658db695940b53c7bf83bc89f49640b066\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/ConfModule.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15639,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22688084,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:387c6f3a403d3e4cd862b3e68450ab014be1b3b7b6c5824e09ad2f590aae2314\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Config.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7020,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22691708,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cd8de0d581b2ef08ff3deddd060fed52e4a914ddc0b59d46e3af617ee4961d1d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Db.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1202,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22694150,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c0e7a554455e3cf9c42d937bbc8a701627b43f048cbf7a1d7590af44f218338f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/Backup.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1638,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22694834,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0dd39de90e426e2062483ea468348aef62ecbdfb76fb1292728f3679a42b9dfd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/Cache.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4825,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22695517,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7075a4f322db7e12d96e2391267073cf11a01277ed972b8fd5285c8b3b89e272\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/Copy.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 950,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22696546,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d79bf94498c68355489fdd90c09d7aaa62116e42f0845ae78ba2c3b45fef9859\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/Debug.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 950,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22697054,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:feb9793dbf296b01cc866c0bb792843e711f2126a2ed4171f4a1f2561da76cb8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/DirTree.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1990,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22697621,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:57aba77c08bd3c0106b9d21c1c177984e20a477c2528b85b13ef1345b20af677\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/Directory.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3609,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22698531,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ecf618cb2a38996f131f775e72084062b9c942c274133f7adb50ab8c36ef598f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/File.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3633,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22699802,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18906996142065a6c897392a366934054c821d08f34acacb645724da5f6235d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/LDAP.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6226,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22701131,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:633a36005440e5101b822a293751d63e0574787fe2b13157aacc2bc00fb0ef02\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/PackageDir.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3671,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22703234,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:081953795cd5ffbfc2b56cdc1e24c59f76be1fd7664ceaaee6688a55f12c1a3e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/Pipe.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1783,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22704553,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b50341f54a9e86d13c0fc1b607466df39f8db062f226b22123a97d73b1d73063\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver/Stack.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5256,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22705362,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f55d0e3f3f4f3ad8910ca1db54838eea67ee5b4fd4efdfa668e4fb23b432f6b9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/DbDriver.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2359,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22706941,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ce0f564262a8d5dcdc1027951b080af151669b1841ac88cf6db54f9f5dcacab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/Boolean.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 729,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22707971,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:81d60ef5716baeedcd3ec9ed5d59d8d310d6a187d7c902133770fa201604cfa5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/Error.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 331,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22708430,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94044eacc5f6137204dc1c805e9323d8ee370163e21e16485961c073bd244c16\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/Multiselect.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1832,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22708761,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6731d2d9fec3870ff1bece763a60b97666dc9401a52ca5abac9a5c981b607e3b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/Note.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 330,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22709571,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:768e0c2ebfbc4e9227ce359f38b2469e070135c56adba1ec7f5b7505e8ec87e6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/Password.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 690,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22709902,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0f795cb55435e9660233584f899e769e263d1e605e9748860b5edb02ffad3aae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/Progress.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1846,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22710363,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:abe844eae752340e23f9f21ddcb6b24764f0eb980471c25f5158c452cfce961d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/Select.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1350,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22711099,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:53b327be9f1f04b236b0b5baa15b3ec041f56cf9b6f6f98cad37860a495d81bb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/String.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 788,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22711762,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6c2a414ab5362a2d25f5d080c18da7dfb6efee6d6073635b6e3f1da5793ffac8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Dialog/Text.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 330,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22712227,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d95c589193ffc32fa5f5c7fb151a458f210ec17a8f33ef5d1644b61110c7a8b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/Boolean.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1009,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22712592,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:03aaf5a065ce57bce012d4ac22f19c776eb5b49daf5842f06bf50de0948b7b17\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/Error.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 165,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22713132,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dea5e8e710441f23f824944d013a72167c5e5a0eb9ed31502b543e6aea6d33ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/Multiselect.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 916,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22713367,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6a607d19aec535e157cc301eb01a49d25335000d3312f5d0a06e9701d46edfb3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/Note.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 164,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22713948,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f3922ec83c3ff8ab7f2a0c9a832628c64aeff1a92249544259df48f642df14b7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/Password.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 171,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22714182,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e0802d54649714aafd6d6ef426ed4bf4f0429bc8b5ad930e8822b4835d66c4be\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/Progress.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 235,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22714419,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f5b8cf39ff9f833f719d260e27466e4e11839a488286c25dacb56a23b049f831\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/Select.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 834,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22714684,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4d8a031e7a23ad208675d097d700692b04304704fca6764630ffaeaa647843d0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/String.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 439,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22715194,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f8aec4b503d26da2b87eba5acb67456aa6752ad37add8915beee15646626d4a6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Editor/Text.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 316,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22715552,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5478c4f864725771238f7a4d42071be055fdf1781098f9a67671ce4c082d6236\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/Boolean.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 684,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22715912,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c318ba062e156a6aee047e374602c3706c6b411fc42a3ec7e007e72d0ed9a633\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/Error.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1166,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22716373,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:30728fd5851c519aa6d04fc389141c269b933e715c7e4f34c4b374eea08f0e6e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/Multiselect.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2479,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22717012,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f038ebdef7cac98c970b5a009e72c9436addd0bb43b5c3dad66cde38601b4422\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/Note.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1076,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22718096,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ebb6c28c8d917316a985911221448d6df0b448db5ac259b8e6281e82d600762d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/Password.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 580,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22718691,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:909030e9b56deb035d804e5acf0bbb8e31d57cf6b7ded3c2bc44634ca1465a41\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/Progress.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1113,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22719113,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:88e82679aa749d40dc705ddd37bc9b39732c8d67444c2a0d1b8bba605bc53309\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/Select.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 975,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22719663,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:15ae5e72faf962e197edc6da61a5a12aa660027e8ab4e4294c6571dbe2271cf9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/String.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 649,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22720228,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb92206c450cf81313d1c96a9905a2e5a74fadcf9eb810bd7f5ad1e54d57c207\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome/Text.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 300,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22720673,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:21ebacfb1853ff920ebf8ec0d948ffba52863e7acf3d95185bc0c3c213f02af3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Gnome.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2956,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22720986,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7a249e4a2d49d59af9d1432adda52712f607ee20c85b0748356f85e25d17d729\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/Boolean.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 730,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22722086,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:00fe2541a80981c26a26f33df614e88a080c00d592088c6c065a560af16030d2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/Error.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 339,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22722556,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:587b37fd9a3dbdb70116fa02a95592b6c713852df37c8bd67d10884aa9778cae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/Multiselect.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1241,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22722886,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e76353e8dd6e224fdf11c0589a4d9fc50f2658f0a3830f4c7b154fd58f6354b3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/Note.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 365,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22723575,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3dcea774a31296c300a5b3f3759e4280dca2b6ed4d603758102caac2a4f8b23\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/Password.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 605,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22723906,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a1cf8c7a6c23c4011d59b0e5d947f76edf59d2ec2a0ad59d6b1c962c477f81ae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/Progress.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1164,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22724332,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f72dcf155b89c7b6275f246f083d5aeefc188a66056c49bf0420f30968606b26\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/Select.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1083,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22724884,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:531a4048d81c02f477ac9405a13ca1110c63dcd8bd7a28607afe670cf081fdcf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/String.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 636,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22725519,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:daaaf6d66dca96cca82e9d64c563c705927d1a604a18fb352d3fa17b32f09547\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde/Text.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 323,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22725961,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b49c5cf58bf4ce29ed7d2789f6b8f44480d84527dd166f80fc3abd2272c0a394\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Kde.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2185,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22726278,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:46e40500a4283dc9d8a581182cc5ccbfed82c54163969a4f425568e303e323f1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Multiselect.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 916,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22727089,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8f4919e0b67b61f650af51406b13998467a477cd04f7772bc8b5ad6cb18649c3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/Boolean.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 178,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22727632,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:13e3e74cafc97617862521b51e2c4ba4b87e87658363d1537452fcd5d874d261\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/Error.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1666,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22727869,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:799e48fc5a362d653334159305bafe67cd451420d98988d3047d515b2408120b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/Multiselect.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 182,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22728700,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:14bbbea9a46115ea16632083ea3ba850b13594957e5dc49b7907ec07e14a0789\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/Note.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 175,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22728938,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:88f2b6eaca06a4b404d62cbdaad4f497aa17aca4d44e785c3a78a763b66c24d4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/Password.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 179,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22729174,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5a046112c91b00436a614d93590338a04ad14710cf3af56ebdb883041e38a955\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/Progress.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 258,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22729413,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f21d00539d3a4b8dafa82322d0e0cb1281f0493995723dfdd9a6fc7cc28a7434\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/Select.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 602,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22729684,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e0b972e4af3cefd2ab4858fac0a20df5ac91feb886bb8f0003cfac187581609b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/String.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 177,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22730106,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:505643b340d236ba8fe6e3bb930640e79ecf6ac15b43513456cb81228c946e23\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive/Text.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 226,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22730341,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:17d40add0e5bf98fdfb6ad5f71f337a04536c57c5b4e663cb6f5308398f27349\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Noninteractive.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 342,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22730614,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e1b6db74cda4b4b43bdf2244350494ea6a53d13a1f7dfeaca90ed16b22d13791\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Select.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1982,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22730932,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:249a05d5f564db0f40e09c13d79b0a77ab128563a19a1ceee585c3431b844d1e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/Boolean.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1196,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22731691,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a97d6deb504426af124f6c1dd8d522a6abd009dbb37fbe0a3e2a284b921ea1f3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/Error.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 170,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22732309,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a271b558a75a7617474d93cd77402c339334e84938651ea0a01f7336db09d010\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/Multiselect.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1899,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22732550,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dccdb67e08a4053c00c2395d4178ecf37ce8e64e81c63b4807e1d763ab0d5450\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/Note.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 403,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22733446,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0ea94576f9890a0f5f9a4a59361bd1e0f6153b3ff23b883e6078b2e08063155d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/Password.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 629,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22733811,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9c3cc0ef1ccbe6da38b3885610369edef2005a691d043023c27689621e027a39\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/Progress.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 805,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22734250,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:63968f89058f1066176e80bc3a4e4ada8f4f24dcf78fc56c722edc7aa12f0f9c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/Select.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3292,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22734710,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a5749589dee50745a7db1e2c6743788334381461cca018552058183edae81d8c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/String.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 573,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22736001,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9bbe2c52e9629b135b888fe81fdcaf9eb1280076df252bb86292ba904aad8a1c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Teletype/Text.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 315,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22736409,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f61a5ec96a09bf7671dadd87281a75622df7043b2736d788af6767f6827bcbba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/Boolean.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 660,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22736769,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e74c742b01709c060bd24a58f960c03cbe688a818919037295d6222f8c3165ee\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/Error.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 160,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22737256,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1699c8211d030d2d67fcfaafd5e30867d2661c21dad41c574dec2d88bd96ebc6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/Multiselect.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 958,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22737491,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:367f3dce72c5bb9e40587416570903867824a063eb04319b6d57afdce1039d01\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/Note.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 159,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22738086,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6654230ab4dc25692f22f7eae0798896067c2f5471ceabc4bbfdfa63258970aa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/Password.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 483,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22738319,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aff9175f3d6d46cd1a98d602e670d565c66005bc1e482174ca8ca75b53a40300\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/Progress.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 231,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22738728,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:430c8365d9c3278fc0375434cc93725f8fa75a5353b072f0f8cfdfe4c7dd4dfc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/Select.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 877,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22738993,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:42a7752151c302e29228a17fa3d0fa8bd65dc999025846c013ee580e06d78766\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/String.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 467,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22739538,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3dacc1ab78f01cd9db77d95163cc33fec708f1ba1d3ca10146f5b14c6096def7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element/Web/Text.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 315,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22739935,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:03e9ea3bda1040086d423f3fbe2ee6cc93f59d90d26b4bf8554ab5c6cdc73885\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Element.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 196,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22740263,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:00c10272de11fd0ddfbacf752982b22623e629b9d796533c95d586d858ce2c39\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Encoding.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1487,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22740523,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:801fe349da27f9312f3b6c60ea38e44e34bf7fce5138a0a9235b5efd1f7ff7eb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Format/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Format/822.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2139,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22741293,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:47bb2e39010d9e051b79bdae364bb5824c663441b05037babae6a634fd4c0fb4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Format.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 133,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22742209,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5ce727bb1a20759b641ffb8bd6c45176bae65e65f907e237c6dc1f093899b02f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Dialog.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7389,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22742465,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:03417133c48efa609a58085ee135db1008ac8326a6457874df9105ad5fce075e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Editor.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2165,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22745016,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:24b3da6ed94ce2682a51501683188675dbb50d4b154496e875ef1488c391711c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Gnome.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4956,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22746092,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a2e09f7bbe1cbd15850b432a626a0321bba98cec860960e8fc01963c446faea0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Kde/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Kde/Ui_DebconfWizard.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4244,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22747752,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:649442e8cccc20d0f5937021d5f5fc551f4c91d9fc30f2c6181d295824a4948e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Kde/Wizard.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1707,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22748897,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9ae54bf90aa55c3aaca791616079cc9c342364995f992bc1e03d374440a9dc62\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Kde.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4409,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22749664,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:457b5677b1907bf3b85fd3189efdd47a537dcbce15943f953495e9739ad82825\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Noninteractive.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 734,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22751134,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1604a04e4c2ddebc03659bef3bfe94a1f97330ca8e4ea88b036b10ca509308e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Passthrough.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6438,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22751635,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6cc52e0f85ac962e7fcdf11cabf01b13a7493d02209c23e8690a0c9afa3426da\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Readline.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3486,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22753569,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:de513abc3901f8244dc3cee1f84ccbeb817f7c3594167c9d3d52c074ea586d81\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/ScreenSize.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 881,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22754913,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:abd4a309996b0f8798df81bd51d881fa014b66ebbd0d626220884aee2868922e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Teletype.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1573,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22755436,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e01ec0a98b14a8092dda1656e66248212dc4f164248f4058178e2964e5b72928\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Text.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 155,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22756257,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cf4595fb746e12a9c0a43cd6806aec7d45523aa71b2bf9d98328d8c713c8470b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd/Web.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2665,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22756483,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ca7b97f7c6ecd207e6b161a89a0d42e5e547c81206b09c430b9a4ac1f0b9f847\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/FrontEnd.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2864,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22757757,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e7a545c137bb45bfc70dc75f6f14f2246219a4cf9a60344bff9dcf04b1e25b33\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Gettext.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 301,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22758780,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a88fa616d014b4668aa0acddd4b62c6f16f23ca4d770f74c42a465bccd757ddf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Iterator.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 198,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22759107,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:25e26945b7cd46f0807fc71e4aa0187668d883f9068076356ec4fc3515d58b15\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Log.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 914,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22759368,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:295705788c02bc5ecab17acab91e8bca411c88a5ec5404b64ea1bf85f408d98a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Path.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 291,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22759962,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:028380a22abab29ad18b0f4411bb3f1a1f3bf192f139ae61121393cebf5acc6e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Priority.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 642,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22760266,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bf398f78a07d12eb8aee3fb782ffd002f311027279d076eaa6fffd0de11ce0d1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Question.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5867,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22760693,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:457f0d6a12d8dc4ab1fc109b5c54c423a703184630b50e49abfd3b2cbba2e640\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Template/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Template/Transient.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1108,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22762474,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a0e780834bf3c643f32931ad4fe02b3447343b1a54def72f03e15823e6723ae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/Template.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8201,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22763043,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4ee3d67fccb651ed7bca60a48bd85758e3a177fdda3167a5209f1513379eb6ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debconf/TmpFile.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 374,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22765731,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01a27c6a5acbf11d145efb8341e0328892a0c00db0526ad522a8c2165e4e01f6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debian/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debian/AdduserCommon.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6185,\n\t\t\t\"modtime\": \"2016-06-26T22:55:16Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22766120,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94551d94231a98889d4fe7559c990cd5b26abf14c53a5ed8d072287e66b637d1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debian/DebConf/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debian/DebConf/Client/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/perl5/Debian/DebConf/Client/ConfModule.pm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 610,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22768783,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18613eb5076afb75cd5cd97811c465b78533ab566d482023c9f3379f4f7fe7a0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pixmaps/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/pixmaps/debian-logo.png\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1718,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22769254,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18aa40cbfcd56cd1dddb005a7b20560d5466046472c665bad8683dfa9e17d6f2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/tabset/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/tabset/std\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 135,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22771163,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fbadb5f608b355fe481c0c7d9c6265b2372bfa35250662f81f68d46540080770\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/tabset/stdcrt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 95,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22771283,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cf6c37b18ceea7c306f7e3a5e604a03b0dfb9c22ec99163e4b52f885ce063145\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/tabset/vt100\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 160,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22771399,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:075251754239d9973945d82b95c18cd90997acd2017393e70c8832e9297de056\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/tabset/vt300\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 64,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22771518,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:61f8388cad6a381feb819bc6a8d299d06a853d15e1f4bfdfd6b6f40069ad4956\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/terminfo/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Abidjan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 170,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22771745,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d5ded126df8f693ce1ff83e85aa4d44185c2bdef7da1f915b214f53deffdee47\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Accra\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 842,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22771916,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ea0a89ec3c253390f746107c3ea69392270d8df0dc2d2aed6f23f4cff852bf91\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Addis_Ababa\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 285,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22772459,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f143bcb83b80bc1ad0bbb8ad736c852e62bbeb6b3134412bfa77684663ed222a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Algiers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 760,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22772689,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d777e8eecb9ebe269692349daa6b45b2463e4a3c2d107ccd139b6206c4fa73cc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Asmara\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Asmera\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Bamako\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Bangui\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 171,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22773263,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e40c3386f3a5cd88a03c811fa30ecac34f31368f960ae79e4a90de295c5b1938\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Banjul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Bissau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 208,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22773480,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8ddad13adc33cdee8eaf55cfa31efcafd79305ae8dfcc3be06ff78299f29f1d8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Blantyre\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 171,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22773681,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3d7e6d17cabdaa1814a56dddec02687e1087bc3334fe920ad268a892bf080511\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Brazzaville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Bujumbura\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Cairo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Egypt\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Casablanca\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1629,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22773963,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:afb98baa9972580559410aa145c57fb8c86689a05f7f0e97815f96bdea7af5ad\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Ceuta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2059,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22774905,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:387d2c354117fe2a22f6f3b429e4193a331d3e93d7007a55c50b3b9eedee63de\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Conakry\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Dakar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Dar_es_Salaam\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Djibouti\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Douala\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/El_Aaiun\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1459,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22776159,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9c3a4c95fd64c01a78dcd44ca4b16cf72f2416be4704e8c5d52ffc7c131ae015\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Freetown\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Gaborone\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Harare\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Johannesburg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 271,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22777115,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fcec4247091905d88a0b869e8e5c7ee6bcfba7db6c310165baa95078b0be31af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Juba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 683,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22777350,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:73d986c70173c763e9b262dbf367120bc2a4f63f006c1d412ea9adab77e09da3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Kampala\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Khartoum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22777856,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5256a96f78382e82db80ad8591240c3886fc58f9a83fe94506e3a192fbcf2f4e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Kigali\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Kinshasa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Lagos\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Libreville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Lome\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Luanda\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Lubumbashi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Lusaka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Malabo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Maputo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Maseru\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Johannesburg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Mbabane\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Johannesburg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Mogadishu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Monrovia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 233,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22778584,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3f9672c98983af595b3c6274cf8135728c8815a4f9c98ffba043707609e5d122\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Nairobi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Ndjamena\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 225,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22778843,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b1391c8edd23b3f73e0bfacf8b878801c58206ca42349c30b22fcb7e8d13de3a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Niamey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Nouakchott\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Ouagadougou\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Porto-Novo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Sao_Tome\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 234,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22779160,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8d9cc441a8cb7dfebbf23510dba8510ba8b7a2cac7661b0cccab368555d865bf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Timbuktu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Tripoli\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Libya\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Tunis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 710,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22779449,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eecc34436d1dd96c49d6b671ed61bc594548d280a967537a9653841b537a9a92\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Africa/Windhoek\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 988,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22779935,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f6d37353c3cf02bb1b950cdc1cc024e9849a374532a8f7e4ee0bb00bdd4b6ab1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Adak\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2365,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22780581,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c45c94d316413c8f666aff65ed1f837a7e2d392262de31ce59fac2e96a1edc81\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Anchorage\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2380,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22781880,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f5df0a6f7f9d43cbbd3e74d33a23fe686080eb55965f5d9246b6e859b3db9d18\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Anguilla\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 170,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22783178,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b2659c267f7555c0640505660234cbe0d7feead3a5e29f41272e28a1d7d18962\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Antigua\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Araguaina\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 896,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22783403,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:272c5c90b22d2661b00ed78567b641a8e7aacd3261e19c40ef191af4c7b1c60c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/Buenos_Aires\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Buenos_Aires\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/Catamarca\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Catamarca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/ComodRivadavia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Catamarca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/Cordoba\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Cordoba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/Jujuy\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Jujuy\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/La_Rioja\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1109,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22784151,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:621f1bb3113e8ef3675827b6bcd718fc09f13157639ce8986c98bde382f3c957\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/Mendoza\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Mendoza\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/Rio_Gallegos\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1095,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22784897,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:29a13c6e65962f48b48ba73bffd41474a98257d1212584f32b3b51e5daa092a9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/Salta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1067,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22785586,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:113093ce6d0f2189f9a34183b0a1117b028c89761740700378f64c26ca60a884\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/San_Juan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1109,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22786267,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01d61c864a3edb46fc9c0245bda0c551c6b12253e962178ad42b9fa3d2ea96a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/San_Luis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1125,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22786966,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:954240d24edafb8de8aec83efe5f926bde08620d4564105c68b5e59afcddcaf4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/Tucuman\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1123,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22787667,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:82abb66f092dc63c03be1c298b65a8266ec6a638d17c00051701138b9bf7e00e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Argentina/Ushuaia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1095,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22788378,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1caf03ba65f9d802fd8160f103c613ba9266500ef95956af6af8636ac4f5a7e3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Aruba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 212,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22789059,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:023d877932f35d889772f561f79e266c8541b984e0ce2bd257723aafc7d883c1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Asuncion\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2063,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22789263,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f84a9ad05fdbc043ec0d57f60c0d9dde2c4979ff53de5f4b09520174f908c8c1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Atikokan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 345,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22790378,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c30226b472b507b5a30b69557d56f24fcc8e9467110e4d3ec15c2c51de5d245c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Atka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Adak\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Bahia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1036,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22790689,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2907605adbb291db6f65ffa990fb28e2150b37896752171c664a9cff6b4a890d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Bahia_Banderas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1588,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22791336,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9d0e0d9f6168635a5f98550a170d423854ff5b662ce0d874c3cba77199bf1cbd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Barbados\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 344,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22792245,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9b1a7857a01ae2a3ae9a51e0b40cfbed91bac468579ed3c08b54466276bbb1fa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Belem\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 588,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22792521,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cab597d9b0946c0542e1e7efc41de81ffb67e5ad1b982ba7512e7c3b7abf9712\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Belize\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 978,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22792941,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eb4e57a8c657d0c253ef4e0a5af118c928e6e5875564081a714563addfd4b31a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Blanc-Sablon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 307,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22793566,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c7d383bfb7e85331030f8091a9055a5f424e3674407ca0c76cce06b5a0316fdb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Boa_Vista\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 644,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22793828,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:593ec3794b5fdc2fdb6141cf37eb943ccaf64818224f4c6c9eb64e001562eecc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Bogota\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 257,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22794278,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7035a44b8a40432315da50a5db760cabde6fb2ad4004e1416645a04841c72b79\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Boise\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2403,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22794506,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:33353ef05ccdda7debe757cf865ee7bd78031f38c6797b8fbfc11f9010f55a10\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Buenos_Aires\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1095,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22795805,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:734a334127e43faddb2bc722a0e508719105a4aa25897c2a280fb1dfec261113\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Cambridge_Bay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2098,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22796491,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0aeaed5b104ee99ab13a9f5b5a7aaf7f6c9a7f59bdefd15d3c9951551c7b5f6f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Campo_Grande\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2016,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22797635,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ef672b3c0637f5e677307da2759bc261afa4f07e52fe45197f85b211f8bb9364\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Cancun\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 816,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22798770,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d22316873f309799c6f97fefb8a0a8897d0df4eb376f84bb0b71602ec240d04f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Caracas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 275,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22799294,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2f9e7150c7461615db09d15ae2ac14d42d3fa06327f57fa7a4064a9bedba2992\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Catamarca\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1095,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22799541,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:81e2c01af75fe321d32147db82facd088b6c191e9ea4cc3f8dd0ca36d90c1d12\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Cayenne\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 210,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22800223,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0afd6f15f47edfdfdeb34d7cfd8e1c1da974259085acec6fa03ad2f2c27f138a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Cayman\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 203,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22800426,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc4fbba14653a3186f3c5b719f7b9bf7d8a5824401064cf6d508205592e55a9f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Chicago\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3585,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22800632,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:143f29b957173a46008187230a38125bd3a03b3dbcba0dc1d1b8661331f71693\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Chihuahua\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1522,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22802506,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a7d150e716db5b1c96bb0e50252b80306e1d9e8bcc2bf90a3ae7071906e71513\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Coral_Harbour\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Atikokan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Cordoba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1095,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22803431,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa24a2867e3cdce8158a4abb12118fff2a65c7ead38edbb8d56a43b8345b3600\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Costa_Rica\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 341,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22804110,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4e6ff29a776e053226bf590ebe734896f9150d69074f22a16a1c7199a1484ec5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Creston\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 233,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22804393,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:97b74beec3714be518219f24533cc21edf9b53d01f4ab792a6fe0f88973449eb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Cuiaba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1988,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22804608,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1df651a890eb83ad31e503fa10697555f735974ae4501b48735d67cddf5f4a2b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Curacao\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Danmarkshavn\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 712,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22805784,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:087e39cd6f10b6944b68b1de557289ef33769467f1b29806b96a16cf8e438e6e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Dawson\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2093,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22806252,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2d01b4b6114df8b0ed8aa64654f777842f20729818f1566a5f341d73ef7093dc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Dawson_Creek\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1059,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22807410,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:29d0245bc04dadcbb196a3b6a81bace1696451166a7417d5bb2a8610f37ec5ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Denver\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Detroit\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2188,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22808104,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d9037aded390d30e2e30f2302062ad6042651b261392872ef772cad5afaed92a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Dominica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Edmonton\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2402,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22809338,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6678c23f86573b6c95e6c748a317aa8ce90f68636bcdad18db081e70986fb54e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Eirunepe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 676,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22810634,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1cf7b8dcba3182d527e72c1307bb6fc6908e8722d7ae10ff6522608df38d70c3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/El_Salvador\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 250,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22811100,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:63215b213a31505bfd545fd52b11214cb614f13f0f55911f414edb44286e7f8a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Ensenada\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2356,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22811333,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d827b95b4fa16b8c56d9a1636341c9112657e567ae84b37a9bfca133ae31babb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Fort_Nelson\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2249,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22812593,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e7ce9a01cdd313d20352112430341c262e1b90182de490fc95c132daac118ce7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Fort_Wayne\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1675,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22813803,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:55c2f3feb241f88435e9876e76e2c69ddfd0dfd36a273b551ff480e2cfad99fe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Fortaleza\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 728,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22814775,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dc020e10d5350251d78744ffa59f54a7fc47eb521e3813a4811d614067a929ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Glace_Bay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2206,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22815275,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e6af24e3b9f1240abb8618fac326ee3a1ecccd25d2fa4936b2a28b0b0880e550\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Godthab\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1878,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22816473,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69351ff5190c3330d5910eb4d23211674dca4a120c6636bd535d6b6687f96b23\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Goose_Bay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3219,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22817492,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f0c06c6a1841cdc37bfb311c11caba1c974d0d6c27725c04b69657e7ca112a49\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Grand_Turk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1881,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22819220,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:90848fabb8bcfdbb4e66f5a624c4e7fa88962f16f8b6005f527cd84abebfa574\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Grenada\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Guadeloupe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Guatemala\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 306,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22820334,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:795cc25e5ffe825a8b3d86eed98ad5f9bb9f6d152df2b624f0e2a63b17f0ee43\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Guayaquil\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 257,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22820599,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b144b87141ba1c6e6e7e0da5b35ec3c50d57dda3b2be94caf3186062563ccf35\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Guyana\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 252,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22820833,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b38a7f5eb21df41f8efbca839606a2b76dcb13f13aecab80956d6cb1196a76a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Halifax\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3438,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22821055,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:627e18218c6f3c3f446c4970abe8164672e2a7ba94bcf841b1e06af5089b94ea\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Havana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Cuba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Hermosillo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 454,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22822913,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ec6eb21d068f1ca8e80a9e825206ad1b5a04b1e8abb2dd981c6c90b7686b8820\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indiana/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indiana/Indianapolis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indiana/Knox\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Knox_IN\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indiana/Marengo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1731,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22823353,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:64bb87669a7c161454b283e5855e28de7655450680cc403eea0572e580eb2625\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indiana/Petersburg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1913,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22824368,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3eb5dd510d677f9118ec4bca7892db4ed181722fbaf94ef9cb1a441718400321\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indiana/Tell_City\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1735,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22825472,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:268c538689f4815f86ae1d100b4b072a785d5e68b03de71b74f437135bc52843\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indiana/Vevay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1423,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22826469,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5cf728ac267cce51bddf1875219bf0e800d5aaa17794dc2c7408293773f516e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indiana/Vincennes\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1703,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22827322,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a9db38f7575f9e2a624c9466128927caef0eea7e9a3841679cd6eb129b019d3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indiana/Winamac\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1787,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22828318,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d2dc919207b8db95bd82aff68b8a498a6d3bec2c33220ba5381ebca171dcc095\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Indianapolis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Inuvik\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1928,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22829403,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ea64cbc0bf92cf88c8917222f11db8838f42e2d41360cd81bb93f669a2bc685b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Iqaluit\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2046,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22830466,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eb8797250b8bd8c3d09893b4f261ffb1bedd668869a051c8e2c80f6c0d63408c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Jamaica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Jamaica\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Jujuy\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1067,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22831625,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9e5e87b452a3cdc3f010537e096150239b10ee67ec1c438b7864096a96758992\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Juneau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2362,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22832294,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8185913ee68f7ec72cd98efcee68d1b6bd0c304e303a2dc613b06cd97e6333c8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Kentucky/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Kentucky/Louisville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Louisville\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Kentucky/Monticello\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2361,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22833680,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b87081e46bbe688816a7e03cfdc5b4efe10bd6b92cb5a780df6b0c86af4c1a37\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Knox_IN\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2437,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22834964,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9e75dd6c52c5339c8e2b195ff8ac6a7212e2c5e84b2be3023cc355972c20d856\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Kralendijk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/La_Paz\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 243,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22836334,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:379b1f2fd14b7f6b584e9e7030f45b580a84fc7c0c96314006c76c0afd620532\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Lima\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 417,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22836556,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4adf338b94b1680c4e114ffa17669dba4363a08009d6e21f090610e55aaa30a1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Los_Angeles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2845,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22836893,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fea9d66ff6522e69d22073dc4e84179b7cac2e372b398dc2fafdfdb61a9eb2e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Louisville\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2781,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22838408,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:779c6a6c566774f94f754dad8936ea7f7f6afb028ed9c76b74d8f375355439ee\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Lower_Princes\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Maceio\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 756,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22839952,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c640e22f9bb0f3c376f8a3440622e7a29de3b48d71d06d900ae66e0e2ea4f392\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Managua\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 463,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22840458,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a3c1f00bc879ee84e623d25252f1fb8ffd8cf43cd9c8b8bf12b6b5eda8045683\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Manaus\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 616,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22840809,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7a411c339329e8984d50258dd3bbf44e06e4a86db28d1b34a27c056f2a00686a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Marigot\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Martinique\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 257,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22841288,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e087c3e4ae20234a08667adcf6ab4cd03ab3aeee7e035278f271ddb0b65cfff2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Matamoros\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1416,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22841520,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4398d831df4bfcfd9bafa22ac35cd55dbb7dfd5f25c138452e8adf275ea11735\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Mazatlan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1564,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22842351,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9340b719b250773262cec62e771d121105aed168836723dfc305e30bb04cfbb1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Mendoza\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1095,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22843245,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:38933e04d16131a11b1052c7daba2794b994030dd485142d8766f7f13d105b61\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Menominee\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2283,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22843927,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:46ced580e74834d2c68a80a60ae05a0b715014bb2b4dad67cf994ac20ce2ac22\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Merida\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1456,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22845164,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ecdcf4b29f7b439152b9e9b559f04d7d4ba759dd942c2fd685a4ee36798fc8d1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Metlakatla\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1418,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22846006,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:49ad5e4fc549d0db2e2cc6dcd2936ecb12b8591dbc3a806ffcf843df8240f6a0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Mexico_City\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1618,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22846865,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:88bc3fcb1a92ef053e0af4af9053ecbf12855fdf18f859b2a54d826dbfacb655\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Miquelon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1682,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22847792,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41f2e13c925042a466b8cdcc8bd1dced7e9247cc893bcde20b91d98ce10d316f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Moncton\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3163,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22848744,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1300d5a93bb376cbf23a890a23ea05fa2b229486e7eb7d5959c7834260fbb7b7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Monterrey\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1416,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22850420,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:89dadca852ebf52e4405c958132255c25fb195604d7df9b844bf50b48a0865d8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Montevideo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1550,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22851248,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b58bb9b5a2c6f4f5c20067ff6b4a56037962fa37e5264c521d340eb7323e5b3a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Montreal\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3503,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22852152,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:842f7a103dfac9c0c2c33c9cc392a113d266ac064c5c7497883ab41b797ce194\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Montserrat\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Nassau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2284,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22854046,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4c999dbcc6c6045acbedf6fd48f5b70b20eb8d8b0bd9612d2bea88dc03aa9f4d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/New_York\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../posixrules\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Nipigon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2131,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22855326,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7100ca4bf3044211ff8e770dade20b683880f3965f146ebbdd72c644aaec7c37\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Nome\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2376,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22856491,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d312bc797eb1b384ccfba0c40822d50b2e0abf37d5daa43dd3e255fdc7573b00\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Noronha\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 728,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22857800,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b71d8f0d772be18ab8425cff1be9d927f340511a91e248e962745ccc76ced79\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/North_Dakota/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/North_Dakota/Beulah\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2389,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22858337,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f604eb42f0197f5edefcd6d43051a0b64e6e1327dbd2d3cfa94d0348b23e1fa8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/North_Dakota/Center\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2389,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22859652,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:08efea4af9a2b6a5ab25e86116cfcf4b93c16ba9b7b22f762d9cb3481ecf3ac8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/North_Dakota/New_Salem\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2389,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22860971,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c5a43eb6776c326b1250f914f00e9e00e121b9b51f63665f90f245376da2017a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Ojinaga\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1522,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22862271,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a07ff8fe3ee3531f866afca0f7937d86acec1826fb3eaa655d54300ec22dc713\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Panama\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Cayman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Pangnirtung\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2108,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22863195,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1b6a497653df9220c30a022d87ec2aa1320af9e51bb3cdc48756e72d770a6738\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Paramaribo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 282,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22864347,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:95afc0b1d45e18abc0fc3a8952500b443a1c49174b6a61de4fb09c8a1284131c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Phoenix\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 353,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22864579,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9c013ecf82b6ed1dde235b5fc983fe9d23c8d56d610323f7c94c6ba3cd7b4564\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Port-au-Prince\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1455,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22864881,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b0b60ad1c557c41596e0fcc7fc8b9b39444c78295b147cee495e29985a225da6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Port_of_Spain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Porto_Acre\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 648,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22865790,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f3461eaf7c44f1bf84193b3889dd3ff27901f8d0c4412afe77f917ce1afb2b85\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Porto_Velho\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 588,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22866239,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:526e90a17542252332361dbaf136103513731b094788e8705f5df5d981c1fa4f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Puerto_Rico\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 255,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22866673,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7eee44e1cb7ac885fdd5042815c548bcb6ca84cff8de007e52b53c0b9ad53f19\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Punta_Arenas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1897,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22866911,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:12d157ad893061c7f49cb94cc6a0ec3b20a11ef71fdc150c0baf4c39d97836e6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Rainy_River\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2131,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22867972,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a7b8dd4c968de31fe35fd9fe075fad8afc15892067119f638b5aef0d2288d83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Rankin_Inlet\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1930,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22869151,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b3ae38ccfa3091ebd8037fd5e1fd2715a72008932f94526a15fb1aa7fae722dc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Recife\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 728,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22870219,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a87a7203eb4cb49346d80581463e0b8d0e8fde53f3801cc98c12d26d016708d7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Regina\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 994,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22870714,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:929d07457407529637626d09f5ca975b4f05801f35d0bfac4e3b0027efee6776\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Resolute\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1930,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22871326,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c529141807704725b059187b9f458080f911b6dd4313e74139d2c7dac287c901\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Rio_Branco\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Porto_Acre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Rosario\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Cordoba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Santa_Isabel\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Santarem\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 618,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22872513,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d126927c9419ef3afbb32be4fc3600d5f44c022a4e8472cf2532863ca9787d0b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Santiago\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2524,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22872951,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9250d4f8f07d8cee14e8ae9e2ece611b7ea9bf69bca4fde77788346477b14658\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Santo_Domingo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 491,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22874310,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:adf349e4c7314aaa699c4893c589b077f6dfa7d9a54ea9eae459658f9af41dc7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Sao_Paulo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2016,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22874684,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e54f2d187b08effd2d1ac9c4f66d6bc0a3136704887928557a5c7f74c23af408\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Scoresbysund\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1916,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22875829,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2c37c6a1f497e2c993dadbd3aab2bf04ab72b626c3abde7ac29d55d4601f967e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Shiprock\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Sitka\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2350,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22876913,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ba79b89ecd8e64dba4119f2c5af2373167557c4bc71b7b134ab252e0b7485fdb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/St_Barthelemy\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/St_Johns\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3664,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22878264,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b960a58d6d3f6a272707f941f55b15b8ba3fd0fd55f8680ea84af6b1e98bae0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/St_Kitts\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/St_Lucia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/St_Thomas\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/St_Vincent\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Swift_Current\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 574,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22880313,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6b6029f04ac07c382e20d315da7a72d9204d813ef83585f042562e7f6788a78f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Tegucigalpa\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 278,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22880722,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fd295a9cc689a966786b6e0ec9d0f101796ac8b4f04a6f529b192937df3a2115\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Thule\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1528,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22880965,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a474a1fc764343470d310369cdbf6d7007ea611116e25bea68f60ddf5a6cd68\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Thunder_Bay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2211,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22881853,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aef45e1474369f52e1afb1cd7f312e9f035ca13686092cf2351a353133e1cee6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Tijuana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Toronto\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Montreal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Tortola\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Vancouver\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2901,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22883151,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8b414b9a20be09ad61214deeb2dbff3bb1bd1e9d351a79aceae757fa0fbe91dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Virgin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Whitehorse\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2093,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22884733,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1864fe33d51e58780a5c8400a47e7c42e6e6655abe49a82cc11a461059058313\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Winnipeg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2891,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22885882,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:77be5c08f6f8ebe5330fb86a60c4447ea2549620609f4ef6a7a7a68d1a12d9d6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Yakutat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2314,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22887419,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:07f189f49873b1392989ecbde19d19d33cd6c16953bf7e6b927ca2f1040f7106\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/America/Yellowknife\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1980,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22888688,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3140de7fe4136fb4920e8bb8ed8d707256e78c672edfce1657ae22672de68768\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/Casey\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 297,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22889822,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:235e572b63f7ae91a9cd1f352fef86fb61b506465f418e0127c5ad86c88e2253\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/Davis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 297,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22890070,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ee123489006dfbc147e65020c9836054e7fcb494d150582464bc2060d409a16e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/DumontDUrville\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 202,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22890326,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:26fa92c4c643cc230c34b1641355726fddba6587181ddf3c3b1f1a63149e64c7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/Macquarie\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1529,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22890530,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:19fe3ba56b287f6117a93b06d16402bfd5386deb06676349c1b8501d497f5a90\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/Mawson\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 211,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22891378,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5779e99cfe950860cd5fadb21f21c8a9a3ff264a0e1f06a41de944e8d62d68b0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/McMurdo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/Palmer\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1418,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22891618,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:59261d3bbe6da255add2fc7fb8eb711b6c4a718de8982cde36806c2a766f74eb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/Rothera\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 172,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22892432,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c15f59336f5a90350fb5c13cfe7e4836a54d387f7b7248eaa154ca7e21ca0fbb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/South_Pole\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/Syowa\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22892651,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9b96709317fec4c34c541fd36cf4fe466da31a1f40e62905b1dff9217dcb85c0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/Troll\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1162,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22892830,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5038d1f2d45e68bcadb7c6e3fce73f1b3ed6719c9ae9ff46225ffabe7eadd717\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Antarctica/Vostok\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22893516,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:57d73835fefd936f16f953339a6f0195050e4d1499fb4e6551be1b90c25872c0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Arctic/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Arctic/Longyearbyen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2251,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22893736,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0fa4e635da2b178fa3ea13ff3829c702844cf8bd69e16bca8e1d34dbd9249d01\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Aden\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22894950,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:baacbd8acbcee961f154dbbd5d4b40f82f124576b8191f08c7b1501ad7e78364\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Almaty\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1017,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22895128,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:038801e8f58d0f0166ed053af84d11fde658e6e997c100101a9f4330c8cde4e0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Amman\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1877,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22895726,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ba18a1f823f77e478e7030eeb82ddd71a5f3fae6efdf56325b7776304912da08\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Anadyr\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1208,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22896767,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0bd4d0ef1c353f753b6e034aff4e004b77df3c92d1f0de648b07e03b1f90a253\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Aqtau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1003,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22897471,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4abd31e6c7b73775c51c2bc1c78de6a9901cd9e241627c2c8e311fd306896b0e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Aqtobe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1033,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22898074,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:062a98f4317d5dc621baa9a377caedb8bc5c48163930d33a6ad8747f5d2a49a9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Ashgabat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 637,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22898687,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:205016ab50f3a20f3cdae2177d7e52df062d8fe6f9512adbece19c877575ec58\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Ashkhabad\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ashgabat\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Atyrau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1011,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22899160,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b8946a7b9d150a7179177c8ad06e98f1e283a3496116f4c258e14f16d256f737\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Baghdad\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 990,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22899769,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:21e1a6fad8d08e442b3f0ac5a30f8424f06207083a804d14dea2026432d0a80b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Bahrain\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 211,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22900378,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7bced891a18abd8ea443dd4f0c9d7dd40270fca879e9a116f573b9f73152d5e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Baku\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1255,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22900573,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aeb15bd0c24d68422bff995167cb959c7b060475f6b814cb25b76cd9bafc7b14\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Bangkok\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 206,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22901290,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2417678a4ccd8a6d6ee3cebc6eaadb5991cfaed89d1fee3a4c7f3166a0eb14f4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Barnaul\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1241,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22901493,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5d6b63755c1e59a9b18197b85b39ec174a26cbd578a76aed38f5d43483c3fac2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Beirut\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2175,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22902219,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:abdfa509ed982455873c1035962d8642ae8b88ab75f7f1a9a4cf7eea5ce120ef\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Bishkek\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1031,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22903399,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ea68d645187bc48c3a502d987750306c1c45660d889e2bc641c4f562726319c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Brunei\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 215,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22904019,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f08de1917e19626c3ff34c1cab734a420b3dd4ec3a3446df12b8960f9c7a420f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Calcutta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 312,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22904220,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c71d7bc10d52c64f59eae8eac701c1b156bbec3fd9fe750970bed15e9b408fa5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Chita\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1243,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22904515,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f01ce6d6e72d33ebd2982f99e1070a057a8a4991c60445bfe60fd0963ff4e7e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Choibalsan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 977,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22905226,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f8e8eb47d086dee4559a9db7cca2add3be302c98203b2fbb356e342c5978a480\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Chongqing\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Chungking\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Colombo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 399,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22905870,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:711f68dfe65cec6d99564f98f631d093bc2285e3829aeefea3692002eb45c6e4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Dacca\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 356,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22906154,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:829ff841289d431205ea745311f94fd3c32196a23d492f9f458617e0b5800c30\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Damascus\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2320,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22906436,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0f42d5702ee52944dde43071569de645a5d668a385c4a2e0cd8aa43d39d2ea21\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Dhaka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Dacca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Dili\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 239,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22907724,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8f845da70d08bcd62be5a9d0d80420b08936bfbe1e3012ed18fdcf90f152b91f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Dubai\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22907941,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ee6d427e4bc5e3d6d97b348d4b0cf666636d2ea95bcb117490d8d8ab0641f2ed\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Dushanbe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 607,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22908121,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:68f352f8356e69f25650cb2f25bc7ece7209ef85e73796ce974807136678f175\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Famagusta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2042,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22908539,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a3e66759c060ff5d9e338169781678161df5b9acd9aec6146f1d4d3cfd9030b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Gaza\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2295,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22909640,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a9df8fb70a5130a724e84221e63bb18cc84cf5c6c8788778bee070eb7330ea2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Harbin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Hebron\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2323,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22910928,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:93e1c96bff5d265217a68939ae160e86bbee16d96394d7c2b99589063435eea4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Ho_Chi_Minh\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 375,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22912197,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:23fb827e1435ea540aedbc7725a4ae82980205befe4aff833a0ad039dd14a73c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Hong_Kong\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Hongkong\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Hovd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 907,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22912525,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1561b7c3cc7a943046780584b726eaba320ccab4a46120b2c77af01dea9dfdf3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Irkutsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1262,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22913088,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:102019f46d5e031cbc28520b08c080de899f5b1cadf93590787c1719e5a9dc4f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Istanbul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Turkey\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Jakarta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 392,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22913851,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ea1c3e53a0d3f40cb6d7724f1bacb4fca1cf0ae96d9ab42f00f2d30dc0dee3a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Jayapura\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 251,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22914145,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c6fa24de2e83f471878b8e10ecd68828eb3aba1f49ce462dac7721661386eb0c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Jerusalem\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Israel\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Kabul\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 215,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22914400,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2df091b8e1752a8c8d402b12037977392347626a34c8f011f179ede4079ded1b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Kamchatka\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1184,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22914607,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c5d9b980d12e91cfea342560702708c488aabe957c1fc2b7afc6c996518bef33\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Karachi\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 417,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22915300,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc4b2a68ad79efadecf52f333fa19cbaa5dd084cdc9bf96ab8b65a75c559a370\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Kashgar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22915608,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f582157ddba6cf2bf93e8cd57ecd61318e9faa7fff2abbd0e2e7897690373587\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Kathmandu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 224,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22915789,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b7d597ba6228a77823c20d3b48f343ad78843ee888b1b17a40b05ffcc0da3913\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Katmandu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Kathmandu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Khandyga\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1297,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22916034,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:762a1f42993920d6475e1ef40b46ab6dbc65b6f48ea9537387ce418929c21a3b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Kolkata\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Calcutta\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Krasnoyarsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1229,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22916824,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ec5d6603322f8e1a0d7e5d7a1cf798b66e5def66b2ae79bbc8c961e976ad4a6b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Kuala_Lumpur\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 410,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22917526,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:521d864f401ae2eae2e9f0292aeecf38d2d6daf3e12b442795ee696e629f3700\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Kuching\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 507,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22917820,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b4cb8160273db177c6ddb669dd648162730ef1a1b62d60abff510e37444628e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Kuwait\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aden\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Macao\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 771,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22918221,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c2b8cdca155a78c7ae34ca5c30185713c60b2496b01cfd31f998bb6bda16f3ce\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Macau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Macao\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Magadan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1244,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22918757,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d6f81d26a42303d75910f98033f0fc147eed23c574b016995fa002f5075a3fd6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Makassar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 288,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22919466,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:24fac901695ef43b73fa8b3cd9e4bf893ceb757c5200b6628ae6a0fc70f01956\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Manila\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 353,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22919696,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1f1bc3dd4bac8e3da2ad11709b6882359c9821caced28b545d1b738524f3419b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Muscat\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Dubai\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Nicosia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2016,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22920037,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2aa2a3f77a43b7558a7508a6cd6c50fdf7d991f9d64da5948fd9003923b1d72\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Novokuznetsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1183,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22921136,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ad7f74c0ace0cee04470ceb51df7f58321e23a002f3d3ac64ca0e889b3ab698c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Novosibirsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1241,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22921832,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc386ed4132a37957acfba6984468588a1e9ff08e24bd5c15bf27ccba8a15a0b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Omsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1229,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22922553,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:abaab5e651101ef99c5425ac184efc1b5d778d4c4c3c86aa894d9059dbe951b6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Oral\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1025,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22923251,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eacbd3df5ab43997cf2396786dc819f12461e61de06dd829ee8c8fa76baf7886\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Phnom_Penh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangkok\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Pontianak\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 395,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22923912,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2516ac2bc84fe6498a50bc8865ec00e3499b38f2f485403cd5028578a98d1fd8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Pyongyang\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 267,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22924204,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:40434acc1dc1ac05a9ff3d3bb12448629ca45f7a415f03eb4b13f5416061d299\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Qatar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bahrain\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Qyzylorda\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1033,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22924470,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4530cb2e704a356eaa4aadcbf12e5faafd411ffe3210bd83ed3370d6876e8182\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Rangoon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 283,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22925083,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:95329208ae33f6298dbecd3309e6c397f4a0a42fd3bc214a87a3cbd6278c5752\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Riyadh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aden\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Saigon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ho_Chi_Minh\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Sakhalin\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1220,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22925387,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:597a4d79d7ad4b2ecae1c5dbe53a19716cf30cfccd4fa7452c9e9822ca23ca03\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Samarkand\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 605,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22926102,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:716675c5cb21a2ce4a48b9ce438744a501828079b06c80ce99a7dead0eeb2dc9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Seoul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../ROK\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Shanghai\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Singapore\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Singapore\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Srednekolymsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1230,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22926617,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:84c8f7ebdb10b6720a01a11198c8b1fa1d1856f1bef11473d2c9a33b97f812a6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Taipei\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../ROC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Tashkent\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 621,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22927354,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1cce3ce8c9cb736d9163691f4b6fabd2d2e076c7a209621a57bbc207973a8ef3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Tbilisi\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1066,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22927779,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b3da0a88ac9d5cf61c1e42ca1a941b36d83ecff5e9f819f80876512ddb07e0f1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Tehran\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Iran\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Tel_Aviv\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Israel\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Thimbu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 215,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22928487,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3912ba10af951b2d81f680dee0f89507c14cd7f38bcb9e55a87db48aaed01ab4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Thimphu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Thimbu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Tokyo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Japan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Tomsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1241,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22928752,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b41e5deff2d573ef6e76cf17e0f91ab467576d584b8e5ff5eba01e10f5dee92d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Ujung_Pandang\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Makassar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Ulaanbaatar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 907,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22929528,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa2c8bbf2b6133470875236c95cbea9d75d369475cdb64ec3098781ae89ffe15\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Ulan_Bator\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ulaanbaatar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Urumqi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Kashgar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Ust-Nera\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1276,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22930166,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3711785086a9e0d04a87c1591be40b3a0cd944ea3907182b6b45f6fceb0e024c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Vientiane\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangkok\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Vladivostok\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1230,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22930941,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b86847acf51b50e5286e87efecf44cb0f2ea26735a6c9810623a814c4f69899\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Yakutsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1229,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22931636,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:350cb7d4232de1e621e9363412b75a161053bcc6510401b13cdd2405ddc867ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Yangon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Rangoon\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Yekaterinburg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1267,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22932381,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d36b87b5bbe9787ec26cecca1e9c2446c4126011ea2ae570b59138468f3f2f56\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Asia/Yerevan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1199,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22933097,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c595907a2d221300674badfb7c157198f862936331bc44bcfd6fb22ba953d05a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Azores\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3479,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22933829,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c05864219d3fde7b5d5865bd1433a09f59a08da3980eb550666fdabf99634147\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Bermuda\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2004,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22935633,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:462d205904f32dcb79317f83ddb4dea1548d51849217dc3e42ba17c3cc7fcf08\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Canary\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1911,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22936737,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4617cb1aa75514003f181908e9ccfc1d3d062ef22bb0196867dbe530ec2e1416\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Cape_Verde\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 270,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22937762,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0cf879a38c3443ff0cba02040a778ec7d07971ac3b43943f1e205c77afdd05bc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Faeroe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1829,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22937992,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6b1a5769f8ffa2ec29bf298dffd7fb324e625e36fc527c14bb66b6520e6f76a7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Faroe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Faeroe\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Jan_Mayen\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Arctic/Longyearbyen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Madeira\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3484,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22939064,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:24c616780589fb6a7e22913e3402522517ba4a7460738ccd38f1a3a0e4a21f40\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Reykjavik\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Iceland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/South_Georgia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 150,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22940919,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:64868e0ba919bae24ad2bd06290aef6200296c282cbc74d2d814a07a5e9342a0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/St_Helena\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Atlantic/Stanley\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1237,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22941164,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:53a20741ef1ef47a19fc9c192da23e9a0cf08c3f3b1fd72673d023dce0281890\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/ACT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2223,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22941936,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b540f8e21ed6a6b262336e0eb020c18ab43f283e9774613dd9864239523e4233\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Adelaide\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2238,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22943116,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:735476eef81652d7189574f8b7a11c942a986aba24b6ddc644fbebd1eb49245c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Brisbane\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 452,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22944338,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:74ac9f5d1d15ef0f6bd9e69c687b9047fb1f749c59279475685721f574b427cc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Broken_Hill\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2274,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22944684,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d6451675d3b5afb8572e2cbb4d381730da23daa3bfcb57601fe6f815985237db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Canberra\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Currie\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2223,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22945977,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:543c7afaebfdd907f8d637efce48bf41c407da72658b8e9c12f7208a54d1d84a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Darwin\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 323,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22947148,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6172d8687a78608d884b04903d36053bdfb56433541930b2a42b405cbb62dc0b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Eucla\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 489,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22947450,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:73e13a985c1612b5881e45564bdf93c8f35a30298ee563dcf50d1cc35bf76a44\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Hobart\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2335,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22947817,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:de1bb5e82f86774e70082b906462e02a062238e5c4d76149566e21b1cb31b23a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/LHI\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1875,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22949038,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3d35779f2c81370c90f29ba92693a409a094d84d9f236cccda8438d063fb6e5f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Lindeman\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 522,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22950087,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:663df35f044a15c743b9716e183595147d0c1838e99148a9473623ac82076bf9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Lord_Howe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"LHI\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Melbourne\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2223,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22950514,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:272c1f13d01e35e6a58855cbb53878795451928adbf0c8ca2982b79db1f450a7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/NSW\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/North\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Darwin\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Perth\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 479,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22951747,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4ecd4a085ca9ec5b7903016c2d4e311276024a2bcd0c35d40281658e48421f93\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Queensland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Brisbane\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/South\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Adelaide\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Sydney\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Tasmania\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Hobart\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Victoria\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Melbourne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/West\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Perth\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Australia/Yancowinna\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Broken_Hill\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Brazil/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Brazil/Acre\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Porto_Acre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Brazil/DeNoronha\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Noronha\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Brazil/East\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Sao_Paulo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Brazil/West\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Manaus\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/CET\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2102,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22952449,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3c0029045f6f80bc5a84f1bb8ed36230454759c54578eb9a8c195d14f442213c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/CST6CDT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2294,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22953547,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:44e8b569e60027647f9801a33d0b43be0106a6d3f6cd059677e0ed65c9b8b831\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Canada/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Canada/Atlantic\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Halifax\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Canada/Central\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Winnipeg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Canada/Eastern\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Montreal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Canada/Mountain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Edmonton\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Canada/Newfoundland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/St_Johns\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Canada/Pacific\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Vancouver\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Canada/Saskatchewan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Regina\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Canada/Yukon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Whitehorse\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Chile/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Chile/Continental\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Santiago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Chile/EasterIsland\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2228,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22955143,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c0632af9cba4869ddc8dbfdd78fdc6094d751d0e1d54564e380bad0ff6cbcaf7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Cuba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2437,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22956340,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7871f875a8819f415c292519db1590556a0dc1a6ce691bf4f7af55e6716fb894\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/EET\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1876,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22957640,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0bf6d2669ab45c13a1c9be47c351972feb671770b90a61d9d313fc60b721b2b4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/EST\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 127,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22958639,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c9e75f112a498ff00344551c3c5c4a62bd15d5c218ee951f4363ab218c5d88eb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/EST5EDT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2294,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22958790,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:79ce27e03a2752091e8a49cc7e7ccc9ac202d6c52dd5d224571fe82262fbeec8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Egypt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1972,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22960019,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:279bbe1fa62da67387c63593b60bb655252ef5c8f189cf43469087740af2b4fc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Eire\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3531,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22961121,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:44bdc5d63e5b1663867491cc0d30b81820fc8694ad0fd5ef500ba8ac6b7fba5f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22963015,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f549f85e4a86989da1b3c592cd455d6846f8103c2c1c7c7d193b3e29de92efc9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+10\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22963173,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b331f62b7c4dd05398fe87517e824152a0faa3ffe80d73e3f1b2bab03e16c99\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+11\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22963331,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3be86f06310b626b26b42bee3b8ba37be7b836927e204fa7b84e35758e99dce1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+12\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22963489,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bb3cf7591690fd770967c92719c1ba023f62a7e40de886f89f57178b0faaf616\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+2\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22963644,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ae3b221ddd94a88c94c3a069b042c1b06d2718b5bbe6903724110103621e40c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22963799,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6cdb1f7a18e6008da4e9a72ac9c2be59a26bc03109700b3ec64e4ed8161660db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+4\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22963956,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b4c86cac6e9f40dfdbec05b88a38eea2463fe92f1fff80a6e24ff15a9814218f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+5\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22964113,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a6653c6b0ba94d0c0bd4b8a6f4c69d001db916f93c0723b9c9fcbbaa34bba098\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+6\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22964270,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c4a801cd93bdec1b9341b334868ef1ccaeb01b74a31a9f5bb1f1da90ea985789\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+7\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22964427,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9456c866abdf01fde371357edb5ec59d0c5adc3c09ed9d2bbafd0be21807adad\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+8\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22964584,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7084ca1e2d9a7349e0556d8c63107fdc64cb5d50778cc74b4b9ea3d2ca1eeb43\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT+9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22964740,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:847ded37313ae7de90d5dec700acf7d229ad88cc7462e9527ac5bb37cd2c00ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22964928,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:355d77cdeed83884c287b29454078b89865d4e56508dd71e8597c8c038029ade\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-10\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 131,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22965086,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4653c5c305ed3a46ac02c471feb310f356ed6c8d2465fd37e555132b0004899c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-11\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 131,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22965245,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b65fdb39373fa4c47b1e6a2105931e5459fdceaa74194ea737dd981527e5a1a5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-12\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 131,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22965404,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f67b770d0224c9dbf776e8bc913c0dc462af7eb90f04b88b7387af662c248545\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-13\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 131,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22965561,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:551aebd6c58a89bbc34283170a01c5de12d98ca658aee39f68e8ed7cf11dd872\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-14\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 131,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22965720,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:414d785a776406dce6ccf450aa2ae48c4d3e4db23482ac3cc285567c0624b33f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-2\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22965878,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6a4f02622392c0c01ad74aacdd1d9835949b10084b6ff3494ca593871fa36279\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22966033,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2331d90cf59bd06209da3f57fe71f8eeff4f9987cda8f209f7d19605173c7940\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-4\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22966190,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3d1d2a77c8fc7121113f50455ab5ecf7a83af5d100b1665c069ad2283beedd05\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-5\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22966347,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a998fef5ca21deb83d7b6801cecb36f851af7d09e45b23f1a8e1cab037c94cd2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-6\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22966504,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:59a432b594fd6a1775aaf1798ffded3e325481040786cf56500d61194d156b1d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-7\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22966661,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6b8fd7cee7b9e0ac90f11617a6e4f0c68cda81a2153a0b37a46a3516f94c3e1a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-8\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22966818,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:47625566b0b8e5476810ac5fe4882586ec53793d4f53ed281702a220eee7d554\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT-9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22966975,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2f4662e616bd94e9eb6a2ed069f01bdf316b3e2c39c3b945e5397a53e26d16c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/GMT0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/Greenwich\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/UCT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UCT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/UTC\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/Universal\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Etc/Zulu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Amsterdam\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2949,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22967288,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a813ac6b8d1b68a7960242cae5325a2269fd1c791b203f8d22f2dfa3b61ba87\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Andorra\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1751,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22968805,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:add5505c473225e33a884a02105610a9b95003f429195624b953c18f771317af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Astrakhan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1183,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22969765,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:08873fa11e5ab238e56d7a2fbbfb0876aa3ea0b71ee8ce95b0d5d394be923514\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Athens\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2271,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22970465,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:799090551202c0b8417f836facf75049573dd1c27b5e6adeb584fcc414051139\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Belfast\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Belgrade\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1957,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22971711,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e957543623baaba84999b40188e7e0948471b75a8ff4f88abb267e773feb8e5c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Berlin\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2335,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22972765,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7eb93dcba603d528fdf536160ef6911c16f834afcf88ce23a382b97ff28319d4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Bratislava\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2338,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22973995,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a50be470a22de9def3e4fec7bcd95d5d7e24e5b11edf448a82b04d19da3d3e52\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Brussels\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2970,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22975270,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f372a903a6a57da43a6f500d6aceccfc74e800d7dfe88a7eaf56ca2564557e66\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Bucharest\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2221,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22976855,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3b3a0017333b2f466e59c8ac3dc0cf7aa4f0a4608040a3180f752b19d6a93526\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Budapest\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2405,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22978053,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b67f2c4690a87f294ea5d35ae3967c8aa8bde227aeb36c3877285e4e94a17418\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Busingen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1918,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22979324,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bc45f8c6c8190477cdaae46f77059fab74fde92a02fc57b733f07cb9a55e98a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Chisinau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2445,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22980397,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5749f01c78d0c2fd50d0dc2280c1957ce0419edbfc7c4073c67e6da78153d8c8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Copenhagen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2160,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22981687,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d2d9a359ef02d2afe293f429c4fd60fc04fbf8d1d8343c9b224dcfc116c011a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Dublin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Eire\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Gibraltar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3061,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22982916,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c79088f67ba5d3fa9ad989bd573bfdef0e86c89e310ea70bc3e01e14dca1075e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Guernsey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Helsinki\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1909,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22984560,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ed7d89fae1fb40a9582edd7e03ed02d7fe81ba456b9c1ed8d6ee5f0b931aad45\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Isle_of_Man\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Istanbul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Turkey\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Jersey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Kaliningrad\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1518,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22985701,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:450a2c6ff69d262b5c5d8ef584464e9c8274b389a1c39b7abc5aa70608d29425\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Kiev\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2097,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22986542,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:242912df3212e0725ded4aab25fd869c52f13c3ce619764a883adcbbd937afc5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Kirov\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1153,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22987671,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d562c884fcbbde25ad884da464c7f981296c2c4e13b3b7c1d3c322b82bd4f726\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Lisbon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Portugal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Ljubljana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/London\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Luxembourg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2974,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22988462,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:90b76259274c78a40f34aa5b58545b5409edfbba2fd08efa1b300896cb4062ee\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Madrid\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2637,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22989991,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:74103ad1e48f71f4cd9b6d1c03dcd97b58d87bb8affb02b1d6967b204036ebd6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Malta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2629,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22991364,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c4134c8d37bd159e31fd739e8b1b8203a9f3023788bd9c83b8109e361eee5d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Mariehamn\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Helsinki\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Minsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1356,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22992812,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d0535cb101110d8fbb1238dde8444e980fab90bbdc8402371cc6ab5caa1a96c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Monaco\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2953,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22993582,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c723359888417b86a66a609ffdd0becf81673cbb3e8b011131088b4d26f6bcd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Moscow\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../W-SU\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Nicosia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Asia/Nicosia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Oslo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Arctic/Longyearbyen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Paris\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2971,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22995220,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:735b08e2737de2b47e79f596f3574b5a9e9019e56d2ead0cdc17c0b29e84a585\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Podgorica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Prague\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bratislava\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Riga\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2235,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22996819,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:79d10debbaa2743458d0dec1fb71d3c576cea80d245f84819da82a25d93c1401\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Rome\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2692,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22998013,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3eff2ef2cdc67e2f5cfd44866cdb4d448956b89eae8b0e37f63126f2068ee889\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Samara\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1239,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 22999495,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:24506ef1ada9839602c5d6589f46c16ba427e1e310c473f0ec77f4436b973185\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/San_Marino\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Rome\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Sarajevo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Saratov\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1183,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23000281,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4ad0f06f89a5b7ef2abd7d249300cd31328bfed591f3a6a7acede6bb8c0b7977\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Simferopol\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1490,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23000978,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b1ee6f714fd88fd61fef6df54f95abacb80dd3036c25e9a10708fec9b11c34cf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Skopje\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Sofia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2130,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23001878,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:16813fb30f2ebb782a806ce0664014ddfbf921890d32ec3d1398bd182bf9245c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Stockholm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1918,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23003096,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:07b242f9e3d8150663bfaf417fe7d209927fc299fac487789b70841956c35335\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Tallinn\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2187,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23004161,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3c4ba916c25500c709c56395c040abad62a834fafaf5163a89974b7f66b019a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Tirane\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2098,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23005327,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:62dbc606a32a5f50ceca86c6f96d088ea689bced60a1623c986f045cde9c730a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Tiraspol\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Chisinau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Ulyanovsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1267,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23006502,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d96c23e54ab8bcae4174fe792f1c00e4158f81a5b98039121e6502ce6686716\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Uzhgorod\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2103,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23007229,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:098575b4ec6599758c85bcad8dd21d89bca213a9f890c0ead6defd14878705f3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Vaduz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Busingen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Vatican\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Rome\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Vienna\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2237,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23008430,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:be42c32ad7c54f15dcf5dd9425e289fd20bebe986e5e8c240a11dfeec46550f7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Vilnius\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2199,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23009609,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:75adc0a906b39e283f5e5020984a36f34b4f58ef1d3099efbc899ff07f035f7e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Volgograd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1153,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23010776,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b826a3d9cdffa786e46da2315977f13cac9ce01e4b214415f3362505b97fdd1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Warsaw\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Poland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Zagreb\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Zaporozhye\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2115,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23011522,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b6c5127b52518818e3b4211e89e5e1e9a479cca65f7763a0afb145d512c38e34\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Europe/Zurich\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Busingen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Factory\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 129,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23012709,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ce4929e887a3f9f403d15e734f7798028addf502e767e7da09b8c837e7bd9bbd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/GB\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3687,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23012854,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b14c486019e3cb259cf8235a0d6a4bc3ff6cfa726a165f1ea2df403c8ae31b86\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/GB-Eire\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/GMT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 127,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23014784,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d7b39879094135d13efd282937690b43f48bb53597ce3e78697f48dcceaeb3ec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/GMT+0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/GMT-0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/GMT0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Greenwich\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/HST\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 128,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23015004,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:44048bf7df61bdcf45972c13426b039f0d34d80947d60a2603183b3b6be4027f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Hongkong\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1189,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23015158,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9786fbe4ad9b820f61a5664b3b85dd601aa6e9152c93ff4e14bd54effdf8f1d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Iceland\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1188,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23015865,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9cdcea6aa1eed8276d3f6620e0c0ffae9cfcc3722c443ea6ba39147975eafaa3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Antananarivo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Chagos\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 211,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23016657,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1b1797b71359a3a9fd49683dd9028692c20b4c9b56088c50de6ae122f075f3d1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Christmas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 151,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23016859,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:720ed3c1a13aa4e6b4a9acb7c6f017a5e28e20507169ce1b3ec25075c98be656\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Cocos\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 160,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23017045,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b78aea130d938147f36de61341c44388915da43f467f3723c98dcc3d8b808884\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Comoro\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Kerguelen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23017295,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:29bc1cca3de7cf37433fcee5ec99d490abf20c767f284d5bb40a15feac0ad398\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Mahe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23017469,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aed7dcefc4d7a4659ef1a62e56d1dd6f21cf0e9cea7a1089a94ac1d48113d5fe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Maldives\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 206,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23017651,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:49fa18af1a1c531f2a63bffc82e4cba7c53f4e587376f453c97084d605d4a9f1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Mauritius\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 253,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23017858,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:25c927943cddfb96e41b9bfa014791a9375f8cb77e672f42d72fc81d83607f0c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Mayotte\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Indian/Reunion\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23018144,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:263f52802a6b69445a66bb8d75a4ca3dfe717ce6512d7e2501466e7a1b6d56a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Iran\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1704,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23018313,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:19084f9dda0e334eb24bd8ff70daedffefd64c537cb27e5a54c5df7694c534d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Israel\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2265,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23019248,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:60019ee0d1deb6e6994a1a5c951861e1db9f992a5c027fbc4e3617f942c021cf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Jamaica\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 507,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23020475,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:addb98caf3459bb75d6e14ed76aa66e642bead2d067e7fe81814a4f02cf13503\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Japan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 318,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23020841,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4d598cea3fe55b44afbd9c6f603f748960e4a9806e1ea1e87fc2f2bb98214377\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Kwajalein\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 245,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23021102,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:728eed0b199aa19468fe7f1dd887fe7f0c3a659a897741aa6e2d4f5b80f75eb5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Libya\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 655,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23021318,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8ff53f7072863fb56f1e71339392b6de7e50675efa4333b9e032b677c9c9a527\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/MET\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2102,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23021774,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1fff331a4414e98097d33bec1a9bbf2a155d991b57acd1bb4c11f8559fb4e514\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/MST\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 127,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23022868,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f8fb610056087bb3ca8ecf5cdcb5305c1652b649fde512f606b9ee1b3556fb9e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/MST7MDT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2294,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23023019,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:85452d031526621178e9b24c91af69b7ecc30df47036669378956135c4e735d0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Mexico/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Mexico/BajaNorte\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Mexico/BajaSur\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Mazatlan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Mexico/General\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Mexico_City\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/NZ\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2460,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23024405,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d7b5175387ac78e29f7b9021e411512756be283ed3d1819942ef5d45ecf338e4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/NZ-CHAT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2073,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23025679,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b8f1a26d43eeecaf8302456d69fdf047b847b6973069804c5a39f8ecb886d74c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Navajo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2453,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23026786,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f4df3cc74c79d070a25a7927744d3a422a05d862a9a234a12105c5c964efb22d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/PRC\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 414,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23028092,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:953622bbd7eb9eba8c3b9e8cd5d5ec98cea6a085a9deb1c43e49e889a154d344\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/PST8PDT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2294,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23028413,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4d8e69bd43e8d71f0f58e115593814d68c1a6aa441255b17b3e9a92a9d6efc46\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Apia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1120,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23029687,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:171011084ad201170e51b42435679a50bab661ff6114ca09a764e822f13f45db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Auckland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Bougainville\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 282,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23030404,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:35e0203bf554d7ccf0b4e0176829aa342747427924ae9e9b661e484205e828e2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Chatham\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ-CHAT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Chuuk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 152,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23030725,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6efbcffeaffabb8b91c03e12dd02707f3b2f12ed6c4583ede4d8d6b72721c4fc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Easter\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Chile/EasterIsland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Efate\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 478,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23030964,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:adbee8a8544a400050d7dce148e2c10a785b9120c755a69a674395b04c36092e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Enderbury\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 245,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23031328,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dab23f777b9cb06d602bcd5de7670da9191830816d802041846132e137f7eae6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Fakaofo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 207,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23031556,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0427f848089402d7105907710ec0a9096365b10d1dd3ee015edc5da527e1c3de\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Fiji\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1076,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23031762,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7281ebcc865b2c2712ac51b6f4654543a99ddce68ad42ea7bca0105b825e3a94\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Funafuti\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 152,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23032435,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7fae086ba7234a7684b22e8948faec02be41bb76b3944213206d1857b049ba1a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Galapagos\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 254,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23032625,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c91721b38d5ee01676190b91cf5150050b3fed2ad4634816724f8207d69877be\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Gambier\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 172,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23032851,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5008ae162414c442be54580de29eb211a9f652f8eda265f038a6a82eddd5e5d2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Guadalcanal\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 174,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23033038,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69ec8cb3bd0e92db41f2d7b9ffcdd1881d0f7b7ee6048d3f092ad17cc686e5a5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Guam\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 225,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23033218,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6613576ebdf4d9d6be5eb849539d3f74a4fb137acf6bcf8cda20d28e5c612e77\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Honolulu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 276,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23033439,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:88885824bf915a9a6f39a7030798da825e34be79d1b35c2444696a81c159f2e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Johnston\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Kiritimati\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 249,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23033735,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:43d21c8bf4a0547479d1512db27d5dd7d8b2db69ee232680a88863c3e446bd42\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Kosrae\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 237,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23033959,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dd24709003b34eca2e8975694b370b5892dc8a1560892e42fa5c3a9669dc00b9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Kwajalein\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Kwajalein\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Majuro\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 207,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23034217,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2784fe14ae4b06d84b54e2ef9195ee8fcd33a1151ae9d92b2b144ed80324c4ec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Marquesas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 181,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23034425,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1c151ea927de5f087bab64d962d1bf4c8af0672fb66dab9eb63e93c5c0ce906\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Midway\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 196,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23034611,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7218a2ae386cd5e8981a940f6b56f6f9b60a65f3e3bd2ec1fe6c9d43bac4db1a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Nauru\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 268,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23034809,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8eabc930825033369d3dd4d85d1cab23b40c0214c91a3a2cac6547a2d549b8c2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Niue\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 252,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23035038,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c7247452c2c61010dfc417d172e4f4cf955feefd89b9649fa08e51832d9ed708\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Norfolk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 309,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23035264,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5007254c619ebc6200e235c5aaa3b66eec80e9052d00ba63d84bce6c5408c755\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Noumea\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 314,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23035517,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:47834b191dcb3a4e4f0cb3e6c375ff66c07e609382be7d2c21e0c4d854008dca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Pago_Pago\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Palau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 151,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23035811,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d1a61b4bffd5b61eac5d9ef0a7f10a80ffc1d027a9330e7ad89278a3f3857357\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Pitcairn\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 209,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23036001,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:97a89892a57db71698c25c9ae2bb8cd6436e239988b3bbb5e028fd9b0c233224\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Pohnpei\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 152,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23036208,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9360c42536001cdbe62e033e03b1766ac3dc7315966c31166f86a4e9aafa4567\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Ponape\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Pohnpei\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Port_Moresby\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 174,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23036442,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9c505d421d2cfc45dab9819b6abdf1d9c616d63feab9ec1c22db149b192cdd3f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Rarotonga\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 588,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23036648,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b309575c63dbf5a1a8e499105cfc7b51dbba38302571e4a51d861a3f46eadbc3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Saipan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Guam\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Samoa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Tahiti\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23037129,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b908353b2b5ba977afe11a11c088376c816dd4b7f71358db6b95b060f51b637\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Tarawa\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 152,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23037313,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5c0324994691766186531137a292759ef788a558273a13c7617f3c373b4426ec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Tongatapu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 379,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23037503,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a742868cd652d1ccd0bd219406bc09db1063c057dc2fdc05b3ff96e81b314da\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Truk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Chuuk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Wake\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 152,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23037834,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7d63ddb8dbd42baa9bf4fd136ad3be2612db4402fd498d67ebcfcb93eb42dd6a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Wallis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 152,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23038022,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:25cfc2e1a664e96e86dc7e9bcf754bd5b8608ddf7673ffa407e4a762e309ecf5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Pacific/Yap\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Chuuk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Poland\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2705,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23038247,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:68e7493c1ca050e4134062a74aa4a4fc32159c042b4c9d8d40c8bfc9d273c5fa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Portugal\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3469,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23039667,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4bbe65d4ff3394ffa1b4ae6fe2296e333f55bad0ae49ca6717b6076e53490ea2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/ROC\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 790,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23041447,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:25cfd02bc847bdcb11e586445ba886a76315f1f9be86f7e74944a6e8e8644543\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/ROK\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 531,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23041946,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:22de94642a978a6af463db175e9f93a3292e8a81a74a8b92989bc2174379edd6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Singapore\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 410,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23042328,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1b4684d9bb6ec48169abb530da58b8cb238b785bb5ffeb5e06e50f1b2b9d60e0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/AST4\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Puerto_Rico\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/AST4ADT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Halifax\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/CST6\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Regina\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/CST6CDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Chicago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/EST5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Cayman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/EST5EDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../posixrules\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/HST10\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/MST7\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Phoenix\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/MST7MDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/PST8\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Pitcairn\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/PST8PDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/YST9\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Gambier\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/SystemV/YST9YDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Anchorage\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Turkey\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2152,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23042976,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2a694b73d6e78b3e9d3a94e1bc44c410bc306a360d7eebfabf8fd95c753760a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/UCT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 127,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23044141,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b3b762863cac2569aa33f7da192584afd9965ceeb7263fed4ad87c1b35e4c7d8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Alaska\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Anchorage\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Aleutian\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Adak\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Arizona\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Phoenix\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Central\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Chicago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/East-Indiana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Eastern\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../posixrules\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Hawaii\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Indiana-Starke\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Knox_IN\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Michigan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Detroit\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Mountain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Pacific\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Pacific-New\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/US/Samoa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/UTC\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 127,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23044644,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3c71b358be81e13b1c24e199a119fd001dbcdb90edc7d44c2c7ae175321a0215\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Universal\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/W-SU\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1544,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23044828,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:02d55516d0f9d497998260b4f129aee59867b77a920ba2ca0c58b15ec8588e7a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/WET\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1873,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23045683,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e5e7c4631295e7f17085e3530f99fc2984cc7e4bdb9a07db7702de8c18c2aab1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/Zulu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/iso3166.tab\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4445,\n\t\t\t\"modtime\": \"2017-02-28T16:08:12Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23046733,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fe8bd1792c0e7ec6b42507c58a3ba433ebddadbf4c3031eaca6da9c41def37d2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/leap-seconds.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10666,\n\t\t\t\"modtime\": \"2018-01-15T17:19:18Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23049504,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6255ce742f8189384c18dceb92ecf7639d49c480c4dc83c770e95a6f3bbdef1c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/localtime\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"/etc/localtime\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Abidjan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Accra\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Accra\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Addis_Ababa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Algiers\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Algiers\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Asmara\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Asmera\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Bamako\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Bangui\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Banjul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Bissau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bissau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Blantyre\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Brazzaville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Bujumbura\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Cairo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Egypt\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Casablanca\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Casablanca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Ceuta\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Ceuta\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Conakry\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Dakar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Dar_es_Salaam\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Djibouti\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Douala\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/El_Aaiun\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/El_Aaiun\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Freetown\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Gaborone\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Harare\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Johannesburg\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Johannesburg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Juba\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Juba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Kampala\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Khartoum\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Khartoum\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Kigali\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Kinshasa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Lagos\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Libreville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Lome\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Luanda\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Lubumbashi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Lusaka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Malabo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Maputo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Maseru\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Johannesburg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Mbabane\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Johannesburg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Mogadishu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Monrovia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Monrovia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Nairobi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Ndjamena\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Ndjamena\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Niamey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Nouakchott\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Ouagadougou\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Porto-Novo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Sao_Tome\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Sao_Tome\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Timbuktu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Tripoli\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Libya\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Tunis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Tunis\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Africa/Windhoek\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Windhoek\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Adak\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Adak\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Anchorage\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anchorage\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Anguilla\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Antigua\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Araguaina\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Araguaina\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/Buenos_Aires\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Buenos_Aires\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/Catamarca\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Catamarca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/ComodRivadavia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Catamarca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/Cordoba\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Cordoba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/Jujuy\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Jujuy\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/La_Rioja\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Argentina/La_Rioja\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/Mendoza\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Mendoza\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/Rio_Gallegos\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Argentina/Rio_Gallegos\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/Salta\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Argentina/Salta\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/San_Juan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Argentina/San_Juan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/San_Luis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Argentina/San_Luis\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/Tucuman\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Argentina/Tucuman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Argentina/Ushuaia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Argentina/Ushuaia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Aruba\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Asuncion\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Asuncion\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Atikokan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Atikokan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Atka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Adak\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Bahia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Bahia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Bahia_Banderas\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Bahia_Banderas\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Barbados\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Barbados\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Belem\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Belem\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Belize\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Belize\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Blanc-Sablon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Blanc-Sablon\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Boa_Vista\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Boa_Vista\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Bogota\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Bogota\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Boise\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Boise\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Buenos_Aires\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Buenos_Aires\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Cambridge_Bay\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Cambridge_Bay\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Campo_Grande\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Campo_Grande\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Cancun\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Cancun\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Caracas\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Caracas\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Catamarca\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Catamarca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Cayenne\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Cayenne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Cayman\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Cayman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Chicago\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Chicago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Chihuahua\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Chihuahua\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Coral_Harbour\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Atikokan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Cordoba\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Cordoba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Costa_Rica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Costa_Rica\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Creston\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Creston\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Cuiaba\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Cuiaba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Curacao\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Danmarkshavn\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Danmarkshavn\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Dawson\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Dawson\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Dawson_Creek\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Dawson_Creek\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Denver\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Detroit\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Detroit\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Dominica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Edmonton\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Edmonton\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Eirunepe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Eirunepe\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/El_Salvador\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/El_Salvador\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Ensenada\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Fort_Nelson\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Fort_Nelson\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Fort_Wayne\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Fortaleza\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Fortaleza\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Glace_Bay\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Glace_Bay\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Godthab\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Godthab\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Goose_Bay\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Goose_Bay\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Grand_Turk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Grand_Turk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Grenada\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Guadeloupe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Guatemala\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Guatemala\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Guayaquil\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Guayaquil\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Guyana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Guyana\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Halifax\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Halifax\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Havana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Cuba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Hermosillo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Hermosillo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indiana/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indiana/Indianapolis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indiana/Knox\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Knox_IN\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indiana/Marengo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Indiana/Marengo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indiana/Petersburg\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Indiana/Petersburg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indiana/Tell_City\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Indiana/Tell_City\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indiana/Vevay\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Indiana/Vevay\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indiana/Vincennes\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Indiana/Vincennes\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indiana/Winamac\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Indiana/Winamac\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Indianapolis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Inuvik\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Inuvik\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Iqaluit\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Iqaluit\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Jamaica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Jamaica\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Jujuy\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Jujuy\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Juneau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Juneau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Kentucky/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Kentucky/Louisville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Louisville\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Kentucky/Monticello\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/Kentucky/Monticello\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Knox_IN\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Knox_IN\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Kralendijk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/La_Paz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/La_Paz\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Lima\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Lima\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Los_Angeles\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Louisville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Louisville\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Lower_Princes\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Maceio\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Maceio\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Managua\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Managua\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Manaus\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Manaus\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Marigot\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Martinique\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Martinique\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Matamoros\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Matamoros\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Mazatlan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Mazatlan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Mendoza\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Mendoza\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Menominee\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Menominee\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Merida\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Merida\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Metlakatla\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Metlakatla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Mexico_City\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Mexico_City\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Miquelon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Miquelon\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Moncton\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Moncton\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Monterrey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Monterrey\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Montevideo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Montevideo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Montreal\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Montreal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Montserrat\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Nassau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Nassau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/New_York\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../posixrules\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Nipigon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Nipigon\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Nome\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Nome\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Noronha\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Noronha\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/North_Dakota/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/North_Dakota/Beulah\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/North_Dakota/Beulah\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/North_Dakota/Center\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/North_Dakota/Center\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/North_Dakota/New_Salem\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../../America/North_Dakota/New_Salem\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Ojinaga\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Ojinaga\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Panama\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Cayman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Pangnirtung\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Pangnirtung\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Paramaribo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Paramaribo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Phoenix\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Phoenix\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Port-au-Prince\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Port-au-Prince\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Port_of_Spain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Porto_Acre\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Porto_Acre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Porto_Velho\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Porto_Velho\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Puerto_Rico\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Puerto_Rico\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Punta_Arenas\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Punta_Arenas\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Rainy_River\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Rainy_River\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Rankin_Inlet\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Rankin_Inlet\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Recife\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Recife\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Regina\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Regina\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Resolute\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Resolute\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Rio_Branco\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Porto_Acre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Rosario\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Cordoba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Santa_Isabel\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Santarem\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Santarem\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Santiago\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Santiago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Santo_Domingo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Santo_Domingo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Sao_Paulo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Sao_Paulo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Scoresbysund\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Scoresbysund\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Shiprock\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Sitka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Sitka\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/St_Barthelemy\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/St_Johns\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/St_Johns\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/St_Kitts\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/St_Lucia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/St_Thomas\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/St_Vincent\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Swift_Current\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Swift_Current\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Tegucigalpa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Tegucigalpa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Thule\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Thule\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Thunder_Bay\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Thunder_Bay\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Tijuana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Toronto\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Montreal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Tortola\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Vancouver\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Vancouver\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Virgin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Whitehorse\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Whitehorse\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Winnipeg\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Winnipeg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Yakutat\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Yakutat\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/America/Yellowknife\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Yellowknife\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/Casey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/Casey\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/Davis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/Davis\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/DumontDUrville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/DumontDUrville\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/Macquarie\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/Macquarie\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/Mawson\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/Mawson\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/McMurdo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/Palmer\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/Palmer\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/Rothera\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/Rothera\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/South_Pole\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/Syowa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/Syowa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/Troll\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/Troll\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Antarctica/Vostok\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Antarctica/Vostok\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Arctic/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Arctic/Longyearbyen\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Arctic/Longyearbyen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Aden\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Aden\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Almaty\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Almaty\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Amman\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Amman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Anadyr\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Anadyr\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Aqtau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Aqtau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Aqtobe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Aqtobe\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Ashgabat\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Ashgabat\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Ashkhabad\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Ashgabat\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Atyrau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Atyrau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Baghdad\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Baghdad\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Bahrain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Bahrain\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Baku\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Baku\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Bangkok\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Bangkok\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Barnaul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Barnaul\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Beirut\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Beirut\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Bishkek\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Bishkek\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Brunei\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Brunei\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Calcutta\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Calcutta\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Chita\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Chita\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Choibalsan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Choibalsan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Chongqing\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Chungking\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Colombo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Colombo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Dacca\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Dacca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Damascus\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Damascus\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Dhaka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Dacca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Dili\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Dili\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Dubai\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Dubai\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Dushanbe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Dushanbe\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Famagusta\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Famagusta\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Gaza\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Gaza\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Harbin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Hebron\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Hebron\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Ho_Chi_Minh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Ho_Chi_Minh\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Hong_Kong\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Hongkong\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Hovd\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Hovd\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Irkutsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Irkutsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Istanbul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Turkey\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Jakarta\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Jakarta\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Jayapura\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Jayapura\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Jerusalem\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Israel\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Kabul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Kabul\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Kamchatka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Kamchatka\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Karachi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Karachi\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Kashgar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Kashgar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Kathmandu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Kathmandu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Katmandu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Kathmandu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Khandyga\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Khandyga\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Kolkata\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Calcutta\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Krasnoyarsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Krasnoyarsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Kuala_Lumpur\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Kuala_Lumpur\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Kuching\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Kuching\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Kuwait\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Aden\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Macao\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Macao\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Macau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Macao\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Magadan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Magadan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Makassar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Makassar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Manila\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Manila\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Muscat\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Dubai\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Nicosia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Nicosia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Novokuznetsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Novokuznetsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Novosibirsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Novosibirsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Omsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Omsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Oral\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Oral\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Phnom_Penh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Bangkok\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Pontianak\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Pontianak\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Pyongyang\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Pyongyang\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Qatar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Bahrain\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Qyzylorda\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Qyzylorda\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Rangoon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Rangoon\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Riyadh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Aden\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Saigon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Ho_Chi_Minh\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Sakhalin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Sakhalin\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Samarkand\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Samarkand\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Seoul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../ROK\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Shanghai\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Singapore\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Singapore\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Srednekolymsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Srednekolymsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Taipei\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../ROC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Tashkent\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Tashkent\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Tbilisi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Tbilisi\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Tehran\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Iran\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Tel_Aviv\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Israel\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Thimbu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Thimbu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Thimphu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Thimbu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Tokyo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Japan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Tomsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Tomsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Ujung_Pandang\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Makassar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Ulaanbaatar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Ulaanbaatar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Ulan_Bator\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Ulaanbaatar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Urumqi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Kashgar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Ust-Nera\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Ust-Nera\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Vientiane\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Bangkok\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Vladivostok\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Vladivostok\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Yakutsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Yakutsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Yangon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Rangoon\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Yekaterinburg\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Yekaterinburg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Asia/Yerevan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Yerevan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Azores\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Atlantic/Azores\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Bermuda\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Atlantic/Bermuda\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Canary\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Atlantic/Canary\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Cape_Verde\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Atlantic/Cape_Verde\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Faeroe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Atlantic/Faeroe\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Faroe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Atlantic/Faeroe\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Jan_Mayen\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Arctic/Longyearbyen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Madeira\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Atlantic/Madeira\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Reykjavik\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Iceland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/South_Georgia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Atlantic/South_Georgia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/St_Helena\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Atlantic/Stanley\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Atlantic/Stanley\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/ACT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Adelaide\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Adelaide\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Brisbane\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Brisbane\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Broken_Hill\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Broken_Hill\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Canberra\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Currie\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Currie\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Darwin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Darwin\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Eucla\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Eucla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Hobart\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Hobart\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/LHI\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/LHI\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Lindeman\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Lindeman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Lord_Howe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/LHI\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Melbourne\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Melbourne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/NSW\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/North\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Darwin\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Perth\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Perth\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Queensland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Brisbane\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/South\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Adelaide\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Sydney\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Tasmania\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Hobart\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Victoria\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Melbourne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/West\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Perth\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Australia/Yancowinna\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Australia/Broken_Hill\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Brazil/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Brazil/Acre\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Porto_Acre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Brazil/DeNoronha\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Noronha\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Brazil/East\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Sao_Paulo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Brazil/West\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Manaus\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/CET\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../CET\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/CST6CDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../CST6CDT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Canada/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Canada/Atlantic\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Halifax\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Canada/Central\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Winnipeg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Canada/Eastern\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Montreal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Canada/Mountain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Edmonton\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Canada/Newfoundland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/St_Johns\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Canada/Pacific\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Vancouver\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Canada/Saskatchewan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Regina\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Canada/Yukon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Whitehorse\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Chile/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Chile/Continental\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Santiago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Chile/EasterIsland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Chile/EasterIsland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Cuba\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Cuba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/EET\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../EET\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/EST\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../EST\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/EST5EDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../EST5EDT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Egypt\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Egypt\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Eire\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Eire\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+1\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+10\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+10\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+11\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+11\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+12\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+12\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+2\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+3\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+3\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+4\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+4\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+5\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+6\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+6\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+7\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+7\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+8\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+8\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT+9\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT+9\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-1\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-1\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-10\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-10\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-11\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-11\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-12\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-12\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-13\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-13\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-14\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-14\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-2\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-2\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-3\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-3\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-4\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-4\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-5\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-6\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-6\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-7\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-7\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-8\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-8\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT-9\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Etc/GMT-9\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/GMT0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/Greenwich\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/UCT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../UCT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/UTC\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/Universal\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Etc/Zulu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Amsterdam\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Amsterdam\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Andorra\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Andorra\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Astrakhan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Astrakhan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Athens\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Athens\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Belfast\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Belgrade\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Berlin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Berlin\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Bratislava\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Bratislava\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Brussels\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Brussels\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Bucharest\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Bucharest\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Budapest\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Budapest\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Busingen\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Busingen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Chisinau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Chisinau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Copenhagen\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Copenhagen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Dublin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Eire\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Gibraltar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Gibraltar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Guernsey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Helsinki\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Helsinki\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Isle_of_Man\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Istanbul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Turkey\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Jersey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Kaliningrad\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Kaliningrad\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Kiev\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Kiev\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Kirov\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Kirov\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Lisbon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Portugal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Ljubljana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/London\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Luxembourg\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Luxembourg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Madrid\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Madrid\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Malta\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Malta\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Mariehamn\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Helsinki\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Minsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Minsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Monaco\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Monaco\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Moscow\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../W-SU\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Nicosia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Asia/Nicosia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Oslo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Arctic/Longyearbyen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Paris\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Paris\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Podgorica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Prague\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Bratislava\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Riga\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Riga\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Rome\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Rome\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Samara\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Samara\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/San_Marino\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Rome\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Sarajevo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Saratov\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Saratov\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Simferopol\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Simferopol\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Skopje\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Sofia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Sofia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Stockholm\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Stockholm\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Tallinn\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Tallinn\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Tirane\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Tirane\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Tiraspol\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Chisinau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Ulyanovsk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Ulyanovsk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Uzhgorod\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Uzhgorod\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Vaduz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Busingen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Vatican\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Rome\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Vienna\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Vienna\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Vilnius\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Vilnius\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Volgograd\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Volgograd\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Warsaw\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Poland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Zagreb\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Zaporozhye\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Zaporozhye\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Europe/Zurich\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Europe/Busingen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Factory\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Factory\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/GB\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/GB-Eire\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/GMT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/GMT+0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/GMT-0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/GMT0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Greenwich\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/HST\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../HST\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Hongkong\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Hongkong\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Iceland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Iceland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Antananarivo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Chagos\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Indian/Chagos\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Christmas\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Indian/Christmas\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Cocos\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Indian/Cocos\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Comoro\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Kerguelen\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Indian/Kerguelen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Mahe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Indian/Mahe\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Maldives\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Indian/Maldives\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Mauritius\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Indian/Mauritius\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Mayotte\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Indian/Reunion\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Indian/Reunion\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Iran\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Iran\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Israel\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Israel\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Jamaica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Jamaica\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Japan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Japan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Kwajalein\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Kwajalein\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Libya\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Libya\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/MET\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../MET\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/MST\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../MST\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/MST7MDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../MST7MDT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Mexico/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Mexico/BajaNorte\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Mexico/BajaSur\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Mazatlan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Mexico/General\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Mexico_City\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/NZ\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/NZ-CHAT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ-CHAT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Navajo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/PRC\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/PST8PDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PST8PDT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Apia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Apia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Auckland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Bougainville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Bougainville\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Chatham\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../NZ-CHAT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Chuuk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Chuuk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Easter\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Chile/EasterIsland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Efate\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Efate\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Enderbury\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Enderbury\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Fakaofo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Fakaofo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Fiji\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Fiji\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Funafuti\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Funafuti\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Galapagos\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Galapagos\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Gambier\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Gambier\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Guadalcanal\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Guadalcanal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Guam\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Guam\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Honolulu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Johnston\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Kiritimati\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Kiritimati\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Kosrae\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Kosrae\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Kwajalein\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Kwajalein\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Majuro\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Majuro\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Marquesas\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Marquesas\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Midway\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Nauru\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Nauru\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Niue\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Niue\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Norfolk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Norfolk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Noumea\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Noumea\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Pago_Pago\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Palau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Palau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Pitcairn\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Pitcairn\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Pohnpei\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Pohnpei\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Ponape\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Pohnpei\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Port_Moresby\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Port_Moresby\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Rarotonga\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Rarotonga\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Saipan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Guam\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Samoa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Tahiti\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Tahiti\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Tarawa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Tarawa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Tongatapu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Tongatapu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Truk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Chuuk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Wake\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Wake\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Wallis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Wallis\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Pacific/Yap\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Chuuk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Poland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Poland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Portugal\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Portugal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/ROC\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../ROC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/ROK\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../ROK\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Singapore\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Singapore\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/AST4\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Puerto_Rico\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/AST4ADT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Halifax\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/CST6\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Regina\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/CST6CDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Chicago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/EST5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Cayman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/EST5EDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../posixrules\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/HST10\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/MST7\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Phoenix\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/MST7MDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/PST8\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Pitcairn\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/PST8PDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/YST9\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Gambier\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/SystemV/YST9YDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anchorage\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Turkey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Turkey\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/UCT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UCT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Alaska\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Anchorage\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Aleutian\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Adak\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Arizona\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Phoenix\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Central\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Chicago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/East-Indiana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Eastern\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../posixrules\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Hawaii\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Indiana-Starke\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Knox_IN\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Michigan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Detroit\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Mountain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Pacific\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Pacific-New\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/US/Samoa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../../Pacific/Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/UTC\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Universal\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/W-SU\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../W-SU\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/WET\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../WET\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posix/Zulu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/posixrules\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3545,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23065057,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5fa6dccc303352e1195c4348b189f3085014d8a56a1976c8e8a32bd4fedb69fd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Abidjan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 710,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23066974,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c177f3894cfb7acf27cfefcefd177aebfa1699e409e7fc4cd5a11ef116f8d236\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Accra\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1382,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23067446,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fbee22da817893911690f2ee7093499893985e39c0ced1116709947f9bd206d5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Addis_Ababa\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 825,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23068277,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ae39f133e4fad735bf5e099f9090b322f84efb7fe050968da196289a3c703905\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Algiers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1300,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23068801,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:84081708d8029add247fd5add1ed963c2811b8b7841b65540ba7bbb02a068019\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Asmara\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Asmera\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Bamako\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Bangui\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 711,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23069674,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:699bdf57ddb361bef922d520674b4fecd15db812c73e984727455fa7c3ada2d3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Banjul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Bissau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 748,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23070186,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:197606820a95c35d6c3d2f64e5e1d9542e198732db52d3b9ca6ff7294bb0ff9b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Blantyre\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 711,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23070680,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3e39755e95604e242f4218d248dafd51ffa09392975c3f86c26907e6aad60da9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Brazzaville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Bujumbura\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Cairo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Egypt\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Casablanca\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2169,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23071255,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:891b90e824430fb61b050271bf1f409a9166b28f55885e50ca63ebb24d0679ab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Ceuta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2599,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23072513,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ca6b06411c93017e93ded83d917cac8399690d6fb2771bcc66ecf132ee2e3ef6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Conakry\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Dakar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Dar_es_Salaam\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Djibouti\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Douala\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/El_Aaiun\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1999,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23074107,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9568caf33829340936f06819a98b4458092b9c363ab915421ea3bf46e0665e9f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Freetown\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Gaborone\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Harare\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Johannesburg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 811,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23075380,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:af7338314b4255661ce9afdd064e487321d4369ce15488395bb20bb4627d1ae2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Juba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1223,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23075905,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2837717687d9cf2982e14bc35199ebe448380678330f15de5a6a2c49ef204b3c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Kampala\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Khartoum\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1253,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23076712,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0cd1350c87bd18606418d615dd78790f8ee9458ade7acb1af82b67afbdfc27f1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Kigali\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Kinshasa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Lagos\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Libreville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Lome\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Luanda\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Lubumbashi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Lusaka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Malabo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Maputo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Blantyre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Maseru\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Johannesburg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Mbabane\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Johannesburg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Mogadishu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Monrovia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 773,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23077761,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eb1deb0dd9325844227c376d1532b484511c76f79f42032806553d36a9464e55\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Nairobi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Ndjamena\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 765,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23078309,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:180050fab205819406f6d6b572fe6f37eb805cc3f796543185c3229108470189\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Niamey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Nouakchott\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Ouagadougou\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Porto-Novo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangui\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Sao_Tome\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 774,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23078918,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:29e95715ef8893f1bd3f1a1625d200fdd0fe65fe0432b659130b69cff2460dbb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Timbuktu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Tripoli\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Libya\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Tunis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1250,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23079488,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dbc64f2ddde5756e10d2ec8156bbe83f6f9ecbeb33b5bd6d771542f623d8fc39\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Africa/Windhoek\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1528,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23080260,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9232e815aee566ea37642ad831abe23161c2f1c286dcffdc72d95f71d5e40289\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Adak\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2905,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23081220,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6d3e31970fee36399f30950e3f68ce7a5038be38a64547241c2ac97daaccd994\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Anchorage\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2920,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23082890,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b5b62f7337785e26117bbc34ef7976018f021e63eb3e208f8c752d4f949ef2ef\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Anguilla\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 710,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23084562,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dbe365d9a8abfd164690db1cec6c51c19f86154900595509c991401e13a16585\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Antigua\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Araguaina\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1436,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23085077,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:43bf02f6b5a9899a0f6991d0077f4d2216971d7b30b5de2fc790e327e019ee5e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/Buenos_Aires\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Buenos_Aires\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/Catamarca\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Catamarca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/ComodRivadavia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Catamarca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/Cordoba\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Cordoba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/Jujuy\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Jujuy\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/La_Rioja\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1649,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23086135,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c7ded9821e935c4b533f557a31ccc2e4c3e89589091854b080f633b4a914c21c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/Mendoza\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Mendoza\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/Rio_Gallegos\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1635,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23087183,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e94db6d4db923985621567e409b6db116b4ef5bee49c750518bd2f6be1f6863b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/Salta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1607,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23088175,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6829678c15796b06de4b1da92b4eb8468d2ad8b25e2811c5faca7e6d4cf96098\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/San_Juan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1649,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23089159,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:87e65aaeddf18f1584306b42fc929f85e875f4eb729d15e2fb872bce277dc4c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/San_Luis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1665,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23090160,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:959fd4de4b39ef6c77a411d434d75fe5941da9374d58f9d40fbeef0e01f0886c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/Tucuman\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1663,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23091165,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:daae915c9ee5454bf0caff7c0e76f34166a3f6a3f2457325f02cdfe628324d04\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Argentina/Ushuaia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1635,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23092175,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:45587dee42013d07c5cbe4cc755f71552d24755d364f933de4f0cbd595545f42\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Aruba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 752,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23093157,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ec9709d87bbdd0aae7be4070156e5dc05c12d822da203cb1030354342bae2df0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Asuncion\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2603,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23093653,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1f9c20fdeff202451fcef7540f2787175f5c494157805091e7943d736dbcd919\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Atikokan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 885,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23095126,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2fe220cd5f52ece0e3aa468ed33c443eaad61fc9e3bfbb47b7b754e8ad1a4613\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Atka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Adak\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Bahia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1576,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23095721,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9945af7dcc0f3d98b12a34a0f312f79d54ae2cbd8261d4be697e3e0cd10f1b56\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Bahia_Banderas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2128,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23096687,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e44343d2e96738b96a6d83d5327dda8d041b1fb8e62b281f7fac7e56642b960b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Barbados\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 884,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23097912,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:64d664790217c76976a3a1f386ac82fc0f2295247f64547385711656b9f8f13b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Belem\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1128,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23098477,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5c276cfcf3596de48c0e4945ac5d19041e615fe79cd9e87fdaff0e7aaa558b7d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Belize\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1518,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23099183,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8128f9212e7e47481a2893da5f65f2c0047bf1329e314591435d7bb18b81b136\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Blanc-Sablon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 847,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23100102,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6e9969e343200d865e82628b88310774524c38ae9c5ede30b7e5163acb70e6a1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Boa_Vista\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1184,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23100654,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:33c2236e501f89ef5f2a5d1afcfc1434c264b10d1e14f9def6efd4c00c3f5003\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Bogota\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 797,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23101399,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b517e5bdb8aeeede03927787dcf5529f4fb33fbcb76daa7c5bcfda5320cd4468\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Boise\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2943,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23101924,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7189c739198e19615b75a8a336aabd3cb223a765487382eb16c783cbb91c8c95\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Buenos_Aires\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1635,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23103582,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d47983ff5ce9a8ecb9d65fdea3f3f603ccccdd170da513266c852d25ade2a6ca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Cambridge_Bay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2638,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23104571,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dfa58c30cd1217d5f8e9dcb757d64bfb901c28a5f9475a38ac7de9e03c2d80c0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Campo_Grande\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2556,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23106050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dab46c4d5ef0c2ec09cbf68010b9f73c7e5082669c3b92e3be032a6af4ccb61d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Cancun\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1356,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23107525,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8ce65577ce494166ad8f57f14a55ae961e27dd7aa356d8802fb5c9f2d510fb6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Caracas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 815,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23108350,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:08c9e8707db81610f374294e7d3e8338ce329e60bc467547ef1714287271f563\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Catamarca\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1635,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23108882,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d0d4323f8e3489b61b4c512a2300d68672a9f92a8d7bf5ecaf6e2dd786ee449\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Cayenne\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 750,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23109869,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b11737b697bbe5e67a9fc1ab08a0dd868df4b2290225e3b15d7b677ec2009bcb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Cayman\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 743,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23110367,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6962181adfca6314029efa4c3a2dae17c775d6031cff3bd6c63d49ed30c31cb1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Chicago\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4125,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23110864,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94f71253caa6bde6db52f2f5ad3b816df0c2da9af7cc7d4a4abf1b91e391821f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Chihuahua\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2062,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23113109,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1f0007a74669d2ede5ccea2c49ff17ced52ae2e28756ebbf5eb08aa08b3e9d45\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Coral_Harbour\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Atikokan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Cordoba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1635,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23114349,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3941316300e3137c4e8826d17e00a9df06aff8cec73034e6b61e9b371bb0a540\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Costa_Rica\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 881,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23115335,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a697b205589062aab7599c2e812f164df50b32f2d9c8f2ea7b42f1e53b4e3e94\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Creston\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 773,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23115910,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:071acbeb9c771d5bd244b0d6bd73b7e7893aa40deb19c1074908a0094de4463f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Cuiaba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2528,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23116419,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7728725c174a947f2e7c6acee48c0b40b6ef1947aa706c8b3ef1bff9a3b4a453\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Curacao\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Danmarkshavn\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1252,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23117933,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:99b1ff4ad370c93145279b56504ccd2d0bb39f92c002aaa490bd5969285cdd1f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Dawson\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2633,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23118705,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:93a9938a26f814adf696f2e4f537164bc8ca9e4843d8bc6cb96dc59377534437\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Dawson_Creek\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1599,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23120198,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4f2bb35e6c4c8804409dc81ad024881457705dca4ae468184f73c04bff51ead1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Denver\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Detroit\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2728,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23121184,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d7c0f33030d0e2d553b385457787d9faf8ce714c0b3a17778d5d45ad1a6560b2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Dominica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Edmonton\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2942,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23122773,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:da80c9534c7b548bbb92e982c1ca2b15b30608ca72567d20e9881444cf58b4aa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Eirunepe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1216,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23124428,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9396017faecf7a3931851bec7fc924eeb8a2a53ceda91da3d458edcb555ced62\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/El_Salvador\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 790,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23125181,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:04993007b8086580ac35e8fa524bbdcd45f045c965608fca3da26deaa1ede337\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Ensenada\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2896,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23125708,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a1a5199868d6aa4c24fef5e908e99e4c6e116d16afc554d25ec431990d8f02da\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Fort_Nelson\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2789,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23127332,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c20108fb21d7e76aef2c0bd669f1dfd6043b5269020bde6cff669f088d13abec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Fort_Wayne\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2215,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23128915,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7dfb7b2796f9b9d9a69d402b2e8269a2f834e1d01e2da34af490b2b24c21ace5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Fortaleza\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1268,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23130193,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6ab4cad81917df05f5ba0f3dc90923aa5074f740095a6439a8739249bc26df0e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Glace_Bay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2746,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23130981,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:799c72cab5fafdcf48dfe766d52c24e7fd7f4a61e0d554c97888023766219287\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Godthab\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2418,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23132536,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c9d318e4f59dd5f3016f5e3981a67ab34140b767c987178738e14a80eae74976\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Goose_Bay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3759,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23133907,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:462bef059c879d10cbcce574a128bc2d847dfc342dd77f43e6494f3aba6cf94c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Grand_Turk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2421,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23135999,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:50148cea43182f25effdaba081e72c55239b58f5985a2af2e1ace6d591ef2388\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Grenada\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Guadeloupe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Guatemala\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 846,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23137448,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b8d8d7b3edd1a237b4d4aee860162700cf11e25aa9102ba61bed6640ced94463\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Guayaquil\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 797,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23138012,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cd8bef091fd1f925658709c0f130381dc8b9406dd50af15dbba3ee0740761777\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Guyana\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 792,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23138541,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:607345856a6751417bbfc7c185e9245fc34af1d87b2ea11c77aadc7b8f7b7799\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Halifax\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3978,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23139058,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:86c84ef0a21a387fdd0058046268c5eca94c10cb73231638724d344cc478bd10\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Havana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Cuba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Hermosillo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 994,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23141298,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:778350bbb96f05ab2e74834f35be215801da358dd7c261f1ba3bfe6f1c9b07e9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indiana/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indiana/Indianapolis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indiana/Knox\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Knox_IN\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indiana/Marengo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2271,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23142027,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b3e8fe887a5ce407f7208f16d0b296a4594b3f93de33b70d5a260139f66cfab2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indiana/Petersburg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2453,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23143358,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:285f27ebb54838060d3a33238dae6ee695af5c258d40780fc89c797a239360ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indiana/Tell_City\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2275,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23144773,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:17b0f617df438b7a18a3bbb5f43d1a0fbda97ac074c429d699fc6ff2b70f9080\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indiana/Vevay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1963,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23146072,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:74d2b6f797d63017075f1425e695e5f61a6e1b3ef08f812bc330e22fae18333a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indiana/Vincennes\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2243,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23147239,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:970baaf1ed777c07d74546d61282e9df9a0488ad90084210a770c82ae78b8357\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indiana/Winamac\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2327,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23148540,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cade9b122bd306fd5bb1fd4ff0471861c8eaed414a166ba570554a349a7a20b6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Indianapolis\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Inuvik\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2468,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23149925,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c51f2f3cef4844e5c800ed3592d85bc69e5f05dc4a53e94c76b2433be16b1a5f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Iqaluit\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2586,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23151324,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7179d696e8f2aac641bbe8a0b0635128246fd4669e258befaac2e91170f75d1e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Jamaica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Jamaica\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Jujuy\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1607,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23152819,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:29822a6d077e97673b9e892cd65c00709d43e0aa90ce6d84b0c1228083def36d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Juneau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2902,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23153792,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2be628832b78514026f7932644e221fd4490d502f686f069d7ebf8ba0b220c40\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Kentucky/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Kentucky/Louisville\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Louisville\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Kentucky/Monticello\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2901,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23155552,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ff56ff4d9ee52923c57354d5d836e87cc8acb748bbf0648c2406bcbafaa4227c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Knox_IN\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2977,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23157195,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ac4c928ad03acaf42f346aa81bf9d269a513adb14a955ff55a5177927832c6a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Kralendijk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/La_Paz\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 783,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23158926,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:beab009d797e8c2a8607eaf7192b5ff2736c220073fc5c29e45a8cd9dc6a5a1e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Lima\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 957,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23159443,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c75b82ab26d2838d0eec739aabecbc33de43a72d3f7551e25284197563ad6fcb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Los_Angeles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3385,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23160074,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5f2a6fb2744e29e2a6ac88e89843ce0c74f8934b37d1b35d67e115d5363c9e57\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Louisville\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3321,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23161959,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2d8d4b0dbd3eda1d9c9992b42fb309f7c645a9ac0048e2dba3283e7ad9d67f1b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Lower_Princes\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aruba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Maceio\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1296,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23163862,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dd3e4475c42101aaa3010513fb3dc80dcf598582c4d7aa3caa0dd1cbd55e23ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Managua\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1003,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23164661,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1a2e937499925a46e4d2b93113e7b035fdc270174a8fb4b65fd61f163b430ca3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Manaus\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1156,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23165300,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:876c087b224fcebb22e281b18dadd4283844ab83280afc8c9092ad2f8defd3a4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Marigot\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Martinique\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 797,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23166078,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18a0f75cca7c62ff1b7c8e0463856c1fa811e796806ef23cfd53d40a860861fa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Matamoros\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1956,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23166601,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:298a0a44d6576a9c127e048262a3f7f1b613653e0520a75bf912a65ccef50771\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Mazatlan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2104,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23167751,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:972ebc94965c29a285412a68e853fc7729bd741b5be52edeb9f3b9a1a707ac43\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Mendoza\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1635,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23168962,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0f4bf9977f2591788ba0b60418f7b932da1112abffe03a742ee2b770d4fcefbf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Menominee\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2823,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23169947,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a9f238c519f7699a3bdd001ffb5588fc5c80329a14c95309aa424c0026440108\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Merida\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1996,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23171534,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a6352eb8ee46c326f0231e5e22ae330d465964514c21390e28aa5ddee377fb5c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Metlakatla\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1958,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23172688,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e130ce578bb5bffd9871e92519541592cca5e32e28912f82883efb4348f7382\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Mexico_City\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2158,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23173867,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b2e4e7d462f693d46142205a03882b383f3cfbc6eaa0a4c514fe71fd5112f12\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Miquelon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2222,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23175115,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7da3a78f48b2870cdb2b246107ad28ad353c006f6d10e26034f8bb7ae299e837\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Moncton\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3703,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23176404,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d587577011570e8271781f98b52f5ccb8650a7a1dc2c50789f4cb5d5d7e9c13a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Monterrey\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1956,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23178451,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a0334e1c8f6ebfdb959a536fea620a72031db45036d563864cdaba4e34b0c2c7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Montevideo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2090,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23179597,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:17c9e4bcff4188d1cb3a8bc583991d6ee81896fc64664f8d6b01c02fda66c1a3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Montreal\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4043,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23180808,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bd1fdaf567be65339c2fe8cadf9e690d0929548cd731edcb41ae7f322885a590\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Montserrat\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Nassau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2824,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23183080,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b3526d4c47155f9f9049070f75b3981b9f17b153e9482afe6e3f83e0f84adad6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/New_York\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4085,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23184683,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9699b3dbf1b5a2fe33cc0eeb1bae542d83608786c0b1872b07b24adda81556a1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Nipigon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2671,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23186917,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bedddedf42d1ecd3db1eeb61988fa1216f75b06c45a768822a16b4bf3e78542f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Nome\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2916,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23188435,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2f167608a9d4171d89ee0a4d68c3ee845ebbd073e3759dc663a95dc8c865e4c1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Noronha\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1268,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23190108,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:276cc0daf61bee62a6f8ca0636b0da6a4bebf95dbdde6859c7b53434ab6e3eaa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/North_Dakota/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/North_Dakota/Beulah\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2929,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23190948,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5a05c79be4ba9c4ed5a70aedbb8e83c2864c9ee5d974824130552d11097f654d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/North_Dakota/Center\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2929,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23192612,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c4daf0f8f179948ca4f3edfef1c4bf6ea9926d157cbb83334d990c4f3ae76fb3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/North_Dakota/New_Salem\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2929,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23194273,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f728e13f15039666ade97ebb9e0e7d54b575495e14aa88ccf2761d29e5a390f4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Ojinaga\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2062,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23195927,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e9cb05ec786e833e837b19a3d7bfe611e6d3ff3da1fc576fa5ea4f44c43f937f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Panama\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Cayman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Pangnirtung\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2648,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23197164,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c71e8ae865312e517ebc4076ecb9665c2cfdc7155549d18462e01275961925b8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Paramaribo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 822,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23198646,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69e775220eadc309a7cfce0aabc4936f9e5631a4a64a844d157a8371d5293c5c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Phoenix\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 893,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23199171,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a89f0e65cd0a0b2edbbf65a7a81441aa91073b133edac17c25c6c9f809b8995\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Port-au-Prince\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1995,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23199760,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aab1855d3200ed78c12406a44d8558a9a875dc57f94090b2c205811a92b5e066\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Port_of_Spain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Porto_Acre\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1188,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23200987,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa8436992c68303c75f248539845c855269b6f3c307032f2510b43e0779efbe4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Porto_Velho\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1128,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23201719,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:753c3bf10a58b02e6b991d48e356a4953cc1cdd3042665a1824dadf58d6ace07\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Puerto_Rico\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 795,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23202435,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a9e478dd8515a4c8086ff535afe44db1cf53b9400ec62aed7b6d122ecfb778f3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Punta_Arenas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2437,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23202967,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9039a86b9fae5f31ebd11cf51e70e79d7fe7e082ef0f9f85a6dac48cb7f945eb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Rainy_River\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2671,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23204364,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1680a0ae7e1d154aa9672b6e2d24155987de256acd7273f23177ef258d4ffe16\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Rankin_Inlet\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2470,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23205889,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1bb3cc33e21e5e7663a0cabcb02f9e7f74ee0619dcd0d84d4a4a31f611698b57\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Recife\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1268,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23207291,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1e7229c4468b197480ae588656cd52e8ff11bacb3af0bdfab2f090e6d25a9e0c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Regina\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1534,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23208080,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ef7b8f3a4e1baf07289907c77a4218ac0be68c7a24e980940a05cbba77e53c9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Resolute\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2470,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23208978,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2a208ed79da175c5081c8db0fb767d9b0e0270e4a73bb95f24ae0ffd22b6354f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Rio_Branco\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Porto_Acre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Rosario\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Cordoba\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Santa_Isabel\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Santarem\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1158,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23210497,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1a927437ef7079f8ce9cb80607c823e609f1c9cd757282718932435dd4e8a5bf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Santiago\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3064,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23211220,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1f31a3a5f1e1ea4f97a2cd73d27dc28c51ca294378f1268b021e2e0be6a336c2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Santo_Domingo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1031,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23212957,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:24bf349defe5c3ed5d8950593acbcd57dc662784ddfae68b31cddfa02746f2ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Sao_Paulo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2556,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23213625,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:11592bb442b3322b0f50685787c1ea58e5db05774a5c2cb6e133cbdd763c2bc5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Scoresbysund\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2456,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23215107,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:42653212318e5d075e6fddd5a579507a13bbd0538623d1943cfff1569e24d0de\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Shiprock\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Sitka\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2890,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23216534,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:81ba6e3b87b7f9c9814c4f607a3c722a0bbd8355ab1647c51847882b3a3c0628\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/St_Barthelemy\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/St_Johns\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4204,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23218260,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:10784794564849767481803ad10924bd7092c041b5e5859dc7cdf883abe13a7e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/St_Kitts\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/St_Lucia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/St_Thomas\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/St_Vincent\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Swift_Current\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1114,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23220672,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7752d4a7cd93e6c9a16f89dfa148ce6ac6f491cf40359f9d6730e03b4aedf848\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Tegucigalpa\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 818,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23221355,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c37dd7463adb25b95fd20bd17473e710e03c9c5d36481b4626a82aabd7469983\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Thule\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2068,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23221893,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:67e571d61867a4ea726d7b19f5fabca2a7751219685d57eee29570ec9225f0ea\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Thunder_Bay\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2751,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23223108,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2c04cafec84e648e5d1154986626b32ebdb0def10d7c8843d27bbee20ad82e5e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Tijuana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Toronto\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Montreal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Tortola\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Vancouver\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3441,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23224766,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:20b9d3c10c060d827a80bb81260a5407b879a95af0e114b9a258c9214ac55f22\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Virgin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Anguilla\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Whitehorse\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2633,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23226731,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:84e26d472821fc0a5280f3bbd9b7d6d4130ccd78272d637314628cf299f203e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Winnipeg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3431,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23228220,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a91e3074914af25d44e7428f07b7e15c46a9b1c61adf146d78058bfb95128031\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Yakutat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2854,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23230115,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a8d6177b9fb9653500c7a5468e35508251be2a6dce9040ad9ebfbffcd4cc3ad2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/America/Yellowknife\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2520,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23231745,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ffb6c39b1c757ff250651391b07dc8d3e3ea361f837472ef57c62eea144677ef\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/Casey\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 837,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23233212,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2ca1ef915c00d2afcdb6d67afb8f02bd84eaa77953373a0b0744bb22814e632\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/Davis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 837,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23233752,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:68203c490a421f72442b46179525552b863773b136d499e9fda7dde39a52b234\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/DumontDUrville\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 742,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23234302,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3b2fc9d546516f429b2e95338925a2e52c328d0145157b311830c8f8fcbe56ea\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/Macquarie\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2069,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23234801,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05971185e4ba26201409ea2b3045b99efc9402e78cbb89bd4fcaaaaef76ec016\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/Mawson\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 751,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23235993,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6d71da7e0dc64cde67ba892f72d2635aecfc6f8b5ba32d8e4bce77b6d43b7b1c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/McMurdo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/Palmer\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1958,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23236524,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:890b910a9d56462b6b02cb97f94e4c6b1bc21d28e22c91856ffdb4491e5c9af1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/Rothera\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 712,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23237665,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2248bdca29d8909f713111c13c4562206c315e778dae04191e2c71be7e41d66e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/South_Pole\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/Syowa\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23238183,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2ed146fb4b60eec7f3fd2a45ec5a47efe97628bc6f6d718bbadc4e7d0efd2699\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/Troll\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1702,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23238657,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0015c4226733a9e187e53587097ff75b4cb2aedf4157811e50d2aa88c658cb08\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Antarctica/Vostok\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23239650,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ac1aa91f07d0fe56ae6f0df158a36e86063712784e6692f95b1804815cbf1ee9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Arctic/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Arctic/Longyearbyen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2791,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23240160,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b9f4a8a248c4b945a12640b4be549baaa438a9c3472822028e9f4988cd4e8b63\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Aden\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23241753,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cc7153eb830b43242dfe8683480c44497fc209145045c93d2e75774495d2cfc8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Almaty\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1557,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23242229,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cd94dd030db0f5d766b246af2dc09f394a1e1a6abca0b84385a6b460c0a95001\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Amman\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2417,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23243139,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0dfa946fc43a7d4ad00e75aba44720018d82f36411351b2e5a103dbfadaf0d8c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Anadyr\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1748,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23244511,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:658b7df8bb11f46e1c785e1ecb46e54a7e4e4435da78edf0ed9f3c8920ee7e9e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Aqtau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1543,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23245534,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e900765cb6d9b6c7d3320185701d7f70c8bfe1e462abf1ec687c2494afbe027a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Aqtobe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1573,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23246447,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fe5ae88a2c0c1af7dab63e796db665ef7037a045ee93bb480f742b24143dc13e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Ashgabat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1177,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23247367,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ce671b85f724114ded28698c8a0f90df2451b52b1ab02bc266067c6236b45792\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Ashkhabad\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ashgabat\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Atyrau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1551,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23248131,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ba6963e4536ac91a31a8c53de06b962be6f2265828c1fb7d8471ad2513a6c72\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Baghdad\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1530,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23249050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d50a00eca951cc4945a502bfc4993096fdf661213ec534bb8a7dc4774af88000\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Bahrain\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 751,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23249965,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c39550b6dca350b213a7bd957339b96089c9d4ce4d5dd975444af4d848afd06c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Baku\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1795,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23250454,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:15d6954f582895136fe83e61ef7defe2abe84ae2670be41a46adfdf5021d152a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Bangkok\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 746,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23251494,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:27712ede5e3faa189b802aff8b25bb37058710ca9d62439643304bc522ba03d8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Barnaul\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1781,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23251991,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f422f78d9ea036ae9979c3ea4ec864d06930257d671613e49457160d602c2019\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Beirut\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2715,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23253036,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3e24a502c1fb5fb0dd7a8c738f28074b8e785311ba73a33fb597c2172ca288a0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Bishkek\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1571,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23254578,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ea503d6f5d42be0d3b9cc97dcc71a07b570be925d94104180652bd4ad8667031\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Brunei\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 755,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23255497,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:38e8f436a5483d23eb24c1422a098014239e51cf74ae41120f3d98662a9513d2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Calcutta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 852,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23255993,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:637147fe7b40e10955c08b61ecc5639148589ce9bd6939cf7b98bc02cccd5036\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Chita\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1783,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23256570,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0b4b8ac6a5125aae18dad505db9a49a269f4c61054dc0adf0bc3e19436fc809a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Choibalsan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1517,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23257605,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:edc88f73de96408868609ce2dfa5c125aededfd799ff7b3b2c2e5c216898cd31\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Chongqing\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Chungking\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Colombo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 939,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23258557,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:514a6511932107df30932d496a3e469a0415837679103d50ac262694b0699b61\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Dacca\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 896,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23259131,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bc6a481333c3867538193302c3390acc62a591d8556f378fc0fb90f30c75c66e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Damascus\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2860,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23259697,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e23e8576a6f8b5b65a356e535ba0ffc916d211a155207e486dd40b1757f3b831\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Dhaka\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Dacca\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Dili\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 779,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23261338,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:29412d668b9a191c7ca3132f85e479f4fbba5daa8b7ddc6ea599639e96fe9299\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Dubai\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23261846,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8137fb36c9c9f6f273c75abeb39d415d411777289d0dc361c28d23e741933d20\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Dushanbe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1147,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23262323,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18ba97fd4f84ae2c99f6a60b651ec043bf5d464600aa68b7fdd331a15455c5e2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Famagusta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2582,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23263022,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:40438f760718c79a99e171a199690123f0cc531fef996423c2ca840d20b6bce9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Gaza\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2835,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23264463,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6ed90d85deebc9fb9292b65cbb103fea833bd5c9c3890598c587a5ff66fb01b1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Harbin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Hebron\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2863,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23266107,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa78ccb4bf6e2c7c212cb2ffd3d0e892ab59db2f96cba57d67e1bfc84c40096f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Ho_Chi_Minh\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 915,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23267728,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:18f4bc73f6e1b70aa7af8cb7f03b6191b91c4fe160cdabe7365a8c15c98fd209\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Hong_Kong\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Hongkong\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Hovd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1447,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23268339,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:68a7869d2b4493ef412edda98d0c69171d9012de857f78f93bc1aa511d357753\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Irkutsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1802,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23269212,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:758dfc5e377e82cab46bde761d3678cb8136a7e3f6b7bc4f18a14ed8e2e45ade\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Istanbul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Turkey\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Jakarta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 932,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23270295,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1e1d6c8a2a336137b702b0e68da98b2b2c3135a1844f9bc17d05d0eff1ef18bd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Jayapura\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 791,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23270873,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ccfa8a6a43b97d5dd2e2c33f84951460b2bffcc1202919ef38c3b097a83167db\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Jerusalem\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Israel\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Kabul\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 755,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23271421,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05079923f0dcdb139abc702b063aec10c46f283019af08087b4d126f3317a5f9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Kamchatka\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1724,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23271922,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:91922e506d3db985233b289c6c5be03d1c9a87cf18253b47ab3a77217e52a8c3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Karachi\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 957,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23272934,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:08c8c89e2687b19464bc067b6b368bfe3106c980538c0b3314e7301e192a295a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Kashgar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23273531,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7e9286573873c9113636fbac7e5559a35faeca0db3fb73da0a3bd4fc5f65a456\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Kathmandu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 764,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23274009,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8bd14af9de4726482304666173d593a0847f2b429cada1a7fea3fa70a10696e4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Katmandu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Kathmandu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Khandyga\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1837,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23274544,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b08289062a1307816fb246bf351b9264af434aa6a6a65551b8e6cfaa208e5f8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Kolkata\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Calcutta\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Krasnoyarsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1769,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23275644,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e93c034f7647538f5a51adc8195d9cace109a45b5c5e3e6481fd0247c0ad11f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Kuala_Lumpur\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 950,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23276677,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c8b289f4113407322af39192ffae6d4bd70fc07dece86db7afbf51bf51ab36ab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Kuching\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1047,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23277254,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d16f6894cb9b51fa6426bf60bf6e28ca8953776a5d007d6f95a9a160658be40\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Kuwait\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aden\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Macao\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1311,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23277938,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d776cf7633495715a0794e17c4cad9338ab05fb74fce498890acd45b6922082\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Macau\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Macao\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Magadan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1784,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23278774,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1e59de996c881c4e1440a0840b80ae9accef36d547f947e7d139629675a95ba5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Makassar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 828,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23279806,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6bb9b9d31d2f3c57b17a9ec143294ffaa86669e793adf98c5acd1a980d6d4125\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Manila\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 893,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23280325,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eef003e76600751c7e9e742f9aadee8e9a54fea94aba62815ec755d633772d32\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Muscat\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Dubai\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Nicosia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2556,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23280953,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b801d86c6b957dd1affe34a2d19a0c580be861d8ccd283d9f48e2dc991fe3696\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Novokuznetsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1723,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23282384,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:25ec788512729a0767bf726100faadc6e7d9d8c3d2f93f05a537480a1677c594\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Novosibirsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1781,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23283404,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:133caf0866411002a774c95699d4c3d655fc32451cd6622142cbfe322f2f9b0c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Omsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1769,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23284446,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e4e00ab7d4297379b94c840a93dec5aa02ee4675c0b0a063c6bb28ffb8a8ff96\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Oral\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1565,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23285470,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8538cffe3000c7c62519075440e7efcf120610601bc38d4f74cf8c0c20fe8326\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Phnom_Penh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangkok\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Pontianak\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 935,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23286440,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5387a863122580120cb3ee351bcada3b3dfbf163424291b97bac4e2cabd9845f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Pyongyang\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 807,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23287017,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1ee9bd69289e2d175fc25a780f11c1c4b71ff6dd172427015e47e8b9afc7d9c0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Qatar\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bahrain\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Qyzylorda\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1573,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23287578,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d58e0f06c11ed11cbc3543944c48df4e7850c15f375b2c0784bc40181f5cbcaa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Rangoon\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 823,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23288499,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e82e81e81d7becfd4796a9620afc7950e9dc8ea1cf28ce85b91f11f8e94ff2b3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Riyadh\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Aden\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Saigon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ho_Chi_Minh\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Sakhalin\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1760,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23289091,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:20e5edafd438adf3d299e2d1020f3034b18cc943e0b8e6183a4783fd68c91660\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Samarkand\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1145,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23290126,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:610fa9ffafe3bf07021986093d23c13be582da74f5240418538dce729e52cac7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Seoul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../ROK\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Shanghai\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../PRC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Singapore\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Singapore\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Srednekolymsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1770,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23290931,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a86ea1167361757c9c361e526dc5d6dc955e54127bbe26bb329c10cdaf3b910c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Taipei\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../ROC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Tashkent\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1161,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23291991,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2c547ea5d0b629d373549ae10d689305371b1b2ad50f50a9674d9dddb9d6c292\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Tbilisi\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1606,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23292699,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc510dc1e0fb0046ab25efb7e690494b8de952653c47e36e120126ae8f90090e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Tehran\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Iran\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Tel_Aviv\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Israel\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Thimbu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 755,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23293713,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ff501701002f41f0a8104e3f6bf7e510ed880c196cf00fd5df68c05af58368c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Thimphu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Thimbu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Tokyo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Japan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Tomsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1781,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23294266,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2607287c46263b4309de532febe5bef76f9608d9ff63086073d70106f1244fe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Ujung_Pandang\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Makassar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Ulaanbaatar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1447,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23295371,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fb2a3f180a8e9876464b94f82d304af657abe650242cca5e1f213c79ad23d1fa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Ulan_Bator\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Ulaanbaatar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Urumqi\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Kashgar\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Ust-Nera\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1816,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23296320,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8d96e0257286d1a9a587ab8282502edfd46ff11f689c1781024ef1983698b483\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Vientiane\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bangkok\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Vladivostok\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1770,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23297410,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:baa65ed34a7bd4fb6cb2d3049bd300e8d1a4c94da531440f228eabf118cbdf1d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Yakutsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1769,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23298432,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:198fe2c858c12f6ea9694e14082c83d7cd2b0cfad08d777e24649a32f4d4cd77\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Yangon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Rangoon\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Yekaterinburg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1807,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23299500,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b628820d8324f3f6f5158b205f2d2ad039c39f902c224069a0b1e4fe5d34d2fc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Asia/Yerevan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1739,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23300540,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ef2995b9457cf5a134415bd2edc791e517cf105b82c996d562ff7924e96ef17a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Azores\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4019,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23301590,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:94aa009afe8600f7e4e9d2e08010d9e8e298c7db4b5d037083aae2623dd39c7e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Bermuda\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2544,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23303763,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d6de741b6c7895bfd687374854ea64fb2998d65436d657d27bd4c7c59b351918\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Canary\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2451,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23305215,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f0bf9911e3c52ec1a10e1b9c0cb94d323c7425614948efc559ffe15c67fb48cd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Cape_Verde\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 810,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23306595,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:26e5af107ba390b89da815bf73393eda913c93bf59da49028d07c2de8c47a93f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Faeroe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2369,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23307116,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4f5a41b4ae349e1c6466cba14b5afaf7d7b4a9623fc8395173e4d3a2b4a5f90d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Faroe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Faeroe\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Jan_Mayen\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Arctic/Longyearbyen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Madeira\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4024,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23308535,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:35dedfac50f7e188bdf50bf3e03fd597e822d77b353461bbb60e3ffc3be1b71f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Reykjavik\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Iceland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/South_Georgia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 690,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23310760,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:443c6fad70d4b18113f7c9377ee84d4449aa7fca3b0b7a215fe7ef37405210a5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/St_Helena\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Africa/Abidjan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Atlantic/Stanley\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1777,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23311300,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fb5739968a69015fe6f3848e3139045a95883307b05b8f7d21ffb48182bf4567\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/ACT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2763,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23312393,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3cb5754502c335e80d639b47a7f36ddda899d8456ebfe72308882ee5ef92a698\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Adelaide\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2778,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23313946,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:02aaaee74a3e5b3d1629ae41daa5b46da01708d3bb87b3c7100c1e7b8202ab81\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Brisbane\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 992,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23315538,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ddda440f5a5595a004677523165714a25709a156027554a06dd427d5308d9b18\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Broken_Hill\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2814,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23316176,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fd0d2135fb2fa2835646f9e83c23e040bbd8e45b949f3b181925049c7cf419d9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Canberra\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Currie\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2763,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23317839,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f37c37574a6bbbebaf7d25eae300f4499741c50b8967335185ba7ee122c56869\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Darwin\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 863,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23319388,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a7223b77c9ca3ab6de014f4f9b566c79dd3f4161c5ea4223b6ff8608285535d9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Eucla\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1029,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23319975,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b7483a966785d32052458bb16347dc254f8b94bcfab5eb914f4fb68b6b2a044\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Hobart\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2875,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23320635,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b833dd205698e9e4ec4f134c910a46c2c203379594b70fb3dc15dac7d8d15a42\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/LHI\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2415,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23322236,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:63e2d8d01b17c6ca1a6e7c7eedeb65f1fd8c2611c7354458bd44dac83e8f4c84\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Lindeman\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1062,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23323610,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9134536b2b9078c1807e7529de64da0bc34f32f97aea996b769ccaa474c3aa12\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Lord_Howe\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"LHI\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Melbourne\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2763,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23324330,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f11ce1fe7a552704c280c6e642ab51a416aff8ad6b9d9c987e90280ce0c6fc3f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/NSW\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/North\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Darwin\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Perth\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1019,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23325936,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dd69002d8273324fcb2dff6a52a11667b34b9cdbd36858d5ccda4f2785b7ef7a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Queensland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Brisbane\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/South\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Adelaide\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Sydney\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"ACT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Tasmania\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Hobart\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Victoria\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Melbourne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/West\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Perth\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Australia/Yancowinna\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Broken_Hill\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Brazil/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Brazil/Acre\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Porto_Acre\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Brazil/DeNoronha\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Noronha\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Brazil/East\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Sao_Paulo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Brazil/West\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Manaus\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/CET\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2642,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23326941,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a9ab0888ef44577631cf924205405001a436f7d97899c8989907aba1b77a61be\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/CST6CDT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2834,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23328412,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc4181f42429479b45e3b5d1e9d8775017957bca5c82fc9530769fcb81b2fe8e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Canada/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Canada/Atlantic\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Halifax\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Canada/Central\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Winnipeg\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Canada/Eastern\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Montreal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Canada/Mountain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Edmonton\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Canada/Newfoundland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/St_Johns\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Canada/Pacific\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Vancouver\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Canada/Saskatchewan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Regina\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Canada/Yukon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Whitehorse\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Chile/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Chile/Continental\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Santiago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Chile/EasterIsland\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2768,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23330371,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b8c22dce2336c2177f7f27feecaf145c40f13e16b5038abe13ce8dd764ec6673\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Cuba\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2977,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23331930,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0d4bfd6b414442661f79556ac625c9f30e051af6694be67e3ad312e9e9589c50\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/EET\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2416,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23333598,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7a4178745768032216702f31fa03f676677d5951079d7e17856ab4be0ddc4061\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/EST\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 667,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23334948,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e7c90a5d782d8843b78996aaf9cc7d332f29d923e8b41739fa0d523b6675a816\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/EST5EDT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2834,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23335393,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0f7e22d9f44ba8c1c49034d187a3910eabea89ea5702363f55eadfcd12e01daa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Egypt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2512,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23336984,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a3c84ceb744bbb495b49ef286308143f267da03f75931b82fdcb5c5a3aebcdd8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Eire\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4071,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23338418,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2004b00c415e097897394d0fcbe0e1b28f6db7b708f7777d51344a73de890132\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23340689,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9012b089ee5a16e2015052ea85bac9a4b506801bb4acbdc9e03b4d712ef198dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+10\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23341141,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:76db27877af699cfe9adbc2bff16b7cef3fe3b9f74f09cf277b129e32260f736\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+11\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23341593,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:704c6797421f83f7b8a2e0d2fb8dc81bdcb0d35557fac776eb3f015f86405ed6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+12\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23342046,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cf46ced23a838bea5786cb93a1d8a6fecc8767bdf8e038d288f29716ee516393\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+2\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23342499,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d79c8c528f6339f8db638202241705f906bfc75898e1898c163fa660e3139e69\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23342952,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c779ce86e70bb6f078ae7eaea3eec065cf34d174193efe2c0d8269ab56a315a5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+4\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23343405,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c0127004db0b9e3f959a7d5a2ce85e945d9f6cbab766b84ea7ad290c205a36fa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+5\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23343856,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b4c34c2105cee69da93a16895a70309d6f66cbc3963e50fbc34a3323c1fb702d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+6\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23344307,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ee118477c847ebfb76305fb363fb15e85eb96321c4ddbf7342c66e2e96ce3dbd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+7\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23344760,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b27b23ce790d6fd0c471e0e3b982d8c17bf3c4eb80b5e96c4746d188d9e0befd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+8\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23345214,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:86c26e9def2a5dcee6c2df681fab85b0bc007d9598ec04b9322f43238cb29d15\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT+9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23345668,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a90f65d22e4d8e80308d4dc9bef7b81d8cdb0a475725df4fe8b4629afa28b9d0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-1\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23346152,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a41423d3823b3f569397236083416aad827ce76ba59b60c3e90b7d770399c51a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-10\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 671,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23346603,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4d69d3e560e906a2577bcd83ad7311ec9dbdd30eea0f7d8528a2b6e16c7a0232\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-11\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 671,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23347056,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1f5428fafb9651fd439f216d062ee891777ab36678e3691b0aefe33c124b59e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-12\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 671,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23347507,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:50a8dc6b9660c4aca6babc6af0470463410d0196745f49824f38a03e0f6c1410\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-13\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 671,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23347959,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c11600b000c15510f07608a1e114b211b9cfd1503d3b2218fc6714bff20d66ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-14\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 671,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23348412,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41247eb4e0246a199f0efcec850f45bb8af4eb81a9a3370cc826b782ea741df6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-2\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23348865,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d12a5d3f5ce6aaa1cf0c06dbb47f0453cc50df54294775dfff2572ace625985d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-3\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23349316,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ecc1a893c3f29152db79772575ffabd6560594896bad41a22a891b22063b24fd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-4\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23349768,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8cc82f5c8d7c9c91f94e85b79bfff7f6cd20c6caf8b7e584a801453f7665d109\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-5\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23350218,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ab8fd10e20bcc651da9a0576a54ba9a078a5c5cb5d0b3360b62cf2f89c107448\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-6\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23350669,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c42ac9c37dd6f9693b5688d7dfd969c78dd830dd9c937c1fc1866009f4fa8c57\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-7\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23351119,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a5dbdf8cfcc24be96f0e4050f77cf2955d7e1c6b0b22f80acf3257b33677878\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-8\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23351571,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5b800d1e9507634e1e900f3a9ef7389852954cec6bdac489beac822a5dfdbc1b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT-9\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23352023,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4e3d7d971253c770534e2344257199faa641ee50f914237c23a81af9b0ebcef8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/GMT0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/Greenwich\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/UCT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UCT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/UTC\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/Universal\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Etc/Zulu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Amsterdam\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3489,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23352633,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ae32e0cb5a9ea89b38213163daf4feb4840a6b72e82d5464c647d0a618531697\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Andorra\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2291,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23354524,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1330f8009adea3c6e5134cdeadaedaa6fbbcd72b2753207ccbb953ccf5001d18\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Astrakhan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1723,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23355815,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d5a385bc8f28267d22d117464f6cb9a9cb179dfd192a4f04a5cc49044b6cf3bf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Athens\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2811,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23356823,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0c23a856f0e9c47bba55cb81c426eca0d190aea6043b018e2affa55f21b43664\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Belfast\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Belgrade\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2497,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23358438,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3debded934cdf0c472df38375bd1a69c9135fb21890969bd68a50956e7181e7c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Berlin\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2875,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23359833,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0b4604767edbae4fc43cd24bd96ec235232471fddff9dc15328c0b74d4c3dc90\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Bratislava\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2878,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23361442,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:faec42cc5833011f1a0f07219bbdea30138befb2c85258c5e5a0d37961a0bae7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Brussels\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3510,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23363099,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b7389bbaad40e29c14b6286ef458854c08a820a22dabc9a9df0a9a371589da0a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Bucharest\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2761,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23365064,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4052f7958d6994e77da457cc9255749b2df0a6270841d23cb93937d58e1f4ec2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Budapest\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2945,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23366618,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:865242b95f7d1177e289a4853ab538079af84710f8f09b4908db5928670e016a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Busingen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2458,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23368270,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:46a95ddb0c5047f5b03c6ebdd2c35f87f59e6719d2a2385134408f826753e60f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Chisinau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2985,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23369688,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ea169f6577633d68990e74350d1f53c54d309ea1fb461bc235f6dc3c2bfd03c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Copenhagen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2700,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23371326,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cc7d0746ef3061d3de714685a821a4781abe813fdc6327f162fc70b0c22d62ac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Dublin\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Eire\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Gibraltar\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3601,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23372927,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:16fa8d1cb048eb5d4defb961df736ae7db4d477b6f08b9d94572da2303681fe7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Guernsey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Helsinki\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2449,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23374929,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a1894d50d5bc5e541f340d601cd8ababe40da90fa867cc7ed3215be1cd6282de\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Isle_of_Man\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Istanbul\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Turkey\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Jersey\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Kaliningrad\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2058,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23376409,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5776b8702f94742194f5280ee49e61d1b8474b6d4808284afb2aaf62b9c4c7fb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Kiev\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2637,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23377565,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:24c81f9cf9518821df795eb6c2660d1de98a29d658922bec6f70b05dc9f427e7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Kirov\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1693,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23379024,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:07d63183733df20b6fd7ab0978715f8635406b229e4c8f0b6340aadd57567618\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Lisbon\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Portugal\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Ljubljana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/London\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Luxembourg\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3514,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23380120,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:af6eb983dfb45c9e363dafb9d26b8466179415e37ef87991b258523a36c18239\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Madrid\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3177,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23382026,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01a00debc9c470fe55edfa31568135024d2450ba34c1c88ed16d620b67af5d83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Malta\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3169,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23383772,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:80919f93a3dd18f905ec9ecc82797ea80f289fe05795f32bd9390dbed7ff7d05\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Mariehamn\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Helsinki\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Minsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1896,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23385589,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c77b4d9a74af85f48b6bea8b640f6c5de557d64f3995567d4978fad4e8263f21\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Monaco\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3493,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23386672,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7bac15b163365f1415bd5830c70e2433d36b70b490a393be07d0562071bdc98c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Moscow\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../W-SU\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Nicosia\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Asia/Nicosia\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Oslo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Arctic/Longyearbyen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Paris\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3511,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23388684,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6cd62d7d4c3d0be12b47e2e3c026ad0b5513f16e3dbf46d7812f0501c0522def\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Podgorica\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Prague\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Bratislava\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Riga\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2775,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23390657,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:543f059b0b90d203ac284c74a9eb1a43acfb6f6de2c3f618b9df24b1b53564d8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Rome\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3232,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23392186,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:52028442c2ca14e1c747c8a0e0c5c152b1e0faacdabe0dec7e93374bf5d36ec8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Samara\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1779,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23394045,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e1ba77c8d804455d5fee38e828902dba23e86521f398f406523a4de117599f6b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/San_Marino\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Rome\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Sarajevo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Saratov\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1723,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23395140,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:38653f429ca844f5c49babb688a91384baa163800bcdd63fd80197d042b3ed86\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Simferopol\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2030,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23396154,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c749271304d25a3772fec2f14e1a9fe29d66a993e88384b4fb8c35305208aa06\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Skopje\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Sofia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2670,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23397362,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2d9a0ae58e5f9d5b678d68e5874b4d4bf0481a5decd3e9a097bed5f172a16cd0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Stockholm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2458,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23398913,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:57c9a0626fe99afad4195a26bdd53a0013d465c876e4970a365196242191009a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Tallinn\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2727,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23400331,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3ce08292fa8bf8241cfc2bd85b05dec3459e3b653a0333720380ef66841e9db1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Tirane\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2638,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23401829,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aecddbe0e431c06b7d90ce8c9be834f2aafeba71716812b98797272f72d54141\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Tiraspol\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Chisinau\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Ulyanovsk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1807,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23403357,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:40df4bd977a40651e76d094572dd6bdef9124ee8d9d534ed06aebbfc8c5abbc3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Uzhgorod\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2643,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23404397,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7ede029288ea2e0af7da34e57ef3414159d510db5e41db99ef2bd0becff29c72\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Vaduz\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Busingen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Vatican\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Rome\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Vienna\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2777,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23405928,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0157530a51d22c4596dfb3d37153ba3b41379ddafd6ca1ec40ea288b3fe64dd5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Vilnius\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2739,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23407483,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:60409d0bfd11d41ed822fbc0564645c41d63b215b8b1822c369a5af7824631fe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Volgograd\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1693,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23408974,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:75aa972974961db6368d4fde9ce7d891f1b5dbac6911f636330347f5ef3e8513\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Warsaw\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Poland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Zagreb\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Belgrade\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Zaporozhye\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2655,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23410037,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:67d4c4e23f865eeb4fcc7779563524189dd9852d7547ab5b9374f637f4f3faef\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Europe/Zurich\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Busingen\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Factory\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 669,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23411552,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:10cef6c7d0457d242b17866e3e811bed8a06ab56064acebac07f0debcbe92006\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/GB\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4227,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23411990,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:256c78cc8a67c9b7796737d6af67860246715133443319c41c5962d4d4411f6d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/GB-Eire\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GB\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/GMT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 667,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23414295,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:da4f5e177e0e5138774896d0b82b59cce878cf3700734a5d6cdfac2f0f96eb28\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/GMT+0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/GMT-0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/GMT0\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Greenwich\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"GMT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/HST\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 668,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23414810,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d6c14dcfa90060f656344c7f7078d78fd6046e38d850b78de5f066c0f3c0c655\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Hongkong\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1729,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23415259,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:49e939c0d7b29e67f9aa7c598b0f9b058f41ea38a34c76622346a60315c4312f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Iceland\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1728,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23416264,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a419779c4e933cb9ba204355f1a3649c72d443a95e0a6d81ff506ab467293c0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Antananarivo\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Chagos\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 751,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23417349,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:be59ae7c9d5f671c7ed258fc7096743913d78bea71902d23bb77c54b8d0175eb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Christmas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 691,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23417847,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:38acf43ebd68867bedb27ae1544e6c1f25942ed76726c77e08ef523d84e57c9b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Cocos\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 700,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23418329,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e0ee8a9a676f4bb453d822ceab90aea7d606f9db114a0b1f97bd8f301db00f51\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Comoro\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Kerguelen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23418870,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:efeb12b4af7ee8fb2896dfa04e1864e486423a653258b5bcc24b126eaca3f260\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Mahe\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23419339,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:99669b539e7dbdd6a9a06df816e3b5b9e3596c9daf2df41605609c1a0507cd9c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Maldives\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 746,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23419818,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:882ac362aab99f9682e268966fed6700a7981dbbfd2d64ad9e2bd864f752d996\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Mauritius\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 793,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23420316,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6e54749fc42ea492dce64468fec1dd4ce09ac3270884a0e3b92a804126940b1c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Mayotte\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Africa/Addis_Ababa\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Indian/Reunion\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23420891,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c271916f61f082d48ae258c12cf41ee28dd98e83d370deb4599ae69b6e8afa59\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Iran\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2244,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23421357,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d3001b5add2c5861093986cd21513ff46898e42b18f10a60693dbf6c53d9f8f7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Israel\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2805,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23422628,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a8271f9608d08293b37ec6a3ce75711954ee4fbce8cc80b19e5c4249618ac3a0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Jamaica\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1047,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23424200,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:47ddec901639efbe7268363dcc0d8b92a855372b0cae12720d68cce9a8974fdb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Japan\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 858,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23424863,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f3fe73852e6756d6691f8c06056cde1a666f23d1f9bc940ac0e11c7fed3805dc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Kwajalein\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 785,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23425419,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e6d534633a44ad56204f74ad53a6329eda2bc44a9ec9f8b9d9942431f2c8ce9d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Libya\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1195,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23425926,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:72bb85f8ac4ec74b2ae92214c047c82f1f39c9c0785d0f54e152b8c1d940adda\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/MET\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2642,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23426660,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:735b7a481c6b4024076996235dc00c88eba04788ea0d2320f52f3b6f832e2c5c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/MST\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 667,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23428127,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d7ed7889d7e664fa5f24d3ebca03abc5e6f4c1af886e13b6d057d0aa4009a953\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/MST7MDT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2834,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23428574,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f5bff9e9551d99b333440822fd3fa74d2bf03b0303585ce0705557b869e47e83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Mexico/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Mexico/BajaNorte\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Ensenada\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Mexico/BajaSur\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Mazatlan\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Mexico/General\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Mexico_City\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/NZ\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3000,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23430323,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c6fa7d47e6fb209806155ca05d2d0721726515ad678714f3197b9daeb9da3a96\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/NZ-CHAT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2613,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23431982,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:26f595850d1431c8e91ec414ecd29867fe361f2e49ae0d04f44ed3b53df66240\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Navajo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2993,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23433446,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7448c66048e5489a28ecad3adc495351163e62cedff714bec6d15506a9e1f548\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/PRC\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 954,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23435124,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ad1e89bcb5b895b4163043ba8b4806c1dd3d1886964770688532adbc0d6ffc4a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/PST8PDT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2834,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23435732,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f08ae6766d50d2008608f2e668ff34560eef0fb62b3e60df8c019e04cb914780\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Apia\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1660,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23437373,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d83e28595f25234e2e75a754d66606779f497f41f3e1e5a8389c62c85f8456e8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Auckland\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Bougainville\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 822,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23438397,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:74c033543ad47e18b82f929308eb88b742b84a4b718d0c743e87339a917730b3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Chatham\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../NZ-CHAT\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Chuuk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23439002,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:31b6fa3e8b930a5d14cf1fe401480d9bd3acc0d2b202ee8d0e2a72aeed2e3be9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Easter\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Chile/EasterIsland\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Efate\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1018,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23439534,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:11867f8f79968dab62432ae65be80de4c1ce8c9f4f2509c73f1239f87a389e74\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Enderbury\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 785,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23440190,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4980802f3f305cbbc84449c6318262384c855d2c2b1c86cdddc64c50b6eb2f17\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Fakaofo\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 747,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23440705,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ffa2f3656163dac98d7128708f767a9003fea91c6a0eab4e088c8530ad819ff7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Fiji\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1616,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23441201,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c48cfd35fece2a2e2d9e69bf8a6ac59c85db1414f67d322e98d21b6ad246a80\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Funafuti\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23442179,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3b3a5bbce2ef074a52e8c7d0c1152b4859439e053ab54fbf8fcac3416946313f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Galapagos\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 794,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23442666,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a73b7fbb4d963a4de8a2116696fb14cc1d4fea7f4ee63a7bebf3de6d37ea3f35\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Gambier\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 712,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23443183,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1467e739b00e63003ee811eb5f3a7598ec82c8e69132c9d13b05b4c972afb883\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Guadalcanal\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 714,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23443666,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:305ea4443760cd08775ece730d93eead1265d9c30f02f162009397a653892294\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Guam\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 765,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23444142,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ee75c94a1fc4f5a363f4c6af4f386a4ba4751b6dbb43068cadaa613fa4ea2219\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Honolulu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 816,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23444659,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb9b83b1f1adf4db95a208e851e6681f5111c25071b85e42620aae507b93ee40\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Johnston\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Kiritimati\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 789,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23445243,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b72c4f9c16069a15f87449a89faf1d1cea5388eef787f99f605a5c24316ae995\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Kosrae\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 777,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23445758,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:330b3690e2848d83b135182823d6a896338ee4512e9a3bd59b166395992d289a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Kwajalein\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Kwajalein\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Majuro\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 747,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23446307,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:896736fad3956359a0366760467b2af60178d8c6dbc439a3d004dfa02bfb3130\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Marquesas\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 721,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23446804,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:90d1dafd8f01d16ee5d029e9c9643275a6ce5f611a99580243a478cdd9d334c3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Midway\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 736,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23447285,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c996db6822af6b663b37e0c8750132432169950eed2c24bab4c9f843475b5cb5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Nauru\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 808,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23447774,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:636be1327c578fde487fbba425de45a1b6ed7ad12921b99b74f40443ff10a28a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Niue\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 792,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23448291,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6ea86a60548452d527af1bf1437a846d35a2023295426a924060e001d9b34986\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Norfolk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 849,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23448807,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:46a26c4fc3281118941c7da66a7b333ff252e5c411310a13ef974e4600e4635b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Noumea\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 854,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23449346,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4181221801b85e6905d0523c8ad5a799c5827cbe3813676d40c47ba8f2a53043\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Pago_Pago\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Palau\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 691,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23449932,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4353921b3ff2f1d2e37cb674dbcd8ce1ed96401630d55a21bdddadd87a5af7f1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Pitcairn\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 749,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23450416,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9a483181af824f93b4626871dae31022260d27180e0f15a7dbfe076bedebcb71\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Pohnpei\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23450913,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01f21467d5a56ff85427dc4cff9466eb47be79d73fa657658c111453d0653919\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Ponape\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Pohnpei\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Port_Moresby\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 714,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23451438,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dd70e9df820da5d290670f409b945186fb3e4c2597b981f6aa00618f9e9fe602\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Rarotonga\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1128,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23451938,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:03017bb1fd0bc79957dbac5888563c69e0b2dace69e995e7f5dec95d15cdb78d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Saipan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Guam\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Samoa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Tahiti\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 713,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23452715,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa925368f0d1362d2c8c738f6d78e729bce16dfafb6a19111ba54c28cfcf77af\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Tarawa\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23453192,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d1e0a1228e386b4a69c1d79581e8d034f919c251109e6ad18a7ba7a269cc0e1d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Tongatapu\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 919,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23453679,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9729f5d257db4cd92c0055ba6c667f6e5ee21ee7436cb5df495a887d2481cccd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Truk\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Chuuk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Wake\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23454297,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8258c1f19702e381c4bfce3cb5b1335814a593531d3211b7a4a323d42aed7140\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Wallis\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23454780,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2077f480b59aec6abf5cc989c61246f8fc4c1e8cd8a3e5738eb9ce63b543d586\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Pacific/Yap\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"Chuuk\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Poland\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3245,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23455299,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2776052936d3361f49da479c0a6d522ea7ec256300cc9263d1011848ab2bb3a9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Portugal\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4009,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23457078,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f8e850961fc42ea64edb30cebaabad27fccda97bdf6cf1047e4051298bdf20d0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/ROC\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1330,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23459223,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d5ff02c7a5dc9adb7a5b8de1e492f8ace92d832e8f2f6879265520c47f850078\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/ROK\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1071,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23460015,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8520047dc59323aa8ba91ad43e39229e36e4e0381ad14f59af4395b669845afc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Singapore\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 950,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23460673,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e2140fbf66b5f7a235fca25454176d2eaab4c8b8303fea4ddfec5455c549bbac\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/AST4\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Puerto_Rico\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/AST4ADT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Halifax\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/CST6\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Regina\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/CST6CDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Chicago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/EST5\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Cayman\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/EST5EDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/New_York\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/HST10\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/MST7\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Phoenix\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/MST7MDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/PST8\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Pitcairn\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/PST8PDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/YST9\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Gambier\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/SystemV/YST9YDT\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Anchorage\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Turkey\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2692,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23461615,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5bd39443ec8a05b4c68c2cb546d9a76b11c59a8d66823d6fd2eb6e49c50497ba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/UCT\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 667,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23463108,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:de715c1e70331ba26ec0db477d50f3df14a4be5a552a5b40683a3aa7882b2975\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Alaska\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Anchorage\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Aleutian\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Adak\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Arizona\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Phoenix\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Central\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Chicago\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/East-Indiana\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Fort_Wayne\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Eastern\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/New_York\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Hawaii\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Honolulu\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Indiana-Starke\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Knox_IN\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Michigan\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Detroit\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Mountain\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Navajo\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Pacific\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Pacific-New\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../America/Los_Angeles\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/US/Samoa\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"../Pacific/Midway\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/UTC\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 667,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23463934,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d19fdd5d26a7753518ee9a09ab74a8e4efa9a4e6ed56eff85baabd8af9c0e459\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Universal\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/W-SU\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2084,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23464417,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8e1367300579da7319742b25b9da707131b058482c77e7a707c71aeb60f067ff\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/WET\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2413,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23465586,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e9826478fee66e6f8a7583d9a67d82f114f8a12856b4f4a6bfed5db540c54753\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/right/Zulu\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"linkName\": \"UTC\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/zone.tab\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19165,\n\t\t\t\"modtime\": \"2018-02-16T17:21:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23466994,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:14cdfb2c5e3f7201d82c368d3ac204a3cfb9e50d89dd106d414e302db57c141e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/share/zoneinfo/zone1970.tab\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17781,\n\t\t\t\"modtime\": \"2018-02-16T21:59:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23476414,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3124b997b9183f7029585690ae3cb31afe1e271a4bbdbf05ef002d23d03760b2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"usr/src/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/backups/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/cache/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/cache/apt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/cache/debconf/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/cache/debconf/config.dat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4454,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23485364,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dd96d0ac5c66a80416a50f0d94b856efcb707bbc0c49d7ecf07a4dcf33bc4106\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/cache/debconf/config.dat-old\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4294,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23486224,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:700ffa319f2c418a677fccd79546da9c099e71835817ee040fbc3720840923f2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/cache/debconf/passwords.dat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33152,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/cache/debconf/templates.dat\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 725910,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23487077,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a5076b4345d5aafe17f85ae91c948727df60311056601540afc7c89b449929c8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/cache/debconf/templates.dat-old\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 708570,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23673393,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e4e46a38994fe5ce8a0198f315ddfaaa3fcf76b6d64357d066e2090330eeff90\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/cache/ldconfig/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16832,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/apt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/apt/extended_states\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4437,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23852673,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:54dbd6ae802c89a09e004b60fef8a1af518bf488683b270f72d0e88c842f8e6a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/apt/lists/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/apt/mirrors/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/apt/mirrors/partial/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/apt/periodic/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/alternatives/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/alternatives/awk\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 207,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23853417,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:06c7cfca68d405ca5e20fd379b93fe97fd1698841a1449f9b403115cedcf8eba\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/alternatives/builtins.7.gz\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 83,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23853603,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6cd368606c13e12657f237f25e3ddfd89c6ebc34b52b8391561ff89d0c052f62\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/alternatives/pager\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 150,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23853763,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:904b645490f378ef86609d5f40ddc2334aad824f59ee117664d9598ec0ac48f7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/alternatives/rmt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 113,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23853938,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cc31c88e6e9660da820eaf68418b4e9dfd76dfdbbbcebbaed446afe397971dc9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/available\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60988,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23854101,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2aa0bc06f4328dd5232529021351d42ea097dbc731a3cc1c07fbe208b0f1379f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/cmethopt\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23872106,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:162ba45c89e2735aba3a5fcd4a0ad00efd9120edaa2215a8f541058cb895ce29\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/diversions\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 136,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23872222,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:164c982bde1284c84173ddcfac3bd28581551a51abae77ac01f278829477525a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/diversions-old\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 98,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23872399,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e4c917474e8711b898165d3b464a2c47c027a28ec6d7f87f4bd2fc1deee2a2a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/adduser.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18,\n\t\t\t\"modtime\": \"2016-06-26T22:55:18Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23872595,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2ed8c75e30af614b19760b001063fbeb2a48ebaf469c44d921d3df787f2ca173\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/adduser.config\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 929,\n\t\t\t\"modtime\": \"2016-06-26T22:55:17Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23872725,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7bbbed298ee1cba145ccced3c596025d1bf420c978feef4269e9e3c0c8ef1855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/adduser.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6420,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23873215,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d2871a453ad11657eb656cc724f8fde70e8e618722a033460deb3418a80615d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/adduser.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6061,\n\t\t\t\"modtime\": \"2016-06-26T22:55:18Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23874065,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b64ccdfd5680940021be7d9ce124fe90be65b8680bd1ce1228581d61efa5a616\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/adduser.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 964,\n\t\t\t\"modtime\": \"2016-06-26T22:55:18Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23876178,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:725a17e3ccb6bcda57076fa51d824c1a0903c885261c34e053f9750be30a2755\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/adduser.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 297,\n\t\t\t\"modtime\": \"2016-06-26T22:55:18Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23876695,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:873add4d34b1673f89a54e7bfa41f6d70f006f4c2576259e848063dbe216e233\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/adduser.templates\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 16424,\n\t\t\t\"modtime\": \"2016-06-26T22:55:17Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23876976,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c32dc4475a9743b42b46001f490733dce5bc10ee442208f4f50b406f466c1214\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/apt.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 121,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23884545,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:40d910bb31d4f4744f154ccd80bf53c3ec5574f1577f35af78e5ef77dbcaae47\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/apt.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10104,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23884732,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f7f8f166f78e81f6e3c62b94413224d446b3097bf1bc06553125db46d2d049f2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/apt.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 11361,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23886194,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fb6e26258b39c79746935376b34fb7e5393c1d4f9f599291e7772decf30c5f02\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/apt.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4578,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23890307,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fbbdc95f0bafae4c6e30b833a24a1488415c9cecf5e3b8b77e5eff0515092d21\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/apt.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1313,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23891951,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c98cf0eb8b2f164769d0d658eff78b558ee86604444306f2a8fa6388e53d3b10\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/apt.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 247,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23892610,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dc05f90439c5bc1efaff372a49e9fbc394de3645424b88245fc7b9f42cd0723e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/apt.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 459,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23892864,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:61c2d8f74fc8d7ccfab6bc555d4d658ef270e93aab26fd58d522518e8c225bf5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/apt.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23893211,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ac130374b3322f21573625a13454d60cf7b5166bcd43b931f8ec09e99d54c455\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/apt.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23893346,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-files.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 114,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23893518,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b3e9e5378d40d8d9e7c508b759513975ad83bf6faeaa3a1b1684c53931b8556\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-files.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1749,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23893703,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4bbc622bdfec8ff870c92223f56614cc43a22361d99e7e4f9d4b030c1cd70ba7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-files.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1829,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23894270,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:378b9d019a502f188899b209f441427839c7e49d19db0896481343133e8083a5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-files.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3370,\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23895147,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5b201cc9661b9d7ec075602076165244482cb4b4afadb1a8ed8bc62f10938fd6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-passwd.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1120,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23896095,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:59e7d3f01481b921ab2fe7b7c0f4c9010c5dbd68e63fd6aa6b98144ec444129c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-passwd.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1238,\n\t\t\t\"modtime\": \"2017-01-16T15:52:12Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23896429,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4e1e3bf27aa7bad2a465a62d6db8f7eb57c60ffebd9473e2d0351ad8a92ef117\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-passwd.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2802,\n\t\t\t\"modtime\": \"2017-01-16T15:52:12Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23897056,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01ea366cf8c635d5e21ce289ab3b9998247eac1d3f33312cf002257b0abce445\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-passwd.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 206,\n\t\t\t\"modtime\": \"2017-01-16T15:52:12Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23898426,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1c04914a45a56607aa795b52767684381625c27cb3a8f45302cbfa088f735b5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-passwd.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1516,\n\t\t\t\"modtime\": \"2017-01-16T15:52:12Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23898677,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6e38694265a25ef4a21a595dbcf58679b02eb3ef91a76b8ce293cfb97def209c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/base-passwd.templates\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 108623,\n\t\t\t\"modtime\": \"2017-01-16T15:52:12Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23899429,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f7de1e47978fedea5a736df4f16b947218f4e65735753d97c1c8954e8312c776\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/bash.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 77,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23906721,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:547d1cf6291bce0dcc569f9caad2b7d204f42efb7a20047d86aa48e0c305a52f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/bash.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4636,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23906872,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:58b51db22b40ea38bb1ba60552d57ad2f97a790e218779fde6502d1bb2df8dc4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/bash.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4281,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23907602,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d31124a7c119d4a35de5759395224b560bcd1f0d475877e11be7cb455c3ddb33\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/bash.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 596,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23909308,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:28393012a0c44900dd8c3c0cb5a707ff1774556a5630efb2d853ab4d2564ec58\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/bash.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 493,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23909725,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:614ae2549afbdf6887b92b717a380196b3da6e892df5594b37b1490a94c9d65b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/bash.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 36112,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23910111,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:41dc07e488ade0ebca895980e2be50c12111e82784e27949a0a4418c04bec114\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/bash.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 289,\n\t\t\t\"modtime\": \"2017-05-15T19:45:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23923457,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8d4c0e961f582ca7821cd5b81c8ba304a90f2ddfd6efd963f58cf6020eb2198a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/bsdutils.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 851,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23923757,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d4b57cd70404a8b1f20addaa2a31b0ff0539f2b9175814229e904f5f4804661a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/bsdutils.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1262,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23924053,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7c9fe1c6a5c5d8bd7615a54b636fa7f952de2f9c66b3d62fd5df7e98f366b38d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/coreutils.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 9706,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23924713,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:73887279428ab722d2e19ab01daa96efa399ff7fd71c5670f3b692d86dacf190\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/coreutils.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 15674,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23926177,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dc2084243a4eadceb52eb0911ca26725b3537176ee922973d1c2b4e412cadc91\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/coreutils.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 114,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23932568,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b8cc23953515e77bc392d81af72f7362118a5fdf5961680620c2f832bf4c56a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/coreutils.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 95,\n\t\t\t\"modtime\": \"2017-02-22T12:23:45Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23932765,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fb04069056d6bd6aadb41350b25da0f9da66ff520185f4f16445430535e1bf18\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dash.config\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 769,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23932954,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6ce6e1f0695bac42e20a96be49b70c79cf596e8f81047ff4ea3cf922c0a9cc57\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dash.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 418,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23933488,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8c70bf1decf43dd6558efc6fd6115e0a7079f2ed6b6d67cdd16b3cddd170ef83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dash.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 569,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23933727,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bbb41d92377cc9909cbb9eff846728815b57b30770a7e4435570bc839f136596\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dash.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3651,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23934134,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0ba947daf43666c6e13f9da16a5afe0349c1bb89de4776f9fcf10f73a426e23b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dash.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 341,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23935661,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9f0a19bf26bba371cd2ddc8b00ef14af396d279c5838beb2a13faa9a7ea624bc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dash.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1025,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23935929,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3de6d6ca5b09c610c66ec74b2e40f3d68b11c7c982639a588e5533505ee4a6b5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dash.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 563,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23936576,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2b6e56c709fbdf8956f50193ca6312a74f598c49269298699df88a5aa1df704a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dash.templates\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8304,\n\t\t\t\"modtime\": \"2017-01-24T05:16:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23937002,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9451f0fff5c8aa0da29e1947305f9430ab0b1ee6d7eac8b23f46d73716c5c64c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debconf.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 48,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23940553,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1980054721522ce9b99b3c1ea992a517b0ae93c7eebb9c502129c5f12ad928a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debconf.config\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 478,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23940693,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4f6cca919cf82b607d0ec001e451566c887383c41320d796021eee66b4473db2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debconf.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7673,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23941070,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:87aabfdba6416de57218fc0c9df32a0ee7ca4135c6c27ff1ba3439538983ee79\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debconf.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 11273,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23942199,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4ee64bce4e28a40642b016c6600a3a750c01b04da33b2fc70efd7327483adda9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debconf.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2771,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23946063,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4cbedde53a7f9b8656d360515ba3c21687202322424f3425ec94f6418befa5d6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debconf.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 173,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23947305,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:51a4e382b6fe7c3211ff6bbe2284d0556e92c66d8204f35314687236b1d0bf36\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debconf.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 304,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23947542,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:790e4c93cdc18ccaafffb44e248525d75f467aa801915de8bf6e5b73e8e37050\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debconf.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 563,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 23947827,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:70c4846220638de0c245ad9c355927c73569e9bacb8d2b0b502c60bf33112713\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debconf.templates\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 143753,\n\t\t\t\"modtime\": \"2017-05-21T17:08:30Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 23948268,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2dbd5c40bbf8d9c6b5f4130166e3ff9fd011bb821baa748aaa18215c00f8931d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debian-archive-keyring.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 484,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24004857,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:654e2a0d33fb4d1c829c44c70dafa3e5595e38d152995596e376c06642eeefea\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debian-archive-keyring.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 856,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24005062,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:96f4f39133ba8c082c06a57b06c06aad72883f4200d0393ac33b48703a7675c9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debian-archive-keyring.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 408,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24005347,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:54f451ebd946b6a0d11d99c92515a5038a0f82c6b47899e1e34b644baf4c7b17\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debian-archive-keyring.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1003,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24005655,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2f8c9f4f5775f627d7be2a1243f276d0102cd21a538e29c09be63533f93c9938\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debian-archive-keyring.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 502,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24006260,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b5d6c516c9658fca66891cf2d4cbefa8df3a7589ac59823648d922e8e3f2da20\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debian-archive-keyring.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 386,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24006579,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ecd03bbc5ff5faaafb62bf6386197c83d87ef43cf40d3bb61207c36950e85e65\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debian-archive-keyring.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 386,\n\t\t\t\"modtime\": \"2017-05-25T18:17:13Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24006845,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f5ce562982ff479363c27e6ee1205852f1112277e91f449e1f8c17018ed6b340\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debianutils.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3047,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24007107,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ce60da81c5675bf3052f1bc84b3716607de015c561813f1420797e4a106e3efe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debianutils.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4707,\n\t\t\t\"modtime\": \"2017-04-02T17:10:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24007642,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7e90c622a29d314ec3518d506f3aaca217a8df282813351308a62ef199ae2e81\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debianutils.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 467,\n\t\t\t\"modtime\": \"2015-04-26T14:59:54Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24009426,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d7aa50ccd2391e2b8c627cde1ca98128022bcc387801ef50c12fee0bca864ddc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/debianutils.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 377,\n\t\t\t\"modtime\": \"2015-04-26T15:13:56Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24009780,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cb0dfa3fc27cf2dfac46a355e383fc25a920cda0622e1225cc74fc3b01a6c4b1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/diffutils.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3727,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24010100,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:368baf799339402c56245928477592cbb954b5da994f62c79d5b0e641b100746\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/diffutils.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3329,\n\t\t\t\"modtime\": \"2017-01-09T22:55:10Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24010617,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ca2a2ba957ccbf9b43ed420641684fe93521f7e1772f816f3d39cd8edc30e55c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dpkg.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 87,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24011873,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e862d61384229595858b2123b380b187a831dacd342813efd146386e09a6d91b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dpkg.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8442,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24012043,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:893380cde895568233bd6640c6e79a271f5cfc599389e056f2f5b504afbb302e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dpkg.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 9424,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24013171,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:87683e11f19a7ef51d7fb580d027cbd03e08e4ec18df283d24deafc688e769e5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dpkg.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 718,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24016462,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f8cee032bc3abd6ef824d60fd2ebedd9c676c0dad1468dcffafaeb1f44d8b2fa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dpkg.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 873,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24016981,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9340ee2661b36e6e22ced24f954f6e372792c9fb08808de2286592031388e507\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/dpkg.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4320,\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24017569,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:90d17414a0558d9c3fa44570de414a3aca7efe58019a9dd008776c2d4fa0d4eb\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fslibs:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 309,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24019268,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dda7841fc00411ce8a30c6df76478ba03721a0624593cc3dc1f368a7bc51eb00\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fslibs:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 285,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24019488,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eb214c1b1b7446602a6a9e5ee69b74795987566d6384bf9ed3ec5216e4f43b8a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fslibs:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 102,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24019775,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0a5eff72f9cdae23f1af177e666a874f6b7762fe6d059cd5f6c2a59f6687b9d3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fslibs:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22220,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24019943,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01c14a7a5cc623a23209987e9efd7f93157653e312ebba93a2860b4dcabc0bd3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fslibs:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24023654,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fsprogs.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24023824,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a21d18e62ee18b0b1afd94364e581e0b9b9881ea6e2df831fe8d4086a9672b9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fsprogs.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3724,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24023956,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:57ef0996457e5974ef969080522b44c749a50a1eaa75213139bec8cfa323242a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fsprogs.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4105,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24024636,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:09b53240f72858bef3331cb8bd2fc2d699ce58d604fb4abb1f19347d4e9eb0f5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fsprogs.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 162,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24026378,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6cd869d76cb66fbd9e1cbeb40d7a21a060ffbef4337f5486ec167b9fa733c240\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/e2fsprogs.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 259,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24026600,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0ac4873d936cbf6ea2c958b686aa5097f82306e1bd50fa6eff1b95337664dac1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/findutils.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4524,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24026905,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6cc308cb40b40db24caf9341efaf30f30cac9d69f53fa2a1316d95d49603ff4b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/findutils.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3992,\n\t\t\t\"modtime\": \"2017-02-18T15:37:32Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24027492,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1035eade64b7d7879968133488de2363b3631c5ac2eb17a2394b5d764a588432\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/findutils.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1195,\n\t\t\t\"modtime\": \"2017-02-18T15:37:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24028958,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c42144b0d65ed7c0e11524c73d8d8d3eb4effc7fa0f5f9625a0fcbf3a1447417\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/findutils.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2426,\n\t\t\t\"modtime\": \"2017-02-18T15:37:32Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24029640,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3e3c2ec17f71c24420c30fc67e3ad2b333e57e2482397c793ed79d0824872393\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/format\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24030546,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/gcc-6-base:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 349,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24030672,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4ae17456b60df15cf95281a880673f742c88d849f8fa894e6947001e9b773e1c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/gcc-6-base:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 301,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24030906,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01193a7e0f32c2ff715c52b21b473c39664a88cdc2f4d57cfffc38741aa62baa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/gpgv.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 280,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24031184,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa4d4420c6b77df26e9b1b0a18411c1430ad18ef9dfbb5e833d8b5480954c598\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/gpgv.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 380,\n\t\t\t\"modtime\": \"2018-06-08T18:12:24Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24031387,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3246d99396b1b6878d53e58d30c99e85f22d6b5ce05e31535894cdecd188903f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/grep.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4692,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24031702,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa6915ec381a63d8a0a642d76ca65dc13762d2148bf113aa53899a0ae8168026\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/grep.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4003,\n\t\t\t\"modtime\": \"2017-01-23T18:18:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24032323,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:96b2aaba953973e6dfc8d42bc8cdffbcc30c66b48611b709c8bf13aaf53e13b9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/gzip.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1024,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24033852,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a2f948cb270e6e1b596c66c81badfec1a83a66c51d685cbb913e4b579db389d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/gzip.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1664,\n\t\t\t\"modtime\": \"2016-03-14T20:41:45Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24034205,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9edef4bf71da5d06c2135332126caae7d5685da7264f3fe6da0065924a32b404\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/hostname.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 484,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24035094,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2e13d739864a9c8648b05ddd0d95c9774a37e57684ba6bad8e0b3d2e806c4f0f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/hostname.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 327,\n\t\t\t\"modtime\": \"2016-07-03T19:26:17Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24035326,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:670b5c913b6da065c03bfe8ea8c01748271833e08edd312b50cfcfd7b032625f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/init-system-helpers.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1012,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24035622,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9746762ee1530db38b7065f1c13389638e238c6215ea54bec21d0fdaafdaf31f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/init-system-helpers.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1142,\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24035978,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:666ecb63b005586a769fdfce6e438c8fac1159b6f7062f2c3808356f2135fb15\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/init-system-helpers.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 275,\n\t\t\t\"modtime\": \"2017-05-02T10:20:21Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24036596,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fc3b0684d7e3817cd81b736b6705541dd779e8af434558ccb9b370d0f52bfc8a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libacl1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 317,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24036878,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e2629d1d7243300ab8132dec55f14a86cd969a75cd29eedd44307cd00b14cd41\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libacl1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 364,\n\t\t\t\"modtime\": \"2016-02-06T22:10:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24037091,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:da8ad230618cacd1466ab9a4162a4b78bafcc18481adf556636c3bb29c9a4e5f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libacl1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31,\n\t\t\t\"modtime\": \"2016-02-06T22:10:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24037397,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:22cf70aad343f840f2ad3e2248b2afa1211b91e83ae25ccdd93c34cfcb64ed1b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libacl1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2016-02-06T22:10:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24037544,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libapt-pkg5.0:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4833,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24037722,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f8dd334e23c8030e4860575052965286e08b44db92dd22cb81669f9d9ab65966\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libapt-pkg5.0:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3882,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24038309,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:736c62eded3c14d921f9cc373dfbc0ae6a2b0b052c3126e123ea70b45921de98\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libapt-pkg5.0:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 29,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24039624,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:66acf56dd792547b8f0503be6e9d104da1c208fce8864bbc2b472efc009005f6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libapt-pkg5.0:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 143029,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24039768,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aa71b10df877584493174076f143defdcaaf59e4771aaafe34bede8857579ea7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libapt-pkg5.0:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24057089,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libattr1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 324,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24057261,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e3ea509a127c52d380f9c63b130034276a4a91ba0abe0a384a6e7bfbecd8b88\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libattr1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 369,\n\t\t\t\"modtime\": \"2014-09-08T07:27:07Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24057475,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8c1f3dde4ab64f0f2f275a58274b92c7ac6503664e35ec68f0b684a60d12f780\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libattr1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 81,\n\t\t\t\"modtime\": \"2014-09-08T07:27:07Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24057780,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:748a3ebb90124c9caad8a81d4f484295df4f49ab91c9012b5e7cad01140c88a6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libattr1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2014-09-08T07:27:07Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24057943,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libaudit-common.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24058120,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e59079facf60922dd9bef9974c852e6ad3315ca2639141786bb268e8e877bec3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libaudit-common.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 299,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24058253,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:809f79c7732df66a7252edea0a4ef3388b43e122fedd8a27bf0a90a059c5c3d8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libaudit-common.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 307,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24058457,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ec9f52547dddbb491f7347c0c8869c5c77f62e0190d48bcedc5ddb31b7dec556\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libaudit1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 280,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24058733,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:af8c5c402019fb6f8eb0afeb14b68d25173855aab601b50c3fedeede3f1bbab5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libaudit1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 290,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24058942,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c50686eda08e1f881321c160bdd141c8372bb4ead4455878ced47463626fbc95\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libaudit1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 21,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24059225,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7f372d6c7b0b7c8da4b6d8de368a525bf6ecbd2c1508e2a9e78a1b1aeb8684b7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libaudit1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2729,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24059361,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f536380e2359838d0d7b6e4f39d035fffa27cbaf0ee6c037bc8961dcd109fe35\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libaudit1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-04-12T16:17:21Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24060080,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libblkid1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 280,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24060252,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6780ed0dca80693cadcbb6c482432ea79e940e32e4022372a0ea1a67475e0d22\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libblkid1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 290,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24060463,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cbdc8b7425256a16bfb81bcccaf719d5105ef7defa393995222e4a9c5562c72f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libblkid1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 73,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24060744,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9c7ba7351473074d5a2f0f23a2378307bfbe271e53d689db16663870b1e7e3aa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libblkid1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4619,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24060904,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b951a14c5f41e6ab1aa17a3ca0cffcf5f8d6c88de04ced37d6369cc6af34fbc5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libblkid1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24061842,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libbz2-1.0:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 316,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24062016,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dcc4781ab86d80723d1cfe1f0ffe2494bbf07fb9c0f68133289d0f67816b3613\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libbz2-1.0:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 291,\n\t\t\t\"modtime\": \"2017-01-29T18:30:31Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24062230,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ca7005e5434d78e7e4eb43e5cb453f72563f1c39cd3a5f63e6fbbd43c29574c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libbz2-1.0:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 22,\n\t\t\t\"modtime\": \"2017-01-29T17:57:57Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24062515,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a48a7878642bc8269876a391a88dd3be02eeff425924be9462c4306ecccbcb20\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libbz2-1.0:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-01-29T18:30:31Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24062655,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc-bin.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 103,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24062826,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ed1819b3573af7f7dfa94bc34567884dce8f5fabd0ae065a646d4f23d28ade32\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc-bin.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1353,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24062997,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5f95bcc50c60a7da16e8712cf72a7e7eae8a4f89640a790b0f86414ae5498a90\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc-bin.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2032,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24063486,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:39a13558bc6e5e62157aea5f1874eb4b3d4199960efe0556fbc839ab39a67827\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc-bin.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1222,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24064565,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:47fc92ea75c72d16a695f78d1fc35671020810e4bef594266a269b34d6e9ac9a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc-bin.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24065205,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3766ef03d6f8c75bc29b5131021ba41e1787667878a97b81264c5fac6ec07ae4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 40,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24065345,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a59a14914231cc9a833ba49b14308e57b755236ff70bc3b0c4ee77b2bd34eed8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 13478,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24065499,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:510f950eefd185e3b1e8ca219c366602149dccfc13ccd0c1b2bc8b3497b19b29\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 21875,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24067091,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7b72ebbbdbef6e0b3516a86fb65d6b7384367b943ee17d8499336efa424bbb71\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10697,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24074198,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:985a06a1f9156657c6a0db76cb2eeae6ceb2878668067c7b05a54e8f44f1ac73\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2186,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24078145,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:19000428e9404e06ed796d7dce5be523f175a88691e101df1fe0b5b3cb3cfe68\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 17153,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24079117,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:792222823d198c8bcadfe6753386216da79458f15b78675634fced792929f91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1047,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24084363,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:005d577db433aef01db36bf3cdd005b18e1f432f594e3399179f27165bcde2b8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 114353,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24084689,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:aaad67bd69138c3eb8deacd4e39786f2ce2a32fc1a656965f11bcc617587d0e9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.templates\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 77955,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24100943,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:da65f855fe06ff7bca68e544a08fb5191abd6f68450b6d7e6201d26bc2f2e03e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libc6:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24128786,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libcap-ng0:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 347,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24128960,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7693823b3ad20f192c8094c97d956b9c74db6589b7bddf8949e8fa74ae377bf9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libcap-ng0:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 379,\n\t\t\t\"modtime\": \"2016-07-03T19:04:40Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24129179,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:06038ad6ef856d76ac52a74735cbb48b6aa3b0ab85a0cd1aaf330bcb73895201\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libcap-ng0:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23,\n\t\t\t\"modtime\": \"2016-07-03T19:04:40Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24129487,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a6ed952c5c08c8997ec9e95b301fe30a0f32e984ed47ba51b542e208ee63143f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libcap-ng0:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2016-07-03T19:04:40Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24129625,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libcomerr2:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 247,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24129800,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9f75eec6de039a666ceb3b8c0e090728947957d50e3dd48336266c4bd24d32b3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libcomerr2:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 221,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24130013,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f76f1ed9c07f3abc32de857fcaf7e3c13b77e27e886a6c72f63c5b571a32654c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libcomerr2:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 58,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24130273,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4b4d72efc9babddd5618d2fbd2b3bb3ba97f06b4e82c8660bf2df6391b137f54\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libcomerr2:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 574,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24130433,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:55c2170f11bf72c7ea81ecf80cd619f1ead728f739bc048ec7989abea0b627dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libcomerr2:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24130750,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libdb5.3:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 346,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24130923,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3d4faca15ced03057f8bc69053d5e2e67c00703abfcf93632139571546ad916f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libdb5.3:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 370,\n\t\t\t\"modtime\": \"2017-09-24T07:14:53Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24131161,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d1729499e5e3880d6c9fa118f119c908c0591aa46bdb93e734ec9e887a786a65\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libdb5.3:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19,\n\t\t\t\"modtime\": \"2017-09-24T07:14:53Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24131487,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:43a64578438bcbe0fa74ce2478b2f913223f79a3f76d18a41a389ec6d7e509d3\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libdb5.3:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-09-24T07:14:53Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24131622,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libdebconfclient0:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 291,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24131801,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:91c1e72cb0d152067397a31ea09d54b6593c93164a399b8f6be9a0bcddb9e5d0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libdebconfclient0:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 240,\n\t\t\t\"modtime\": \"2017-04-03T05:58:27Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24132007,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:17d7b1886ddb3fcdb0bdc192d6bd6c3bfe13425f06119042a0325acdf40da30f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libdebconfclient0:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 85,\n\t\t\t\"modtime\": \"2017-04-03T05:58:27Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24132262,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:31978d3a0c5700466d753a9b79e77e61a871511da1b0dbb2b70f696378c94217\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libdebconfclient0:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 143,\n\t\t\t\"modtime\": \"2017-04-03T05:58:27Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24132419,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e237639741b96561a9a2b619cf681517370df3a03896fa12b247be2b529827a0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libdebconfclient0:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-04-03T05:58:27Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24132610,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libfdisk1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 280,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24132781,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cf7d82e71a043affb869d05ea4b7eed4f8f56c2f3ffeb4c924fcbf8fb7f9d36e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libfdisk1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 290,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24132991,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:058eb37fa093aa54b1c4d8de8b22a469debcf5dc9ef179e741819d409ce3ab73\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libfdisk1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 75,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24133272,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:162982062d89eaa9d5eac8ff1977aa687f1eb0640d3ff21ecca969a62bb8a605\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libfdisk1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 11005,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24133433,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a53c2e609f5a5860dd0485715f6362a0a88fd77628db72cc5e2bf3404385db9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libfdisk1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24135118,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcc1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 205,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24135289,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bfd58c1e14511b97df3f8e414924c7759e0da246e1ea62500e9240007c1060dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcc1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 139,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24135485,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cd76e81c89511ba018765a2b3e6da8de7ee448c6aab0abb110cb0ba9e290c995\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcc1:amd64.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 180,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24135707,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:91466095137000731e5aaa4c2e0a84b5c5817ef0c3e4152901d2c0dd753d2b90\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcc1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24135944,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bd9a2ed68fc98f63e44063dc4f3f7baaa2a26699e91e00f864d8ae1ae459beee\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcc1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4360,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24136079,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1ea41fd012f575401b19ea387b90bed877f20087b3720253828f5a451a0ead8a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcc1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24137047,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcrypt20:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 439,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24137221,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:91683fea355adec504710db635979e8817691c8cbf8c83cff1b988cbb0092783\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcrypt20:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 577,\n\t\t\t\"modtime\": \"2018-06-15T09:58:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24137470,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:69a2e988b1b547f1219f24a0de4f02388f52202474bd125b92d599ebc8d5b7be\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcrypt20:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 85,\n\t\t\t\"modtime\": \"2018-06-15T09:58:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24137879,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9f43b99b16c2a39b2f53ff68fc28c1aec77d7daa459c4ccee2fb319138e3dc84\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcrypt20:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7364,\n\t\t\t\"modtime\": \"2018-06-15T09:58:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24138044,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0c0a991c6f2cc653d05fd1322535590fd83ac863f1bdd9f45bbda58d0c4faa1a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgcrypt20:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-06-15T09:58:05Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24139220,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgpg-error0:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2337,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24139397,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:36afe0dc7ee8330b2dc1b1df8b9ea152ec4ad1445ea8862e2d1771ab1725f623\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgpg-error0:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1943,\n\t\t\t\"modtime\": \"2017-01-18T16:27:10Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24139809,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:10d0827517555904cceb0b464dc4a4730aea28f269d7cbce3138268b5b6da215\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgpg-error0:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 89,\n\t\t\t\"modtime\": \"2017-01-18T16:27:10Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24140600,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6369bf8001d9f8e107f7c57e0fa983c27c234db6f67ce6a38e4dc2f9076bfcda\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgpg-error0:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3652,\n\t\t\t\"modtime\": \"2017-01-18T16:27:10Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24140763,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9be5deaeebda64772fdca2136bf03412dd183c255a2d2c8c8dbf97df6ff17817\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libgpg-error0:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-01-18T16:27:10Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24141435,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblz4-1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 301,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24141607,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1b8651c732da43e7bbedfb35730a94b753486eea886a6004b3f3aea93a23e13f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblz4-1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 302,\n\t\t\t\"modtime\": \"2016-02-17T15:27:54Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24141819,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f490e2a1b302cc5342c931e0aac525fad2e2dd2743d99835ba672c500f55cf43\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblz4-1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18,\n\t\t\t\"modtime\": \"2016-02-17T15:27:54Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24142101,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:88f3b33028e4581770c7c23cdf757398b80bc672210d8ff5dc9b78aadaf40722\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblz4-1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3436,\n\t\t\t\"modtime\": \"2016-02-17T15:27:54Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24142236,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:60d87d63ced63b4cc5e06660925c131ac795036909f9ea3a35e9e82ce1dbc5aa\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblz4-1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2016-02-17T15:27:54Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24142920,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblzma5:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 419,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24143094,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3a391825d566d675fddca15f6e4086f4369271bf056ee9d94294146b835c235c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblzma5:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 563,\n\t\t\t\"modtime\": \"2016-10-08T13:11:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24143341,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4cf1bd29dd0f2be41754f6984bce0563d48dddabd94af2cc61c1af496fc99290\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblzma5:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19,\n\t\t\t\"modtime\": \"2016-10-08T13:11:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24143746,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8a99812b1ff7964dc1406e712978d1ebc4e7ef9d74bc1b271c28a2a48446769d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblzma5:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4880,\n\t\t\t\"modtime\": \"2016-10-08T13:11:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24143882,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:682a57db44010fb9eeb18ce1a2e7792b2aaf77f0ffd39d95f8a444d43e97c86c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/liblzma5:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2016-10-08T13:11:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24144639,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libmount1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 280,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24144813,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0f8689fb2b0b1547e30af3725a7be7fcafb94c85206a373d1c14f934f1d458a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libmount1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 290,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24145023,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:71d40c703c53148c3cb8f6d818da8b5f9b297f3cbcf4f832bcc731bf99fc5d5c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libmount1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 75,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24145305,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a524d83582803e9f8c30a1731b71f3a538c74a8dbdce4506922d2ff257674970\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libmount1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 11419,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24145470,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cec9fd5edad1e27fda3d91132929d1559b9ae6bb7df61ad71bb8928e97ee8bc1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libmount1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24147308,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libncursesw5:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 452,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24147483,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:14d7e39ef1e7a0aa1ebfb268d7e55e8317ef7dd893410351ac024bae982d7ea9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libncursesw5:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 300,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24147698,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:394c6d75586d60423595b6d5cec4e9e822e4d36ca23dbdbb5b602ba3a84baab1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libncursesw5:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 128,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24147961,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:37120c652701ac2173dafe1cde3a1243897f02a48ccb6025dbb1c198afc62445\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libncursesw5:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 25048,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24148130,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:80047a5dfe0a4aa69614140fd9d270d20a3cfa971b34c3da53fbef887afa585a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libncursesw5:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24151006,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-modules-bin.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 692,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24151180,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:df966cbf9d317eac8664ace185fcc8719052f35021d521c74d83c79054fd58a6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-modules-bin.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1020,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24151487,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0678312e97ff9641033dd232de0c4275f4fb33c976f95a791127ab3ebe35225e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-modules:amd64.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 214,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24152083,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d55c2f2fa42a5a8d21bb599e010aa7053a91156c8523bc54fe6907ddfbf665dd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-modules:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4547,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24152279,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:76d7cfa38780402b874c7125a4597155f4eb73df587b929630963eda56ac9f8c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-modules:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7235,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24153050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e6249c0bb8c62d8fb7508eae5768d38d0c7620f2cc297e9d419ba66266a2a3ee\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-modules:amd64.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 706,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24155725,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a7cc62a56ddb6c83ffa89bc07acc3a39173336c24e030f94359ee202e3c04581\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-modules:amd64.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 206,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24156207,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1c04914a45a56607aa795b52767684381625c27cb3a8f45302cbfa088f735b5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-modules:amd64.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 259,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24156462,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bb1e2ecebc040efddf6cd8a31d090bd0f7dd7f7aa897e55b0176c52f2f186c9a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-modules:amd64.templates\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 13331,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24156752,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:492118f3907959065d04da4f35ebcf39f0c80bf68e0c2e3314967f390cd53714\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-runtime.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 31,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24162918,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e5df5e3149674007ef3a300996163a4d8692d21dabe9df527cf6a07e3abd65d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-runtime.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8374,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24163062,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d4f0f038515bd00292f58941c66c08f36505f1d3b8a646644af7169f3670586a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-runtime.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7166,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24164016,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:40df1963a92dd2d90b50962e8b268178e071b61bd7049cc9a2e0135109a747fe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-runtime.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1282,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24166482,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d6db2d0dd0999f840faaacc10a2cdc4e6b9227022b2d72da42ee67fe7c5968ec\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-runtime.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 517,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24167161,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:dda72491512e6f9757bec477428df23d17cd1f20c9c6c6b72599db270a0e62ea\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-runtime.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 92,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24167516,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b3e3b7ea23ac1d1c74ebc6aa3efee132675f5e69d9e2caba6c23e64a7b94b7f8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam-runtime.templates\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 34973,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24167717,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:96fc978c5f7ce82b7aa2ab6a57a91228f44836db4288d95a50f42056c7581b14\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam0g:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 710,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24181173,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:14c598b8be0d1f112802deb1b52843e3d9d9bdcc78f187c7093111c7b33391f8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam0g:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 865,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24181476,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b8bc98dbb552c8df8ef92a791d1d5bc2cf227706e21c5b5bb9738ea1b5654d4b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam0g:amd64.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5194,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24182005,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b1ea7619ae35ddbee9f58c0f71db9124ea5fab366e61309077dee4ef09ee0174\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam0g:amd64.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 206,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24184093,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c1c04914a45a56607aa795b52767684381625c27cb3a8f45302cbfa088f735b5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam0g:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24184344,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a9c316ab6c53dfa6f54c6eaa85530094f69c5da701e5edba5fad35ba336c2704\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam0g:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2959,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24184490,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d031a2a300bdc8769b22fe280cbb8d05fdb812b92a73b8454fe3ded9fe1f021d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam0g:amd64.templates\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35685,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24185131,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d27358a3c3a7cddd4ba50ab21b8dcf903b0bb32f25c51703bda07d450a3f4b7f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpam0g:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-05-27T15:44:02Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24199156,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpcre3:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 630,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24199329,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a2e555c79ca4430e5833b31e4e8fadb8282bd948756095acd44081a976dfcc0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpcre3:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 707,\n\t\t\t\"modtime\": \"2017-03-21T22:03:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24199625,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b267cc3b7967e3d2776b1e83a22dd8699cc3099874aa6cd7b47998211c41a7c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpcre3:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 156,\n\t\t\t\"modtime\": \"2017-03-21T22:03:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24200093,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0777f0af691ada09d50ad2634d2eb2a2f29faa1ef79b9be0f5688e568b90dc75\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpcre3:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1125,\n\t\t\t\"modtime\": \"2017-03-21T22:03:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24200266,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b6c27cab7115a1677a8bfcd33ad4b5e644aa729086c14e20fba7d8bf44d8a659\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libpcre3:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-03-21T22:03:19Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24200667,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libselinux1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 303,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24200842,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:243992305f3d7120e42236255f9ec91df9cfd525ffcb6d1d5098d7e7dbcc7213\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libselinux1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 380,\n\t\t\t\"modtime\": \"2017-09-24T15:30:16Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24201052,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5b4a608204edd53909754f87f898ee8758f058548f2af020d7a77295563de5e9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libselinux1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 61,\n\t\t\t\"modtime\": \"2017-09-24T15:30:16Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24201358,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2b70f61e92067b391c00c2c7f7b2f9322c979cf0b8073969f12dda8130c1209\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libselinux1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 7774,\n\t\t\t\"modtime\": \"2017-09-24T15:30:16Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24201509,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:45c42758b028297f26de8ff6726c232a701c1a337149f6e10d08f50fcb7d67ab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libselinux1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-09-24T15:30:16Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24203194,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsemanage-common.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24203372,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e0b0a931b5ae99c4bc030b6ecb183385a46fbd5e55e0e10cce9d5ed1eae556e2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsemanage-common.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 332,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24203517,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:efcc339a072893927b9f958a2c0bc7a572c06e8ded38a584aeac11042daa35c4\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsemanage-common.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 316,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24203732,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f4273b00cf42096e4fae6cc517c36887f62ba0cb157994d6bf834d3fdf8f0d10\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsemanage1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 267,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24204007,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:61cec03dea647551fb6f821e1943cb5e12d98ab7083369b3637e273bc206f142\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsemanage1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 302,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24204214,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9e3daa074a4802ec23550997202c21727b53421b347d2d1f21594b5fd48062ad\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsemanage1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 27,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24204494,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:efe84e47b7324e371a1b1263461f16814e0c9e6946e1351c507d025d34acf475\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsemanage1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 14021,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24204634,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b3961b9b87663a5ec73130821a6f55c1eb9f8741c809805dc893d6363253bd58\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsemanage1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2016-12-30T15:42:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24206155,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsepol1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 240,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24206328,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:520817a40e203c8c1229c95fd28404339755cf77be8104fa74c10ce6cb3f17c5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsepol1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 286,\n\t\t\t\"modtime\": \"2016-12-03T23:19:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24206535,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1ac559eb4577215f3e7a264c2f76c440dcc8b5db0fcd4ebd230febe0b8d0c586\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsepol1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 21,\n\t\t\t\"modtime\": \"2016-12-03T23:19:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24206814,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cc698287eb9ae72e133e0c0626577b90bea3ce48a97d3e66f5b64930faed553f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsepol1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8778,\n\t\t\t\"modtime\": \"2016-12-03T23:19:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24206951,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:36f5937b5da6e3caa3656b4b21ef446363313fa285587827f20855714ab3f1cd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsepol1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2016-12-03T23:19:56Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24208263,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsmartcols1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 304,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24208440,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0cd160716b9177e16605a23da8290f36f84c720bab0d86f9f927af83e795ef2a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsmartcols1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 306,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24208654,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:24eaa7f521a0bb356fab52ee49aa1c449d51246e7a2f28c24e170af01144db6f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsmartcols1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 91,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24208939,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ec414a341698598b15f989a8b16843af57299e1cb21fda64bbf5f35c569202a8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsmartcols1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 6360,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24209104,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:722622113db03ecb577f0d6b5a5157f2b1c4f5d774da1e3d1134a1f18e48b368\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsmartcols1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24210116,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libss2:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 225,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24210288,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:bd2cbff7ebeb04d501ae90b49ff4df1c1aa732ef53f42440a141901bf2678292\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libss2:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 208,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24210495,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a8d87407d1ae7edf18cdc4ffe8d4c4639585f560af6482e1c02ed4dc99e61fbf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libss2:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 44,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24210751,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fe74b5099d94fe674169a287bcaf1faf7b1c47bd4e0942912045bbf2f07f7d7e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libss2:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 948,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24210903,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:95b3f9a1df92569d95521970b6cb9bc2bdce224c6e110d4f29257438e83cc952\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libss2:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-02-01T00:54:55Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24211308,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libstdc++6:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 716,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24211483,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e69f4b8a0543c85ca3630f04e065aacd94d2e685c8e087fae406f05292fe565\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libstdc++6:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 514,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24211754,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a2507120023b89d1313adc62772d3c33383b0fe687522d701acf92a84aae9352\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libstdc++6:amd64.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 523,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24212112,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d58ab32524b4b72f16d6d6a55c792491bef47487e605b655cf92bd19d1363002\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libstdc++6:amd64.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 402,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24212494,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:be4d3d37ee6abd9f99c8eddd0c20e012aaffbdd984fbbc3ed6322adbd32a93f2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libstdc++6:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 23,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24212857,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:610aef7f93b6381fbcd118f65502ff420c29f00846ea92e308f1a66b1e34a98d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libstdc++6:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 369490,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24212995,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7baf601dddcf028a6542863262791417cf2ba4b2646f823022988ffc65146f0e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libstdc++6:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-02-14T16:53:20Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24241707,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsystemd0:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 253,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24241880,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cc07699f8e6948f95a506e8bd0eeee0a7a2a4dc0934110a0b2f7ce8dc22c0914\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsystemd0:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 226,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24242091,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fbbd82eb187521829fac79a610e0821ebb14a26e775b70fbe170c03126b0a35b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsystemd0:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 25,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24242353,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7305604403b49cd3046a4557ea2e0fd922a284501901c382934a6930c6d34175\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsystemd0:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19018,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24242492,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:49364dbae4b83985980134598def25260a777915a93f1843eefe640689c4eeae\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libsystemd0:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24245204,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libtinfo5:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 457,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24245376,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a0f01eff00a4161b5ad6557223b01fd261da27a523a70a13189a72a308c2d1b1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libtinfo5:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 493,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24245618,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4d3d4430b4f7545a3adc282e107efa016a1aa9a9959b424e00e2e19706918945\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libtinfo5:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 93,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24245979,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1d1e509ac4df064ec070dae7db743cbbdf4f0e89293c9e36dad136b01c7acae8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libtinfo5:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10583,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24246139,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:31a47ec102f3e749acb433cc824795306a932dfdddc8b07df81260f82be0ad3c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libtinfo5:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24247745,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libudev1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 237,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24247918,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6304d6cc70c1fbac022db9e86253dccac0d732dc65dba5d9a3d5180bbcc768f0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libudev1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 216,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24248128,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:808b5d81ac9664efe9106b1a0fe73fdb3cfe5b93abb0ff2b8c552d41e40fe160\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libudev1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 49,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24248387,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1ec36f721c65c10a314a26f2c2eab2e8646738f213c1ea46b3ab5b7032be656e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libudev1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4117,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24248535,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:58bbd25ce4937cdf92003159e262eb853b16d6e2a0dfd203f3e2cc780260ec2f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libudev1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-06-13T20:20:36Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24249349,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libustr-1.0-1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 361,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24249526,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ce9393596d841f4e0e573108c148bc013c3707c7847bc11236d834e3fcbfda27\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libustr-1.0-1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 385,\n\t\t\t\"modtime\": \"2016-11-23T19:59:34Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24249753,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4dfa449478b952b012c7c93a19af0f27ee539ee745c1d5f6947b01fed7297379\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libustr-1.0-1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 28,\n\t\t\t\"modtime\": \"2016-11-23T19:59:34Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24250069,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1afc929d34afd105bd39adb703aec7c834edac65652ca6921ef065320811a1da\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libustr-1.0-1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 18424,\n\t\t\t\"modtime\": \"2016-11-23T19:59:34Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24250210,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9d5b87acbd80cd5b9e2c496f184353ee33a28425121131dd963cf3625874fcde\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libustr-1.0-1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2016-11-23T19:59:34Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24252282,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libuuid1:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 274,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24252455,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2409d77e3d353fc085b09905265dbc76ab7ca8455834f058f2f8c883408a4a14\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libuuid1:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 286,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24252664,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cc145fbd4b2f26de67cfff818b6f793213812e790154502120071910d35099fd\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libuuid1:amd64.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1223,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24252949,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7575000f027ad8adff7f6512d37f7c9fa1ccdf9b7703076fe605a1cf70e84d0e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libuuid1:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 73,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24253621,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fa73b85ed0ceadffbcb5b0449a3c3c506e99fe78a4da2a6e5fec839711ffc06c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libuuid1:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 655,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24253781,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ba5466eb5b879be271cc4783c6d5a549e862799db4064cd4e37a841ccee9dad6\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/libuuid1:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24254085,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/login.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 62,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24254252,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3f7efa04144f955d2ff173cfc54734d007eeefb9b474237040f5a3e74d43be91\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/login.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 8764,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24254402,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d3e2e91cc4337468ae7420115b52a0779e752c059b487af8b2d18573b1b3bf34\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/login.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10068,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24255528,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:74cf33cb4937f5502456d8c4456ed6fc2ed3d432fcc2b7ed6debc819a3da144c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/login.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1214,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24259071,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:13780f74190f9e9564d2eaf2d4f9d26e09c67b15a61ebae713b070854e263f58\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/login.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1048,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24259587,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:60940bcd58ac8bc2308601c284183358fa5814064ac33e90345f706dc35f473b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/lsb-base.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 319,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24260256,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cdb270a80c74a84629d08e14fe0e6cefadb23bfe782bcbc828e7c119d5cffc18\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/lsb-base.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 419,\n\t\t\t\"modtime\": \"2016-11-25T15:15:24Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24260485,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e1742e14feb7ee32fe0d7d8b7296b9d68f713dc006ca49aba1a5325598f5ae6b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/mawk.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 772,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24260826,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:362378374a77852a70e0e0131ef2241675623e663817a1167f8db4497ae9e80a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/mawk.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1239,\n\t\t\t\"modtime\": \"2012-03-23T20:15:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24261125,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:66921a131a48fd13c2ea73b30af7873a74b632d845164aefee1f4dae60a0a55e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/mawk.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 299,\n\t\t\t\"modtime\": \"2012-03-23T20:15:00Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24261785,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6374f7996297a6933c9ccae7eecc506a14c85112bf1984c12da1f975dab573b2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/mawk.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 104,\n\t\t\t\"modtime\": \"2012-03-23T20:15:00Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24262010,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7f5bf8abeb16efa0dea7513462bf1a1dbfee6a7945dc39424d87547128d52aca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/mount.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1131,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24262209,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0e92f2cd59071401cf442f4425247ec2a370687d275b7a708be3e868fab9cad5\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/mount.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1691,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24262559,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:891211cc70fcbc9a6acfbe22962959861d83f5d7b75934075a3c3b3c09b7297e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/multiarch-support.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 209,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24263409,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a07b2062b40da61f3acde302fe39f3702ce54c8cabd2052a550065579d897ea0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/multiarch-support.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 241,\n\t\t\t\"modtime\": \"2018-01-14T10:39:44Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24263593,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:215fc7a9a5de62426e894e146f56220eeed171590d1b01f97bf9535d224bc521\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/ncurses-base.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 21,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24263839,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b97a47660009db296563cccb2fdce8826e134e3b1bf90248d9c7cf825f06e50a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/ncurses-base.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1710,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24263977,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f6c127275c38e828d43d2b3d539e01d38521f5f88b8a4619180d826fda4d9121\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/ncurses-base.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2733,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24264443,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:0f31ffcd76b076fab4bff5ef9f7a9b8ff672fcdc07b68c5f5760fdaccc456006\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/ncurses-bin.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 829,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24265733,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:eba367c1ae9cf3bb8c3a404926611d885a84edef9dce4a7b03f87b7eb6ff3a4e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/ncurses-bin.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1326,\n\t\t\t\"modtime\": \"2017-12-28T09:47:33Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24266036,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f75af139f1b948c4d15cc7d94672d15900cef875cbc38b2a05944f8c3800f755\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/passwd.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 134,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24266742,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05cfff1ddfa6cf7fc524250fe96fba6e443e070b15a4014b74c7a4a5d07a12a2\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/passwd.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 12326,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24266917,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3054328771c1a422e3af1132091b55842b27ef0c50de8d95faad643a4a12e895\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/passwd.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 20584,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24268517,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:753f53b1dfa3d2dca894c5f6f1a6de36ec7730e48a8fa8cc66c920c99cd38967\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/passwd.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1574,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24275157,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:59054ead4042a38538dde7f4921de2afc56f2c694cf0ed439b3a872c9185c325\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/passwd.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1044,\n\t\t\t\"modtime\": \"2017-05-17T11:59:59Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24276104,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:cf6e8844db16f76a96c215d16d674c35d3ff7128fef855c6c690f04f3aa38a64\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/perl-base.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 35267,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24276772,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f5958bd11445205585820d8e92386d6d3388798f23db3dd33f3da11014d2d7fc\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/perl-base.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 47930,\n\t\t\t\"modtime\": \"2018-06-10T17:37:28Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24279426,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ddbed287c72567e570a07ccda9e4caba252e0276241ce0a819d0fc1d623b3395\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/sed.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4224,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24292597,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5ade75cbe445776676e0d7b189262df16f41b85cc3277075a969540b1d30d2f0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/sed.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3659,\n\t\t\t\"modtime\": \"2017-02-04T15:16:08Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24293194,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:fe65ce9bfe5ece14806214a7744ef962f38cc54c18da0342a47caf2a58bdbdf8\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/sensible-utils.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1573,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24294631,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:2188612130b563d8c56994d94dee0071b9ce86fa383cba21b0cf281f1d77b031\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/sensible-utils.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1058,\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24294982,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b5edfd558e93ead2a8dce4cbf7977b3a6a252f755293ba1609f71b1768abc302\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/sensible-utils.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 283,\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24295533,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f679fc646210850d00acf80323dd891df6c1e5dbc73741a5078c1322f609df11\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/sensible-utils.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 313,\n\t\t\t\"modtime\": \"2017-12-20T13:39:04Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24295822,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:338cfffb71842952258014189d1fad44046418b6fb2d0799cab294bb1619d223\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/sysvinit-utils.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 552,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24296120,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:201c4dc0cc171838e01e801bfdf022ac760fef040ffe2a8997d66033430f41ca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/sysvinit-utils.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 792,\n\t\t\t\"modtime\": \"2017-02-12T21:55:39Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24296402,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:7371e60db15baaa34dbc98c231754b058da015e9791e89cf71ceae366b30bcf9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tar.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 9,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24296908,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a1edc2c1b98b0d285ada5f8075b6d1dcfe08be7a7c177462542023d293f667e9\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tar.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 4262,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24297029,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f1d513203e8b5b15753ef78caf5ca6a0db6268a4d4ba27eb6c0797a59a5f3161\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tar.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3760,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24297652,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6d445fa9a5cc958326e9d95ecdcd4b7c0a9f9d411852e9cfe35bde24462da261\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tar.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 270,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24299129,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4eed7466e8f44c6b480002d80becc0d998c462b759c0118e285170a93f4b3dca\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tar.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 317,\n\t\t\t\"modtime\": \"2016-10-30T06:35:31Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24299393,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4d2e0a20637a93acbba993f09ed56659869ed3b5749243c2441f8443fa0bdc83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tzdata.config\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10137,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24299704,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:06b375f4c33ed60b3a5c0509e77d6e1268afcdafee18f7a93ac7cb60ffe1fd67\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tzdata.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 73851,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24302050,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f493aa8eb818ba2b93305d8bdb78380398a02bed5159e1af89b10b99155f4e52\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tzdata.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 55759,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24311261,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6a93492f5bf955082bec9f1b49cf3940c9fcb36291de452c1729614ddab0fd56\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tzdata.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1330,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24330605,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d0b65a6ef298850b186a12b84cdeff63f79b272a259b2f4495aca6f3e14eed86\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tzdata.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 298,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24331329,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e64bf8cc4b58a0536bb10676fc0b9e59a00b8451b76be07cedb2f7a660e49443\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/tzdata.templates\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 267379,\n\t\t\t\"modtime\": \"2018-05-04T18:22:35Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24331619,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:3bd45d8ada7d2659c953df98d4f8c5ebf0988fe1597675614610c6be9e3bc768\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/util-linux.conffiles\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 84,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24387384,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:ab71f6f05a3f0a7cb78fe1ec8c90af9cd821e9f66bcbde54cd6769696300317f\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/util-linux.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 10638,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24387550,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:1151138a9f9dd100ca903a2eedd17d89a8f1dc0cf3e7c1fb28b8efa928b2101d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/util-linux.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 19143,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24389331,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:8e3d967d38b96c3898bab4656a4aa000c44d3b16184d2498b29f92b6aed3310e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/util-linux.postinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 1500,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24396523,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f694e5496272871d77a31cbb471c96c8a4de630b62d90b1c1a03cceeda2513a7\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/util-linux.postrm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 148,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24397317,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e6a730615e91fb9c7a3729817fc8208e889cd52aa80d31dbb3adf993711a9a8b\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/util-linux.preinst\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 205,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24397547,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:5cc1c06e4e2aee2896e0fc0e6aae4a18070677a42fe98cb84e02007e83cbd6f0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/util-linux.prerm\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 192,\n\t\t\t\"modtime\": \"2018-03-07T18:29:09Z\",\n\t\t\t\"mode\": 33261,\n\t\t\t\"offset\": 24397815,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:75c29194452a7242c7363da15ce655cca80fdf31d31a1836e820d74e5fc5381d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/zlib1g:amd64.list\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 260,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24398048,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e60913bb8b589fb1d44cd9b89f1bb69096dd12c93041242ecc30f1093d2e1266\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/zlib1g:amd64.md5sums\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 277,\n\t\t\t\"modtime\": \"2017-01-29T17:22:23Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24398257,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b66744b6adc964b7ef438a144ed211fa482a3183352a3aef4036fccf95df05d1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/zlib1g:amd64.shlibs\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 83,\n\t\t\t\"modtime\": \"2017-01-29T17:22:23Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24398539,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:b83364c157bf331505e018105935763d36db4e070e26d1f7d6c08ea576fc7d5c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/zlib1g:amd64.symbols\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 2752,\n\t\t\t\"modtime\": \"2017-01-29T17:22:23Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24398706,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:01394311eb033a90295b3de0e879a126e5f0d65250cb06dec4c239e57fbedff0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/info/zlib1g:amd64.triggers\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 60,\n\t\t\t\"modtime\": \"2017-01-29T17:22:23Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24399426,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f2bec0f57ef529571abb4370d4e3cfa911ae3606a0d31559bca5980c0a1de91e\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/lock\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33184,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/parts/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T10:28:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/statoverride\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/status\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 68838,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24399656,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:c09e66b2e4369263618d407aaa41a5cd56b41edfc6f9a52036f41d6e20c7e44a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/status-old\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 68559,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24420214,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:f9aab52daeabfffab21c128e899a2ad3dfaa28de29eaf97a1d0df2ac7a59c18d\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/triggers/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/triggers/Lock\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33152,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/triggers/Unincorp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/triggers/ldconfig\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 9,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24440548,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e1919c8b2afb858bd2aadc7ccb27c847b3b687ed9dffe00219d645d0c30b8b83\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/dpkg/updates/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/misc/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/pam/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/pam/account\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 76,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24440733,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:9f0f66ec5d201dd496bda06760e5871fa68e349fb9d423eac447d332652f6f13\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/pam/auth\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 68,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24440906,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:6f405869d7e61b56e8b4c6eab08c60c538dc24853867655e208b09778d656aab\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/pam/password\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 69,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24441075,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:78f7673a76134223418cd0b3479b892bb260a7d6b734bfc9caca62edcfb22d7a\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/pam/seen\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 5,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24441240,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:d66f691617a7b447171b7586b8f16741a023a810f1307542c254053318f19ca0\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/pam/session\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 75,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24441349,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a0e1452e4462ee2c1337989554acb3fe7a2473086870ec5b16e46aceb48e0e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/pam/session-noninteractive\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 75,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24441526,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:4a0e1452e4462ee2c1337989554acb3fe7a2473086870ec5b16e46aceb48e0e1\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/systemd/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/systemd/deb-systemd-helper-enabled/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/systemd/deb-systemd-helper-enabled/apt-daily-upgrade.timer.dsh-also\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 64,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24441766,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:05e0a72e601e00feaeff5d237f892b5f891cbb9c156fc5da667ac56c25f20fdf\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/systemd/deb-systemd-helper-enabled/apt-daily.timer.dsh-also\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 56,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24441940,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:71649d5e78c0ba864daf3778e8d90a3707b88c587a4634cba67aa9094def7750\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/systemd/deb-systemd-helper-enabled/timers.target.wants/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/systemd/deb-systemd-helper-enabled/timers.target.wants/apt-daily-upgrade.timer\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lib/systemd/deb-systemd-helper-enabled/timers.target.wants/apt-daily.timer\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/local/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 50,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/lock\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/run/lock\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/log/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/log/apt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2017-09-13T16:47:33Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/log/btmp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33200,\n\t\t\t\"gid\": 43,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/log/faillog\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 3232,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33188,\n\t\t\t\"offset\": 24442276,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:df66d6e43afb0468eda3149e5eaaffda44271cf157a9d9ea4ff6b6dafccb030c\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/log/lastlog\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"size\": 29492,\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33204,\n\t\t\t\"gid\": 43,\n\t\t\t\"offset\": 24442396,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:a04ece22923d2adaafa89580dbe2851cc93eee9f1c8f43264638d002229f2cfe\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/log/wtmp\",\n\t\t\t\"type\": \"reg\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 33204,\n\t\t\t\"gid\": 43,\n\t\t\t\"NumLink\": 0,\n\t\t\t\"digest\": \"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/mail/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 17917,\n\t\t\t\"gid\": 8,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/opt/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/run\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"/run\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/spool/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"mode\": 16877,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/spool/mail\",\n\t\t\t\"type\": \"symlink\",\n\t\t\t\"modtime\": \"2018-10-11T00:00:00Z\",\n\t\t\t\"linkName\": \"../mail\",\n\t\t\t\"mode\": 41471,\n\t\t\t\"NumLink\": 0\n\t\t},\n\t\t{\n\t\t\t\"name\": \"var/tmp/\",\n\t\t\t\"type\": \"dir\",\n\t\t\t\"modtime\": \"2018-06-26T12:03:08Z\",\n\t\t\t\"mode\": 17407,\n\t\t\t\"NumLink\": 0\n\t\t}\n\t]\n}"
  },
  {
    "path": "pkg/store/daemonstore.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage store\n\nimport (\n\t\"context\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n)\n\ntype DaemonRafsStore struct {\n\tdb *Database // save daemons in database\n}\n\nfunc NewDaemonRafsStore(db *Database) (*DaemonRafsStore, error) {\n\treturn &DaemonRafsStore{\n\t\tdb: db,\n\t}, nil\n}\n\n// If the daemon is inserted to DB before, return error ErrAlreadyExisted.\nfunc (s *DaemonRafsStore) AddDaemon(d *daemon.Daemon) error {\n\t// Save daemon info in case snapshotter restarts so that we can restore the\n\t// daemon states and reconnect the daemons.\n\treturn s.db.SaveDaemon(context.TODO(), d)\n}\n\nfunc (s *DaemonRafsStore) UpdateDaemon(d *daemon.Daemon) error {\n\treturn s.db.UpdateDaemon(context.TODO(), d)\n}\n\nfunc (s *DaemonRafsStore) DeleteDaemon(id string) error {\n\treturn s.db.DeleteDaemon(context.TODO(), id)\n}\n\nfunc (s *DaemonRafsStore) WalkDaemons(ctx context.Context, cb func(d *daemon.ConfigState) error) error {\n\treturn s.db.WalkDaemons(ctx, cb)\n}\n\nfunc (s *DaemonRafsStore) CleanupDaemons(ctx context.Context) error {\n\treturn s.db.CleanupDaemons(ctx)\n}\n\nfunc (s *DaemonRafsStore) AddRafsInstance(r *rafs.Rafs) error {\n\treturn s.db.AddRafsInstance(context.TODO(), r)\n}\n\nfunc (s *DaemonRafsStore) UpdateRafsInstance(r *rafs.Rafs) error {\n\treturn s.db.UpdateRafsInstance(context.TODO(), r)\n}\n\nfunc (s *DaemonRafsStore) DeleteRafsInstance(snapshotID string) error {\n\treturn s.db.DeleteRafsInstance(context.TODO(), snapshotID)\n}\n\nfunc (s *DaemonRafsStore) WalkRafsInstances(ctx context.Context, cb func(*rafs.Rafs) error) error {\n\treturn s.db.WalkRafsInstances(ctx, cb)\n}\n\nfunc (s *DaemonRafsStore) NextInstanceSeq() (uint64, error) {\n\treturn s.db.NextInstanceSeq()\n}\n"
  },
  {
    "path": "pkg/store/database.go",
    "content": "/*\n * Copyright (c) 2021. Ant Financial. All rights reserved.\n  * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n*/\n\npackage store\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\n\t\"github.com/pkg/errors\"\n\tbolt \"go.etcd.io/bbolt\"\n)\n\nconst (\n\tdatabaseFileName = \"nydus.db\"\n)\n\n// Bucket names:\n// Buckets hierarchy:\n//\t- v1:\n//\t\t- daemons\n//\t\t- instances\n\nvar (\n\tv1RootBucket = []byte(\"v1\")\n\t// Nydusd daemon instances.\n\t// A daemon may host one (dedicated mode) or more (shared mode) RAFS filesystem instances.\n\tversionKey    = []byte(\"version\")\n\tdaemonsBucket = []byte(\"daemons\")\n\t// RAFS filesystem instances.\n\t// A RAFS filesystem may have associated daemon or not.\n\tinstancesBucket = []byte(\"instances\")\n)\n\n// Database keeps infos that need to survive among snapshotter restart\ntype Database struct {\n\tdb *bolt.DB\n}\n\n// NewDatabase creates a new or open existing database file\nfunc NewDatabase(rootDir string) (*Database, error) {\n\tf := filepath.Join(rootDir, databaseFileName)\n\tif err := ensureDirectory(filepath.Dir(f)); err != nil {\n\t\treturn nil, err\n\t}\n\n\topts := bolt.Options{Timeout: time.Second * 4}\n\n\tdb, err := bolt.Open(f, 0600, &opts)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\td := &Database{db: db}\n\tif err := d.initDatabase(); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to initialize database\")\n\t}\n\treturn d, nil\n}\n\nfunc ensureDirectory(dir string) error {\n\tif _, err := os.Stat(dir); os.IsNotExist(err) {\n\t\treturn os.MkdirAll(dir, 0700)\n\t}\n\n\treturn nil\n}\n\nfunc getDaemonsBucket(tx *bolt.Tx) *bolt.Bucket {\n\tbucket := tx.Bucket(v1RootBucket)\n\treturn bucket.Bucket(daemonsBucket)\n}\n\nfunc getInstancesBucket(tx *bolt.Tx) *bolt.Bucket {\n\tbucket := tx.Bucket(v1RootBucket)\n\treturn bucket.Bucket(instancesBucket)\n}\n\nfunc updateObject(bucket *bolt.Bucket, key string, obj interface{}) error {\n\tkeyBytes := []byte(key)\n\n\tvalue, err := json.Marshal(obj)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"marshall key %s\", key)\n\t}\n\n\tif err := bucket.Put(keyBytes, value); err != nil {\n\t\treturn errors.Wrapf(err, \"put key %s\", key)\n\t}\n\n\treturn nil\n}\n\nfunc putObject(bucket *bolt.Bucket, key string, obj interface{}) error {\n\tkeyBytes := []byte(key)\n\n\tif bucket.Get(keyBytes) != nil {\n\t\treturn errors.Errorf(\"object with key %q already exists\", key)\n\t}\n\n\tvalue, err := json.Marshal(obj)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"marshall %s\", key)\n\t}\n\n\tif err := bucket.Put(keyBytes, value); err != nil {\n\t\treturn errors.Wrapf(err, \"put key %s\", key)\n\t}\n\n\treturn nil\n}\n\n// A basic wrapper to retrieve a object from bucket.\nfunc getObject(bucket *bolt.Bucket, key string, obj interface{}) error {\n\tif obj == nil {\n\t\treturn errdefs.ErrInvalidArgument\n\t}\n\n\tvalue := bucket.Get([]byte(key))\n\tif value == nil {\n\t\treturn errdefs.ErrNotFound\n\t}\n\n\tif err := json.Unmarshal(value, obj); err != nil {\n\t\treturn errors.Wrapf(err, \"unmarshall %s\", key)\n\t}\n\n\treturn nil\n}\n\nfunc (db *Database) initDatabase() error {\n\tvar notV1 = false\n\tvar version string\n\terr := db.db.Update(func(tx *bolt.Tx) error {\n\n\t\tbk := tx.Bucket(v1RootBucket)\n\t\tif bk == nil {\n\t\t\tnotV1 = true\n\t\t}\n\n\t\t// Must create v1 bucket\n\t\tbk, err := tx.CreateBucketIfNotExists(v1RootBucket)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif _, err := bk.CreateBucketIfNotExists(daemonsBucket); err != nil {\n\t\t\treturn errors.Wrapf(err, \"bucket %s\", daemonsBucket)\n\t\t}\n\n\t\tif _, err := bk.CreateBucketIfNotExists(instancesBucket); err != nil {\n\t\t\treturn errors.Wrapf(err, \"bucket %s\", instancesBucket)\n\t\t}\n\n\t\tif val := bk.Get(versionKey); val == nil {\n\t\t\tversion = \"v1.0\"\n\t\t} else {\n\t\t\tversion = string(val)\n\t\t}\n\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif notV1 {\n\t\tif err := db.tryTranslateRecords(); err != nil && !errors.Is(err, errdefs.ErrNotFound) {\n\t\t\treturn errors.Wrapf(err, \"convert old database\")\n\t\t}\n\t}\n\n\tif version == \"v1.0\" {\n\t\tif err := db.tryUpgradeRecords(version); err != nil && !errors.Is(err, errdefs.ErrNotFound) {\n\t\t\treturn errors.Wrapf(err, \"convert old database\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (db *Database) Close() error {\n\terr := db.db.Close()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to close boltdb\")\n\t}\n\n\treturn nil\n}\n\nfunc (db *Database) SaveDaemon(_ context.Context, d *daemon.Daemon) error {\n\treturn db.db.Update(func(tx *bolt.Tx) error {\n\t\tbucket := getDaemonsBucket(tx)\n\t\tvar existing daemon.ConfigState\n\t\tif err := getObject(bucket, d.ID(), &existing); err == nil {\n\t\t\treturn errdefs.ErrAlreadyExists\n\t\t}\n\t\treturn putObject(bucket, d.ID(), d.States)\n\t})\n}\n\nfunc (db *Database) UpdateDaemon(_ context.Context, d *daemon.Daemon) error {\n\treturn db.db.Update(func(tx *bolt.Tx) error {\n\t\tbucket := getDaemonsBucket(tx)\n\n\t\tvar existing daemon.ConfigState\n\t\tif err := getObject(bucket, d.ID(), &existing); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\treturn updateObject(bucket, d.ID(), d.States)\n\t})\n}\n\nfunc (db *Database) DeleteDaemon(_ context.Context, id string) error {\n\treturn db.db.Update(func(tx *bolt.Tx) error {\n\t\tbucket := getDaemonsBucket(tx)\n\n\t\tif err := bucket.Delete([]byte(id)); err != nil {\n\t\t\treturn errors.Wrapf(err, \"delete daemon %s\", id)\n\t\t}\n\n\t\treturn nil\n\t})\n}\n\n// Cleanup deletes all daemon records\nfunc (db *Database) CleanupDaemons(_ context.Context) error {\n\treturn db.db.Update(func(tx *bolt.Tx) error {\n\t\tbucket := getDaemonsBucket(tx)\n\n\t\treturn bucket.ForEach(func(k, _ []byte) error {\n\t\t\treturn bucket.Delete(k)\n\t\t})\n\t})\n}\n\nfunc (db *Database) WalkDaemons(_ context.Context, cb func(info *daemon.ConfigState) error) error {\n\treturn db.db.View(func(tx *bolt.Tx) error {\n\t\tbucket := getDaemonsBucket(tx)\n\n\t\treturn bucket.ForEach(func(key, value []byte) error {\n\t\t\tstates := &daemon.ConfigState{}\n\n\t\t\tif err := json.Unmarshal(value, states); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"unmarshal %s\", key)\n\t\t\t}\n\n\t\t\treturn cb(states)\n\t\t})\n\t})\n}\n\n// WalkDaemons iterates all daemon records and invoke callback on each\nfunc (db *Database) WalkRafsInstances(_ context.Context, cb func(r *rafs.Rafs) error) error {\n\treturn db.db.View(func(tx *bolt.Tx) error {\n\t\tbucket := getInstancesBucket(tx)\n\n\t\treturn bucket.ForEach(func(key, value []byte) error {\n\t\t\tinstance := &rafs.Rafs{}\n\n\t\t\tif err := json.Unmarshal(value, instance); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"unmarshal %s\", key)\n\t\t\t}\n\n\t\t\treturn cb(instance)\n\t\t})\n\t})\n}\n\nfunc (db *Database) AddRafsInstance(_ context.Context, instance *rafs.Rafs) error {\n\treturn db.db.Update(func(tx *bolt.Tx) error {\n\t\tbucket := getInstancesBucket(tx)\n\n\t\treturn putObject(bucket, instance.SnapshotID, instance)\n\t})\n}\n\nfunc (db *Database) UpdateRafsInstance(_ context.Context, instance *rafs.Rafs) error {\n\treturn db.db.Update(func(tx *bolt.Tx) error {\n\t\tbucket := getInstancesBucket(tx)\n\n\t\treturn updateObject(bucket, instance.SnapshotID, instance)\n\t})\n}\n\nfunc (db *Database) DeleteRafsInstance(_ context.Context, snapshotID string) error {\n\treturn db.db.Update(func(tx *bolt.Tx) error {\n\t\tbucket := getInstancesBucket(tx)\n\n\t\tif err := bucket.Delete([]byte(snapshotID)); err != nil {\n\t\t\treturn errors.Wrapf(err, \"instance snapshot ID %s\", snapshotID)\n\t\t}\n\n\t\treturn nil\n\t})\n}\n\nfunc (db *Database) NextInstanceSeq() (uint64, error) {\n\ttx, err := db.db.Begin(true)\n\tif err != nil {\n\t\treturn 0, errors.New(\"failed to start transaction\")\n\t}\n\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tif err := tx.Rollback(); err != nil {\n\t\t\t\tlog.L.WithError(err).Errorf(\"Rollback error when getting next sequence\")\n\t\t\t}\n\t\t}\n\t}()\n\n\tbk := getInstancesBucket(tx)\n\tif bk == nil {\n\t\treturn 0, errdefs.ErrNotFound\n\t}\n\n\tseq, err := bk.NextSequence()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tif err := tx.Commit(); err != nil {\n\t\treturn 0, err\n\t}\n\n\treturn seq, nil\n}\n"
  },
  {
    "path": "pkg/store/database_compat.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage store\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\t\"github.com/pkg/errors\"\n\tbolt \"go.etcd.io/bbolt\"\n)\n\nconst SharedNydusDaemonID = \"shared_daemon\"\n\ntype CompatDaemon struct {\n\tID               string\n\tSnapshotID       string\n\tConfigDir        string\n\tSocketDir        string\n\tLogDir           string\n\tLogLevel         string\n\tLogToStdout      bool\n\tSnapshotDir      string\n\tPid              int\n\tImageID          string\n\tFsDriver         string\n\tAPISock          *string\n\tRootMountPoint   *string\n\tCustomMountPoint *string\n}\n\nfunc (db *Database) WalkCompatDaemons(_ context.Context, handler func(cd *CompatDaemon) error) error {\n\n\treturn db.db.View(func(tx *bolt.Tx) error {\n\t\tbucket := tx.Bucket(daemonsBucket)\n\t\tif bucket == nil {\n\t\t\treturn errdefs.ErrNotFound\n\t\t}\n\n\t\treturn bucket.ForEach(func(key, value []byte) error {\n\t\t\td := &CompatDaemon{}\n\n\t\t\tif err := json.Unmarshal(value, d); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"unmarshal %s\", key)\n\t\t\t}\n\n\t\t\treturn handler(d)\n\t\t})\n\t})\n}\n\n// Snapshotter v0.3.0 and lower store nydusd and rafs instance configurations in the different folders.\nfunc RedirectInstanceConfig(newPath, oldPath string) error {\n\toldConfig, err := os.Open(oldPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer oldConfig.Close()\n\n\terr = os.MkdirAll(filepath.Dir(newPath), 0700)\n\tif err != nil {\n\t\treturn err\n\t}\n\tnewConfig, err := os.Create(newPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer newConfig.Close()\n\n\t_, err = io.Copy(newConfig, oldConfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (db *Database) tryTranslateRecords() error {\n\tlog.L.Info(\"Trying to translate bucket records...\")\n\tdaemons := make([]*CompatDaemon, 0)\n\n\terr := db.WalkCompatDaemons(context.TODO(), func(cd *CompatDaemon) error {\n\t\tdaemons = append(daemons, cd)\n\t\treturn nil\n\t})\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar sharedMode = false\n\tvar configDir string\n\n\t// Scan all the daemons if it is started as shared mode last time\n\tfor _, d := range daemons {\n\t\tif d.ID == SharedNydusDaemonID {\n\t\t\tsharedMode = true\n\t\t} else if configDir == \"\" {\n\t\t\tconfigDir = d.ConfigDir\n\t\t}\n\t}\n\n\tfor _, d := range daemons {\n\t\tvar mp string\n\t\tvar newDaemon *daemon.Daemon\n\t\tif sharedMode {\n\t\t\tif d.ID == SharedNydusDaemonID {\n\n\t\t\t\toldConfig := path.Join(configDir, \"config.json\")\n\t\t\t\tnewConfig := filepath.Join(filepath.Dir(configDir), SharedNydusDaemonID, \"config.json\")\n\n\t\t\t\tnewDaemon = &daemon.Daemon{\n\t\t\t\t\tStates: daemon.ConfigState{\n\t\t\t\t\t\tID:         d.ID,\n\t\t\t\t\t\tProcessID:  d.Pid,\n\t\t\t\t\t\tAPISocket:  path.Join(d.SnapshotDir, \"api.sock\"),\n\t\t\t\t\t\tFsDriver:   d.FsDriver,\n\t\t\t\t\t\tMountpoint: *d.RootMountPoint,\n\t\t\t\t\t\tLogDir:     d.LogDir,\n\t\t\t\t\t\tLogLevel:   d.LogLevel,\n\t\t\t\t\t\t// Shared daemon does not need config file when start\n\t\t\t\t\t\tConfigDir: filepath.Dir(newConfig),\n\t\t\t\t\t}}\n\n\t\t\t\tif err := RedirectInstanceConfig(newConfig, oldConfig); err != nil {\n\t\t\t\t\tlog.L.WithError(err).Warnf(\"Redirect configuration from %s to %s\", oldConfig, newConfig)\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\t// Redirect rafs instance configuration files. We have to do it here to\n\t\t\t\t// prevent scattering compatibility code anywhere.\n\t\t\t\toldConfig := path.Join(d.ConfigDir, \"config.json\")\n\t\t\t\tnewConfig := path.Join(filepath.Dir(d.ConfigDir), SharedNydusDaemonID,\n\t\t\t\t\td.SnapshotID, \"config.json\")\n\t\t\t\tlog.L.Infof(\"Redirect configuration to %s\", newConfig)\n\t\t\t\tif err := RedirectInstanceConfig(newConfig, oldConfig); err != nil {\n\t\t\t\t\tlog.L.WithError(err).Warnf(\"Redirect configuration from %s to %s\", oldConfig, newConfig)\n\t\t\t\t}\n\t\t\t}\n\t\t} else if !sharedMode {\n\t\t\tmp = *d.CustomMountPoint\n\t\t\tnewDaemon = &daemon.Daemon{\n\t\t\t\tStates: daemon.ConfigState{\n\t\t\t\t\tID:         d.ID,\n\t\t\t\t\tProcessID:  d.Pid,\n\t\t\t\t\tAPISocket:  path.Join(d.SocketDir, \"api.sock\"),\n\t\t\t\t\tFsDriver:   d.FsDriver,\n\t\t\t\t\tMountpoint: mp,\n\t\t\t\t\tLogDir:     d.LogDir,\n\t\t\t\t\tLogLevel:   d.LogLevel,\n\t\t\t\t\tConfigDir:  d.ConfigDir,\n\t\t\t\t}}\n\t\t}\n\n\t\tvar instance *rafs.Rafs\n\t\tif !sharedMode {\n\t\t\tinstance = &rafs.Rafs{\n\t\t\t\tSnapshotID:  d.SnapshotID,\n\t\t\t\tImageID:     d.ImageID,\n\t\t\t\tDaemonID:    d.ID,\n\t\t\t\tSnapshotDir: path.Join(d.SnapshotDir, d.SnapshotID),\n\t\t\t\tMountpoint:  path.Join(d.SnapshotDir, d.SnapshotID, \"mnt\"),\n\t\t\t}\n\t\t} else if sharedMode && d.ID != SharedNydusDaemonID {\n\t\t\tinstance = &rafs.Rafs{\n\t\t\t\tSnapshotID:  d.SnapshotID,\n\t\t\t\tImageID:     d.ImageID,\n\t\t\t\tDaemonID:    SharedNydusDaemonID,\n\t\t\t\tSnapshotDir: path.Join(d.SnapshotDir, d.SnapshotID),\n\t\t\t\tMountpoint:  path.Join(*d.RootMountPoint, d.SnapshotID),\n\t\t\t}\n\t\t}\n\n\t\tif newDaemon != nil {\n\t\t\tif err := db.SaveDaemon(context.TODO(), newDaemon); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tif instance != nil {\n\t\t\tif err := db.AddRafsInstance(context.TODO(), instance); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (db *Database) tryUpgradeRecords(version string) error {\n\tlog.L.Infof(\"Trying to update bucket records from %s to v1.1 ...\", version)\n\n\tif version == \"v1.0\" {\n\t\tdaemons := make([]*daemon.ConfigState, 0)\n\t\terr := db.WalkDaemons(context.TODO(), func(cd *daemon.ConfigState) error {\n\t\t\tdaemons = append(daemons, cd)\n\t\t\treturn nil\n\t\t})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tfor _, d := range daemons {\n\t\t\tif d.DaemonMode == \"\" {\n\t\t\t\tswitch d.FsDriver {\n\t\t\t\tcase config.FsDriverFscache:\n\t\t\t\t\td.DaemonMode = config.DaemonModeShared\n\t\t\t\tcase config.FsDriverFusedev:\n\t\t\t\t\tif d.Mountpoint == config.GetRootMountpoint() {\n\t\t\t\t\t\td.DaemonMode = config.DaemonModeShared\n\t\t\t\t\t} else {\n\t\t\t\t\t\td.DaemonMode = config.DaemonModeDedicated\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar daemon = daemon.Daemon{States: *d}\n\t\t\t\terr := db.UpdateDaemon(context.TODO(), &daemon)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn errors.Wrapf(err, \"upgrade daemon instance %s\", d.ID)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\terr := db.db.Update(func(tx *bolt.Tx) error {\n\t\tbk := tx.Bucket(v1RootBucket)\n\t\tif bk != nil {\n\t\t\treturn bk.Put(versionKey, []byte(\"v1.1\"))\n\t\t}\n\t\treturn errors.New(\"boltdb is not v1\")\n\t})\n\n\treturn err\n}\n"
  },
  {
    "path": "pkg/store/database_test.go",
    "content": "package store\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\tbolt \"go.etcd.io/bbolt\"\n)\n\nfunc Test_daemon(t *testing.T) {\n\trootDir := \"testdata/snapshot\"\n\terr := os.MkdirAll(rootDir, 0755)\n\trequire.Nil(t, err)\n\tdefer func() {\n\t\t_ = os.RemoveAll(rootDir)\n\t}()\n\n\tdb, err := NewDatabase(rootDir)\n\trequire.Nil(t, err)\n\n\tctx := context.TODO()\n\t// Add daemons\n\td1 := daemon.Daemon{States: daemon.ConfigState{ID: \"d1\"}}\n\td2 := daemon.Daemon{States: daemon.ConfigState{ID: \"d2\"}}\n\td3 := daemon.Daemon{States: daemon.ConfigState{ID: \"d3\"}}\n\terr = db.SaveDaemon(ctx, &d1)\n\trequire.Nil(t, err)\n\terr = db.SaveDaemon(ctx, &d2)\n\trequire.Nil(t, err)\n\terr = db.SaveDaemon(ctx, &d3)\n\tassert.Nil(t, err)\n\trequire.Nil(t, err)\n\t// duplicate daemon id should fail\n\terr = db.SaveDaemon(ctx, &d1)\n\trequire.Error(t, err)\n\n\t// Delete one daemon\n\terr = db.DeleteDaemon(ctx, \"d2\")\n\trequire.Nil(t, err)\n\n\t// Check records\n\tids := make(map[string]string)\n\t_ = db.WalkDaemons(ctx, func(info *daemon.ConfigState) error {\n\t\tids[info.ID] = \"\"\n\t\treturn nil\n\t})\n\t_, ok := ids[\"d1\"]\n\trequire.Equal(t, ok, true)\n\t_, ok = ids[\"d2\"]\n\trequire.Equal(t, ok, false)\n\t_, ok = ids[\"d3\"]\n\trequire.Equal(t, ok, true)\n\n\t// Cleanup records\n\terr = db.CleanupDaemons(ctx)\n\trequire.Nil(t, err)\n\tids2 := make([]string, 0)\n\terr = db.WalkDaemons(ctx, func(info *daemon.ConfigState) error {\n\t\tids2 = append(ids2, info.ID)\n\t\treturn nil\n\t})\n\trequire.Nil(t, err)\n\trequire.Equal(t, len(ids2), 0)\n}\n\nfunc TestLegacyRecordsMultipleDaemonModes(t *testing.T) {\n\trootDir := t.TempDir()\n\tprepareCompatTestConfig(t, rootDir, config.FsDriverFusedev, config.DaemonModeDedicated)\n\n\tmount1 := filepath.Join(rootDir, \"mounts\", \"daemon-1\")\n\tmount2 := filepath.Join(rootDir, \"mounts\", \"daemon-2\")\n\tsnapshotsDir := filepath.Join(rootDir, \"snapshots\")\n\n\trecords := []*CompatDaemon{\n\t\t{\n\t\t\tID:               \"daemon-1\",\n\t\t\tSnapshotID:       \"snapshot-1\",\n\t\t\tConfigDir:        filepath.Join(rootDir, \"config\", \"daemon-1\"),\n\t\t\tSocketDir:        filepath.Join(rootDir, \"socket\", \"daemon-1\"),\n\t\t\tLogDir:           filepath.Join(rootDir, \"logs\", \"daemon-1\"),\n\t\t\tLogLevel:         \"info\",\n\t\t\tSnapshotDir:      snapshotsDir,\n\t\t\tPid:              101,\n\t\t\tImageID:          \"image-1\",\n\t\t\tFsDriver:         config.FsDriverFusedev,\n\t\t\tCustomMountPoint: &mount1,\n\t\t},\n\t\t{\n\t\t\tID:               \"daemon-2\",\n\t\t\tSnapshotID:       \"snapshot-2\",\n\t\t\tConfigDir:        filepath.Join(rootDir, \"config\", \"daemon-2\"),\n\t\t\tSocketDir:        filepath.Join(rootDir, \"socket\", \"daemon-2\"),\n\t\t\tLogDir:           filepath.Join(rootDir, \"logs\", \"daemon-2\"),\n\t\t\tLogLevel:         \"debug\",\n\t\t\tSnapshotDir:      snapshotsDir,\n\t\t\tPid:              202,\n\t\t\tImageID:          \"image-2\",\n\t\t\tFsDriver:         config.FsDriverFusedev,\n\t\t\tCustomMountPoint: &mount2,\n\t\t},\n\t}\n\n\twriteLegacyDatabase(t, rootDir, records)\n\n\tdb, err := NewDatabase(rootDir)\n\trequire.NoError(t, err)\n\tt.Cleanup(func() {\n\t\trequire.NoError(t, db.Close())\n\t})\n\n\tgotDaemons := listDaemons(t, db)\n\trequire.Len(t, gotDaemons, len(records))\n\tfor _, record := range records {\n\t\tgot := gotDaemons[record.ID]\n\t\trequire.Equal(t, record.ID, got.ID)\n\t\trequire.Equal(t, record.Pid, got.ProcessID)\n\t\trequire.Equal(t, path.Join(record.SocketDir, \"api.sock\"), got.APISocket)\n\t\trequire.Equal(t, config.DaemonModeDedicated, got.DaemonMode)\n\t\trequire.Equal(t, record.FsDriver, got.FsDriver)\n\t\trequire.Equal(t, record.LogDir, got.LogDir)\n\t\trequire.Equal(t, record.LogLevel, got.LogLevel)\n\t\trequire.Equal(t, *record.CustomMountPoint, got.Mountpoint)\n\t\trequire.Equal(t, record.ConfigDir, got.ConfigDir)\n\t}\n\n\tgotInstances := listRafsInstances(t, db)\n\trequire.Len(t, gotInstances, len(records))\n\tfor _, record := range records {\n\t\tgot := gotInstances[record.SnapshotID]\n\t\trequire.Equal(t, record.ImageID, got.ImageID)\n\t\trequire.Equal(t, record.ID, got.DaemonID)\n\t\trequire.Equal(t, path.Join(record.SnapshotDir, record.SnapshotID), got.SnapshotDir)\n\t\trequire.Equal(t, path.Join(record.SnapshotDir, record.SnapshotID, \"mnt\"), got.Mountpoint)\n\t}\n}\n\nfunc TestLegacyRecordsSharedDaemonModes(t *testing.T) {\n\trootDir := t.TempDir()\n\tprepareCompatTestConfig(t, rootDir, config.FsDriverFscache, config.DaemonModeShared)\n\n\trootMountpoint := filepath.Join(rootDir, \"mnt\")\n\tsnapshotsDir := filepath.Join(rootDir, \"snapshots\")\n\tconfigDir1 := filepath.Join(rootDir, \"config\", \"instance-1\")\n\tconfigDir2 := filepath.Join(rootDir, \"config\", \"instance-2\")\n\n\twriteConfigFile(t, filepath.Join(configDir1, \"config.json\"), []byte(`{\"instance\":\"1\"}`))\n\twriteConfigFile(t, filepath.Join(configDir2, \"config.json\"), []byte(`{\"instance\":\"2\"}`))\n\n\trecords := []*CompatDaemon{\n\t\t{\n\t\t\tID:             \"instance-daemon-1\",\n\t\t\tSnapshotID:     \"snapshot-a\",\n\t\t\tConfigDir:      configDir1,\n\t\t\tLogDir:         filepath.Join(rootDir, \"logs\", \"shared\"),\n\t\t\tLogLevel:       \"info\",\n\t\t\tSnapshotDir:    snapshotsDir,\n\t\t\tPid:            301,\n\t\t\tImageID:        \"image-a\",\n\t\t\tFsDriver:       config.FsDriverFscache,\n\t\t\tRootMountPoint: &rootMountpoint,\n\t\t},\n\t\t{\n\t\t\tID:             \"instance-daemon-2\",\n\t\t\tSnapshotID:     \"snapshot-b\",\n\t\t\tConfigDir:      configDir2,\n\t\t\tLogDir:         filepath.Join(rootDir, \"logs\", \"shared\"),\n\t\t\tLogLevel:       \"info\",\n\t\t\tSnapshotDir:    snapshotsDir,\n\t\t\tPid:            302,\n\t\t\tImageID:        \"image-b\",\n\t\t\tFsDriver:       config.FsDriverFscache,\n\t\t\tRootMountPoint: &rootMountpoint,\n\t\t},\n\t\t{\n\t\t\tID:             SharedNydusDaemonID,\n\t\t\tSnapshotDir:    snapshotsDir,\n\t\t\tPid:            303,\n\t\t\tFsDriver:       config.FsDriverFscache,\n\t\t\tLogDir:         filepath.Join(rootDir, \"logs\", \"shared\"),\n\t\t\tLogLevel:       \"debug\",\n\t\t\tRootMountPoint: &rootMountpoint,\n\t\t},\n\t}\n\n\twriteLegacyDatabase(t, rootDir, records)\n\n\tdb, err := NewDatabase(rootDir)\n\trequire.NoError(t, err)\n\tt.Cleanup(func() {\n\t\trequire.NoError(t, db.Close())\n\t})\n\n\tgotDaemons := listDaemons(t, db)\n\trequire.Len(t, gotDaemons, 1)\n\n\tsharedDaemon := gotDaemons[SharedNydusDaemonID]\n\trequire.Equal(t, SharedNydusDaemonID, sharedDaemon.ID)\n\trequire.Equal(t, 303, sharedDaemon.ProcessID)\n\trequire.Equal(t, path.Join(snapshotsDir, \"api.sock\"), sharedDaemon.APISocket)\n\trequire.Equal(t, config.DaemonModeShared, sharedDaemon.DaemonMode)\n\trequire.Equal(t, config.FsDriverFscache, sharedDaemon.FsDriver)\n\trequire.Equal(t, rootMountpoint, sharedDaemon.Mountpoint)\n\trequire.Equal(t, filepath.Join(rootDir, \"config\", SharedNydusDaemonID), sharedDaemon.ConfigDir)\n\n\tgotInstances := listRafsInstances(t, db)\n\trequire.Len(t, gotInstances, 2)\n\tfor _, record := range records[:2] {\n\t\tgot := gotInstances[record.SnapshotID]\n\t\trequire.Equal(t, record.ImageID, got.ImageID)\n\t\trequire.Equal(t, SharedNydusDaemonID, got.DaemonID)\n\t\trequire.Equal(t, path.Join(record.SnapshotDir, record.SnapshotID), got.SnapshotDir)\n\t\trequire.Equal(t, path.Join(rootMountpoint, record.SnapshotID), got.Mountpoint)\n\t}\n\n\trequire.FileExists(t, filepath.Join(rootDir, \"config\", SharedNydusDaemonID, \"config.json\"))\n\trequire.FileExists(t, filepath.Join(rootDir, \"config\", SharedNydusDaemonID, \"snapshot-a\", \"config.json\"))\n\trequire.FileExists(t, filepath.Join(rootDir, \"config\", SharedNydusDaemonID, \"snapshot-b\", \"config.json\"))\n}\n\nfunc prepareCompatTestConfig(t *testing.T, rootDir, fsDriver string, daemonMode config.DaemonMode) {\n\tt.Helper()\n\n\tcfg := &config.SnapshotterConfig{\n\t\tRoot:       rootDir,\n\t\tDaemonMode: string(daemonMode),\n\t\tDaemonConfig: config.DaemonConfig{\n\t\t\tFsDriver: fsDriver,\n\t\t},\n\t}\n\n\trequire.NoError(t, config.ProcessConfigurations(cfg))\n}\n\nfunc writeLegacyDatabase(t *testing.T, rootDir string, records []*CompatDaemon) {\n\tt.Helper()\n\n\tdb, err := bolt.Open(filepath.Join(rootDir, databaseFileName), 0600, &bolt.Options{Timeout: 4 * time.Second})\n\trequire.NoError(t, err)\n\tdefer func() {\n\t\trequire.NoError(t, db.Close())\n\t}()\n\n\terr = db.Update(func(tx *bolt.Tx) error {\n\t\tbucket, err := tx.CreateBucketIfNotExists(daemonsBucket)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tfor i, record := range records {\n\t\t\tpayload, err := json.Marshal(record)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tkey := fmt.Sprintf(\"%02d-%s\", i, record.ID)\n\t\t\tif err := bucket.Put([]byte(key), payload); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\treturn nil\n\t})\n\trequire.NoError(t, err)\n}\n\nfunc writeConfigFile(t *testing.T, file string, content []byte) {\n\tt.Helper()\n\n\trequire.NoError(t, os.MkdirAll(filepath.Dir(file), 0755))\n\trequire.NoError(t, os.WriteFile(file, content, 0644))\n}\n\nfunc listDaemons(t *testing.T, db *Database) map[string]daemon.ConfigState {\n\tt.Helper()\n\n\tdaemons := make(map[string]daemon.ConfigState)\n\terr := db.WalkDaemons(context.TODO(), func(info *daemon.ConfigState) error {\n\t\tdaemons[info.ID] = *info\n\t\treturn nil\n\t})\n\trequire.NoError(t, err)\n\n\treturn daemons\n}\n\nfunc listRafsInstances(t *testing.T, db *Database) map[string]rafs.Rafs {\n\tt.Helper()\n\n\tinstances := make(map[string]rafs.Rafs)\n\terr := db.WalkRafsInstances(context.TODO(), func(instance *rafs.Rafs) error {\n\t\tinstances[instance.SnapshotID] = *instance\n\t\treturn nil\n\t})\n\trequire.NoError(t, err)\n\n\treturn instances\n}\n"
  },
  {
    "path": "pkg/supervisor/supervisor.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage supervisor\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n\t\"sync\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"path/filepath\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/pkg/errors\"\n\n\t\"golang.org/x/sync/errgroup\"\n\t\"golang.org/x/sync/semaphore\"\n\t\"golang.org/x/sys/unix\"\n)\n\ntype StatesStorage interface {\n\t// Save state to storage space.\n\tSave([]byte)\n\t// Load state from storage space.\n\tLoad() ([]byte, error)\n\t// Clean the previously saved state.\n\tClean()\n}\n\n// Store daemon states in memory\ntype MemStatesStorage struct {\n\tdata []byte\n}\n\nfunc newMemStatesStorage() *MemStatesStorage {\n\treturn &MemStatesStorage{\n\t\tdata: []byte{},\n\t}\n}\n\nfunc (mss *MemStatesStorage) Save(data []byte) {\n\tmss.data = make([]byte, len(data))\n\tcopy(mss.data, data)\n}\n\nfunc (mss *MemStatesStorage) Load() ([]byte, error) {\n\tdata := make([]byte, len(mss.data))\n\tcopy(data, mss.data)\n\treturn data, nil\n}\n\nfunc (mss *MemStatesStorage) Clean() {\n\tmss.data = []byte{}\n}\n\n// Use daemon ID as the supervisor ID\ntype Supervisor struct {\n\tid string\n\t// To which nydusd daemon will try to connect\n\tpath string\n\t// Hold the sended file descriptors.\n\tfd          int\n\tdataStorage StatesStorage\n\tmu          sync.Mutex\n\tsem         *semaphore.Weighted\n}\n\nfunc (su *Supervisor) save(data []byte, fd int) {\n\tsu.mu.Lock()\n\tdefer su.mu.Unlock()\n\n\t// Always overwrite states and FDs\n\t// We should clean up the stored states since each received states set is atomic\n\tsu.dataStorage.Clean()\n\tif fd > 0 {\n\t\tsu.fd = fd\n\t}\n\tsu.dataStorage.Save(data)\n}\n\n// Load resources kept by this supervisor\n//  1. daemon runtime states\n//  2. file descriptor\n//\n// Note: the resources should be not be consumed.\nfunc (su *Supervisor) load() ([]byte, int, error) {\n\tsu.mu.Lock()\n\tdefer su.mu.Unlock()\n\n\tdata, err := su.dataStorage.Load()\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\n\treturn data, su.fd, nil\n}\n\nfunc recv(uc *net.UnixConn) ([]byte, int, error) {\n\tdata := make([]byte, 0)\n\toob := make([]byte, 0)\n\n\tvar dataBufLen = 1024 * 256 // Bytes\n\n\t// oobSpace is the size of the oob slice required to store for multiple FDs. Note\n\t// that unix.UnixRights appears to make the assumption that fd is always int32,\n\t// so sizeof(fd) = 4.\n\t// At most can accommodate 64 fds\n\tvar oobSpace = unix.CmsgSpace(4) * 64\n\n\tfor {\n\t\tdataBuf := make([]byte, dataBufLen)\n\t\toobBuf := make([]byte, oobSpace)\n\n\t\tn, oobn, _, _, err := uc.ReadMsgUnix(dataBuf, oobBuf)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, io.EOF) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn nil, 0, errors.Wrap(err, \"receive message\")\n\t\t}\n\t\tif n == 0 {\n\t\t\tbreak // EOF\n\t\t}\n\n\t\tdata = append(data, dataBuf[:n]...)\n\t\toob = append(oob, oobBuf[:oobn]...)\n\t}\n\n\tscms, err := unix.ParseSocketControlMessage(oob)\n\tif err != nil {\n\t\treturn nil, 0, errors.Wrap(err, \"parse control message\")\n\t}\n\n\tvar fds []int\n\tif len(scms) == 0 {\n\t\treturn nil, 0, fmt.Errorf(\"received no control file descriptor\")\n\t}\n\n\tscm := scms[0]\n\tfds, err = unix.ParseUnixRights(&scm)\n\tif err != nil {\n\t\treturn nil, 0, errors.Wrap(err, \"extract file descriptors\")\n\t}\n\n\tvar fd int\n\tif len(fds) > 0 {\n\t\tfd = fds[0]\n\t} else {\n\t\tfd = -1\n\t}\n\n\treturn data, fd, nil\n}\n\nfunc send(uc *net.UnixConn, data []byte, fd int) error {\n\toob := syscall.UnixRights(fd)\n\n\tfor len(data) > 0 || len(oob) > 0 {\n\t\tn, oobn, err := uc.WriteMsgUnix(data, oob, nil)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"send message, datan %d oobn %d\", n, oobn)\n\t\t}\n\n\t\tdata = data[n:]\n\t\toob = oob[oobn:]\n\t}\n\n\treturn nil\n}\n\n// There are several stages from different goroutines to trigger sending daemon states\n// the waiter will overlap each other causing the UDS being deleted.\n// But we don't want to keep the server listen for ever.\n// `to` equal to zero indicates that caller should call the receiver the receive stats\n// when it thinks is appropriate. `to` is not zero, no receiver callback will be returned.\n// Then this method is responsible to receive states inside.\nfunc (su *Supervisor) waitStatesTimeout(to time.Duration) (func() error, error) {\n\tif err := os.Remove(su.path); err != nil {\n\t\tif !os.IsNotExist(err) {\n\t\t\tlog.L.Warnf(\"Unable to remove existed socket file %s, %s\", su.path, err)\n\t\t}\n\t}\n\n\tlistener, err := net.Listen(\"unix\", su.path)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"listen on socket %s\", su.path)\n\t}\n\n\treceiver := func() error {\n\t\tdefer func() { _ = listener.Close() }()\n\n\t\t// After the listener is closed, Accept() wakes up\n\t\tconn, err := listener.Accept()\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"Listener is closed\")\n\t\t}\n\t\tdefer func() { _ = conn.Close() }()\n\n\t\tdata, fd, err := recv(conn.(*net.UnixConn))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlog.L.Infof(\"Supervisor %s receives states. data %d\", su.id, len(data))\n\n\t\tsu.save(data, fd)\n\n\t\treturn nil\n\t}\n\n\tcancelTimer := make(chan int, 1)\n\t// Once timeouts, stop waiting for states\n\tif to > 0 {\n\t\ttimer := time.NewTimer(to)\n\t\tgo func() {\n\t\t\tselect {\n\t\t\tcase <-timer.C:\n\t\t\t\tlog.L.Warnf(\"Receiving state timeouts after %s\", to)\n\t\t\t\t// Wake up the blocking `Accept`\n\t\t\t\t_ = listener.Close()\n\t\t\tcase <-cancelTimer:\n\t\t\t}\n\n\t\t}()\n\n\t\tgo func() {\n\t\t\tif err := receiver(); err != nil {\n\t\t\t\tlog.L.Errorf(\"receiver fails, %s\", err)\n\t\t\t}\n\t\t\tif to > 0 {\n\t\t\t\tcancelTimer <- 1\n\t\t\t}\n\t\t}()\n\n\t\t// With non-zero timeout parameter, call should be aware that receiver is nil\n\t\t//nolint: nilnil\n\t\treturn nil, nil\n\t}\n\n\treturn receiver, nil\n}\n\nfunc (su *Supervisor) SendStatesTimeout(to time.Duration) error {\n\t// It is used to receive before\n\tif err := os.Remove(su.path); err != nil {\n\t\tif !os.IsNotExist(err) {\n\t\t\tlog.L.Warnf(\"Unable to remove existed socket file %s, %s\", su.path, err)\n\t\t}\n\t}\n\n\tlistener, err := net.Listen(\"unix\", su.path)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"listen on socket\")\n\t}\n\n\tsender := func() error {\n\t\tdefer func() { _ = listener.Close() }()\n\n\t\tconn, err := listener.Accept()\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"Listener is closed\")\n\t\t}\n\t\tdefer func() { _ = conn.Close() }()\n\n\t\t// FIXME: It's possible that sending states happens before storing state to the storage.\n\t\tdata, fd, err := su.load()\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"load resources for %s\", su.id)\n\t\t}\n\t\tif err := send(conn.(*net.UnixConn), data, fd); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tlog.L.Infof(\"Supervisor %s sends states. data %d\", su.id, len(data))\n\n\t\treturn nil\n\t}\n\n\tcancelTimer := make(chan int, 1)\n\tif to > 0 {\n\t\ttimer := time.NewTimer(to)\n\t\tgo func() {\n\t\t\tselect {\n\t\t\tcase <-timer.C:\n\t\t\t\tlog.L.Warnf(\"Sending state timeouts after %s\", to)\n\t\t\t\t// Wake up the blocking `Accept()`\n\t\t\t\t_ = listener.Close()\n\t\t\tcase <-cancelTimer:\n\t\t\t}\n\n\t\t}()\n\t}\n\n\t// Once timeouts, stop waiting for others fetching states\n\tgo func() {\n\t\terr := sender()\n\t\tif err != nil {\n\t\t\tlog.L.Errorf(\"Sender fails, %s\", err)\n\t\t}\n\t\tif to > 0 {\n\t\t\tcancelTimer <- 1\n\t\t}\n\t}()\n\n\treturn nil\n}\n\nfunc (su *Supervisor) FetchDaemonStates(trigger func() error) error {\n\tif err := su.sem.Acquire(context.TODO(), 1); err != nil {\n\t\treturn err\n\t}\n\n\tdefer su.sem.Release(1)\n\n\treceiver, err := su.waitStatesTimeout(0)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"wait states on %s\", su.Sock())\n\t}\n\n\teg := errgroup.Group{}\n\teg.Go(func() error {\n\t\terr := trigger()\n\t\treturn errors.Wrapf(err, \"trigger on %s\", su.Sock())\n\t})\n\n\teg.Go(func() error {\n\t\terr := receiver()\n\t\treturn errors.Wrapf(err, \"receiver on %s\", su.Sock())\n\t})\n\n\t// FIXME: With Timeout context!\n\treturn eg.Wait()\n}\n\n// The unix domain socket on which nydus daemon is connected to\nfunc (su *Supervisor) Sock() string {\n\treturn su.path\n}\n\n// Manage all supervisors each of which works for a nydusd to keep its resources\n// for sake of failover and live-upgrade.\ntype SupervisorsSet struct {\n\tmu  sync.Mutex\n\tset map[string]*Supervisor\n\t// A directory where all the supervisor sockets resides.\n\troot string\n}\n\nfunc NewSupervisorSet(root string) (*SupervisorsSet, error) {\n\tif err := os.MkdirAll(root, 0755); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &SupervisorsSet{\n\t\tset:  make(map[string]*Supervisor),\n\t\troot: root}, nil\n}\n\nfunc (ss *SupervisorsSet) NewSupervisor(id string) *Supervisor {\n\tsockPath := filepath.Join(ss.root, fmt.Sprintf(\"%s.sock\", id))\n\n\tsupervisor := &Supervisor{\n\t\tid:   id,\n\t\tpath: sockPath,\n\t\t// Negative value means no FD was ever held.\n\t\tfd:          -1,\n\t\tdataStorage: newMemStatesStorage(),\n\t\tsem:         semaphore.NewWeighted(1),\n\t}\n\n\tss.mu.Lock()\n\tdefer ss.mu.Unlock()\n\n\t// Allow overwrite the old supervisor\n\tss.set[id] = supervisor\n\n\treturn supervisor\n}\n\n// Get supervisor by its id which is typically the nydus damon ID.\nfunc (ss *SupervisorsSet) GetSupervisor(id string) *Supervisor {\n\tss.mu.Lock()\n\tdefer ss.mu.Unlock()\n\n\treturn ss.set[id]\n}\n\nfunc (ss *SupervisorsSet) DestroySupervisor(id string) error {\n\tss.mu.Lock()\n\tdefer ss.mu.Unlock()\n\n\tsupervisor, ok := ss.set[id]\n\tif !ok {\n\t\treturn errdefs.ErrNotFound\n\t}\n\n\tdelete(ss.set, id)\n\n\tsupervisor.mu.Lock()\n\tdefer supervisor.mu.Unlock()\n\n\tif supervisor.fd > 0 {\n\t\t// Prevent hanging after nydusd exits.\n\t\tif err := syscall.Close(supervisor.fd); err != nil {\n\t\t\tlog.L.Errorf(\"Fail to close fd %d, %s\", supervisor.fd, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/supervisor/supervisor_test.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage supervisor\n\nimport (\n\t\"crypto/rand\"\n\t\"net\"\n\t\"os\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestSupervisor(t *testing.T) {\n\trootDir, err1 := os.MkdirTemp(\"\", \"supervisor\")\n\tassert.Nil(t, err1)\n\n\tt.Cleanup(func() {\n\t\tos.RemoveAll(rootDir)\n\t})\n\n\tsupervisorSet, err := NewSupervisorSet(rootDir)\n\tassert.Nil(t, err)\n\n\tsu1 := supervisorSet.NewSupervisor(\"su1\")\n\tassert.NotNil(t, su1)\n\tdefer func() {\n\t\terr = supervisorSet.DestroySupervisor(\"su1\")\n\t\tassert.NotNil(t, su1)\n\t}()\n\n\tsock := su1.Sock()\n\taddr, err := net.ResolveUnixAddr(\"unix\", sock)\n\tassert.Nil(t, err)\n\n\t// Build a large data to test the multiple recvmsg / sendmsg\n\t// syscalls can handle all the data.\n\tsentData := make([]byte, 1024*1024*2)\n\t_, err = rand.Read(sentData)\n\tassert.Nil(t, err)\n\n\ttmpFile, err := os.CreateTemp(\"\", \"nydus-supervisor-test\")\n\tassert.Nil(t, err)\n\tdefer tmpFile.Close()\n\tdefer os.Remove(tmpFile.Name())\n\n\tnydusdSendFd := func() error {\n\t\tconn, err := net.DialUnix(\"unix\", nil, addr)\n\t\tassert.Nil(t, err)\n\t\tdefer func() { _ = conn.Close() }()\n\n\t\terr = send(conn, sentData, int(tmpFile.Fd()))\n\t\tassert.Nil(t, err)\n\n\t\treturn nil\n\t}\n\n\terr = su1.FetchDaemonStates(nydusdSendFd)\n\tassert.NoError(t, err)\n\n\tnydusdTakeover := func() {\n\t\terr = su1.SendStatesTimeout(0)\n\t\tassert.Nil(t, err)\n\n\t\tconn, err := net.DialUnix(\"unix\", nil, addr)\n\t\tassert.Nil(t, err)\n\n\t\trecvData, _, err := recv(conn)\n\t\tassert.Nil(t, err)\n\n\t\tassert.Equal(t, len(sentData), len(recvData))\n\t\tassert.True(t, reflect.DeepEqual(recvData, sentData))\n\t}\n\n\tnydusdTakeover()\n}\n\nfunc TestSupervisorTimeout(t *testing.T) {\n\trootDir, err1 := os.MkdirTemp(\"\", \"supervisor\")\n\tassert.Nil(t, err1)\n\n\tt.Cleanup(func() {\n\t\tos.RemoveAll(rootDir)\n\t})\n\n\tsupervisorSet, err := NewSupervisorSet(rootDir)\n\tassert.Nil(t, err, \"%v\", err)\n\n\tsu1 := supervisorSet.NewSupervisor(\"su1\")\n\tassert.NotNil(t, su1)\n\n\terr = su1.SendStatesTimeout(10 * time.Millisecond)\n\tassert.Nil(t, err, \"%v\", err)\n\tsock := su1.Sock()\n\n\ttime.Sleep(200 * time.Millisecond)\n\n\taddr, err := net.ResolveUnixAddr(\"unix\", sock)\n\tassert.Nil(t, err)\n\n\t_, err = net.DialUnix(\"unix\", nil, addr)\n\tassert.NotNil(t, err, \"%v\", err)\n}\n"
  },
  {
    "path": "pkg/system/system.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage system\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/gorilla/mux\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/filesystem\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/manager\"\n\tmetrics \"github.com/containerd/nydus-snapshotter/pkg/metrics/tool\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/prefetch\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/signals\"\n)\n\nconst (\n\t// NOTE: Below service endpoints are still experimental.\n\n\tendpointDaemons string = \"/api/v1/daemons\"\n\t// Retrieve daemons' persisted states in boltdb. Because the db file is always locked,\n\t// it's very helpful to check daemon's record in database.\n\tendpointDaemonRecords  string = \"/api/v1/daemons/records\"\n\tendpointDaemonsUpgrade string = \"/api/v1/daemons/upgrade\"\n\tendpointPrefetch       string = \"/api/v1/prefetch\"\n\t// Provide backend information\n\tendpointGetBackend string = \"/api/v1/daemons/{id}/backend\"\n)\n\nconst defaultErrorCode string = \"Unknown\"\n\n// Nydus-snapshotter might manage dozens of running nydus daemons, each daemon may have multiple\n// file system instances attached. For easy maintenance, the system controller can interact with\n// all the daemons in a consistent and automatic way.\n\n// 1. Get all daemons status and information\n// 2. Trigger all daemons to restart and reload configuration\n// 3. Rolling update\n// 4. Daemons failures record as metrics\ntype Controller struct {\n\tfs       *filesystem.Filesystem\n\tmanagers []*manager.Manager\n\t// httpSever *http.Server\n\taddr   *net.UnixAddr\n\tuid    int\n\tgid    int\n\trouter *mux.Router\n}\n\ntype upgradeRequest struct {\n\tNydusdPath string `json:\"nydusd_path\"`\n\tVersion    string `json:\"version\"`\n\tPolicy     string `json:\"policy\"`\n}\n\ntype errorMessage struct {\n\tCode    string `json:\"code\"`\n\tMessage string `json:\"message\"`\n}\n\nfunc newErrorMessage(message string) errorMessage {\n\treturn errorMessage{Code: defaultErrorCode, Message: message}\n}\n\nfunc (m *errorMessage) encode() string {\n\tmsg, err := json.Marshal(&m)\n\tif err != nil {\n\t\tlog.L.Errorf(\"Failed to encode error message, %s\", err)\n\t\treturn \"\"\n\t}\n\treturn string(msg)\n}\n\nfunc jsonResponse(w http.ResponseWriter, payload interface{}) {\n\trespBody, err := json.Marshal(&payload)\n\tif err != nil {\n\t\tlog.L.Errorf(\"marshal error, %s\", err)\n\t\tm := newErrorMessage(err.Error())\n\t\thttp.Error(w, m.encode(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tw.WriteHeader(http.StatusOK)\n\tw.Header().Set(\"Content-Type\", \"application/json\")\n\tif _, err := w.Write(respBody); err != nil {\n\t\tlog.L.Errorf(\"write body %s\", err)\n\t}\n}\n\ntype daemonInfo struct {\n\tID                    string  `json:\"id\"`\n\tPid                   int     `json:\"pid\"`\n\tAPISock               string  `json:\"api_socket\"`\n\tSupervisorPath        string  `json:\"supervisor_path\"`\n\tReference             int     `json:\"reference\"`\n\tHostMountpoint        string  `json:\"mountpoint\"`\n\tStartupCPUUtilization float64 `json:\"startup_cpu_utilization\"`\n\tMemoryRSS             float64 `json:\"memory_rss_kb\"`\n\tReadData              float32 `json:\"read_data_kb\"`\n\n\tInstances map[string]rafsInstanceInfo `json:\"instances\"`\n}\n\ntype rafsInstanceInfo struct {\n\tSnapshotID  string `json:\"snapshot_id\"`\n\tSnapshotDir string `json:\"snapshot_dir\"`\n\tMountpoint  string `json:\"mountpoint\"`\n\tImageID     string `json:\"image_id\"`\n}\n\nfunc NewSystemController(fs *filesystem.Filesystem, managers []*manager.Manager, sock string, uid, gid int) (*Controller, error) {\n\tif err := os.MkdirAll(filepath.Dir(sock), os.ModePerm); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := os.Remove(sock); err != nil {\n\t\tif !os.IsNotExist(err) {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\taddr, err := net.ResolveUnixAddr(\"unix\", sock)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"resolve address %s\", sock)\n\t}\n\n\tsc := Controller{\n\t\tfs:       fs,\n\t\tmanagers: managers,\n\t\taddr:     addr,\n\t\tuid:      uid,\n\t\tgid:      gid,\n\t\trouter:   mux.NewRouter(),\n\t}\n\n\tsc.registerRouter()\n\n\treturn &sc, nil\n}\n\nfunc (sc *Controller) Run() error {\n\tlog.L.Infof(\"Start system controller API server on %s\", sc.addr)\n\tstopChan := signals.SetupSignalHandler()\n\tlistener, err := net.ListenUnix(\"unix\", sc.addr)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"listen to socket %s \", sc.addr)\n\t}\n\n\tif err := os.Chown(sc.addr.String(), sc.uid, sc.gid); err != nil {\n\t\treturn errors.Wrap(err, \"chown socket\")\n\t}\n\n\tgo func() {\n\t\t<-stopChan\n\t\tif err := listener.Close(); err != nil {\n\t\t\tlog.L.Errorf(\"Failed to close listener %s, err: %v\", sc.addr.String(), err)\n\t\t}\n\t}()\n\n\terr = http.Serve(listener, sc.router)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"system management serving\")\n\t}\n\n\treturn nil\n}\n\nfunc (sc *Controller) registerRouter() {\n\tsc.router.HandleFunc(endpointDaemons, sc.describeDaemons()).Methods(http.MethodGet)\n\tsc.router.HandleFunc(endpointDaemonsUpgrade, sc.upgradeDaemons()).Methods(http.MethodPut)\n\tsc.router.HandleFunc(endpointDaemonRecords, sc.getDaemonRecords()).Methods(http.MethodGet)\n\tsc.router.HandleFunc(endpointPrefetch, sc.setPrefetchConfiguration()).Methods(http.MethodPut)\n\tsc.router.HandleFunc(endpointGetBackend, sc.getBackend()).Methods(http.MethodGet)\n}\n\nfunc (sc *Controller) getBackend() func(w http.ResponseWriter, r *http.Request) {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tvar err error\n\t\tvar statusCode int\n\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\tm := newErrorMessage(err.Error())\n\t\t\t\thttp.Error(w, m.encode(), statusCode)\n\t\t\t}\n\t\t}()\n\n\t\tvars := mux.Vars(r)\n\t\tid := vars[\"id\"]\n\n\t\tfor _, ma := range sc.managers {\n\t\t\tma.Lock()\n\t\t\td := ma.GetByDaemonID(id)\n\n\t\t\tif d != nil {\n\t\t\t\tbackendType, backendConfig := d.Config.StorageBackend()\n\t\t\t\tbackend := struct {\n\t\t\t\t\tBackendType string      `json:\"type\"`\n\t\t\t\t\tConfig      interface{} `json:\"config\"`\n\t\t\t\t}{\n\t\t\t\t\tbackendType,\n\t\t\t\t\tbackendConfig,\n\t\t\t\t}\n\t\t\t\tjsonResponse(w, backend)\n\t\t\t\tma.Unlock()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tma.Unlock()\n\t\t}\n\n\t\terr = errdefs.ErrNotFound\n\t\tstatusCode = http.StatusNotFound\n\t}\n}\n\nfunc (sc *Controller) setPrefetchConfiguration() func(w http.ResponseWriter, r *http.Request) {\n\treturn func(_ http.ResponseWriter, r *http.Request) {\n\t\tbody, err := io.ReadAll(r.Body)\n\t\tif err != nil {\n\t\t\tlog.L.Errorf(\"Failed to read prefetch list: %v\", err)\n\t\t\treturn\n\t\t}\n\t\tif err = prefetch.Pm.SetPrefetchFiles(body); err != nil {\n\t\t\tlog.L.Errorf(\"Failed to parse request body: %v\", err)\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc (sc *Controller) describeDaemons() func(w http.ResponseWriter, r *http.Request) {\n\treturn func(w http.ResponseWriter, _ *http.Request) {\n\t\tinfo := make([]daemonInfo, 0, 10)\n\n\t\tfor _, manager := range sc.managers {\n\t\t\tdaemons := manager.ListDaemons()\n\n\t\t\tfor _, d := range daemons {\n\t\t\t\tinstances := make(map[string]rafsInstanceInfo)\n\t\t\t\tfor _, i := range d.RafsCache.List() {\n\t\t\t\t\tinstances[i.SnapshotID] = rafsInstanceInfo{\n\t\t\t\t\t\tSnapshotID:  i.SnapshotID,\n\t\t\t\t\t\tSnapshotDir: i.SnapshotDir,\n\t\t\t\t\t\tMountpoint:  i.GetMountpoint(),\n\t\t\t\t\t\tImageID:     i.ImageID,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmemRSS, err := metrics.GetProcessMemoryRSSKiloBytes(d.Pid())\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.L.Warnf(\"Failed to get daemon %s RSS memory\", d.ID())\n\t\t\t\t}\n\n\t\t\t\tvar readData float32\n\t\t\t\tfsMetrics, err := d.GetFsMetrics(\"\")\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.L.Warnf(\"Failed to get file system metrics\")\n\t\t\t\t} else {\n\t\t\t\t\treadData = float32(fsMetrics.DataRead) / 1024\n\t\t\t\t}\n\n\t\t\t\ti := daemonInfo{\n\t\t\t\t\tID:                    d.ID(),\n\t\t\t\t\tPid:                   d.Pid(),\n\t\t\t\t\tAPISock:               d.GetAPISock(),\n\t\t\t\t\tSupervisorPath:        d.States.SupervisorPath,\n\t\t\t\t\tHostMountpoint:        d.HostMountpoint(),\n\t\t\t\t\tReference:             int(d.GetRef()),\n\t\t\t\t\tInstances:             instances,\n\t\t\t\t\tStartupCPUUtilization: d.StartupCPUUtilization,\n\t\t\t\t\tMemoryRSS:             memRSS,\n\t\t\t\t\tReadData:              readData,\n\t\t\t\t}\n\n\t\t\t\tinfo = append(info, i)\n\t\t\t}\n\t\t}\n\n\t\tjsonResponse(w, &info)\n\t}\n}\n\n// TODO: Implement me!\nfunc (sc *Controller) getDaemonRecords() func(w http.ResponseWriter, r *http.Request) {\n\treturn func(w http.ResponseWriter, _ *http.Request) {\n\t\tm := newErrorMessage(\"not implemented\")\n\t\thttp.Error(w, m.encode(), http.StatusNotImplemented)\n\t}\n}\n\n// PUT /api/v1/nydusd/upgrade\n// body: {\"nydusd_path\": \"/path/to/new/nydusd\", \"version\": \"v2.2.1\", \"policy\": \"rolling\"}\n// Possible policy: rolling, immediate\n// Live upgrade procedure:\n//  1. Check if new version of nydusd executive is existed.\n//  2. Validate its version matching `version` in this request.\n//  3. Upgrade one nydusd:\n//     a. Lock the whole manager daemons cache, no daemon can be inserted of deleted from manager\n//     b. Start a new nydusd with `--upgrade` flag, wait until it reaches INTI state\n//     c. Validate the new nydusd's version returned by API /daemon\n//     d. Send resources like FD and daemon running states to the new nydusd by API /takeover\n//     e. Wait until new nydusd reaches state READY\n//     f. Command the old nydusd to exit\n//     g. Send API /start to the new nydusd making it take over the whole file system service\n//\n// 4. Upgrade next nydusd like step 3.\n// 5. If upgrading a certain nydusd fails, abort!\n// 6. Delete the old nydusd executive\nfunc (sc *Controller) upgradeDaemons() func(w http.ResponseWriter, r *http.Request) {\n\treturn func(w http.ResponseWriter, r *http.Request) {\n\t\tvar c upgradeRequest\n\t\tvar err error\n\t\tvar statusCode int\n\n\t\tdefer func() {\n\t\t\tif err != nil {\n\t\t\t\tm := newErrorMessage(err.Error())\n\t\t\t\thttp.Error(w, m.encode(), statusCode)\n\t\t\t}\n\t\t}()\n\n\t\terr = json.NewDecoder(r.Body).Decode(&c)\n\t\tif err != nil {\n\t\t\tlog.L.Errorf(\"request %v, decode error %s\", r, err)\n\t\t\tstatusCode = http.StatusBadRequest\n\t\t\treturn\n\t\t}\n\n\t\tfor _, manager := range sc.managers {\n\t\t\tmanager.Lock()\n\t\t\tdefer manager.Unlock()\n\n\t\t\tdaemons := manager.ListDaemons()\n\n\t\t\t// TODO: Keep the nydusd executive path in Daemon state and persis it since nydusd\n\t\t\t// can run on both versions.\n\t\t\t// Create a dedicated directory storing nydusd of various versions?\n\t\t\t// TODO: daemon client has a method to query daemon version and information.\n\t\t\tfor _, d := range daemons {\n\t\t\t\terr = sc.upgradeNydusDaemon(d, c, manager)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.L.Errorf(\"Upgrade daemon %s failed, %s\", d.ID(), err)\n\t\t\t\t\tstatusCode = http.StatusInternalServerError\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsourcePath := c.NydusdPath\n\t\t\tdestinationPath := manager.NydusdBinaryPath\n\n\t\t\tif err = upgradeNydusdWithSymlink(sourcePath, destinationPath); err != nil {\n\t\t\t\tlog.L.Errorf(\"Failed to copy nydusd binary from %s to %s: %v\",\n\t\t\t\t\tsourcePath, destinationPath, err)\n\t\t\t\tstatusCode = http.StatusInternalServerError\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Provide minimal parameters since most of it can be recovered by nydusd states.\n// Create a new daemon in Manger to take over the service.\nfunc (sc *Controller) upgradeNydusDaemon(d *daemon.Daemon, c upgradeRequest, manager *manager.Manager) error {\n\tsupervisor := d.Supervisor\n\tif supervisor == nil {\n\t\treturn errors.New(\"should set recover policy to failover to enable hot upgrade\")\n\t}\n\n\tlog.L.Infof(\"Upgrading nydusd %s, request %v\", d.ID(), c)\n\n\tfs := sc.fs\n\n\tnewDaemon := daemon.Daemon{\n\t\tStates:     d.States,\n\t\tSupervisor: supervisor,\n\t}\n\tnewDaemon.CloneRafsInstances(d)\n\n\ts := path.Base(d.GetAPISock())\n\tnext, err := buildNextAPISocket(s)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tupgradingSocket := path.Join(path.Dir(d.GetAPISock()), next)\n\tnewDaemon.States.APISocket = upgradingSocket\n\n\tcmd, err := manager.BuildDaemonCommand(&newDaemon, c.NydusdPath, true)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := supervisor.SendStatesTimeout(time.Second * 10); err != nil {\n\t\treturn errors.Wrap(err, \"Send states\")\n\t}\n\n\tif err := cmd.Start(); err != nil {\n\t\treturn errors.Wrap(err, \"start process\")\n\t}\n\n\tnewDaemon.States.ProcessID = cmd.Process.Pid\n\n\tif err := newDaemon.WaitUntilState(types.DaemonStateInit); err != nil {\n\t\treturn errors.Wrap(err, \"wait until init state\")\n\t}\n\n\tif err := newDaemon.TakeOver(); err != nil {\n\t\treturn errors.Wrap(err, \"take over resources\")\n\t}\n\n\tif err := newDaemon.WaitUntilState(types.DaemonStateReady); err != nil {\n\t\treturn errors.Wrap(err, \"wait unit ready state\")\n\t}\n\n\tif err := manager.UnsubscribeDaemonEvent(d); err != nil {\n\t\treturn errors.Wrap(err, \"unsubscribe daemon event\")\n\t}\n\n\t// Let the older daemon exit without umount\n\tif err := d.Exit(); err != nil {\n\t\treturn errors.Wrap(err, \"old daemon exits\")\n\t}\n\n\tfs.TryRetainSharedDaemon(&newDaemon)\n\n\tif err := newDaemon.Start(); err != nil {\n\t\treturn errors.Wrap(err, \"start file system service\")\n\t}\n\n\tif err := manager.SubscribeDaemonEvent(&newDaemon); err != nil {\n\t\treturn &json.InvalidUnmarshalError{}\n\t}\n\n\tlog.L.Infof(\"Started service of upgraded daemon on socket %s\", newDaemon.GetAPISock())\n\n\tif err := manager.UpdateDaemonLocked(&newDaemon); err != nil {\n\t\treturn err\n\t}\n\n\tlog.L.Infof(\"Upgraded daemon success on socket %s\", newDaemon.GetAPISock())\n\n\treturn nil\n}\n\n// Name next api socket path based on currently api socket path listened on.\n// The principle is to add a suffix number to api[0-9]+.sock\nfunc buildNextAPISocket(cur string) (string, error) {\n\tn := strings.Split(cur, \".\")\n\tif len(n) != 2 {\n\t\treturn \"\", errdefs.ErrInvalidArgument\n\t}\n\tr := regexp.MustCompile(`[0-9]+`)\n\tm := r.Find([]byte(n[0]))\n\tvar num int\n\tif m == nil {\n\t\tnum = 1\n\t} else {\n\t\tvar err error\n\t\tnum, err = strconv.Atoi(string(m))\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tnum++\n\t}\n\n\tnextSocket := fmt.Sprintf(\"api%d.sock\", num)\n\treturn nextSocket, nil\n}\n\n// upgradeNydusdWithSymlink atomically creates a symbolic link from destinationPath to sourcePath.\n// It uses atomic rename to avoid any gap period where the destination doesn't exist.\n// Running processes are not affected as they hold file descriptors to the original inode.\nfunc upgradeNydusdWithSymlink(sourcePath, destinationPath string) error {\n\t// Ensure source file exists and is accessible\n\tif _, err := os.Stat(sourcePath); err != nil {\n\t\treturn fmt.Errorf(\"source file %s does not exist or is not accessible: %w\", sourcePath, err)\n\t}\n\n\t// Ensure destination directory exists\n\tdestDir := filepath.Dir(destinationPath)\n\tif err := os.MkdirAll(destDir, 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create destination directory %s: %w\", destDir, err)\n\t}\n\n\t// Use absolute path for source to avoid relative path issues\n\tabsSourcePath, err := filepath.Abs(sourcePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get absolute path for %s: %w\", sourcePath, err)\n\t}\n\n\t// Get absolute path for destination to compare\n\tabsDestinationPath, err := filepath.Abs(destinationPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get absolute path for %s: %w\", destinationPath, err)\n\t}\n\n\t// Check if source and destination are the same to avoid circular symlink\n\tif absSourcePath == absDestinationPath {\n\t\treturn fmt.Errorf(\"source path and destination path are the same: %s\", absSourcePath)\n\t}\n\n\t// Create a temporary symbolic link first\n\ttempSymlinkPath := absDestinationPath + \".tmp\"\n\tif err := os.Symlink(absSourcePath, tempSymlinkPath); err != nil {\n\t\treturn fmt.Errorf(\"failed to create temporary symbolic link %s: %w\", tempSymlinkPath, err)\n\t}\n\n\t// Atomically replace the destination with the temporary symlink\n\tif err := os.Rename(tempSymlinkPath, absDestinationPath); err != nil {\n\t\t// Clean up temporary symlink if rename fails\n\t\tos.Remove(tempSymlinkPath)\n\t\treturn fmt.Errorf(\"failed to atomically replace symlink %s: %w\", absDestinationPath, err)\n\t}\n\n\tlog.L.Infof(\"Successfully created symbolic link from %s to %s\", absDestinationPath, absSourcePath)\n\treturn nil\n}\n"
  },
  {
    "path": "pkg/system/system_test.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage system\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestBuildUpgradeSocket(t *testing.T) {\n\tcur := \"api.sock\"\n\n\tnext, err := buildNextAPISocket(cur)\n\tassert.Nil(t, err)\n\tassert.Equal(t, next, \"api1.sock\")\n\n\tcur = \"api2.sock\"\n\n\tnext, err = buildNextAPISocket(cur)\n\tassert.Nil(t, err)\n\tassert.Equal(t, \"api3.sock\", next)\n\n\tcur = \"api23.sock\"\n\n\tnext, err = buildNextAPISocket(cur)\n\tassert.Nil(t, err)\n\tassert.Equal(t, \"api24.sock\", next)\n\n\tcur = \"api222.sock\"\n\n\tnext, err = buildNextAPISocket(cur)\n\tassert.Nil(t, err)\n\tassert.Equal(t, \"api223.sock\", next)\n}\n"
  },
  {
    "path": "pkg/tarfs/tarfs.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage tarfs\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\t\"syscall\"\n\n\t\"github.com/containerd/containerd/v2/core/snapshots/storage\"\n\t\"github.com/containerd/containerd/v2/pkg/archive/compression\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/remote/remotes\"\n\tlosetup \"github.com/freddierice/go-losetup\"\n\t\"github.com/opencontainers/go-digest\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x/sync/semaphore\"\n\t\"golang.org/x/sync/singleflight\"\n\t\"golang.org/x/sys/unix\"\n\t\"k8s.io/utils/lru\"\n)\n\nconst (\n\tTarfsStatusInit    = 0\n\tTarfsStatusPrepare = 1\n\tTarfsStatusReady   = 2\n\tTarfsStatusFailed  = 3\n)\n\nconst (\n\tMaxManifestConfigSize   = 0x100000\n\tTarfsLayerBootstrapName = \"layer.boot\"\n\tTarfsImageBootstrapName = \"image.boot\"\n\tTarfsLayerDiskName      = \"layer.disk\"\n\tTarfsImageDiskName      = \"image.disk\"\n)\n\ntype Manager struct {\n\tsnapshotMap          map[string]*snapshotStatus // tarfs snapshots status, indexed by snapshot ID\n\tmutex                sync.Mutex\n\tmutexLoopDev         sync.Mutex\n\tcacheDirPath         string\n\tnydusImagePath       string\n\tinsecure             bool\n\tvalidateDiffID       bool // whether to validate digest for uncompressed content\n\tcheckTarfsHint       bool // whether to rely on tarfs hint annotation\n\tmaxConcurrentProcess int64\n\tprocessLimiterCache  *lru.Cache // cache image ref and concurrent limiter for blob processes\n\ttarfsHintCache       *lru.Cache // cache oci image ref and tarfs hint annotation\n\tdiffIDCache          *lru.Cache // cache oci blob digest and diffID\n\tsg                   singleflight.Group\n}\n\ntype snapshotStatus struct {\n\tmutex           sync.Mutex\n\tstatus          int\n\tblobID          string\n\tblobTarFilePath string\n\terofsMountPoint string\n\tdataLoopdev     *losetup.Device\n\tmetaLoopdev     *losetup.Device\n\twg              *sync.WaitGroup\n\tcancel          context.CancelFunc\n}\n\nfunc NewManager(insecure, checkTarfsHint bool, cacheDirPath, nydusImagePath string, maxConcurrentProcess int64) *Manager {\n\treturn &Manager{\n\t\tsnapshotMap:          map[string]*snapshotStatus{},\n\t\tcacheDirPath:         cacheDirPath,\n\t\tnydusImagePath:       nydusImagePath,\n\t\tinsecure:             insecure,\n\t\tvalidateDiffID:       true,\n\t\tcheckTarfsHint:       checkTarfsHint,\n\t\tmaxConcurrentProcess: maxConcurrentProcess,\n\t\ttarfsHintCache:       lru.New(50),\n\t\tprocessLimiterCache:  lru.New(50),\n\t\tdiffIDCache:          lru.New(1000),\n\t\tsg:                   singleflight.Group{},\n\t}\n}\n\n// Fetch image manifest and config contents, cache frequently used information.\n// FIXME need an update policy\nfunc (t *Manager) fetchImageInfo(ctx context.Context, remote *remote.Remote, ref string, manifestDigest digest.Digest) error {\n\tmanifest, err := t.fetchImageManifest(ctx, remote, ref, manifestDigest)\n\tif err != nil {\n\t\treturn err\n\t}\n\tconfig, err := t.fetchImageConfig(ctx, remote, ref, &manifest)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif t.checkTarfsHint {\n\t\t// cache ref & tarfs hint annotation\n\t\tt.tarfsHintCache.Add(ref, label.HasTarfsHint(manifest.Annotations))\n\t}\n\tif t.validateDiffID {\n\t\t// cache OCI blob digest & diff id\n\t\tfor i := range manifest.Layers {\n\t\t\tt.diffIDCache.Add(manifest.Layers[i].Digest, config.RootFS.DiffIDs[i])\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (t *Manager) fetchImageManifest(ctx context.Context, remote *remote.Remote, ref string, manifestDigest digest.Digest) (ocispec.Manifest, error) {\n\trc, desc, err := t.getBlobStream(ctx, remote, ref, manifestDigest)\n\tif err != nil {\n\t\treturn ocispec.Manifest{}, err\n\t}\n\tdefer rc.Close()\n\tif desc.Size > MaxManifestConfigSize {\n\t\treturn ocispec.Manifest{}, errors.Errorf(\"image manifest content size %x is too big\", desc.Size)\n\t}\n\tbytes, err := io.ReadAll(rc)\n\tif err != nil {\n\t\treturn ocispec.Manifest{}, errors.Wrap(err, \"read image manifest content\")\n\t}\n\n\tvar manifestOCI ocispec.Manifest\n\tif err := json.Unmarshal(bytes, &manifestOCI); err != nil {\n\t\treturn ocispec.Manifest{}, errors.Wrap(err, \"unmarshal OCI image manifest\")\n\t}\n\tif len(manifestOCI.Layers) < 1 {\n\t\treturn ocispec.Manifest{}, errors.Errorf(\"invalid OCI image manifest without any layer\")\n\t}\n\n\treturn manifestOCI, nil\n}\n\nfunc (t *Manager) fetchImageConfig(ctx context.Context, remote *remote.Remote, ref string, manifest *ocispec.Manifest) (ocispec.Image, error) {\n\t// fetch image config content and extract diffIDs\n\trc, desc, err := t.getBlobStream(ctx, remote, ref, manifest.Config.Digest)\n\tif err != nil {\n\t\treturn ocispec.Image{}, errors.Wrap(err, \"fetch image config content\")\n\t}\n\tdefer rc.Close()\n\tif desc.Size > MaxManifestConfigSize {\n\t\treturn ocispec.Image{}, errors.Errorf(\"image config content size %x is too big\", desc.Size)\n\t}\n\tbytes, err := io.ReadAll(rc)\n\tif err != nil {\n\t\treturn ocispec.Image{}, errors.Wrap(err, \"read image config content\")\n\t}\n\n\tvar config ocispec.Image\n\tif err := json.Unmarshal(bytes, &config); err != nil {\n\t\treturn ocispec.Image{}, errors.Wrap(err, \"unmarshal image config\")\n\t}\n\tif len(config.RootFS.DiffIDs) != len(manifest.Layers) {\n\t\treturn ocispec.Image{}, errors.Errorf(\"number of diffIDs does not match manifest layers\")\n\t}\n\n\treturn config, nil\n}\n\nfunc (t *Manager) getBlobDiffID(ctx context.Context, remote *remote.Remote, ref string, manifestDigest, layerDigest digest.Digest) (digest.Digest, error) {\n\tif diffid, ok := t.diffIDCache.Get(layerDigest); ok {\n\t\treturn diffid.(digest.Digest), nil\n\t}\n\n\tif _, err, _ := t.sg.Do(ref, func() (interface{}, error) {\n\t\terr := t.fetchImageInfo(ctx, remote, ref, manifestDigest)\n\t\treturn nil, err\n\t}); err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif diffid, ok := t.diffIDCache.Get(layerDigest); ok {\n\t\treturn diffid.(digest.Digest), nil\n\t}\n\n\treturn \"\", errors.Errorf(\"get blob diff id failed\")\n}\n\nfunc (t *Manager) getBlobStream(ctx context.Context, remote *remote.Remote, ref string, contentDigest digest.Digest) (io.ReadCloser, ocispec.Descriptor, error) {\n\tfetcher, err := remote.Fetcher(ctx, ref)\n\tif err != nil {\n\t\treturn nil, ocispec.Descriptor{}, errors.Wrap(err, \"get remote fetcher\")\n\t}\n\n\tfetcherByDigest, ok := fetcher.(remotes.FetcherByDigest)\n\tif !ok {\n\t\treturn nil, ocispec.Descriptor{}, errors.Errorf(\"fetcher %T does not implement remotes.FetcherByDigest\", fetcher)\n\t}\n\n\treturn fetcherByDigest.FetchByDigest(ctx, contentDigest)\n}\n\n// generate tar file and layer bootstrap, return if this blob is an empty blob\nfunc (t *Manager) generateBootstrap(tarReader io.Reader, snapshotID, layerBlobID, upperDirPath string) (err error) {\n\tsnapshotImageDir := filepath.Join(upperDirPath, \"image\")\n\tif err := os.MkdirAll(snapshotImageDir, 0750); err != nil {\n\t\treturn errors.Wrapf(err, \"create data dir %s for tarfs snapshot\", snapshotImageDir)\n\t}\n\tlayerMetaFile := t.layerMetaFilePath(upperDirPath)\n\tif _, err := os.Stat(layerMetaFile); err == nil {\n\t\treturn errdefs.ErrAlreadyExists\n\t}\n\tlayerMetaFileTmp := layerMetaFile + \".tarfs.tmp\"\n\tdefer os.Remove(layerMetaFileTmp)\n\n\tlayerTarFile := t.layerTarFilePath(layerBlobID)\n\tlayerTarFileTmp := layerTarFile + \".tarfs.tmp\"\n\ttarFile, err := os.Create(layerTarFileTmp)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"create temporary file to store tar stream\")\n\t}\n\tdefer tarFile.Close()\n\tdefer os.Remove(layerTarFileTmp)\n\n\tfifoName := filepath.Join(upperDirPath, \"layer_\"+snapshotID+\"_\"+\"tar.fifo\")\n\tif err = syscall.Mkfifo(fifoName, 0644); err != nil {\n\t\treturn err\n\t}\n\tdefer os.Remove(fifoName)\n\n\tgo func() {\n\t\tfifoFile, err := os.OpenFile(fifoName, os.O_WRONLY, os.ModeNamedPipe)\n\t\tif err != nil {\n\t\t\tlog.L.Warnf(\"can not open fifo file,  err %v\", err)\n\t\t\treturn\n\t\t}\n\t\tdefer fifoFile.Close()\n\t\tif _, err := io.Copy(fifoFile, io.TeeReader(tarReader, tarFile)); err != nil {\n\t\t\tlog.L.Warnf(\"tar stream copy err %v\", err)\n\t\t}\n\t}()\n\n\toptions := []string{\n\t\t\"create\",\n\t\t\"--type\", \"tar-tarfs\",\n\t\t\"--bootstrap\", layerMetaFileTmp,\n\t\t\"--blob-id\", layerBlobID,\n\t\t\"--blob-dir\", t.cacheDirPath,\n\t\tfifoName,\n\t}\n\tcmd := exec.Command(t.nydusImagePath, options...)\n\tvar errb, outb bytes.Buffer\n\tcmd.Stderr = &errb\n\tcmd.Stdout = &outb\n\tlog.L.Debugf(\"nydus image command %v\", options)\n\terr = cmd.Run()\n\tif err != nil {\n\t\tlog.L.Warnf(\"nydus image exec failed, %s\", errb.String())\n\t\treturn errors.Wrap(err, \"converting OCIv1 layer blob to tarfs\")\n\t}\n\tlog.L.Debugf(\"nydus image output %s\", outb.String())\n\tlog.L.Debugf(\"nydus image err %s\", errb.String())\n\n\tif err := os.Rename(layerTarFileTmp, layerTarFile); err != nil {\n\t\treturn errors.Wrapf(err, \"rename file %s to %s\", layerTarFileTmp, layerTarFile)\n\t}\n\tif err := os.Rename(layerMetaFileTmp, layerMetaFile); err != nil {\n\t\treturn errors.Wrapf(err, \"rename file %s to %s\", layerMetaFileTmp, layerMetaFile)\n\t}\n\n\treturn nil\n}\n\nfunc (t *Manager) getImageBlobInfo(metaFilePath string) (string, error) {\n\tif _, err := os.Stat(metaFilePath); err != nil {\n\t\treturn \"\", err\n\t}\n\n\toptions := []string{\n\t\t\"inspect\",\n\t\t\"-R blobs\",\n\t\tmetaFilePath,\n\t}\n\tcmd := exec.Command(t.nydusImagePath, options...)\n\tvar errb, outb bytes.Buffer\n\tcmd.Stderr = &errb\n\tcmd.Stdout = &outb\n\tlog.L.Debugf(\"nydus image command %v\", options)\n\terr := cmd.Run()\n\tif err != nil {\n\t\tlog.L.Warnf(\"nydus image exec failed, %s\", errb.String())\n\t\treturn \"\", errors.Wrap(err, \"converting OCIv1 layer blob to tarfs\")\n\t}\n\n\treturn outb.String(), nil\n}\n\n// download & uncompress an oci/docker blob, and then generate the tarfs bootstrap\nfunc (t *Manager) blobProcess(ctx context.Context, wg *sync.WaitGroup, snapshotID, ref string,\n\tmanifestDigest, layerDigest digest.Digest, upperDirPath string) error {\n\tlayerBlobID := layerDigest.Hex()\n\tepilog := func(err error, msg string) {\n\t\tst, err1 := t.getSnapshotStatus(snapshotID, true)\n\t\tif err1 != nil {\n\t\t\t// return errors.Errorf(\"can not found status object for snapshot %s after prepare\", snapshotID)\n\t\t\terr1 = errors.Wrapf(err1, \"can not found status object for snapshot %s after prepare\", snapshotID)\n\t\t\tlog.L.WithError(err1).Errorf(\"async prepare tarfs layer for snapshot ID %s\", snapshotID)\n\t\t\treturn\n\t\t}\n\t\tdefer st.mutex.Unlock()\n\n\t\tst.blobID = layerBlobID\n\t\tst.blobTarFilePath = t.layerTarFilePath(layerBlobID)\n\t\tif err != nil {\n\t\t\tlog.L.WithError(err).Error(msg)\n\t\t\tst.status = TarfsStatusFailed\n\t\t} else {\n\t\t\tst.status = TarfsStatusReady\n\t\t}\n\t\tlog.L.Info(msg)\n\t}\n\n\tkeyChain, err := auth.GetKeyChainByRef(ref, nil)\n\tif err != nil {\n\t\tepilog(err, \"create key chain for connection\")\n\t\treturn err\n\t}\n\tremote := remote.New(keyChain, t.insecure)\n\trc, _, err := t.getBlobStream(ctx, remote, ref, layerDigest)\n\tif err != nil && remote.RetryWithPlainHTTP(ref, err) {\n\t\trc, _, err = t.getBlobStream(ctx, remote, ref, layerDigest)\n\t}\n\tif err != nil {\n\t\tepilog(err, \"get blob stream for layer\")\n\t\treturn errors.Wrapf(err, \"get blob stream by digest\")\n\t}\n\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tdefer rc.Close()\n\n\t\tds, err := compression.DecompressStream(rc)\n\t\tif err != nil {\n\t\t\tepilog(err, \"unpack layer blob stream for tarfs\")\n\t\t\treturn\n\t\t}\n\t\tdefer ds.Close()\n\n\t\tif t.validateDiffID {\n\t\t\tdiffID, err := t.getBlobDiffID(ctx, remote, ref, manifestDigest, layerDigest)\n\t\t\tif err != nil {\n\t\t\t\tepilog(err, \"get layer diffID\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tdigester := digest.Canonical.Digester()\n\t\t\tdr := io.TeeReader(ds, digester.Hash())\n\t\t\terr = t.generateBootstrap(dr, snapshotID, layerBlobID, upperDirPath)\n\t\t\tswitch {\n\t\t\tcase err != nil && !errdefs.IsAlreadyExists(err):\n\t\t\t\tepilog(err, \"generate tarfs from image layer blob\")\n\t\t\tcase err == nil && digester.Digest() != diffID:\n\t\t\t\tepilog(err, \"image layer diffID does not match\")\n\t\t\tdefault:\n\t\t\t\tmsg := fmt.Sprintf(\"nydus tarfs for snapshot %s is ready, digest %s\", snapshotID, digester.Digest())\n\t\t\t\tepilog(nil, msg)\n\t\t\t}\n\t\t} else {\n\t\t\terr = t.generateBootstrap(ds, snapshotID, layerBlobID, upperDirPath)\n\t\t\tif err != nil && !errdefs.IsAlreadyExists(err) {\n\t\t\t\tepilog(err, \"generate tarfs data from image layer blob\")\n\t\t\t} else {\n\t\t\t\tmsg := fmt.Sprintf(\"nydus tarfs for snapshot %s is ready\", snapshotID)\n\t\t\t\tepilog(nil, msg)\n\t\t\t}\n\t\t}\n\t}()\n\n\treturn err\n}\n\nfunc (t *Manager) PrepareLayer(snapshotID, ref string, manifestDigest, layerDigest digest.Digest, upperDirPath string) error {\n\tt.mutex.Lock()\n\tif _, ok := t.snapshotMap[snapshotID]; ok {\n\t\tt.mutex.Unlock()\n\t\treturn errors.Errorf(\"snapshot %s has already been prapared\", snapshotID)\n\t}\n\twg := &sync.WaitGroup{}\n\twg.Add(1)\n\tctx, cancel := context.WithCancel(context.Background())\n\n\tt.snapshotMap[snapshotID] = &snapshotStatus{\n\t\tstatus: TarfsStatusPrepare,\n\t\twg:     wg,\n\t\tcancel: cancel,\n\t}\n\tt.mutex.Unlock()\n\n\treturn t.blobProcess(ctx, wg, snapshotID, ref, manifestDigest, layerDigest, upperDirPath)\n}\n\nfunc (t *Manager) MergeLayers(s storage.Snapshot, storageLocater func(string) string) error {\n\tmergedBootstrap := t.imageMetaFilePath(storageLocater(s.ParentIDs[0]))\n\tif _, err := os.Stat(mergedBootstrap); err == nil {\n\t\tlog.L.Debugf(\"tarfs snapshot %s already has merged bootstrap %s\", s.ParentIDs[0], mergedBootstrap)\n\t\treturn nil\n\t}\n\n\tbootstraps := []string{}\n\t// When merging bootstrap, we need to arrange layer bootstrap in order from low to high\n\tfor idx := len(s.ParentIDs) - 1; idx >= 0; idx-- {\n\t\tsnapshotID := s.ParentIDs[idx]\n\t\terr := t.waitLayerReady(snapshotID)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"wait for tarfs snapshot %s to get ready\", snapshotID)\n\t\t}\n\n\t\tst, err := t.getSnapshotStatus(snapshotID, false)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif st.status != TarfsStatusReady {\n\t\t\treturn errors.Errorf(\"tarfs snapshot %s is not ready, %d\", snapshotID, st.status)\n\t\t}\n\n\t\tmetaFilePath := t.layerMetaFilePath(storageLocater(snapshotID))\n\t\tbootstraps = append(bootstraps, metaFilePath)\n\t}\n\n\tmergedBootstrapTmp := mergedBootstrap + \".tarfs.tmp\"\n\tdefer os.Remove(mergedBootstrapTmp)\n\n\toptions := []string{\n\t\t\"merge\",\n\t\t\"--bootstrap\", mergedBootstrapTmp,\n\t}\n\toptions = append(options, bootstraps...)\n\tcmd := exec.Command(t.nydusImagePath, options...)\n\tvar errb, outb bytes.Buffer\n\tcmd.Stderr = &errb\n\tcmd.Stdout = &outb\n\tlog.L.Debugf(\"nydus image command %v\", options)\n\terr := cmd.Run()\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"merge tarfs image layers\")\n\t}\n\n\terr = os.Rename(mergedBootstrapTmp, mergedBootstrap)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"rename merged bootstrap file\")\n\t}\n\n\treturn nil\n}\n\nfunc (t *Manager) ExportBlockData(s storage.Snapshot, perLayer bool, labels map[string]string, storageLocater func(string) string) ([]string, error) {\n\tupdateFields := []string{}\n\n\twholeImage, exportDisk, withVerity := config.GetTarfsExportFlags()\n\n\tlog.L.Debugf(\"ExportBlockData wholeImage = %v, exportDisk = %v, withVerity = %v, perLayer = %v\", wholeImage, exportDisk, withVerity, perLayer)\n\t// Nothing to do for this case, all needed datum are ready.\n\tif !exportDisk && !withVerity {\n\t\treturn updateFields, nil\n\t} else if !wholeImage != perLayer {\n\t\t// Special handling for `layer_block` mode\n\t\tif exportDisk && !withVerity && !perLayer {\n\t\t\tlabels[label.NydusLayerBlockInfo] = \"\"\n\t\t\tupdateFields = append(updateFields, \"labels.\"+label.NydusLayerBlockInfo)\n\t\t}\n\t\treturn updateFields, nil\n\t}\n\n\tvar snapshotID string\n\tif perLayer {\n\t\tsnapshotID = s.ID\n\t} else {\n\t\tif len(s.ParentIDs) == 0 {\n\t\t\treturn updateFields, errors.Errorf(\"snapshot %s has no parent\", s.ID)\n\t\t}\n\t\tsnapshotID = s.ParentIDs[0]\n\t}\n\terr := t.waitLayerReady(snapshotID)\n\tif err != nil {\n\t\treturn updateFields, errors.Wrapf(err, \"wait for tarfs snapshot %s to get ready\", snapshotID)\n\t}\n\tst, err := t.getSnapshotStatus(snapshotID, false)\n\tif err != nil {\n\t\treturn updateFields, err\n\t}\n\tif st.status != TarfsStatusReady {\n\t\treturn updateFields, errors.Errorf(\"tarfs snapshot %s is not ready, %d\", snapshotID, st.status)\n\t}\n\n\tblobID, ok := labels[label.NydusTarfsLayer]\n\tif !ok {\n\t\treturn updateFields, errors.Errorf(\"Missing Nydus tarfs layer annotation for snapshot %s\", s.ID)\n\t}\n\n\tvar metaFileName, diskFileName string\n\tif wholeImage {\n\t\tmetaFileName = t.imageMetaFilePath(storageLocater(snapshotID))\n\t\tdiskFileName = t.ImageDiskFilePath(blobID)\n\t} else {\n\t\tmetaFileName = t.layerMetaFilePath(storageLocater(snapshotID))\n\t\tdiskFileName = t.LayerDiskFilePath(blobID)\n\t}\n\n\t// Do not regenerate if the disk image already exists.\n\tif _, err := os.Stat(diskFileName); err == nil {\n\t\treturn updateFields, nil\n\t}\n\tdiskFileNameTmp := diskFileName + \".tarfs.tmp\"\n\tdefer os.Remove(diskFileNameTmp)\n\n\toptions := []string{\n\t\t\"export\",\n\t\t\"--block\",\n\t\t\"--localfs-dir\", t.cacheDirPath,\n\t\t\"--bootstrap\", metaFileName,\n\t\t\"--output\", diskFileNameTmp,\n\t}\n\tif withVerity {\n\t\toptions = append(options, \"--verity\")\n\t}\n\tlog.L.Debugf(\"nydus image command %v\", options)\n\tcmd := exec.Command(t.nydusImagePath, options...)\n\tvar errb, outb bytes.Buffer\n\tcmd.Stderr = &errb\n\tcmd.Stdout = &outb\n\terr = cmd.Run()\n\tif err != nil {\n\t\treturn updateFields, errors.Wrap(err, \"merge tarfs image layers\")\n\t}\n\tlog.L.Debugf(\"nydus image export command, stdout: %s, stderr: %s\", &outb, &errb)\n\n\tblockInfo := \"\"\n\tif withVerity {\n\t\tpattern := \"dm-verity options: --no-superblock --format=1 -s \\\"\\\" --hash=sha256 --data-block-size=512 --hash-block-size=4096 --data-blocks %d --hash-offset %d %s\\n\"\n\t\tvar dataBlobks, hashOffset uint64\n\t\tvar rootHash string\n\t\tif count, err := fmt.Sscanf(outb.String(), pattern, &dataBlobks, &hashOffset, &rootHash); err != nil || count != 3 {\n\t\t\treturn updateFields, errors.Errorf(\"failed to parse dm-verity options from nydus image output: %s\", outb.String())\n\t\t}\n\t\tblockInfo = strconv.FormatUint(dataBlobks, 10) + \",\" + strconv.FormatUint(hashOffset, 10) + \",\" + \"sha256:\" + rootHash\n\t}\n\tif wholeImage {\n\t\tlabels[label.NydusImageBlockInfo] = blockInfo\n\t\tupdateFields = append(updateFields, \"labels.\"+label.NydusImageBlockInfo)\n\t} else {\n\t\tlabels[label.NydusLayerBlockInfo] = blockInfo\n\t\tupdateFields = append(updateFields, \"labels.\"+label.NydusLayerBlockInfo)\n\t}\n\tlog.L.Debugf(\"export block labels %v\", labels)\n\n\terr = os.Rename(diskFileNameTmp, diskFileName)\n\tif err != nil {\n\t\treturn updateFields, errors.Wrap(err, \"rename disk image file\")\n\t}\n\n\treturn updateFields, nil\n}\n\nfunc (t *Manager) MountTarErofs(snapshotID string, s *storage.Snapshot, labels map[string]string, rafs *rafs.Rafs) error {\n\tif s == nil {\n\t\treturn errors.New(\"snapshot object for MountTarErofs() is nil\")\n\t}\n\n\t// Copy meta info from snapshot to rafs\n\tt.copyTarfsAnnotations(labels, rafs)\n\n\tupperDirPath := path.Join(rafs.GetSnapshotDir(), \"fs\")\n\tif !config.GetTarfsMountOnHost() {\n\t\trafs.SetMountpoint(upperDirPath)\n\t\treturn nil\n\t}\n\n\tmergedBootstrap := t.imageMetaFilePath(upperDirPath)\n\tblobInfo, err := t.getImageBlobInfo(mergedBootstrap)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"get image blob info\")\n\t}\n\n\tvar devices []string\n\t// When merging bootstrap, we need to arrange layer bootstrap in order from low to high\n\tfor idx := len(s.ParentIDs) - 1; idx >= 0; idx-- {\n\t\tsnapshotID := s.ParentIDs[idx]\n\t\terr := t.waitLayerReady(snapshotID)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"wait for tarfs conversion task\")\n\t\t}\n\n\t\tst, err := t.getSnapshotStatus(snapshotID, true)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif st.status != TarfsStatusReady {\n\t\t\tst.mutex.Unlock()\n\t\t\treturn errors.Errorf(\"snapshot %s tarfs format error %d\", snapshotID, st.status)\n\t\t}\n\n\t\tvar blobMarker = \"\\\"blob_id\\\":\\\"\" + st.blobID + \"\\\"\"\n\t\tif strings.Contains(blobInfo, blobMarker) {\n\t\t\tif st.dataLoopdev == nil {\n\t\t\t\tloopdev, err := t.attachLoopdev(st.blobTarFilePath)\n\t\t\t\tif err != nil {\n\t\t\t\t\tst.mutex.Unlock()\n\t\t\t\t\treturn errors.Wrapf(err, \"attach layer tar file %s to loopdev\", st.blobTarFilePath)\n\t\t\t\t}\n\t\t\t\tst.dataLoopdev = loopdev\n\t\t\t}\n\t\t\tdevices = append(devices, \"device=\"+st.dataLoopdev.Path())\n\t\t}\n\n\t\tst.mutex.Unlock()\n\t}\n\tmountOpts := strings.Join(devices, \",\")\n\n\tst, err := t.getSnapshotStatus(snapshotID, true)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer st.mutex.Unlock()\n\n\tmountPoint := path.Join(rafs.GetSnapshotDir(), \"mnt\")\n\tif len(st.erofsMountPoint) > 0 {\n\t\tif st.erofsMountPoint == mountPoint {\n\t\t\tlog.L.Debugf(\"tarfs for snapshot %s has already been mounted at %s\", snapshotID, mountPoint)\n\t\t\treturn nil\n\t\t}\n\t\treturn errors.Errorf(\"tarfs for snapshot %s has already been mounted at %s\", snapshotID, st.erofsMountPoint)\n\t}\n\n\tif st.metaLoopdev == nil {\n\t\tloopdev, err := t.attachLoopdev(mergedBootstrap)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"attach merged bootstrap %s to loopdev\", mergedBootstrap)\n\t\t}\n\t\tst.metaLoopdev = loopdev\n\t}\n\tdevName := st.metaLoopdev.Path()\n\n\tif err = os.MkdirAll(mountPoint, 0750); err != nil {\n\t\treturn errors.Wrapf(err, \"create tarfs mount dir %s\", mountPoint)\n\t}\n\n\terr = unix.Mount(devName, mountPoint, \"erofs\", 0, mountOpts)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"mount erofs at %s with opts %s\", mountPoint, mountOpts)\n\t}\n\tst.erofsMountPoint = mountPoint\n\trafs.SetMountpoint(mountPoint)\n\treturn nil\n}\n\nfunc (t *Manager) UmountTarErofs(snapshotID string) error {\n\tst, err := t.getSnapshotStatus(snapshotID, true)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"umount a tarfs snapshot %s which is already removed\", snapshotID)\n\t}\n\tdefer st.mutex.Unlock()\n\n\tif len(st.erofsMountPoint) > 0 {\n\t\terr := unix.Unmount(st.erofsMountPoint, 0)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"umount erofs tarfs %s\", st.erofsMountPoint)\n\t\t}\n\t\tst.erofsMountPoint = \"\"\n\t}\n\n\treturn nil\n}\n\nfunc (t *Manager) DetachLayer(snapshotID string) error {\n\tst, err := t.getSnapshotStatus(snapshotID, true)\n\tif err != nil {\n\t\treturn os.ErrNotExist\n\t}\n\n\tif len(st.erofsMountPoint) > 0 {\n\t\terr := unix.Unmount(st.erofsMountPoint, 0)\n\t\tif err != nil {\n\t\t\tst.mutex.Unlock()\n\t\t\treturn errors.Wrapf(err, \"umount erofs tarfs %s\", st.erofsMountPoint)\n\t\t}\n\t\tst.erofsMountPoint = \"\"\n\t}\n\n\tif st.metaLoopdev != nil {\n\t\terr := st.metaLoopdev.Detach()\n\t\tif err != nil {\n\t\t\tst.mutex.Unlock()\n\t\t\treturn errors.Wrapf(err, \"detach merged bootstrap loopdev for tarfs snapshot %s\", snapshotID)\n\t\t}\n\t\tst.metaLoopdev = nil\n\t}\n\n\tif st.dataLoopdev != nil {\n\t\terr := st.dataLoopdev.Detach()\n\t\tif err != nil {\n\t\t\tst.mutex.Unlock()\n\t\t\treturn errors.Wrapf(err, \"detach layer bootstrap loopdev for tarfs snapshot %s\", snapshotID)\n\t\t}\n\t\tst.dataLoopdev = nil\n\t}\n\n\tst.mutex.Unlock()\n\t// TODO: check order\n\tst.cancel()\n\n\tt.mutex.Lock()\n\tdelete(t.snapshotMap, snapshotID)\n\tt.mutex.Unlock()\n\treturn nil\n}\n\nfunc (t *Manager) getSnapshotStatus(snapshotID string, lock bool) (*snapshotStatus, error) {\n\tt.mutex.Lock()\n\tdefer t.mutex.Unlock()\n\tst, ok := t.snapshotMap[snapshotID]\n\tif ok {\n\t\tif lock {\n\t\t\tst.mutex.Lock()\n\t\t}\n\t\treturn st, nil\n\t}\n\treturn nil, errors.Errorf(\"not found snapshot %s\", snapshotID)\n}\n\nfunc (t *Manager) waitLayerReady(snapshotID string) error {\n\tst, err := t.getSnapshotStatus(snapshotID, false)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif st.status != TarfsStatusReady {\n\t\tlog.L.Debugf(\"wait tarfs conversion task for snapshot %s\", snapshotID)\n\t}\n\tst.wg.Wait()\n\tif st.status != TarfsStatusReady {\n\t\treturn errors.Errorf(\"snapshot %s is in state %d instead of ready state\", snapshotID, st.status)\n\t}\n\treturn nil\n}\n\nfunc (t *Manager) attachLoopdev(blob string) (*losetup.Device, error) {\n\t// losetup.Attach() is not thread-safe hold lock here\n\tt.mutexLoopDev.Lock()\n\tdefer t.mutexLoopDev.Unlock()\n\tdev, err := losetup.Attach(blob, 0, false)\n\treturn &dev, err\n}\n\nfunc (t *Manager) CheckTarfsHintAnnotation(ctx context.Context, ref string, manifestDigest digest.Digest) (bool, error) {\n\tif !t.checkTarfsHint {\n\t\treturn true, nil\n\t}\n\n\tkeyChain, err := auth.GetKeyChainByRef(ref, nil)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tremote := remote.New(keyChain, t.insecure)\n\n\thandle := func() (bool, error) {\n\t\tif tarfsHint, ok := t.tarfsHintCache.Get(ref); ok {\n\t\t\treturn tarfsHint.(bool), nil\n\t\t}\n\n\t\tif _, err, _ := t.sg.Do(ref, func() (interface{}, error) {\n\t\t\terr := t.fetchImageInfo(ctx, remote, ref, manifestDigest)\n\t\t\treturn nil, err\n\t\t}); err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tif tarfsHint, ok := t.tarfsHintCache.Get(ref); ok {\n\t\t\treturn tarfsHint.(bool), nil\n\t\t}\n\n\t\treturn false, errors.Errorf(\"get tarfs hint annotation failed\")\n\t}\n\n\ttarfsHint, err := handle()\n\tif err != nil && remote.RetryWithPlainHTTP(ref, err) {\n\t\ttarfsHint, err = handle()\n\t}\n\treturn tarfsHint, err\n}\n\nfunc (t *Manager) GetConcurrentLimiter(ref string) *semaphore.Weighted {\n\tif t.maxConcurrentProcess <= 0 {\n\t\treturn nil\n\t}\n\n\tif limiter, ok := t.processLimiterCache.Get(ref); ok {\n\t\treturn limiter.(*semaphore.Weighted)\n\t}\n\n\tlimiter := semaphore.NewWeighted(t.maxConcurrentProcess)\n\tt.processLimiterCache.Add(ref, limiter)\n\treturn limiter\n}\n\nfunc (t *Manager) copyTarfsAnnotations(labels map[string]string, rafs *rafs.Rafs) {\n\tkeys := []string{\n\t\tlabel.NydusTarfsLayer,\n\t\tlabel.NydusImageBlockInfo,\n\t\tlabel.NydusLayerBlockInfo,\n\t}\n\n\tfor _, k := range keys {\n\t\tif v, ok := labels[k]; ok {\n\t\t\trafs.AddAnnotation(k, v)\n\t\t}\n\t}\n}\n\nfunc (t *Manager) layerTarFilePath(blobID string) string {\n\treturn filepath.Join(t.cacheDirPath, blobID)\n}\n\nfunc (t *Manager) LayerDiskFilePath(blobID string) string {\n\treturn filepath.Join(t.cacheDirPath, blobID+\".\"+TarfsLayerDiskName)\n}\n\nfunc (t *Manager) ImageDiskFilePath(blobID string) string {\n\treturn filepath.Join(t.cacheDirPath, blobID+\".\"+TarfsImageDiskName)\n}\n\nfunc (t *Manager) layerMetaFilePath(upperDirPath string) string {\n\treturn filepath.Join(upperDirPath, \"image\", TarfsLayerBootstrapName)\n}\n\nfunc (t *Manager) imageMetaFilePath(upperDirPath string) string {\n\treturn filepath.Join(upperDirPath, \"image\", TarfsImageBootstrapName)\n}\n"
  },
  {
    "path": "pkg/utils/display/display.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage display\n\nimport \"fmt\"\n\nfunc ByteToReadableIEC(b uint32) string {\n\tconst unit = 1024\n\tif b < unit {\n\t\treturn fmt.Sprintf(\"%d B\", b)\n\t}\n\tdiv, exp := int64(unit), 0\n\tfor n := b / unit; n >= unit; n /= unit {\n\t\tdiv *= unit\n\t\texp++\n\t}\n\treturn fmt.Sprintf(\"%.1f %ciB\",\n\t\tfloat64(b)/float64(div), \"KMGTPE\"[exp])\n}\n\nfunc MicroSecondToReadable(b uint64) string {\n\tconst unit = 1000\n\tif b < unit {\n\t\treturn fmt.Sprintf(\"%d us\", b)\n\t}\n\n\tif b < unit*unit {\n\t\treturn fmt.Sprintf(\"%.3f ms\", float64(b)/float64(unit))\n\t}\n\n\treturn fmt.Sprintf(\"%.3f s\", float64(b)/float64(unit*unit))\n}\n"
  },
  {
    "path": "pkg/utils/erofs/erofs.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage erofs\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/pkg/errors\"\n\t\"golang.org/x/sys/unix\"\n)\n\nfunc Mount(domainID, fscacheID, mountpoint string) error {\n\tmount := unix.Mount\n\tvar opts string\n\n\t// Nydusd must have domain_id specified and it is set to fsid if it is\n\t// never specified.\n\tif domainID != \"\" && domainID != fscacheID {\n\t\topts = fmt.Sprintf(\"domain_id=%s,fsid=%s\", domainID, fscacheID)\n\t} else {\n\t\topts = \"fsid=\" + fscacheID\n\t}\n\tlog.L.Infof(\"Mount erofs to %s with options %s\", mountpoint, opts)\n\n\tif err := mount(\"erofs\", mountpoint, \"erofs\", 0, opts); err != nil {\n\t\tif errors.Is(err, unix.EINVAL) && domainID != \"\" {\n\t\t\tlog.L.Errorf(\"mount erofs with shared domain failed, \" +\n\t\t\t\t\"If using this feature, make sure your Linux kernel version >= 6.1\")\n\t\t}\n\t\treturn errors.Wrapf(err, \"mount erofs at %s\", mountpoint)\n\t}\n\n\treturn nil\n}\n\nfunc Umount(mountPoint string) error {\n\treturn unix.Unmount(mountPoint, 0)\n}\n\nfunc FscacheID(snapshotID string) string {\n\treturn digest.FromString(fmt.Sprintf(\"nydus-snapshot-%s\", snapshotID)).Hex()\n}\n"
  },
  {
    "path": "pkg/utils/file/file.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage file\n\nimport \"os\"\n\nfunc IsDirExisted(path string) (bool, error) {\n\ts, err := os.Stat(path)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn false, nil\n\t\t}\n\t\treturn false, err\n\t}\n\treturn s.IsDir(), nil\n}\n"
  },
  {
    "path": "pkg/utils/mount/mount.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage mount\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/retry\"\n)\n\ntype Interface interface {\n\tUmount(target string) error\n}\n\ntype Mounter struct {\n}\n\nfunc (m *Mounter) Umount(target string) error {\n\tif mounted, err := IsMountpoint(target); err == nil {\n\t\tif !mounted {\n\t\t\treturn errors.New(\"not mounted\")\n\t\t}\n\t} else {\n\t\treturn err\n\t}\n\n\t// return syscall.Unmount(target, syscall.MNT_FORCE)\n\treturn syscall.Unmount(target, 0)\n}\n\nfunc NormalizePath(path string) (realPath string, err error) {\n\tif realPath, err = filepath.Abs(path); err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"get absolute path for %s\", path)\n\t}\n\tif realPath, err = filepath.EvalSymlinks(realPath); err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"canonicalise path for %s\", path)\n\t}\n\tif _, err := os.Stat(realPath); err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"stat target of %s\", path)\n\t}\n\treturn realPath, nil\n}\n\n// return value `true` means the path is mounted\nfunc IsMountpoint(path string) (bool, error) {\n\trealPath, err := NormalizePath(path)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tif path == \"/\" {\n\t\treturn true, nil\n\t}\n\n\tstat, err := os.Stat(realPath)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tparentStat, err := os.Stat(filepath.Dir(realPath))\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\t// If the directory has a different device as parent, then it is a mountpoint.\n\tif stat.Sys().(*syscall.Stat_t).Dev != parentStat.Sys().(*syscall.Stat_t).Dev {\n\t\treturn true, nil\n\t}\n\n\treturn false, nil\n}\n\nfunc WaitUntilUnmounted(path string) error {\n\treturn retry.Do(func() error {\n\t\tmounted, err := IsMountpoint(path)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif mounted {\n\t\t\treturn errdefs.ErrDeviceBusy\n\t\t}\n\n\t\treturn nil\n\t},\n\t\tretry.Attempts(20), // totally wait for 1 seconds, should be enough\n\t\tretry.LastErrorOnly(true),\n\t\tretry.Delay(50*time.Millisecond),\n\t)\n}\n"
  },
  {
    "path": "pkg/utils/parser/parser.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage parser\n\nimport (\n\t\"regexp\"\n\t\"strconv\"\n\t\"sync\"\n\n\t\"github.com/pkg/errors\"\n)\n\nvar (\n\tunitMultipliers     map[string]int64\n\tunitMultipliersOnce sync.Once\n)\n\nfunc InitUnitMultipliers() {\n\tunitMultipliers = make(map[string]int64, 10)\n\n\tunitMultipliers[\"KiB\"] = 1024\n\tunitMultipliers[\"MiB\"] = unitMultipliers[\"KiB\"] * 1024\n\tunitMultipliers[\"GiB\"] = unitMultipliers[\"MiB\"] * 1024\n\tunitMultipliers[\"TiB\"] = unitMultipliers[\"GiB\"] * 1024\n\tunitMultipliers[\"PiB\"] = unitMultipliers[\"TiB\"] * 1024\n\n\tunitMultipliers[\"Ki\"] = 1024\n\tunitMultipliers[\"Mi\"] = unitMultipliers[\"Ki\"] * 1024\n\tunitMultipliers[\"Gi\"] = unitMultipliers[\"Mi\"] * 1024\n\tunitMultipliers[\"Ti\"] = unitMultipliers[\"Gi\"] * 1024\n\tunitMultipliers[\"Pi\"] = unitMultipliers[\"Ti\"] * 1024\n}\n\nfunc MemoryConfigToBytes(data string, totalMemoryBytes int) (int64, error) {\n\tif data == \"\" {\n\t\treturn -1, nil\n\t}\n\n\t// Memory value without unit.\n\tvalue, err := strconv.ParseFloat(data, 64)\n\tif err == nil {\n\t\treturn int64(value), nil\n\t}\n\n\tre := regexp.MustCompile(`(\\d*\\.?\\d+)([a-zA-Z\\%]+)`)\n\tmatches := re.FindStringSubmatch(data)\n\tif len(matches) != 3 {\n\t\treturn 0, errors.Errorf(\"Falied to convert data to bytes: Unknown unit in %s\", data)\n\t}\n\n\t// Parse memory value and unit.\n\tvalueString, unit := matches[1], matches[2]\n\tvalue, err = strconv.ParseFloat(valueString, 64)\n\tif err != nil {\n\t\treturn 0, errors.Wrap(err, \"Failed  to parse memory limit\")\n\t}\n\n\t// Return if the unit is byte.\n\tif unit == \"B\" {\n\t\treturn int64(value), nil\n\t}\n\n\t// Calculate value if the unit is \"%\".\n\tif unit == \"%\" {\n\t\tlimitMemory := float64(totalMemoryBytes) * value / 100\n\t\treturn int64(limitMemory + 0.5), nil\n\t}\n\n\tunitMultipliersOnce.Do(InitUnitMultipliers)\n\n\tmultiplier := unitMultipliers[unit]\n\treturn int64(value * float64(multiplier)), nil\n}\n"
  },
  {
    "path": "pkg/utils/parser/parser_test.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage parser\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestMemoryLimitToBytes(t *testing.T) {\n\ttotalMemoryBytes := 10000\n\n\tfor desc, test := range map[string]struct {\n\t\tMemoryLimit string\n\t\texpected    int64\n\t}{\n\t\t\"memory limit is zero\": {\n\t\t\tMemoryLimit: \"\",\n\t\t\texpected:    -1,\n\t\t},\n\t\t\"memory limit is a percentage\": {\n\t\t\tMemoryLimit: \"20%\",\n\t\t\texpected:    2000,\n\t\t},\n\t\t\"memory limit is a float percentage\": {\n\t\t\tMemoryLimit: \"0.2%\",\n\t\t\texpected:    20,\n\t\t},\n\t\t\"memory limit is a value without unit\": {\n\t\t\tMemoryLimit: \"10240\",\n\t\t\texpected:    10240,\n\t\t},\n\t\t\"memory limit is a value with Byte unit\": {\n\t\t\tMemoryLimit: \"10240B\",\n\t\t\texpected:    10240,\n\t\t},\n\t\t\"memory limit is a value with KiB unit\": {\n\t\t\tMemoryLimit: \"30KiB\",\n\t\t\texpected:    30 * 1024,\n\t\t},\n\t\t\"memory limit is a value with MiB unit\": {\n\t\t\tMemoryLimit: \"30MiB\",\n\t\t\texpected:    30 * 1024 * 1024,\n\t\t},\n\t\t\"memory limit is a value with GiB unit\": {\n\t\t\tMemoryLimit: \"30GiB\",\n\t\t\texpected:    30 * 1024 * 1024 * 1024,\n\t\t},\n\t\t\"memory limit is a value with TiB unit\": {\n\t\t\tMemoryLimit: \"30TiB\",\n\t\t\texpected:    30 * 1024 * 1024 * 1024 * 1024,\n\t\t},\n\t\t\"memory limit is a value with PiB unit\": {\n\t\t\tMemoryLimit: \"30PiB\",\n\t\t\texpected:    30 * 1024 * 1024 * 1024 * 1024 * 1024,\n\t\t},\n\t\t\"memory limit is a value with Ki unit\": {\n\t\t\tMemoryLimit: \"30Ki\",\n\t\t\texpected:    30 * 1024,\n\t\t},\n\t\t\"memory limit is a value with Mi unit\": {\n\t\t\tMemoryLimit: \"30Mi\",\n\t\t\texpected:    30 * 1024 * 1024,\n\t\t},\n\t\t\"memory limit is a value with Gi unit\": {\n\t\t\tMemoryLimit: \"30Gi\",\n\t\t\texpected:    30 * 1024 * 1024 * 1024,\n\t\t},\n\t\t\"memory limit is a value with Ti unit\": {\n\t\t\tMemoryLimit: \"30Ti\",\n\t\t\texpected:    30 * 1024 * 1024 * 1024 * 1024,\n\t\t},\n\t\t\"memory limit is a value with Pi unit\": {\n\t\t\tMemoryLimit: \"30Pi\",\n\t\t\texpected:    30 * 1024 * 1024 * 1024 * 1024 * 1024,\n\t\t},\n\t} {\n\t\tt.Logf(\"TestCase %q\", desc)\n\n\t\tmemoryLimitInBytes, err := MemoryConfigToBytes(test.MemoryLimit, totalMemoryBytes)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t, memoryLimitInBytes, test.expected)\n\t}\n}\n"
  },
  {
    "path": "pkg/utils/registry/registry.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage registry\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"reflect\"\n\t\"strings\"\n\t\"time\"\n\n\tsnpkg \"github.com/containerd/containerd/v2/pkg/snapshotters\"\n\tdistribution \"github.com/distribution/reference\"\n\t\"github.com/google/go-containerregistry/pkg/authn\"\n\t\"github.com/google/go-containerregistry/pkg/name\"\n\t\"github.com/google/go-containerregistry/pkg/v1/remote/transport\"\n\t\"github.com/pkg/errors\"\n)\n\ntype Image struct {\n\tHost string\n\tRepo string\n}\n\nfunc ConvertToVPCHost(registryHost string) string {\n\tparts := strings.Split(registryHost, \".\")\n\tif strings.HasSuffix(parts[0], \"-vpc\") {\n\t\treturn registryHost\n\t}\n\tparts[0] = fmt.Sprintf(\"%s-vpc\", parts[0])\n\treturn strings.Join(parts, \".\")\n}\n\nfunc ParseImage(imageID string) (Image, error) {\n\tnamed, err := distribution.ParseDockerRef(imageID)\n\tif err != nil {\n\t\treturn Image{}, err\n\t}\n\thost := distribution.Domain(named)\n\trepo := distribution.Path(named)\n\treturn Image{\n\t\tHost: host,\n\t\tRepo: repo,\n\t}, nil\n}\n\nfunc ParseLabels(labels map[string]string) (rRef, rDigest string) {\n\tif ref, ok := labels[snpkg.TargetRefLabel]; ok {\n\t\trRef = ref\n\t}\n\tif layerDigest, ok := labels[snpkg.TargetLayerDigestLabel]; ok {\n\t\trDigest = layerDigest\n\t}\n\treturn\n}\n\nfunc AuthnTransport(ref name.Reference, tr http.RoundTripper, keychain authn.Keychain) (http.RoundTripper, error) {\n\tvar err error\n\tvar auth authn.Authenticator\n\n\tif keychain == nil || (reflect.ValueOf(keychain).Kind() == reflect.Ptr && reflect.ValueOf(keychain).IsNil()) {\n\t\tauth = authn.Anonymous\n\t} else {\n\t\tauth, err = keychain.Resolve(ref.Context())\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"failed to resolve reference %q\", ref)\n\t\t}\n\t}\n\n\terrCh := make(chan error)\n\tvar rTr http.RoundTripper\n\tgo func() {\n\t\trTr, err = transport.NewWithContext(\n\t\t\tcontext.TODO(),\n\t\t\tref.Context().Registry,\n\t\t\tauth,\n\t\t\ttr,\n\t\t\t[]string{ref.Scope(transport.PullScope)},\n\t\t)\n\t\terrCh <- err\n\t}()\n\tselect {\n\tcase err = <-errCh:\n\tcase <-time.After(10 * time.Second):\n\t\treturn nil, fmt.Errorf(\"authentication timeout\")\n\t}\n\treturn rTr, err\n}\n"
  },
  {
    "path": "pkg/utils/registry/registry_test.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage registry\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestConvertToVPCHost1(t *testing.T) {\n\ttype args struct {\n\t\tregistryHost string\n\t}\n\ttests := []struct {\n\t\tname string\n\t\targs args\n\t\twant string\n\t}{\n\t\t{\n\t\t\tname: \"with no vpc registry\",\n\t\t\targs: args{\n\t\t\t\tregistryHost: \"acr-nydus-registry.cn-hangzhou.cr.aliyuncs.com\",\n\t\t\t},\n\t\t\twant: \"acr-nydus-registry-vpc.cn-hangzhou.cr.aliyuncs.com\",\n\t\t},\n\t\t{\n\t\t\tname: \"with vpc registry\",\n\t\t\targs: args{\n\t\t\t\tregistryHost: \"acr-nydus-registry-vpc.cn-hangzhou.cr.aliyuncs.com\",\n\t\t\t},\n\t\t\twant: \"acr-nydus-registry-vpc.cn-hangzhou.cr.aliyuncs.com\",\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tif got := ConvertToVPCHost(tt.args.registryHost); got != tt.want {\n\t\t\t\tt.Errorf(\"ConvertToVPCHost() = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestParseImage(t *testing.T) {\n\ttype args struct {\n\t\timageID string\n\t}\n\ttests := []struct {\n\t\tname    string\n\t\targs    args\n\t\twant    Image\n\t\twantErr bool\n\t}{\n\t\t{\n\t\t\tname: \"multi path\",\n\t\t\targs: args{\n\t\t\t\timageID: \"localhost:5000/hello-world/foo/bar:latest\",\n\t\t\t},\n\t\t\twant: Image{\n\t\t\t\tHost: \"localhost:5000\",\n\t\t\t\tRepo: \"hello-world/foo/bar\",\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"no namespace\",\n\t\t\targs: args{\n\t\t\t\timageID: \"localhost:5000/bar:latest\",\n\t\t\t},\n\t\t\twant: Image{\n\t\t\t\tHost: \"localhost:5000\",\n\t\t\t\tRepo: \"bar\",\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"normal\",\n\t\t\targs: args{\n\t\t\t\timageID: \"nydus-registry.cn-hangzhou.cr.aliyuncs.com/poc/tomcat:latest-app-nydus-platform\",\n\t\t\t},\n\t\t\twant: Image{\n\t\t\t\tHost: \"nydus-registry.cn-hangzhou.cr.aliyuncs.com\",\n\t\t\t\tRepo: \"poc/tomcat\",\n\t\t\t},\n\t\t\twantErr: false,\n\t\t},\n\t\t{\n\t\t\tname: \"invalid\",\n\t\t\targs: args{\n\t\t\t\timageID: \"nydus-registry.cn-hangzhou.cr.aliyuncs.com/:latest-app-nydus-platform\",\n\t\t\t},\n\t\t\twant: Image{\n\t\t\t\tHost: \"\",\n\t\t\t\tRepo: \"\",\n\t\t\t},\n\t\t\twantErr: true,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tgot, err := ParseImage(tt.args.imageID)\n\t\t\tif (err != nil) != tt.wantErr {\n\t\t\t\tt.Errorf(\"ParseImage() error = %v, wantErr %v\", err, tt.wantErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif !reflect.DeepEqual(got, tt.want) {\n\t\t\t\tt.Errorf(\"ParseImage() got = %v, want %v\", got, tt.want)\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "pkg/utils/retry/retry.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage retry\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\t\"strings\"\n\t\"time\"\n)\n\ntype RetryableFunc func() error\n\nvar (\n\tDefaultAttempts      = uint(10)\n\tDefaultDelay         = 100 * time.Millisecond\n\tDefaultMaxJitter     = 100 * time.Millisecond\n\tDefaultOnRetry       = func(_ uint, _ error) {}\n\tDefaultRetryIf       = IsRecoverable\n\tDefaultDelayType     = CombineDelay(FixedDelay, RandomDelay)\n\tDefaultLastErrorOnly = false\n)\n\n// Function signature of retry if function\ntype retryIfFunc func(error) bool\n\ntype AbortFunc func(error) bool\n\n// Function signature of OnRetry function\n// n = count of attempts\ntype OnRetryFunc func(n uint, err error)\n\ntype DelayTypeFunc func(n uint, config *Config) time.Duration\n\ntype Config struct {\n\tattempts      uint\n\tdelay         time.Duration\n\tmaxDelay      time.Duration\n\tmaxJitter     time.Duration\n\tonRetry       OnRetryFunc\n\tretryIf       retryIfFunc\n\tdelayType     DelayTypeFunc\n\tlastErrorOnly bool\n}\n\n// Option represents an option for retry.\ntype Option func(*Config)\n\n// return the direct last error that came from the retried function\n// default is false (return wrapped errors with everything)\nfunc LastErrorOnly(lastErrorOnly bool) Option {\n\treturn func(c *Config) {\n\t\tc.lastErrorOnly = lastErrorOnly\n\t}\n}\n\n// Attempts set count of retry\n// default is 10\nfunc Attempts(attempts uint) Option {\n\treturn func(c *Config) {\n\t\tc.attempts = attempts\n\t}\n}\n\n// `abortFunc` return true means no further need to retry\nfunc OnlyRetryIf(abortFunc AbortFunc) Option {\n\treturn func(c *Config) {\n\t\tc.retryIf = func(err error) bool {\n\t\t\tif !IsRecoverable(err) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !abortFunc(err)\n\t\t}\n\t}\n}\n\n// Delay set delay between retry\n// default is 100ms\nfunc Delay(delay time.Duration) Option {\n\treturn func(c *Config) {\n\t\tc.delay = delay\n\t}\n}\n\n// MaxDelay set maximum delay between retry\n// does not apply by default\nfunc MaxDelay(maxDelay time.Duration) Option {\n\treturn func(c *Config) {\n\t\tc.maxDelay = maxDelay\n\t}\n}\n\n// MaxJitter sets the maximum random Jitter between retries for RandomDelay\nfunc MaxJitter(maxJitter time.Duration) Option {\n\treturn func(c *Config) {\n\t\tc.maxJitter = maxJitter\n\t}\n}\n\n// DelayType set type of the delay between retries\n// default is BackOff\nfunc DelayType(delayType DelayTypeFunc) Option {\n\treturn func(c *Config) {\n\t\tc.delayType = delayType\n\t}\n}\n\n// BackOffDelay is a DelayType which increases delay between consecutive retries\nfunc BackOffDelay(n uint, config *Config) time.Duration {\n\treturn config.delay * (1 << n)\n}\n\n// FixedDelay is a DelayType which keeps delay the same through all iterations\nfunc FixedDelay(_ uint, config *Config) time.Duration {\n\treturn config.delay\n}\n\n// RandomDelay is a DelayType which picks a random delay up to config.maxJitter\nfunc RandomDelay(_ uint, config *Config) time.Duration {\n\treturn time.Duration(rand.Int63n(int64(config.maxJitter)))\n}\n\n// CombineDelay is a DelayType the combines all of the specified delays into a new DelayTypeFunc\nfunc CombineDelay(delays ...DelayTypeFunc) DelayTypeFunc {\n\treturn func(n uint, config *Config) time.Duration {\n\t\tvar total time.Duration\n\t\tfor _, delay := range delays {\n\t\t\ttotal += delay(n, config)\n\t\t}\n\t\treturn total\n\t}\n}\n\nfunc OnRetry(onRetry OnRetryFunc) Option {\n\treturn func(c *Config) {\n\t\tc.onRetry = onRetry\n\t}\n}\n\nfunc Do(retryFunc RetryableFunc, opts ...Option) error {\n\tvar n uint\n\n\t// default\n\tconfig := &Config{\n\t\tattempts:      DefaultAttempts,\n\t\tdelay:         DefaultDelay,\n\t\tmaxJitter:     DefaultMaxJitter,\n\t\tonRetry:       DefaultOnRetry,\n\t\tretryIf:       DefaultRetryIf,\n\t\tdelayType:     DefaultDelayType,\n\t\tlastErrorOnly: DefaultLastErrorOnly,\n\t}\n\n\t// apply opts\n\tfor _, opt := range opts {\n\t\topt(config)\n\t}\n\n\tvar errorLog Error\n\tif !config.lastErrorOnly {\n\t\terrorLog = make(Error, config.attempts)\n\t} else {\n\t\terrorLog = make(Error, 1)\n\t}\n\n\tlastErrIndex := n\n\tfor n < config.attempts {\n\t\terr := retryFunc()\n\n\t\tif err != nil {\n\t\t\terrorLog[lastErrIndex] = unpackUnrecoverable(err)\n\n\t\t\tif !config.retryIf(err) {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tconfig.onRetry(n, err)\n\n\t\t\t// if this is last attempt - don't wait\n\t\t\tif n == config.attempts-1 {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tdelayTime := config.delayType(n, config)\n\t\t\tif config.maxDelay > 0 && delayTime > config.maxDelay {\n\t\t\t\tdelayTime = config.maxDelay\n\t\t\t}\n\t\t\ttime.Sleep(delayTime)\n\t\t} else {\n\t\t\treturn nil\n\t\t}\n\n\t\tn++\n\t\tif !config.lastErrorOnly {\n\t\t\tlastErrIndex = n\n\t\t}\n\t}\n\n\tif config.lastErrorOnly {\n\t\treturn errorLog[lastErrIndex]\n\t}\n\treturn errorLog\n}\n\n// Error type represents list of errors in retry\ntype Error []error\n\n// Error method return string representation of Error\n// It is an implementation of error interface\nfunc (e Error) Error() string {\n\tlogWithNumber := make([]string, lenWithoutNil(e))\n\tfor i, l := range e {\n\t\tif l != nil {\n\t\t\tlogWithNumber[i] = fmt.Sprintf(\"#%d: %s\", i+1, l.Error())\n\t\t}\n\t}\n\n\treturn fmt.Sprintf(\"All attempts fail:\\n%s\", strings.Join(logWithNumber, \"\\n\"))\n}\n\nfunc lenWithoutNil(e Error) (count int) {\n\tfor _, v := range e {\n\t\tif v != nil {\n\t\t\tcount++\n\t\t}\n\t}\n\n\treturn\n}\n\n// WrappedErrors returns the list of errors that this Error is wrapping.\n// It is an implementation of the `errwrap.Wrapper` interface\n// in package [errwrap](https://github.com/hashicorp/errwrap) so that\n// `retry.Error` can be used with that library.\nfunc (e Error) WrappedErrors() []error {\n\treturn e\n}\n\ntype unrecoverableError struct {\n\terror\n}\n\n// Unrecoverable wraps an error in `unrecoverableError` struct\nfunc Unrecoverable(err error) error {\n\treturn unrecoverableError{err}\n}\n\n// IsRecoverable checks if error is an instance of `unrecoverableError`\nfunc IsRecoverable(err error) bool {\n\t_, isUnrecoverable := err.(unrecoverableError)\n\treturn !isUnrecoverable\n}\n\nfunc unpackUnrecoverable(err error) error {\n\tif unrecoverable, isUnrecoverable := err.(unrecoverableError); isUnrecoverable {\n\t\treturn unrecoverable.error\n\t}\n\n\treturn err\n}\n"
  },
  {
    "path": "pkg/utils/signals/signal.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage signals\n\nimport (\n\t\"os\"\n\t\"os/signal\"\n\t\"sync\"\n\t\"syscall\"\n)\n\nvar (\n\tonce            sync.Once\n\tstop            chan struct{}\n\tshutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM}\n)\n\nfunc SetupSignalHandler() (stopCh <-chan struct{}) {\n\t// make sure SetupSignalHandler will not call twice\n\tonce.Do(func() {\n\t\tstop = make(chan struct{})\n\t\tc := make(chan os.Signal, 2)\n\t\tsignal.Notify(c, shutdownSignals...)\n\t\tgo func() {\n\t\t\t<-c\n\t\t\tclose(stop)\n\t\t\t<-c\n\t\t\tos.Exit(1)\n\t\t}()\n\t})\n\treturn stop\n}\n"
  },
  {
    "path": "pkg/utils/signals/signal_test.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage signals\n\nimport (\n\t\"sync/atomic\"\n\t\"syscall\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestSetupSignalHandler(t *testing.T) {\n\tsignal := SetupSignalHandler()\n\tvar expected int32 = 2\n\tvar actual int32\n\tvar func1 = func(stop <-chan struct{}) {\n\t\t<-stop\n\t\tatomic.AddInt32(&actual, 1)\n\t}\n\tvar func2 = func(stop <-chan struct{}) {\n\t\t<-stop\n\t\tatomic.AddInt32(&actual, 1)\n\t}\n\tgo func1(signal)\n\tgo func2(signal)\n\terr := syscall.Kill(syscall.Getpid(), syscall.SIGINT)\n\trequire.Nil(t, err)\n\ttime.Sleep(1 * time.Second)\n\trequire.Equal(t, atomic.LoadInt32(&actual), expected)\n}\n"
  },
  {
    "path": "pkg/utils/signer/signer.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage signer\n\nimport (\n\t\"crypto\"\n\t\"crypto/rsa\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/pem\"\n\t\"io\"\n)\n\ntype Signer struct {\n\tpublicKey *rsa.PublicKey\n}\n\nfunc New(publicKey []byte) (*Signer, error) {\n\tblock, _ := pem.Decode(publicKey)\n\tkey, err := x509.ParsePKCS1PublicKey(block.Bytes)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &Signer{\n\t\tpublicKey: key,\n\t}, nil\n}\n\nfunc (s *Signer) Verify(input io.Reader, signature []byte) error {\n\th := sha256.New()\n\t_, err := io.Copy(h, input)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn rsa.VerifyPKCS1v15(s.publicKey, crypto.SHA256, h.Sum(nil), signature)\n}\n"
  },
  {
    "path": "pkg/utils/sysinfo/sysinfo.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage sysinfo\n\nimport (\n\t\"sync\"\n\t\"syscall\"\n)\n\nvar (\n\tsysinfo     *syscall.Sysinfo_t\n\tsysinfoOnce sync.Once\n\tsysinfoErr  error\n)\n\nfunc GetSysinfo() {\n\tvar info syscall.Sysinfo_t\n\terr := syscall.Sysinfo(&info)\n\tif err != nil {\n\t\tsysinfoErr = err\n\t\treturn\n\t}\n\tsysinfo = &info\n\tsysinfoErr = nil\n}\n\nfunc GetTotalMemoryBytes() (int, error) {\n\tsysinfoOnce.Do(GetSysinfo)\n\tif sysinfo == nil {\n\t\treturn 0, sysinfoErr\n\t}\n\n\treturn int(sysinfo.Totalram), nil\n}\n"
  },
  {
    "path": "pkg/utils/transport/pool.go",
    "content": "package transport\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/utils/registry\"\n\t\"github.com/golang/groupcache/lru\"\n\t\"github.com/google/go-containerregistry/pkg/authn\"\n\t\"github.com/google/go-containerregistry/pkg/name\"\n\t\"github.com/pkg/errors\"\n)\n\nvar _ Resolve = &Pool{}\n\nconst HTTPClientTimeOut = time.Second * 60\n\n// LRU cache for authenticated network connections.\ntype Pool struct {\n\ttrPoolMu  sync.Mutex\n\ttrPool    *lru.Cache\n\ttransport http.RoundTripper\n}\n\nfunc NewPool() *Pool {\n\tpool := Pool{\n\t\ttransport: http.DefaultTransport,\n\t\ttrPool:    lru.New(3000),\n\t}\n\treturn &pool\n}\n\ntype Resolve interface {\n\tResolve(ref name.Reference, digest string, keychain authn.Keychain) (string, http.RoundTripper, error)\n}\n\nfunc (r *Pool) Resolve(ref name.Reference, digest string, keychain authn.Keychain) (string, http.RoundTripper, error) {\n\tr.trPoolMu.Lock()\n\tdefer r.trPoolMu.Unlock()\n\tendpointURL := fmt.Sprintf(\"%s://%s/v2/%s/blobs/%s\",\n\t\tref.Context().Scheme(),\n\t\tref.Context().RegistryStr(),\n\t\tref.Context().RepositoryStr(),\n\t\tdigest)\n\n\tif tr, ok := r.trPool.Get(ref.Name()); ok {\n\t\tvar err error\n\t\tif url, err := redirect(endpointURL, tr.(http.RoundTripper)); err == nil {\n\t\t\treturn url, tr.(http.RoundTripper), nil\n\t\t}\n\t\tr.trPool.Remove(ref.Name())\n\t\tlog.L.Warnf(\"redirect %s, failed, err: %s\", endpointURL, err)\n\t}\n\ttr, err := registry.AuthnTransport(ref, r.transport, keychain)\n\tif err != nil {\n\t\treturn \"\", nil, errors.Wrapf(err, \"failed to authn transport\")\n\t}\n\turl, err := redirect(endpointURL, tr)\n\tif err != nil {\n\t\treturn \"\", nil, errors.Wrapf(err, \"failed to redirect %s\", endpointURL)\n\t}\n\tr.trPool.Add(ref.Name(), tr)\n\treturn url, tr, nil\n}\n\nfunc redirect(endpointURL string, tr http.RoundTripper) (url string, err error) {\n\tctx, cancel := context.WithTimeout(context.Background(), HTTPClientTimeOut)\n\tdefer cancel()\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", endpointURL, nil)\n\tif err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"failed to request to the registry\")\n\t}\n\treq.Close = false\n\treq.Header.Set(\"Range\", \"bytes=0-0\")\n\tres, err := tr.RoundTrip(req)\n\tif err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"failed to request to %q\", endpointURL)\n\t}\n\n\tdefer func() {\n\t\t_, err := io.Copy(io.Discard, res.Body)\n\t\tif err != nil {\n\t\t\tlog.L.Warnf(\"Discard body failed %s\", err)\n\t\t}\n\t\tres.Body.Close()\n\t}()\n\n\tif res.StatusCode/100 == 2 {\n\t\turl = endpointURL\n\t} else if redir := res.Header.Get(\"Location\"); redir != \"\" && res.StatusCode/100 == 3 {\n\t\turl = redir\n\t} else {\n\t\tbody, err := io.ReadAll(res.Body)\n\t\tif err != nil {\n\t\t\treturn \"\", errors.Wrapf(err, \"failed to get response body\")\n\t\t}\n\t\treturn \"\", fmt.Errorf(\"failed to access to %q with code %v, body: %s\", endpointURL, res.StatusCode, body)\n\t}\n\treturn\n}\n"
  },
  {
    "path": "pkg/utils/transport/pool_test.go",
    "content": "package transport\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/google/go-containerregistry/pkg/name\"\n\t\"github.com/stretchr/testify/require\"\n)\n\ntype FakeReference struct {\n\tTag        string\n\tRepository name.Repository\n}\n\nvar _ name.Reference = (*FakeReference)(nil)\n\nfunc (t FakeReference) Context() name.Repository {\n\treturn t.Repository\n}\n\nfunc (t FakeReference) Identifier() string {\n\treturn t.Tag\n}\n\nfunc (t FakeReference) Name() string {\n\treturn t.Repository.Name() + \":\" + t.Tag\n}\n\nfunc (t FakeReference) String() string {\n\treturn t.Name()\n}\n\nfunc (t FakeReference) Scope(action string) string {\n\treturn t.Repository.Scope(action)\n}\n\nfunc TestResolve(t *testing.T) {\n\tvar callCount int\n\tfailed := false\n\tsvr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {\n\t\tcallCount++\n\t\tif !failed {\n\t\t\tfmt.Fprintf(w, \"ok\")\n\t\t\treturn\n\t\t}\n\t\tfailed = false\n\t\tw.WriteHeader(http.StatusBadRequest)\n\t}))\n\tdefer svr.Close()\n\n\tpool := NewPool()\n\trepo, err := name.NewRepository(strings.TrimPrefix(svr.URL, \"http://\")+\"/nginx\", name.WeakValidation, name.Insecure)\n\trequire.NoError(t, err)\n\n\tref := &FakeReference{\n\t\tTag:        \"latest\",\n\t\tRepository: repo,\n\t}\n\n\turl1, tr1, err := pool.Resolve(ref, \"fake digest\", nil)\n\trequire.NoError(t, err)\n\t// auth request + redirect request\n\trequire.Equal(t, 2, callCount)\n\t// reset\n\tcallCount = 0\n\turl2, tr2, err := pool.Resolve(ref, \"fake digest\", nil)\n\t// get transport from pool and call redirect\n\trequire.Equal(t, 1, callCount)\n\trequire.NoError(t, err)\n\trequire.Equal(t, tr1, tr2)\n\trequire.Equal(t, url1, url2)\n\n\tfailed = true\n\t// reset\n\tcallCount = 0\n\turl3, tr3, err := pool.Resolve(ref, \"fake digest\", nil)\n\t// redirect failed and retry redirect + auth\n\trequire.Equal(t, 3, callCount)\n\trequire.NoError(t, err)\n\trequire.Equal(t, tr2, tr3)\n\trequire.Equal(t, url2, url3)\n\n}\n"
  },
  {
    "path": "snapshot/mount_option.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage snapshot\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/containerd/containerd/v2/core/mount\"\n\t\"github.com/containerd/containerd/v2/core/snapshots\"\n\t\"github.com/containerd/containerd/v2/core/snapshots/storage\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/config/daemonconfig\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/layout\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/snapshot\"\n\t\"github.com/pkg/errors\"\n)\n\nconst (\n\tKataVirtualVolumeDefaultSource = \"overlay\"\n\tKataVirtualVolumeDummySource   = \"dummy-image-reference\"\n)\n\ntype ExtraOption struct {\n\tSource      string `json:\"source\"`\n\tConfig      string `json:\"config\"`\n\tSnapshotdir string `json:\"snapshotdir\"`\n\tVersion     string `json:\"fs_version\"`\n}\n\nfunc (o *snapshotter) remoteMountWithExtraOptions(ctx context.Context, s storage.Snapshot, id string, overlayOptions []string) ([]mount.Mount, error) {\n\tsource, err := o.fs.BootstrapFile(id)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tinstance := rafs.RafsGlobalCache.Get(id)\n\tdaemon, err := o.fs.GetDaemonByID(instance.DaemonID)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get daemon with ID %s\", instance.DaemonID)\n\t}\n\n\tvar c daemonconfig.DaemonConfig\n\tif daemon.IsSharedDaemon() {\n\t\tc, err = daemonconfig.NewDaemonConfig(daemon.States.FsDriver, daemon.ConfigFile(instance.SnapshotID))\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"Failed to load instance configuration %s\",\n\t\t\t\tdaemon.ConfigFile(instance.SnapshotID))\n\t\t}\n\t} else {\n\t\tc = daemon.Config\n\t}\n\tconfigContent, err := c.DumpString()\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"remoteMounts: failed to marshal config\")\n\t}\n\n\t// get version from bootstrap\n\tf, err := os.Open(source)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"remoteMounts: check bootstrap version: failed to open bootstrap\")\n\t}\n\tdefer f.Close()\n\theader := make([]byte, 4096)\n\tsz, err := f.Read(header)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"remoteMounts: check bootstrap version: failed to read bootstrap\")\n\t}\n\tversion, err := layout.DetectFsVersion(header[0:sz])\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"remoteMounts: failed to detect filesystem version\")\n\t}\n\n\t// when enable nydus-overlayfs, return unified mount slice for runc and kata\n\textraOption := &ExtraOption{\n\t\tSource:      source,\n\t\tConfig:      configContent,\n\t\tSnapshotdir: o.snapshotDir(s.ID),\n\t\tVersion:     version,\n\t}\n\tno, err := json.Marshal(extraOption)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"remoteMounts: failed to marshal NydusOption\")\n\t}\n\t// XXX: Log options without extraoptions as it might contain secrets.\n\tlog.G(ctx).Debugf(\"fuse.nydus-overlayfs mount options %v\", overlayOptions)\n\t// base64 to filter easily in `nydus-overlayfs`\n\topt := fmt.Sprintf(\"extraoption=%s\", base64.StdEncoding.EncodeToString(no))\n\toverlayOptions = append(overlayOptions, opt)\n\n\tmountType := \"fuse.nydus-overlayfs\"\n\tif o.nydusOverlayFSPath != \"\" {\n\t\tlog.G(ctx).Infof(\"Using nydus-overlayfs from path: %s\", o.nydusOverlayFSPath)\n\t\tmountType = fmt.Sprintf(\"fuse.%s\", o.nydusOverlayFSPath)\n\t}\n\n\treturn []mount.Mount{\n\t\t{\n\t\t\tType:    mountType,\n\t\t\tSource:  KataVirtualVolumeDefaultSource,\n\t\t\tOptions: overlayOptions,\n\t\t},\n\t}, nil\n}\n\nfunc (o *snapshotter) mountWithKataVolume(ctx context.Context, id string, overlayOptions []string, key string) ([]mount.Mount, error) {\n\thasVolume := false\n\trafs := rafs.RafsGlobalCache.Get(id)\n\tif rafs == nil {\n\t\treturn []mount.Mount{}, errors.Errorf(\"failed to find RAFS instance for snapshot %s\", id)\n\t}\n\n\t// Insert Kata volume for proxy\n\tif label.IsNydusProxyMode(rafs.Annotations) {\n\t\toptions, err := o.mountWithProxyVolume(*rafs)\n\t\tif err != nil {\n\t\t\treturn []mount.Mount{}, errors.Wrapf(err, \"create kata volume for proxy\")\n\t\t}\n\t\tif len(options) > 0 {\n\t\t\toverlayOptions = append(overlayOptions, options...)\n\t\t\thasVolume = true\n\t\t}\n\t}\n\n\t// Insert Kata volume for tarfs\n\tif blobID, ok := rafs.Annotations[label.NydusTarfsLayer]; ok {\n\t\toptions, err := o.mountWithTarfsVolume(ctx, *rafs, blobID, key)\n\t\tif err != nil {\n\t\t\treturn []mount.Mount{}, errors.Wrapf(err, \"create kata volume for tarfs\")\n\t\t}\n\t\tif len(options) > 0 {\n\t\t\toverlayOptions = append(overlayOptions, options...)\n\t\t\thasVolume = true\n\t\t}\n\t}\n\n\tif hasVolume {\n\t\tlog.G(ctx).Debugf(\"fuse.nydus-overlayfs mount options %v\", overlayOptions)\n\n\t\tmountType := \"fuse.nydus-overlayfs\"\n\t\tif o.nydusOverlayFSPath != \"\" {\n\t\t\tlog.G(ctx).Infof(\"Using nydus-overlayfs from path: %s\", o.nydusOverlayFSPath)\n\t\t\tmountType = fmt.Sprintf(\"fuse.%s\", o.nydusOverlayFSPath)\n\t\t}\n\n\t\tmounts := []mount.Mount{\n\t\t\t{\n\t\t\t\tType:    mountType,\n\t\t\t\tSource:  KataVirtualVolumeDefaultSource,\n\t\t\t\tOptions: overlayOptions,\n\t\t\t},\n\t\t}\n\t\treturn mounts, nil\n\t}\n\n\treturn overlayMount(overlayOptions), nil\n}\n\nfunc (o *snapshotter) mountWithProxyVolume(rafs rafs.Rafs) ([]string, error) {\n\toptions := []string{}\n\tsource := rafs.Annotations[label.CRIImageRef]\n\n\t// In the normal flow, this should correctly return the imageRef. However, passing the CRIImageRef label\n\t// from containerd is not supported. Therefore, the source will be set to \"\".\n\t// But in this case, kata runtime-rs has a non-empty check for the source field. To ensure this field\n\t// remains non-empty, a forced assignment is used here. This does not affect the passing of information.\n\t// it is solely to pass the check.\n\tif len(source) == 0 {\n\t\tsource = KataVirtualVolumeDummySource\n\t}\n\n\tfor k, v := range rafs.Annotations {\n\t\toptions = append(options, fmt.Sprintf(\"%s=%s\", k, v))\n\t}\n\topt, err := o.prepareKataVirtualVolume(label.NydusProxyMode, source, KataVirtualVolumeImageGuestPullType, \"\", options, rafs.Annotations)\n\tif err != nil {\n\t\treturn options, errors.Wrapf(err, \"failed to prepare KataVirtualVolume\")\n\t}\n\treturn []string{opt}, nil\n}\n\nfunc (o *snapshotter) mountWithTarfsVolume(ctx context.Context, rafs rafs.Rafs, blobID, key string) ([]string, error) {\n\toptions := []string{}\n\tif info, ok := rafs.Annotations[label.NydusImageBlockInfo]; ok {\n\t\tpath, err := o.fs.GetTarfsImageDiskFilePath(blobID)\n\t\tif err != nil {\n\t\t\treturn []string{}, errors.Wrapf(err, \"get tarfs image disk file path\")\n\t\t}\n\t\tlog.L.Debugf(\"mountWithTarfsVolume info %v\", info)\n\t\topt, err := o.prepareKataVirtualVolume(label.NydusImageBlockInfo, path, KataVirtualVolumeImageRawBlockType, \"erofs\", []string{\"ro\"}, rafs.Annotations)\n\t\tif err != nil {\n\t\t\treturn options, errors.Wrapf(err, \"failed to prepare KataVirtualVolume for image_raw_block\")\n\t\t}\n\n\t\toptions = append(options, opt)\n\t\tlog.L.Debugf(\"mountWithTarfsVolume type=%v, options %v\", KataVirtualVolumeImageRawBlockType, options)\n\t\treturn options, nil\n\t}\n\n\tif _, ok := rafs.Annotations[label.NydusLayerBlockInfo]; ok {\n\t\tfor {\n\t\t\tpID, pInfo, _, pErr := snapshot.GetSnapshotInfo(ctx, o.ms, key)\n\t\t\tlog.G(ctx).Debugf(\"mountWithKataVolume pID= %v, pInfo = %v\", pID, pInfo)\n\n\t\t\tif pErr != nil {\n\t\t\t\treturn options, errors.Wrapf(pErr, \"failed to get snapshot info\")\n\t\t\t}\n\t\t\tif pInfo.Kind == snapshots.KindActive {\n\t\t\t\tkey = pInfo.Parent\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tblobID = pInfo.Labels[label.NydusTarfsLayer]\n\t\t\tpath, err := o.fs.GetTarfsLayerDiskFilePath(blobID)\n\t\t\tif err != nil {\n\t\t\t\treturn options, errors.Wrapf(err, \"get tarfs image disk file path\")\n\t\t\t}\n\n\t\t\topt, err := o.prepareKataVirtualVolume(label.NydusLayerBlockInfo, path, KataVirtualVolumeLayerRawBlockType, \"erofs\", []string{\"ro\"}, pInfo.Labels)\n\t\t\tif err != nil {\n\t\t\t\treturn options, errors.Wrapf(err, \"failed to prepare KataVirtualVolume for layer_raw_block\")\n\t\t\t}\n\n\t\t\toptions = append(options, opt)\n\n\t\t\tif pInfo.Parent == \"\" {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tkey = pInfo.Parent\n\t\t}\n\t\tlog.L.Debugf(\"mountWithTarfsVolume type=%v, options %v\", KataVirtualVolumeLayerRawBlockType, options)\n\t\treturn options, nil\n\t}\n\n\t// If Neither image_raw_block or layer_raw_block, return empty strings\n\treturn options, nil\n}\n\nfunc (o *snapshotter) prepareKataVirtualVolume(blockType, source, volumeType, fsType string, options []string, labels map[string]string) (string, error) {\n\tvolume := &KataVirtualVolume{\n\t\tVolumeType: volumeType,\n\t\tSource:     source,\n\t\tFSType:     fsType,\n\t\tOptions:    options,\n\t}\n\tswitch blockType {\n\tcase label.NydusImageBlockInfo, label.NydusLayerBlockInfo:\n\t\tdmverityInfo := labels[blockType]\n\t\tif len(dmverityInfo) > 0 {\n\t\t\tdmverity, err := parseTarfsDmVerityInfo(dmverityInfo)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", err\n\t\t\t}\n\t\t\tvolume.DmVerity = &dmverity\n\t\t}\n\tcase label.NydusProxyMode:\n\t\tvolume.ImagePull = &ImagePullVolume{Metadata: labels}\n\t}\n\n\tif !volume.Validate() {\n\t\treturn \"\", errors.Errorf(\"got invalid kata volume, %v\", volume)\n\t}\n\tinfo, err := EncodeKataVirtualVolumeToBase64(*volume)\n\tif err != nil {\n\t\treturn \"\", errors.Errorf(\"failed to encoding Kata Volume info %v\", volume)\n\t}\n\topt := fmt.Sprintf(\"%s=%s\", KataVirtualVolumeOptionName, info)\n\treturn opt, nil\n}\n\nfunc parseTarfsDmVerityInfo(info string) (DmVerityInfo, error) {\n\tvar dataBlocks, hashOffset uint64\n\tvar rootHash string\n\n\tpattern := \"%d,%d,sha256:%s\"\n\tif count, err := fmt.Sscanf(info, pattern, &dataBlocks, &hashOffset, &rootHash); err == nil && count == 3 {\n\t\tdi := DmVerityInfo{\n\t\t\tHashType:  \"sha256\",\n\t\t\tHash:      rootHash,\n\t\t\tBlockNum:  dataBlocks,\n\t\t\tBlocksize: 512,\n\t\t\tHashsize:  4096,\n\t\t\tOffset:    hashOffset,\n\t\t}\n\t\tif err := di.Validate(); err != nil {\n\t\t\treturn DmVerityInfo{}, errors.Wrap(err, \"validate dm-verity information\")\n\t\t}\n\t\treturn di, nil\n\t}\n\n\treturn DmVerityInfo{}, errors.Errorf(\"invalid dm-verity information: %s\", info)\n}\n\n// Consts and data structures for Kata Virtual Volume\nconst (\n\tminBlockSize = 1 << 9\n\tmaxBlockSize = 1 << 19\n)\n\nconst (\n\tKataVirtualVolumeOptionName          = \"io.katacontainers.volume\"\n\tKataVirtualVolumeDirectBlockType     = \"direct_block\"\n\tKataVirtualVolumeImageRawBlockType   = \"image_raw_block\"\n\tKataVirtualVolumeLayerRawBlockType   = \"layer_raw_block\"\n\tKataVirtualVolumeImageNydusBlockType = \"image_nydus_block\"\n\tKataVirtualVolumeLayerNydusBlockType = \"layer_nydus_block\"\n\tKataVirtualVolumeImageNydusFsType    = \"image_nydus_fs\"\n\tKataVirtualVolumeLayerNydusFsType    = \"layer_nydus_fs\"\n\tKataVirtualVolumeImageGuestPullType  = \"image_guest_pull\"\n)\n\n// DmVerityInfo contains configuration information for DmVerity device.\ntype DmVerityInfo struct {\n\tHashType  string `json:\"hashtype\"`\n\tHash      string `json:\"hash\"`\n\tBlockNum  uint64 `json:\"blocknum\"`\n\tBlocksize uint64 `json:\"blocksize\"`\n\tHashsize  uint64 `json:\"hashsize\"`\n\tOffset    uint64 `json:\"offset\"`\n}\n\nfunc (d *DmVerityInfo) Validate() error {\n\terr := d.validateHashType()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif d.BlockNum == 0 || d.BlockNum > uint64(^uint32(0)) {\n\t\treturn fmt.Errorf(\"zero block count for DmVerity device %s\", d.Hash)\n\t}\n\n\tif !validateBlockSize(d.Blocksize) || !validateBlockSize(d.Hashsize) {\n\t\treturn fmt.Errorf(\"unsupported verity block size: data_block_size = %d, hash_block_size = %d\", d.Blocksize, d.Hashsize)\n\t}\n\n\tif d.Offset%d.Hashsize != 0 || d.Offset < d.Blocksize*d.BlockNum {\n\t\treturn fmt.Errorf(\"invalid hashvalue offset %d for DmVerity device %s\", d.Offset, d.Hash)\n\t}\n\n\treturn nil\n}\n\nfunc (d *DmVerityInfo) validateHashType() error {\n\tswitch strings.ToLower(d.HashType) {\n\tcase \"sha256\":\n\t\treturn d.validateHash(64, \"sha256\")\n\tcase \"sha1\":\n\t\treturn d.validateHash(40, \"sha1\")\n\tdefault:\n\t\treturn fmt.Errorf(\"unsupported hash algorithm %s for DmVerity device %s\", d.HashType, d.Hash)\n\t}\n}\n\nfunc (d *DmVerityInfo) validateHash(expectedLen int, hashType string) error {\n\t_, err := hex.DecodeString(d.Hash)\n\tif len(d.Hash) != expectedLen || err != nil {\n\t\treturn fmt.Errorf(\"invalid hash value %s:%s for DmVerity device with %s\", hashType, d.Hash, hashType)\n\t}\n\treturn nil\n}\n\nfunc validateBlockSize(blockSize uint64) bool {\n\treturn minBlockSize <= blockSize && blockSize <= maxBlockSize\n}\n\nfunc ParseDmVerityInfo(option string) (*DmVerityInfo, error) {\n\tno := &DmVerityInfo{}\n\tif err := json.Unmarshal([]byte(option), no); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"DmVerityInfo json unmarshal err\")\n\t}\n\tif err := no.Validate(); err != nil {\n\t\treturn nil, fmt.Errorf(\"DmVerityInfo is not correct, %+v; error = %+v\", no, err)\n\t}\n\treturn no, nil\n}\n\n// DirectAssignedVolume contains meta information for a directly assigned volume.\ntype DirectAssignedVolume struct {\n\tMetadata map[string]string `json:\"metadata\"`\n}\n\nfunc (d *DirectAssignedVolume) Validate() bool {\n\treturn d.Metadata != nil\n}\n\n// ImagePullVolume contains meta information for pulling an image inside the guest.\ntype ImagePullVolume struct {\n\tMetadata map[string]string `json:\"metadata\"`\n}\n\nfunc (i *ImagePullVolume) Validate() bool {\n\treturn i.Metadata != nil\n}\n\n// NydusImageVolume contains Nydus image volume information.\ntype NydusImageVolume struct {\n\tConfig      string `json:\"config\"`\n\tSnapshotDir string `json:\"snapshot_dir\"`\n}\n\nfunc (n *NydusImageVolume) Validate() bool {\n\treturn len(n.Config) > 0 || len(n.SnapshotDir) > 0\n}\n\n// KataVirtualVolume encapsulates information for extra mount options and direct volumes.\ntype KataVirtualVolume struct {\n\tVolumeType   string                `json:\"volume_type\"`\n\tSource       string                `json:\"source,omitempty\"`\n\tFSType       string                `json:\"fs_type,omitempty\"`\n\tOptions      []string              `json:\"options,omitempty\"`\n\tDirectVolume *DirectAssignedVolume `json:\"direct_volume,omitempty\"`\n\tImagePull    *ImagePullVolume      `json:\"image_pull,omitempty\"`\n\tNydusImage   *NydusImageVolume     `json:\"nydus_image,omitempty\"`\n\tDmVerity     *DmVerityInfo         `json:\"dm_verity,omitempty\"`\n}\n\nfunc (k *KataVirtualVolume) Validate() bool {\n\tswitch k.VolumeType {\n\tcase KataVirtualVolumeDirectBlockType:\n\t\tif k.Source != \"\" && k.DirectVolume != nil && k.DirectVolume.Validate() {\n\t\t\treturn true\n\t\t}\n\tcase KataVirtualVolumeImageRawBlockType, KataVirtualVolumeLayerRawBlockType:\n\t\tif k.Source != \"\" && (k.DmVerity == nil || k.DmVerity.Validate() == nil) {\n\t\t\treturn true\n\t\t}\n\tcase KataVirtualVolumeImageNydusBlockType, KataVirtualVolumeLayerNydusBlockType, KataVirtualVolumeImageNydusFsType, KataVirtualVolumeLayerNydusFsType:\n\t\tif k.Source != \"\" && k.NydusImage != nil && k.NydusImage.Validate() {\n\t\t\treturn true\n\t\t}\n\tcase KataVirtualVolumeImageGuestPullType:\n\t\tif k.ImagePull != nil && k.ImagePull.Validate() {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc ParseKataVirtualVolume(option []byte) (*KataVirtualVolume, error) {\n\tno := &KataVirtualVolume{}\n\tif err := json.Unmarshal(option, no); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"KataVirtualVolume json unmarshal err\")\n\t}\n\tif !no.Validate() {\n\t\treturn nil, fmt.Errorf(\"KataVirtualVolume is not correct, %+v\", no)\n\t}\n\n\treturn no, nil\n}\n\nfunc ParseKataVirtualVolumeFromBase64(option string) (*KataVirtualVolume, error) {\n\topt, err := base64.StdEncoding.DecodeString(option)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"KataVirtualVolume base64 decoding err\")\n\t}\n\treturn ParseKataVirtualVolume(opt)\n}\n\nfunc EncodeKataVirtualVolumeToBase64(volume KataVirtualVolume) (string, error) {\n\tvalidKataVirtualVolumeJSON, err := json.Marshal(volume)\n\tif err != nil {\n\t\treturn \"\", errors.Wrapf(err, \"marshal KataVirtualVolume object\")\n\t}\n\tlog.L.Infof(\"encode kata volume %s\", validKataVirtualVolumeJSON)\n\toption := base64.StdEncoding.EncodeToString(validKataVirtualVolumeJSON)\n\treturn option, nil\n}\n"
  },
  {
    "path": "snapshot/mount_option_test.go",
    "content": "package snapshot\n\nimport (\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestDmVerityInfoValidation(t *testing.T) {\n\tTestData := []DmVerityInfo{\n\t\t{\n\t\t\tHashType:  \"md5\", // \"md5\" is not a supported hash algorithm\n\t\t\tBlocksize: 512,\n\t\t\tHashsize:  512,\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    8388608,\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 3000, // Invalid block size, not a power of 2.\n\t\t\tHashsize:  512,\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    8388608,\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 0, // Invalid block size, less than 512.\n\t\t\tHashsize:  512,\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    8388608,\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 524800, // Invalid block size, greater than 524288.\n\t\t\tHashsize:  512,\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    8388608,\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 512,\n\t\t\tHashsize:  3000, // Invalid hash block size, not a power of 2.\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    8388608,\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 512,\n\t\t\tHashsize:  0, // Invalid hash block size, less than 512.\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    8388608,\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 512,\n\t\t\tHashsize:  524800, // Invalid hash block size, greater than 524288.\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    8388608,\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 512,\n\t\t\tHashsize:  512,\n\t\t\tBlockNum:  0, // Invalid BlockNum, it must be greater than 0.\n\t\t\tOffset:    8388608,\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 512,\n\t\t\tHashsize:  512,\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    0, // Invalid offset, it must be greater than 0.\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 512,\n\t\t\tHashsize:  512,\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    8193, // Invalid offset, it must be aligned to 512.\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t\t{\n\t\t\tHashType:  \"sha256\",\n\t\t\tBlocksize: 512,\n\t\t\tHashsize:  512,\n\t\t\tBlockNum:  16384,\n\t\t\tOffset:    8388608 - 4096, // Invalid offset, it must be equal to blocksize * BlockNum.\n\t\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t\t},\n\t}\n\n\tfor _, d := range TestData {\n\t\tassert.Error(t, d.Validate())\n\t}\n\tTestCorrectData := DmVerityInfo{\n\t\tHashType:  \"sha256\",\n\t\tBlocksize: 512,\n\t\tHashsize:  512,\n\t\tBlockNum:  16384,\n\t\tOffset:    8388608,\n\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t}\n\tassert.NoError(t, TestCorrectData.Validate())\n}\n\nfunc TestDirectAssignedVolumeValidation(t *testing.T) {\n\tvalidDirectVolume := DirectAssignedVolume{\n\t\tMetadata: map[string]string{\"key\": \"value\"},\n\t}\n\tassert.True(t, validDirectVolume.Validate())\n\n\tinvalidDirectVolume := DirectAssignedVolume{\n\t\tMetadata: nil,\n\t}\n\tassert.False(t, invalidDirectVolume.Validate())\n}\n\nfunc TestImagePullVolumeValidation(t *testing.T) {\n\tvalidImagePull := ImagePullVolume{\n\t\tMetadata: map[string]string{\"key\": \"value\"},\n\t}\n\tassert.True(t, validImagePull.Validate())\n\n\tinvalidImagePull := ImagePullVolume{\n\t\tMetadata: nil,\n\t}\n\tassert.False(t, invalidImagePull.Validate())\n}\n\nfunc TestNydusImageVolumeValidation(t *testing.T) {\n\tvalidNydusImage := NydusImageVolume{\n\t\tConfig:      \"config_value\",\n\t\tSnapshotDir: \"\",\n\t}\n\tassert.True(t, validNydusImage.Validate())\n\n\tinvalidNydusImage := NydusImageVolume{\n\t\tConfig:      \"\",\n\t\tSnapshotDir: \"\",\n\t}\n\tassert.False(t, invalidNydusImage.Validate())\n}\n\nfunc TestKataVirtualVolumeValidation(t *testing.T) {\n\tvalidKataVirtualVolume := KataVirtualVolume{\n\t\tVolumeType: \"direct_block\",\n\t\tSource:     \"/dev/sdb\",\n\t\tFSType:     \"ext4\",\n\t\tOptions:    []string{\"rw\"},\n\t\tDirectVolume: &DirectAssignedVolume{\n\t\t\tMetadata: map[string]string{\"key\": \"value\"},\n\t\t},\n\t\t// Initialize other fields\n\t}\n\tassert.True(t, validKataVirtualVolume.Validate())\n\n\tinvalidKataVirtualVolume := KataVirtualVolume{\n\t\tVolumeType: \"direct_block\",\n\t\tSource:     \"/dev/sdb\",\n\t\tFSType:     \"\",\n\t\tOptions:    nil,\n\t\tDirectVolume: &DirectAssignedVolume{\n\t\t\tMetadata: nil,\n\t\t},\n\t\t// Initialize other fields\n\t}\n\tassert.False(t, invalidKataVirtualVolume.Validate())\n}\nfunc TestParseDmVerityInfo(t *testing.T) {\n\t// Create a mock valid KataVirtualVolume\n\tvalidDmVerityInfo := DmVerityInfo{\n\t\tHashType:  \"sha256\",\n\t\tBlocksize: 512,\n\t\tHashsize:  512,\n\t\tBlockNum:  16384,\n\t\tOffset:    8388608,\n\t\tHash:      \"9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174\",\n\t}\n\tvalidKataVirtualVolumeJSON, _ := json.Marshal(validDmVerityInfo)\n\n\tt.Run(\"Valid Option\", func(t *testing.T) {\n\t\tvolume, err := ParseDmVerityInfo(string(validKataVirtualVolumeJSON))\n\t\tassert.NoError(t, err)\n\t\tassert.NotNil(t, volume)\n\t\tassert.NoError(t, volume.Validate())\n\t})\n\n\tt.Run(\"Invalid JSON Option\", func(t *testing.T) {\n\t\tvolume, err := ParseDmVerityInfo(\"invalid_json\")\n\t\tassert.Error(t, err)\n\t\tassert.Nil(t, volume)\n\t})\n\n}\nfunc TestParseKataVirtualVolume(t *testing.T) {\n\t// Create a mock valid KataVirtualVolume\n\tvalidKataVirtualVolume := KataVirtualVolume{\n\t\tVolumeType: \"direct_block\",\n\t\tSource:     \"/dev/sdb\",\n\t\tFSType:     \"ext4\",\n\t\tOptions:    []string{\"rw\"},\n\t\tDirectVolume: &DirectAssignedVolume{\n\t\t\tMetadata: map[string]string{\"key\": \"value\"},\n\t\t},\n\t\t// Initialize other fields\n\t}\n\tvalidOption, err := EncodeKataVirtualVolumeToBase64(validKataVirtualVolume)\n\tassert.Nil(t, err)\n\n\tt.Run(\"Valid Option\", func(t *testing.T) {\n\t\tvolume, err := ParseKataVirtualVolumeFromBase64(validOption)\n\n\t\tassert.NoError(t, err)\n\t\tassert.NotNil(t, volume)\n\t\tassert.True(t, volume.Validate())\n\t})\n\n\tt.Run(\"Invalid JSON Option\", func(t *testing.T) {\n\t\tinvalidJSONOption := base64.StdEncoding.EncodeToString([]byte(\"invalid_json\"))\n\t\tvolume, err := ParseKataVirtualVolumeFromBase64(invalidJSONOption)\n\n\t\tassert.Error(t, err)\n\t\tassert.Nil(t, volume)\n\t})\n\n\tinvalidBase64Option := \"invalid_base64\"\n\tt.Run(\"Invalid Base64 Option\", func(t *testing.T) {\n\t\tvolume, err := ParseKataVirtualVolumeFromBase64(invalidBase64Option)\n\n\t\tassert.Error(t, err)\n\t\tassert.Nil(t, volume)\n\t})\n\n\tt.Run(\"Invalid Fields\", func(t *testing.T) {\n\t\t// Create a mock invalid KataVirtualVolume\n\t\tvalidKataVirtualVolume = KataVirtualVolume{\n\t\t\tVolumeType: \"direct_block\",\n\t\t\tSource:     \"/dev/sdb\",\n\t\t\tFSType:     \"ext4\",\n\t\t\tOptions:    []string{\"rw\"},\n\t\t\t// Initialize other fields\n\t\t}\n\t\tinvalidFieldOption, err := EncodeKataVirtualVolumeToBase64(validKataVirtualVolume)\n\t\tassert.Nil(t, err)\n\t\tvolume, err := ParseKataVirtualVolumeFromBase64(invalidFieldOption)\n\t\tassert.Error(t, err)\n\t\tassert.Nil(t, volume)\n\t})\n}\n"
  },
  {
    "path": "snapshot/process.go",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage snapshot\n\nimport (\n\t\"context\"\n\t\"path\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/sirupsen/logrus\"\n\n\t\"github.com/containerd/containerd/v2/core/mount\"\n\t\"github.com/containerd/containerd/v2/core/snapshots/storage\"\n\tsnpkg \"github.com/containerd/containerd/v2/pkg/snapshotters\"\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/snapshot\"\n)\n\n// `storageLocater` provides a local storage for each handler to save their intermediates.\n// Different actions for different layer types\nfunc chooseProcessor(ctx context.Context, logger *logrus.Entry,\n\tsn *snapshotter, s storage.Snapshot, key, parent string, labels map[string]string,\n\tstorageLocater func() string) (_ func() (bool, []mount.Mount, error), target string, commitLabels map[string]string, err error) {\n\tvar handler func() (bool, []mount.Mount, error)\n\tcommitLabels = labels\n\n\t// Handler to prepare a directory for containerd to download and unpacking layer.\n\tdefaultHandler := func() (bool, []mount.Mount, error) {\n\t\tmounts, err := sn.mountNative(ctx, labels, s)\n\t\treturn false, mounts, err\n\t}\n\n\t// Handler to stop containerd from downloading and unpacking layer.\n\tskipHandler := func() (bool, []mount.Mount, error) {\n\t\treturn true, nil, nil\n\t}\n\n\tremoteHandler := func(id string, labels map[string]string) func() (bool, []mount.Mount, error) {\n\t\treturn func() (bool, []mount.Mount, error) {\n\t\t\tlogger.Debugf(\"Prepare remote snapshot %s\", id)\n\t\t\tif err := sn.fs.Mount(ctx, id, labels, &s); err != nil {\n\t\t\t\treturn false, nil, err\n\t\t\t}\n\n\t\t\t// Let Prepare operation show the rootfs content.\n\t\t\tif err := sn.fs.WaitUntilReady(id); err != nil {\n\t\t\t\treturn false, nil, err\n\t\t\t}\n\n\t\t\tlogger.Infof(\"Nydus remote snapshot %s is ready\", id)\n\t\t\tmounts, err := sn.mountRemote(ctx, labels, s, id, key)\n\t\t\treturn false, mounts, err\n\t\t}\n\t}\n\n\tproxyHandler := func() (bool, []mount.Mount, error) {\n\t\tmounts, err := sn.mountProxy(ctx, s)\n\t\treturn false, mounts, err\n\t}\n\n\t// OCI image is also marked with \"containerd.io/snapshot.ref\" by Containerd\n\ttarget, isRoLayer := labels[label.TargetSnapshotRef]\n\n\tif isRoLayer {\n\t\t// Containerd won't consume mount slice for below snapshots\n\t\tswitch {\n\t\tcase config.GetFsDriver() == config.FsDriverProxy:\n\t\t\tlogger.Debugf(\"proxy image pull request to other agents\")\n\t\t\tif ref := labels[label.CRILayerDigest]; len(ref) > 0 {\n\t\t\t\tlabels[label.NydusProxyMode] = \"true\"\n\t\t\t\thandler = skipHandler\n\t\t\t} else {\n\t\t\t\treturn nil, \"\", nil, errors.Errorf(\"missing CRI reference annotation for snapshot %s\", s.ID)\n\t\t\t}\n\t\tcase label.IsNydusMetaLayer(labels):\n\t\t\tlogger.Debugf(\"found nydus meta layer\")\n\t\t\thandler = defaultHandler\n\t\tcase label.IsNydusDataLayer(labels):\n\t\t\tlogger.Debugf(\"found nydus data layer\")\n\t\t\thandler = skipHandler\n\t\tcase sn.fs.CheckIndexAlternative(ctx, labels):\n\t\t\tlogger.Debugf(\"found nydus alternative image in index\")\n\t\t\tcommitLabels[label.NydusIndexAlternative] = \"true\"\n\t\t\thandler = skipHandler\n\t\tcase sn.fs.CheckReferrer(ctx, labels):\n\t\t\tlogger.Debugf(\"found referenced nydus manifest\")\n\t\t\thandler = skipHandler\n\t\tdefault:\n\t\t\tif sn.fs.StargzEnabled() {\n\t\t\t\t// Check if the blob is format of estargz\n\t\t\t\tif ok, blob := sn.fs.IsStargzDataLayer(labels); ok {\n\t\t\t\t\terr := sn.fs.PrepareStargzMetaLayer(blob, storageLocater(), labels)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tlogger.Errorf(\"prepare stargz layer of snapshot ID %s, err: %v\", s.ID, err)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.Debugf(\"found estargz data layer\")\n\t\t\t\t\t\t// Mark this snapshot as stargz layer since estargz image format does not\n\t\t\t\t\t\t// has special annotation or media type.\n\t\t\t\t\t\tlabels[label.StargzLayer] = \"true\"\n\t\t\t\t\t\thandler = skipHandler\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif handler == nil && sn.fs.TarfsEnabled() {\n\t\t\t\tlogger.Debugf(\"convert OCIv1 layer to tarfs\")\n\t\t\t\terr := sn.fs.PrepareTarfsLayer(ctx, labels, s.ID, sn.upperPath(s.ID))\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Warnf(\"snapshot ID %s can't be converted into tarfs, fallback to containerd, err: %v\", s.ID, err)\n\t\t\t\t} else {\n\t\t\t\t\tif config.GetTarfsExportEnabled() {\n\t\t\t\t\t\t_, err = sn.fs.ExportBlockData(s, true, labels, func(id string) string { return sn.upperPath(id) })\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn nil, \"\", nil, errors.Wrap(err, \"export layer as tarfs block device\")\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\thandler = skipHandler\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Container writable layer comes into this branch.\n\t\t// It should not be committed during this Prepare() operation.\n\n\t\tpID, pInfo, _, pErr := snapshot.GetSnapshotInfo(ctx, sn.ms, parent)\n\t\tif treatAsProxyDriver(pInfo.Labels) {\n\t\t\tlogger.Warnf(\"treat as proxy mode for the prepared snapshot by other snapshotter possibly: id = %s, labels = %v\", pID, pInfo.Labels)\n\t\t\thandler = proxyHandler\n\t\t}\n\t\tif pErr == nil && label.IsNydusProxyMode(pInfo.Labels) {\n\t\t\tlogger.Infof(\"Prepare active snapshot %s in proxy mode\", key)\n\t\t\thandler = remoteHandler(pID, pInfo.Labels)\n\t\t}\n\n\t\t// Hope to find bootstrap layer and prepares to start nydusd\n\t\t// TODO: Trying find nydus meta layer will slow down setting up rootfs to OCI images\n\t\tif handler == nil {\n\t\t\tif id, info, err := sn.findMetaLayer(ctx, key); err == nil {\n\t\t\t\tlogger.Infof(\"Prepare active Nydus snapshot %s\", key)\n\t\t\t\thandler = remoteHandler(id, info.Labels)\n\t\t\t}\n\t\t}\n\n\t\tif handler == nil && sn.fs.IndexDetectEnabled() {\n\t\t\tif id, info, err := sn.findIndexAlternativeLayer(ctx, key); err == nil {\n\t\t\t\tlogger.Infof(\"Found nydus alternative image in index for image: %s\", info.Labels[snpkg.TargetRefLabel])\n\t\t\t\tmetaPath := path.Join(sn.snapshotDir(id), \"fs\", \"image.boot\")\n\t\t\t\tif err := sn.fs.TryFetchMetadataFromIndex(ctx, info.Labels, metaPath); err != nil {\n\t\t\t\t\treturn nil, \"\", nil, errors.Wrap(err, \"try fetch metadata\")\n\t\t\t\t}\n\t\t\t\thandler = remoteHandler(id, info.Labels)\n\t\t\t}\n\t\t}\n\n\t\tif handler == nil && sn.fs.ReferrerDetectEnabled() {\n\t\t\tif id, info, err := sn.findReferrerLayer(ctx, key); err == nil {\n\t\t\t\tlogger.Infof(\"Found referenced nydus manifest for image: %s\", info.Labels[snpkg.TargetRefLabel])\n\t\t\t\tmetaPath := path.Join(sn.snapshotDir(id), \"fs\", \"image.boot\")\n\t\t\t\tif err := sn.fs.TryFetchMetadata(ctx, info.Labels, metaPath); err != nil {\n\t\t\t\t\treturn nil, \"\", nil, errors.Wrap(err, \"try fetch metadata\")\n\t\t\t\t}\n\t\t\t\thandler = remoteHandler(id, info.Labels)\n\t\t\t}\n\t\t}\n\n\t\tif handler == nil && pErr == nil && sn.fs.StargzEnabled() && sn.fs.StargzLayer(pInfo.Labels) {\n\t\t\tif err := sn.fs.MergeStargzMetaLayer(ctx, s); err != nil {\n\t\t\t\treturn nil, \"\", nil, errors.Wrap(err, \"merge stargz meta layers\")\n\t\t\t}\n\t\t\thandler = remoteHandler(pID, pInfo.Labels)\n\t\t\tlogger.Infof(\"Generated estargz merged meta for %s\", key)\n\t\t}\n\n\t\tif handler == nil && pErr == nil && sn.fs.TarfsEnabled() && label.IsTarfsDataLayer(pInfo.Labels) {\n\t\t\t// Merge and mount tarfs on the uppermost parent layer.\n\t\t\t// TODO may need to check all parrent layers, in case share layers with other images\n\t\t\t// which have already been prepared by overlay snapshotter\n\n\t\t\tlogger.Infof(\"Prepare active snapshot %s in Nydus tarfs mode\", key)\n\t\t\terr = sn.mergeTarfs(ctx, s, pID, pInfo)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, \"\", nil, errors.Wrapf(err, \"merge tarfs layers for snapshot %s\", pID)\n\t\t\t}\n\t\t\tlogger.Infof(\"Prepared active snapshot %s in Nydus tarfs mode\", key)\n\t\t\thandler = remoteHandler(pID, pInfo.Labels)\n\t\t}\n\t}\n\n\tif handler == nil {\n\t\thandler = defaultHandler\n\t}\n\n\treturn handler, target, commitLabels, err\n}\n"
  },
  {
    "path": "snapshot/renewal.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage snapshot\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/containerd/log\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/auth\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/daemon/types\"\n\tmgr \"github.com/containerd/nydus-snapshotter/pkg/manager\"\n)\n\n// startCredentialRenewal initializes the credential store, runs an initial\n// reconciliation, and starts a background goroutine that periodically\n// renews credentials and hot-reloads running nydusd daemons.\nfunc startCredentialRenewal(ctx context.Context, interval time.Duration, managers []*mgr.Manager) {\n\tauth.InitCredentialStore(interval)\n\treconcileCredentials(ctx, managers)\n\n\tlog.G(ctx).WithField(\"interval\", interval).Info(\"credential renewal initialized\")\n\tgo credentialRenewalLoop(ctx, interval, managers)\n}\n\n// credentialRenewalLoop is the background goroutine that periodically\n// reconciles and renews credentials.\nfunc credentialRenewalLoop(ctx context.Context, interval time.Duration, managers []*mgr.Manager) {\n\tticker := time.NewTicker(interval)\n\tdefer ticker.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn\n\t\tcase <-ticker.C:\n\t\t\treconcileCredentials(ctx, managers)\n\t\t}\n\t}\n}\n\n// reconcileCredentials reconciles the credential store against the live RAFS\n// instances by walking managers -> daemons -> rafs, and renews all entries\n// that should be active. Stale store entries (refs no longer backed by a\n// running rafs) are evicted.\n// 4 different situations are possible for each live ref:\n// - entry in store, live in RAFS: renew + hot-reload (fusedev only)\n// - entry not in store, live in RAFS: add + hot-reload (fusedev only)\n// - entry not in store, not live in RAFS: nothing\n// - entry in store, not live in RAFS: evict\nfunc reconcileCredentials(ctx context.Context, managers []*mgr.Manager) {\n\tlive := make(map[string]struct{})\n\n\tfor _, m := range managers {\n\t\tfor _, d := range m.ListDaemons() {\n\t\t\tif d.State() != types.DaemonStateRunning {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfor _, r := range d.RafsCache.List() {\n\t\t\t\tif r.ImageID == \"\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tlive[r.ImageID] = struct{}{}\n\n\t\t\t\told := auth.GetStoredCredential(r.ImageID)\n\t\t\t\tlog.L.WithField(\"ref\", r.ImageID).Debug(\"renewing credential entry\")\n\t\t\t\tkc := auth.RenewCredential(r.ImageID)\n\t\t\t\tif kc == nil || (old != nil && old.ToBase64() == kc.ToBase64()) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tif err := d.UpdateAuthConfig(r.SnapshotID, kc); err != nil {\n\t\t\t\t\tlog.G(ctx).WithError(err).WithField(\"daemon\", d.ID()).\n\t\t\t\t\t\tWarn(\"failed to hot-reload auth config\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tauth.EvictStaleCredentials(live)\n}\n"
  },
  {
    "path": "snapshot/renewal_test.go",
    "content": "/*\n * Copyright (c) 2026. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage snapshot\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\tmgr \"github.com/containerd/nydus-snapshotter/pkg/manager\"\n)\n\n// TestStartCredentialRenewalLifecycle verifies that the renewal goroutine\n// starts, ticks, and stops cleanly on context cancellation. The managers\n// list is empty so reconcile is a no-op each tick.\nfunc TestStartCredentialRenewalLifecycle(t *testing.T) {\n\tctx, cancel := context.WithCancel(t.Context())\n\n\tstartCredentialRenewal(ctx, 30*time.Millisecond, []*mgr.Manager{})\n\n\t// Let it tick a few times without error.\n\ttime.Sleep(100 * time.Millisecond)\n\n\tcancel()\n\t// Give goroutine time to observe cancellation.\n\ttime.Sleep(60 * time.Millisecond)\n}\n"
  },
  {
    "path": "snapshot/snapshot.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage snapshot\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/containerd/containerd/v2/core/mount\"\n\t\"github.com/containerd/containerd/v2/core/snapshots\"\n\t\"github.com/containerd/containerd/v2/core/snapshots/storage\"\n\tsnpkg \"github.com/containerd/containerd/v2/pkg/snapshotters\"\n\t\"github.com/containerd/continuity/fs\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/nydus-snapshotter/config\"\n\t\"github.com/containerd/nydus-snapshotter/config/daemonconfig\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/rafs\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/cache\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/cgroup\"\n\tv2 \"github.com/containerd/nydus-snapshotter/pkg/cgroup/v2\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/errdefs\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/index\"\n\tmgr \"github.com/containerd/nydus-snapshotter/pkg/manager\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/collector\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/metrics/data\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/pprof\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/referrer\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/system\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/tarfs\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/store\"\n\n\t\"github.com/containerd/nydus-snapshotter/pkg/filesystem\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/signature\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/snapshot\"\n)\n\nvar _ snapshots.Snapshotter = &snapshotter{}\n\ntype snapshotter struct {\n\troot                    string\n\tnydusdPath              string\n\tms                      *storage.MetaStore // Storing snapshots' state, parentage and other metadata\n\tfs                      *filesystem.Filesystem\n\tcgroupManager           *cgroup.Manager\n\tenableNydusOverlayFS    bool\n\tnydusOverlayFSPath      string\n\tenableKataVolume        bool\n\tsyncRemove              bool\n\tcleanupOnClose          bool\n\tenableOverlayfsVolatile bool\n}\n\nfunc NewSnapshotter(ctx context.Context, cfg *config.SnapshotterConfig) (snapshots.Snapshotter, error) {\n\tverifier, err := signature.NewVerifier(cfg.ImageConfig.PublicKeyFile, cfg.ImageConfig.ValidateSignature)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"initialize image verifier\")\n\t}\n\n\tdb, err := store.NewDatabase(cfg.Root)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"create database\")\n\t}\n\n\trp, err := config.ParseRecoverPolicy(cfg.DaemonConfig.RecoverPolicy)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"parse recover policy\")\n\t}\n\n\tvar cgroupMgr *cgroup.Manager\n\tif cfg.CgroupConfig.Enable {\n\t\tcgroupConfig, err := config.ParseCgroupConfig(cfg.CgroupConfig)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"parse cgroup configuration\")\n\t\t}\n\t\tlog.L.Infof(\"parsed cgroup config: %#v\", cgroupConfig)\n\n\t\tcgroupMgr, err = cgroup.NewManager(cgroup.Opt{\n\t\t\tName:   \"nydusd\",\n\t\t\tConfig: cgroupConfig,\n\t\t})\n\t\tif err != nil && (err != cgroup.ErrCgroupNotSupported || err != v2.ErrRootMemorySubtreeControllerDisabled) {\n\t\t\treturn nil, errors.Wrap(err, \"create cgroup manager\")\n\t\t}\n\t}\n\n\tvar skipSSLVerify bool\n\tvar daemonConfig *daemonconfig.DaemonConfig\n\tfsDriver := config.GetFsDriver()\n\tif fsDriver == config.FsDriverFscache || fsDriver == config.FsDriverFusedev {\n\t\tconfig, err := daemonconfig.NewDaemonConfig(config.GetFsDriver(), cfg.DaemonConfig.NydusdConfigPath)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"load daemon configuration\")\n\t\t}\n\t\tdaemonConfig = &config\n\t\t_, backendConfig := config.StorageBackend()\n\t\tskipSSLVerify = backendConfig.SkipVerify\n\t} else {\n\t\tskipSSLVerify = config.GetSkipSSLVerify()\n\t}\n\n\tfsManagers := []*mgr.Manager{}\n\tif cfg.Experimental.TarfsConfig.EnableTarfs {\n\t\tblockdevManager, err := mgr.NewManager(mgr.Opt{\n\t\t\tNydusdBinaryPath: \"\",\n\t\t\tDatabase:         db,\n\t\t\tCacheDir:         cfg.CacheManagerConfig.CacheDir,\n\t\t\tRootDir:          cfg.Root,\n\t\t\tRecoverPolicy:    rp,\n\t\t\tFsDriver:         config.FsDriverBlockdev,\n\t\t\tDaemonConfig:     nil,\n\t\t\tCgroupMgr:        cgroupMgr,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"create blockdevice manager\")\n\t\t}\n\t\tfsManagers = append(fsManagers, blockdevManager)\n\t}\n\n\tif config.GetFsDriver() == config.FsDriverFscache {\n\t\tfscacheManager, err := mgr.NewManager(mgr.Opt{\n\t\t\tNydusdBinaryPath: cfg.DaemonConfig.NydusdPath,\n\t\t\tDatabase:         db,\n\t\t\tCacheDir:         cfg.CacheManagerConfig.CacheDir,\n\t\t\tRootDir:          cfg.Root,\n\t\t\tRecoverPolicy:    rp,\n\t\t\tFsDriver:         config.FsDriverFscache,\n\t\t\tDaemonConfig:     daemonConfig,\n\t\t\tCgroupMgr:        cgroupMgr,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"create fscache manager\")\n\t\t}\n\t\tfsManagers = append(fsManagers, fscacheManager)\n\t}\n\n\tif config.GetFsDriver() == config.FsDriverFusedev {\n\t\tfusedevManager, err := mgr.NewManager(mgr.Opt{\n\t\t\tNydusdBinaryPath: cfg.DaemonConfig.NydusdPath,\n\t\t\tDatabase:         db,\n\t\t\tCacheDir:         cfg.CacheManagerConfig.CacheDir,\n\t\t\tRootDir:          cfg.Root,\n\t\t\tRecoverPolicy:    rp,\n\t\t\tFsDriver:         config.FsDriverFusedev,\n\t\t\tDaemonConfig:     daemonConfig,\n\t\t\tCgroupMgr:        cgroupMgr,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"create fusedev manager\")\n\t\t}\n\t\tfsManagers = append(fsManagers, fusedevManager)\n\t}\n\n\tif config.GetFsDriver() == config.FsDriverProxy {\n\t\tproxyManager, err := mgr.NewManager(mgr.Opt{\n\t\t\tNydusdBinaryPath: \"\",\n\t\t\tDatabase:         db,\n\t\t\tCacheDir:         cfg.CacheManagerConfig.CacheDir,\n\t\t\tRootDir:          cfg.Root,\n\t\t\tRecoverPolicy:    rp,\n\t\t\tFsDriver:         config.FsDriverProxy,\n\t\t\tDaemonConfig:     nil,\n\t\t\tCgroupMgr:        cgroupMgr,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"create proxy manager\")\n\t\t}\n\t\tfsManagers = append(fsManagers, proxyManager)\n\t}\n\n\tmetricServer, err := metrics.NewServer(\n\t\tctx,\n\t\tmetrics.WithProcessManagers(fsManagers),\n\t\tmetrics.WithHungIOInterval(cfg.MetricsConfig.HungIOInterval),\n\t\tmetrics.WithCollectInterval(cfg.MetricsConfig.CollectInterval),\n\t)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"create metrics server\")\n\t}\n\n\t// Start to collect metrics.\n\tif cfg.MetricsConfig.Address != \"\" {\n\t\tif err := metrics.NewMetricsHTTPListenerServer(cfg.MetricsConfig.Address); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"start metrics HTTP server\")\n\t\t}\n\t\tgo func() {\n\t\t\tif err := metricServer.StartCollectMetrics(ctx); err != nil {\n\t\t\t\tlog.L.WithError(err).Errorf(\"Failed to start collecting metrics\")\n\t\t\t}\n\t\t}()\n\n\t\tlog.L.Infof(\"Started metrics HTTP server on %q\", cfg.MetricsConfig.Address)\n\t}\n\n\topts := []filesystem.NewFSOpt{\n\t\tfilesystem.WithManagers(fsManagers),\n\t\tfilesystem.WithNydusdBinaryPath(cfg.DaemonConfig.NydusdPath),\n\t\tfilesystem.WithVerifier(verifier),\n\t\tfilesystem.WithRootMountpoint(config.GetRootMountpoint()),\n\t\tfilesystem.WithEnableStargz(cfg.Experimental.EnableStargz),\n\t}\n\n\tcacheConfig := &cfg.CacheManagerConfig\n\tcacheMgr, err := cache.NewManager(cache.Opt{\n\t\tDatabase: db,\n\t\tPeriod:   cfg.CacheManagerConfig.GCPeriod,\n\t\tCacheDir: cacheConfig.CacheDir,\n\t\tDisabled: cacheConfig.Disable,\n\t})\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"create cache manager\")\n\t}\n\topts = append(opts, filesystem.WithCacheManager(cacheMgr))\n\n\tif cfg.Experimental.EnableIndexDetect {\n\t\tindexMgr := index.NewManager(skipSSLVerify)\n\t\topts = append(opts, filesystem.WithIndexManager(indexMgr))\n\t}\n\n\tif cfg.Experimental.EnableReferrerDetect {\n\t\treferrerMgr := referrer.NewManager(skipSSLVerify)\n\t\topts = append(opts, filesystem.WithReferrerManager(referrerMgr))\n\t}\n\n\tif cfg.Experimental.TarfsConfig.EnableTarfs {\n\t\ttarfsMgr := tarfs.NewManager(skipSSLVerify, cfg.Experimental.TarfsConfig.TarfsHint,\n\t\t\tcacheConfig.CacheDir, cfg.DaemonConfig.NydusImagePath,\n\t\t\tint64(cfg.Experimental.TarfsConfig.MaxConcurrentProc))\n\t\topts = append(opts, filesystem.WithTarfsManager(tarfsMgr))\n\t}\n\n\tnydusFs, err := filesystem.NewFileSystem(ctx, opts...)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"initialize filesystem thin layer\")\n\t}\n\n\t// Start credential renewal after NewFileSystem, which calls Manager.Recover()\n\t// and populates the daemon caches from the DB. Starting earlier would cause\n\t// the initial reconciliation to see empty managers on restart.\n\tif interval := cfg.RemoteConfig.AuthConfig.CredentialRenewalInterval; interval > 0 {\n\t\tstartCredentialRenewal(ctx, interval, fsManagers)\n\t}\n\n\tif config.IsSystemControllerEnabled() {\n\t\tsystemController, err := system.NewSystemController(nydusFs, fsManagers, config.SystemControllerAddress(), cfg.SystemControllerConfig.UID, cfg.SystemControllerConfig.GID)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"create system controller\")\n\t\t}\n\n\t\tgo func() {\n\t\t\tif err := systemController.Run(); err != nil {\n\t\t\t\tlog.L.WithError(err).Error(\"Failed to start system controller\")\n\t\t\t}\n\t\t}()\n\n\t\tlog.L.Infof(\"Started system controller on %q\", config.SystemControllerAddress())\n\n\t\tpprofAddress := config.SystemControllerPprofAddress()\n\t\tif pprofAddress != \"\" {\n\t\t\tif err := pprof.NewPprofHTTPListener(pprofAddress); err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"start pprof HTTP server\")\n\t\t\t}\n\n\t\t\tlog.L.Infof(\"Started pprof sever on %q\", pprofAddress)\n\t\t}\n\t}\n\n\tsupportsDType, err := getSupportsDType(cfg.Root)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !supportsDType {\n\t\treturn nil, fmt.Errorf(\"%s does not support d_type. If the backing filesystem is xfs, please reformat with ftype=1 to enable d_type support\", cfg.Root)\n\t}\n\n\tms, err := storage.NewMetaStore(filepath.Join(cfg.Root, \"metadata.db\"))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif err := os.Mkdir(filepath.Join(cfg.Root, \"snapshots\"), 0700); err != nil && !os.IsExist(err) {\n\t\treturn nil, err\n\t}\n\n\tsyncRemove := cfg.SnapshotsConfig.SyncRemove\n\tif config.GetFsDriver() == config.FsDriverFscache {\n\t\tlog.L.Infof(\"enable syncRemove for fscache mode\")\n\t\tsyncRemove = true\n\t}\n\n\treturn &snapshotter{\n\t\troot:                    cfg.Root,\n\t\tnydusdPath:              cfg.DaemonConfig.NydusdPath,\n\t\tms:                      ms,\n\t\tsyncRemove:              syncRemove,\n\t\tfs:                      nydusFs,\n\t\tcgroupManager:           cgroupMgr,\n\t\tenableNydusOverlayFS:    cfg.SnapshotsConfig.EnableNydusOverlayFS,\n\t\tnydusOverlayFSPath:      cfg.SnapshotsConfig.NydusOverlayFSPath,\n\t\tenableKataVolume:        cfg.SnapshotsConfig.EnableKataVolume,\n\t\tenableOverlayfsVolatile: cfg.SnapshotsConfig.EnableOverlayfsVolatile,\n\t\tcleanupOnClose:          cfg.CleanupOnClose,\n\t}, nil\n}\n\nfunc (o *snapshotter) Cleanup(ctx context.Context) error {\n\tlog.L.Debugf(\"[Cleanup] snapshots\")\n\tif timer := collector.NewSnapshotMetricsTimer(collector.SnapshotMethodCleanup); timer != nil {\n\t\tdefer timer.ObserveDuration()\n\t}\n\n\tcleanup, err := o.cleanupDirectories(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.L.Infof(\"[Cleanup] orphan directories %v\", cleanup)\n\n\tfor _, dir := range cleanup {\n\t\tif err := o.cleanupSnapshotDirectory(ctx, dir); err != nil {\n\t\t\tlog.L.WithError(err).Warnf(\"failed to remove directory %s\", dir)\n\t\t}\n\t}\n\n\tcleanup, err = o.getUnusedCacheBlobs(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tlog.L.Infof(\"[Cleanup] unused cache blobs %v\", cleanup)\n\n\tfor _, blob := range cleanup {\n\t\tif err := ctx.Err(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\t// Add sha256: prefix to make it a valid blob digest\n\t\tif err := o.fs.RemoveCache(\"sha256:\" + blob); err != nil {\n\t\t\tlog.L.WithError(err).Warnf(\"failed to remove cache blob %s\", blob)\n\t\t\tdata.CacheBlobDeletionErrors.Inc()\n\t\t} else {\n\t\t\tdata.CacheBlobsDeleted.Inc()\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (o *snapshotter) Stat(ctx context.Context, key string) (snapshots.Info, error) {\n\t_, info, _, err := snapshot.GetSnapshotInfo(ctx, o.ms, key)\n\treturn info, err\n}\n\nfunc (o *snapshotter) Update(ctx context.Context, info snapshots.Info, fieldpaths ...string) (snapshots.Info, error) {\n\treturn snapshot.UpdateSnapshotInfo(ctx, o.ms, info, fieldpaths...)\n}\n\nfunc (o *snapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) {\n\tid, info, usage, err := snapshot.GetSnapshotInfo(ctx, o.ms, key)\n\tif err != nil {\n\t\treturn snapshots.Usage{}, err\n\t}\n\n\tswitch info.Kind {\n\tcase snapshots.KindActive:\n\t\tupperPath := o.upperPath(id)\n\t\tdu, err := fs.DiskUsage(ctx, upperPath)\n\t\tif err != nil {\n\t\t\treturn snapshots.Usage{}, err\n\t\t}\n\t\tusage = snapshots.Usage(du)\n\tcase snapshots.KindCommitted:\n\t\t// Caculate disk space usage under cacheDir of committed snapshots.\n\t\tif label.IsNydusDataLayer(info.Labels) || label.IsTarfsDataLayer(info.Labels) {\n\t\t\tif blobDigest, ok := info.Labels[snpkg.TargetLayerDigestLabel]; ok {\n\t\t\t\t// Try to get nydus meta layer/snapshot disk usage\n\t\t\t\tcacheUsage, err := o.fs.CacheUsage(ctx, blobDigest)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn snapshots.Usage{}, errors.Wrapf(err, \"try to get snapshot %s nydus disk usage\", id)\n\t\t\t\t}\n\t\t\t\tusage.Add(cacheUsage)\n\t\t\t}\n\t\t}\n\tcase snapshots.KindUnknown:\n\tcase snapshots.KindView:\n\t}\n\n\treturn usage, nil\n}\n\nfunc (o *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) {\n\tlog.L.Debugf(\"[Mounts] snapshot %s\", key)\n\tif timer := collector.NewSnapshotMetricsTimer(collector.SnapshotMethodMount); timer != nil {\n\t\tdefer timer.ObserveDuration()\n\t}\n\tvar (\n\t\tneedRemoteMounts = false\n\t\tmetaSnapshotID   string\n\t)\n\n\tid, info, _, err := snapshot.GetSnapshotInfo(ctx, o.ms, key)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"mounts get snapshot %q info\", key)\n\t}\n\tlog.L.Infof(\"[Mounts] snapshot %s ID %s Kind %s\", key, id, info.Kind)\n\n\tswitch info.Kind {\n\tcase snapshots.KindView:\n\t\tif label.IsNydusMetaLayer(info.Labels) {\n\t\t\terr = o.fs.WaitUntilReady(id)\n\t\t\tif err != nil {\n\t\t\t\t// Skip waiting if clients is unpacking nydus artifacts to `mounts`\n\t\t\t\t// For example, nydus-snapshotter's client like Buildkit is calling snapshotter in below workflow:\n\t\t\t\t//  1. [Prepare] snapshot for the uppermost layer - bootstrap\n\t\t\t\t//  2. [Mounts]\n\t\t\t\t//  3. Unpacking by applying the mounts, then we get bootstrap in its path position.\n\t\t\t\t// In above steps, no container write layer is called to set up from nydus-snapshotter. So it has no\n\t\t\t\t// chance to start nydusd, during which the Rafs instance is created.\n\t\t\t\tif !errors.Is(err, errdefs.ErrNotFound) {\n\t\t\t\t\treturn nil, errors.Wrapf(err, \"mounts: snapshot %s is not ready, err: %v\", id, err)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tneedRemoteMounts = true\n\t\t\t\tmetaSnapshotID = id\n\t\t\t}\n\t\t} else if (o.fs.TarfsEnabled() && label.IsTarfsDataLayer(info.Labels)) || label.IsNydusProxyMode(info.Labels) {\n\t\t\tneedRemoteMounts = true\n\t\t\tmetaSnapshotID = id\n\t\t}\n\tcase snapshots.KindActive:\n\t\tif info.Parent != \"\" {\n\t\t\tpKey := info.Parent\n\t\t\tif pID, pInfo, _, err := snapshot.GetSnapshotInfo(ctx, o.ms, pKey); err == nil {\n\t\t\t\tif label.IsNydusMetaLayer(pInfo.Labels) {\n\t\t\t\t\tif err = o.fs.WaitUntilReady(pID); err != nil {\n\t\t\t\t\t\treturn nil, errors.Wrapf(err, \"mounts: snapshot %s is not ready, err: %v\", pID, err)\n\t\t\t\t\t}\n\t\t\t\t\tneedRemoteMounts = true\n\t\t\t\t\tmetaSnapshotID = pID\n\t\t\t\t} else if (o.fs.TarfsEnabled() && label.IsTarfsDataLayer(pInfo.Labels)) || label.IsNydusProxyMode(pInfo.Labels) {\n\t\t\t\t\tneedRemoteMounts = true\n\t\t\t\t\tmetaSnapshotID = pID\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn nil, errors.Wrapf(err, \"get parent snapshot info, parent key=%q\", pKey)\n\t\t\t}\n\t\t}\n\tcase snapshots.KindCommitted:\n\tcase snapshots.KindUnknown:\n\t}\n\n\tif o.fs.IndexDetectEnabled() && !needRemoteMounts {\n\t\tif id, _, err := o.findIndexAlternativeLayer(ctx, key); err == nil {\n\t\t\tneedRemoteMounts = true\n\t\t\tmetaSnapshotID = id\n\t\t}\n\t}\n\n\tif o.fs.ReferrerDetectEnabled() && !needRemoteMounts {\n\t\tif id, _, err := o.findReferrerLayer(ctx, key); err == nil {\n\t\t\tneedRemoteMounts = true\n\t\t\tmetaSnapshotID = id\n\t\t}\n\t}\n\n\tsnap, err := snapshot.GetSnapshot(ctx, o.ms, key)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get snapshot %s\", key)\n\t}\n\n\tif treatAsProxyDriver(info.Labels) {\n\t\tlog.L.Warnf(\"[Mounts] treat as proxy mode for the prepared snapshot by other snapshotter possibly: id = %s, labels = %v\", id, info.Labels)\n\t\treturn o.mountProxy(ctx, *snap)\n\t}\n\n\tif needRemoteMounts {\n\t\treturn o.mountRemote(ctx, info.Labels, *snap, metaSnapshotID, key)\n\t}\n\n\treturn o.mountNative(ctx, info.Labels, *snap)\n}\n\nfunc (o *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {\n\tlog.L.Infof(\"[Prepare] snapshot with key %s parent %s\", key, parent)\n\n\tif timer := collector.NewSnapshotMetricsTimer(collector.SnapshotMethodPrepare); timer != nil {\n\t\tdefer timer.ObserveDuration()\n\t}\n\n\tlogger := log.L.WithField(\"key\", key).WithField(\"parent\", parent)\n\n\tinfo, s, err := o.createSnapshot(ctx, snapshots.KindActive, key, parent, opts)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlogger.Debugf(\"[Prepare] snapshot with labels %v\", info.Labels)\n\n\tprocessor, target, commitLabels, err := chooseProcessor(ctx, logger, o, s, key, parent, info.Labels, func() string { return o.upperPath(s.ID) })\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tneedCommit, mounts, err := processor()\n\n\tif needCommit {\n\t\terr := o.Commit(ctx, target, key, append(opts, snapshots.WithLabels(commitLabels))...)\n\t\tif err == nil || errdefs.IsAlreadyExists(err) {\n\t\t\treturn nil, errors.Wrapf(errdefs.ErrAlreadyExists, \"target snapshot %q\", target)\n\t\t}\n\t}\n\n\treturn mounts, err\n}\n\n// The work on supporting View operation for nydus-snapshotter is divided into 2 parts:\n// 1. View on the topmost layer of nydus images or zran images\n// 2. View on the any layer of nydus images or zran images\nfunc (o *snapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {\n\tlog.L.Infof(\"[View] snapshot with key %s parent %s\", key, parent)\n\n\tpID, pInfo, _, err := snapshot.GetSnapshotInfo(ctx, o.ms, parent)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"get snapshot %s info\", parent)\n\t}\n\n\tvar (\n\t\tneedRemoteMounts = false\n\t\tmetaSnapshotID   string\n\t)\n\n\tif label.IsNydusMetaLayer(pInfo.Labels) {\n\t\t// Nydusd might not be running. We should run nydusd to reflect the rootfs.\n\t\tif err = o.fs.WaitUntilReady(pID); err != nil {\n\t\t\tif errors.Is(err, errdefs.ErrNotFound) {\n\t\t\t\tif err := o.fs.Mount(ctx, pID, pInfo.Labels, nil); err != nil {\n\t\t\t\t\treturn nil, errors.Wrapf(err, \"mount rafs, instance id %s\", pID)\n\t\t\t\t}\n\n\t\t\t\tif err := o.fs.WaitUntilReady(pID); err != nil {\n\t\t\t\t\treturn nil, errors.Wrapf(err, \"wait for instance id %s\", pID)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn nil, errors.Wrapf(err, \"daemon is not running %s\", pID)\n\t\t\t}\n\t\t}\n\n\t\tneedRemoteMounts = true\n\t\tmetaSnapshotID = pID\n\t} else if label.IsNydusDataLayer(pInfo.Labels) {\n\t\treturn nil, errors.New(\"only can view nydus topmost layer\")\n\t}\n\t// Otherwise, it is OCI snapshots\n\n\tbase, s, err := o.createSnapshot(ctx, snapshots.KindView, key, parent, opts)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif o.fs.TarfsEnabled() && label.IsTarfsDataLayer(pInfo.Labels) {\n\t\tlog.L.Infof(\"Prepare view snapshot %s in Nydus tarfs mode\", pID)\n\t\terr = o.mergeTarfs(ctx, s, pID, pInfo)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"merge tarfs layers for snapshot %s\", pID)\n\t\t}\n\t\tif err := o.fs.Mount(ctx, pID, pInfo.Labels, &s); err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"mount tarfs, snapshot id %s\", pID)\n\t\t}\n\t\tlog.L.Infof(\"Prepared view snapshot %s in Nydus tarfs mode\", pID)\n\t\tneedRemoteMounts = true\n\t\tmetaSnapshotID = pID\n\t}\n\n\tif needRemoteMounts {\n\t\treturn o.mountRemote(ctx, base.Labels, s, metaSnapshotID, key)\n\t}\n\treturn o.mountNative(ctx, base.Labels, s)\n}\n\nfunc (o *snapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) error {\n\tlog.L.Debugf(\"[Commit] snapshot with key %s\", key)\n\n\tctx, t, err := o.ms.TransactionContext(ctx, true)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tif err := t.Rollback(); err != nil {\n\t\t\t\tlog.L.WithError(err).Warn(\"failed to rollback transaction\")\n\t\t\t}\n\t\t}\n\t}()\n\n\t// grab the existing id\n\tid, _, _, err := storage.GetInfo(ctx, key)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tlog.L.Infof(\"[Commit] snapshot with key %q snapshot id %s\", key, id)\n\n\t// For OCI compatibility, we calculate disk usage of the snapshotDir and commit the usage to DB.\n\t// Nydus disk usage under the cacheDir will be delayed until containerd queries.\n\tusage, err := fs.DiskUsage(ctx, o.upperPath(id))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif _, err = storage.CommitActive(ctx, key, name, snapshots.Usage(usage), opts...); err != nil {\n\t\treturn errors.Wrapf(err, \"commit active snapshot %s\", key)\n\t}\n\n\t// Let rollback catch the commit error\n\terr = t.Commit()\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"commit snapshot %s\", key)\n\t}\n\n\treturn err\n}\n\nfunc (o *snapshotter) Remove(ctx context.Context, key string) error {\n\tlog.L.Debugf(\"[Remove] snapshot with key %s\", key)\n\tif timer := collector.NewSnapshotMetricsTimer(collector.SnapshotMethodRemove); timer != nil {\n\t\tdefer timer.ObserveDuration()\n\t}\n\tctx, t, err := o.ms.TransactionContext(ctx, true)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer func() {\n\t\tif err != nil {\n\t\t\tif err := t.Rollback(); err != nil {\n\t\t\t\tlog.G(ctx).WithError(err).Warn(\"failed to rollback transaction\")\n\t\t\t}\n\t\t}\n\t}()\n\n\tid, info, _, err := storage.GetInfo(ctx, key)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"get snapshot %s\", key)\n\t}\n\n\tswitch {\n\tcase label.IsNydusMetaLayer(info.Labels):\n\t\tlog.L.Infof(\"[Remove] nydus meta snapshot with key %s snapshot id %s\", key, id)\n\tcase label.IsNydusDataLayer(info.Labels):\n\t\tlog.L.Infof(\"[Remove] nydus data snapshot with key %s snapshot id %s\", key, id)\n\tcase label.IsTarfsDataLayer(info.Labels):\n\t\tlog.L.Infof(\"[Remove] nydus tarfs snapshot with key %s snapshot id %s\", key, id)\n\tdefault:\n\t\t// For example: remove snapshot with key sha256:c33c40022c8f333e7f199cd094bd56758bc479ceabf1e490bb75497bf47c2ebf\n\t\tlog.L.Infof(\"[Remove] snapshot with key %s snapshot id %s\", key, id)\n\t}\n\n\t_, _, err = storage.Remove(ctx, key)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to remove key %s\", key)\n\t}\n\n\tif o.syncRemove {\n\t\tvar removals []string\n\t\tremovals, err = o.getCleanupDirectories(ctx)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"get directories for removal\")\n\t\t}\n\n\t\t// Remove directories after the transaction is closed, failures must not\n\t\t// return error since the transaction is committed with the removal\n\t\t// key no longer available.\n\t\tdefer func() {\n\t\t\tif err == nil {\n\t\t\t\tfor _, dir := range removals {\n\t\t\t\t\tif err := o.cleanupSnapshotDirectory(ctx, dir); err != nil {\n\t\t\t\t\t\tlog.G(ctx).WithError(err).WithField(\"path\", dir).Warn(\"failed to remove directory\")\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}()\n\t}\n\n\treturn t.Commit()\n}\n\nfunc (o *snapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error {\n\tctx, t, err := o.ms.TransactionContext(ctx, false)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer func() {\n\t\tif err := t.Rollback(); err != nil {\n\t\t\tlog.L.WithError(err)\n\t\t}\n\t}()\n\n\treturn storage.WalkInfo(ctx, fn, fs...)\n}\n\nfunc (o *snapshotter) Close() error {\n\tlog.L.Info(\"[Close] shutdown snapshotter\")\n\n\tif o.cleanupOnClose {\n\t\terr := o.fs.Teardown(context.Background())\n\t\tif err != nil {\n\t\t\tlog.L.Errorf(\"failed to clean up remote snapshot, err %v\", err)\n\t\t}\n\t}\n\n\to.fs.TryStopSharedDaemon()\n\n\tif o.cgroupManager != nil {\n\t\tif err := o.cgroupManager.Delete(); err != nil {\n\t\t\tlog.L.Errorf(\"failed to destroy cgroup, err %v\", err)\n\t\t}\n\t}\n\n\treturn o.ms.Close()\n}\n\nfunc (o *snapshotter) upperPath(id string) string {\n\treturn filepath.Join(o.root, \"snapshots\", id, \"fs\")\n}\n\n// Get the rootdir of nydus image file system contents.\nfunc (o *snapshotter) lowerPath(id string) (mnt string, err error) {\n\tif mnt, err = o.fs.MountPoint(id); err == nil {\n\t\treturn mnt, nil\n\t} else if errors.Is(err, errdefs.ErrNotFound) {\n\t\treturn filepath.Join(o.root, \"snapshots\", id, \"fs\"), nil\n\t}\n\n\treturn \"\", err\n}\n\nfunc (o *snapshotter) workPath(id string) string {\n\treturn filepath.Join(o.root, \"snapshots\", id, \"work\")\n}\n\nfunc (o *snapshotter) findIndexAlternativeLayer(ctx context.Context, key string) (string, snapshots.Info, error) {\n\treturn snapshot.IterateParentSnapshots(ctx, o.ms, key, func(_ string, i snapshots.Info) bool {\n\t\treturn o.fs.CheckIndexAlternative(ctx, i.Labels)\n\t})\n}\n\nfunc (o *snapshotter) findReferrerLayer(ctx context.Context, key string) (string, snapshots.Info, error) {\n\treturn snapshot.IterateParentSnapshots(ctx, o.ms, key, func(_ string, info snapshots.Info) bool {\n\t\treturn o.fs.CheckReferrer(ctx, info.Labels)\n\t})\n}\n\nfunc (o *snapshotter) findMetaLayer(ctx context.Context, key string) (string, snapshots.Info, error) {\n\treturn snapshot.IterateParentSnapshots(ctx, o.ms, key, func(_ string, i snapshots.Info) bool {\n\t\treturn label.IsNydusMetaLayer(i.Labels)\n\t})\n}\n\nfunc (o *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, key, parent string, opts []snapshots.Opt) (info *snapshots.Info, _ storage.Snapshot, err error) {\n\treturn o.createSnapshotWithRecovery(ctx, kind, key, parent, opts, false)\n}\n\n// createSnapshotWithRecovery attempts to create a snapshot and recovers from\n// \"missing parent\" errors by querying containerd for the parent's metadata and\n// recreating it in the local BoltDB. This handles the desynchronization\n// scenarios where nydus-snapshotter's BoltDB is missing entries that\n// containerd knows about.\nfunc (o *snapshotter) createSnapshotWithRecovery(ctx context.Context, kind snapshots.Kind, key, parent string, opts []snapshots.Opt, isRecovery bool) (info *snapshots.Info, _ storage.Snapshot, err error) {\n\tctx, t, err := o.ms.TransactionContext(ctx, true)\n\tif err != nil {\n\t\treturn nil, storage.Snapshot{}, err\n\t}\n\trollback := true\n\tdefer func() {\n\t\tif rollback {\n\t\t\tif rerr := t.Rollback(); rerr != nil {\n\t\t\t\tlog.G(ctx).WithError(rerr).Warn(\"failed to rollback transaction\")\n\t\t\t}\n\t\t}\n\t}()\n\n\tvar base snapshots.Info\n\tfor _, opt := range opts {\n\t\tif err := opt(&base); err != nil {\n\t\t\treturn &base, storage.Snapshot{}, err\n\t\t}\n\t}\n\tif base.Labels == nil {\n\t\tbase.Labels = map[string]string{}\n\t}\n\n\tvar td, path string\n\tdefer func() {\n\t\tif td != \"\" {\n\t\t\tif err1 := o.cleanupSnapshotDirectory(ctx, td); err1 != nil {\n\t\t\t\tlog.G(ctx).WithError(err1).Warn(\"failed to clean up temp snapshot directory\")\n\t\t\t}\n\t\t}\n\t\tif path != \"\" {\n\t\t\tif err1 := o.cleanupSnapshotDirectory(ctx, path); err1 != nil {\n\t\t\t\tlog.G(ctx).WithError(err1).WithField(\"path\", path).Error(\"failed to reclaim snapshot directory, directory may need removal\")\n\t\t\t\terr = errors.Wrapf(err, \"failed to remove path: %v\", err1)\n\t\t\t}\n\t\t}\n\t}()\n\n\ttd, err = o.prepareDirectory(o.snapshotRoot(), kind)\n\tif err != nil {\n\t\treturn nil, storage.Snapshot{}, errors.Wrap(err, \"create prepare snapshot dir\")\n\t}\n\n\ts, err := storage.CreateSnapshot(ctx, kind, key, parent, opts...)\n\tif err != nil {\n\t\t// Check if this is a \"missing parent\" error and we can attempt recovery\n\t\tif !isRecovery && parent != \"\" && o.isMissingParentError(err) {\n\t\t\tlog.G(ctx).WithError(err).Warnf(\"Missing parent %q in local BoltDB, attempting lazy recovery from containerd\", parent)\n\n\t\t\t// Rollback current transaction before recovery\n\t\t\trollback = true\n\t\t\tif rerr := t.Rollback(); rerr != nil {\n\t\t\t\tlog.G(ctx).WithError(rerr).Warn(\"failed to rollback transaction before recovery\")\n\t\t\t}\n\t\t\trollback = false // Don't rollback again in defer\n\n\t\t\t// Clean up the temp directory we created\n\t\t\tif td != \"\" {\n\t\t\t\tif err1 := o.cleanupSnapshotDirectory(ctx, td); err1 != nil {\n\t\t\t\t\tlog.G(ctx).WithError(err1).Warn(\"failed to clean up temp snapshot directory during recovery\")\n\t\t\t\t}\n\t\t\t\ttd = \"\"\n\t\t\t}\n\n\t\t\t// Attempt to recover the parent\n\t\t\t// The recovery function uses a fresh context internally\n\t\t\tif recoverErr := o.recoverParentFromContainerd(ctx, parent); recoverErr != nil {\n\t\t\t\tlog.G(ctx).WithError(recoverErr).Errorf(\"Failed to recover parent %q from containerd\", parent)\n\t\t\t\treturn nil, storage.Snapshot{}, errors.Wrapf(err, \"create snapshot (recovery failed: %v)\", recoverErr)\n\t\t\t}\n\n\t\t\tlog.G(ctx).Infof(\"Successfully recovered parent %q from containerd, retrying snapshot creation\", parent)\n\t\t\t// Retry with recovery flag set to prevent infinite recursion\n\t\t\t// Use the original context for the retry\n\t\t\treturn o.createSnapshotWithRecovery(ctx, kind, key, parent, opts, true)\n\t\t}\n\t\treturn nil, storage.Snapshot{}, errors.Wrap(err, \"create snapshot\")\n\t}\n\n\t// Try to keep the whole stack having the same UID and GID\n\tif len(s.ParentIDs) > 0 {\n\t\tst, err := os.Stat(o.upperPath(s.ParentIDs[0]))\n\t\tif err != nil {\n\t\t\treturn nil, storage.Snapshot{}, errors.Wrap(err, \"stat parent\")\n\t\t}\n\n\t\tif err := lchown(filepath.Join(td, \"fs\"), st); err != nil {\n\t\t\treturn nil, storage.Snapshot{}, errors.Wrap(err, \"perform chown\")\n\t\t}\n\t}\n\n\tpath = o.snapshotDir(s.ID)\n\tif err = os.Rename(td, path); err != nil {\n\t\treturn nil, storage.Snapshot{}, errors.Wrap(err, \"perform rename\")\n\t}\n\ttd = \"\"\n\n\trollback = false\n\tif err = t.Commit(); err != nil {\n\t\treturn nil, storage.Snapshot{}, errors.Wrap(err, \"perform commit\")\n\t}\n\tpath = \"\"\n\n\treturn &base, s, nil\n}\n\n// isMissingParentError checks if the error is a \"missing parent bucket\" error\n// from the storage layer, which indicates the parent snapshot exists in containerd\n// but not in our local BoltDB.\nfunc (o *snapshotter) isMissingParentError(err error) bool {\n\tif err == nil {\n\t\treturn false\n\t}\n\terrStr := err.Error()\n\treturn strings.Contains(errStr, \"missing parent\") && strings.Contains(errStr, \"bucket\")\n}\n\n// recoverParentFromContainerd attempts to recover a missing parent snapshot.\n// This handles the desyncrhonization scenario where nydus-snapshotter's BoltDB\n// was wiped but containerd still has metadata references.\n//\n// For proxy mode (used by Kata Containers for guest image pulling), we create\n// a minimal placeholder snapshot since there's no actual filesystem data stored.\n// The real data will be pulled fresh by the guest.\nfunc (o *snapshotter) recoverParentFromContainerd(ctx context.Context, parent string) error {\n\tlog.G(ctx).Infof(\"Attempting lazy recovery for missing parent: %q\", parent)\n\n\t// For proxy mode (Kata guest pulling), create a minimal placeholder\n\t// since there's no actual filesystem content to restore\n\tfsDriver := config.GetFsDriver()\n\tif fsDriver == config.FsDriverProxy {\n\t\tlog.G(ctx).Infof(\"Proxy mode detected - creating placeholder snapshot for %q\", parent)\n\t\t// Use the full parent key as-is since the storage layer uses this exact key\n\t\treturn o.createPlaceholderSnapshot(ctx, parent)\n\t}\n\n\t// For other modes (fusedev, fscache), we would need the actual parent metadata\n\t// from containerd. Unfortunately, containerd's snapshot service for remote\n\t// snapshotters calls back to us, creating a circular dependency when our DB is empty.\n\treturn errors.Errorf(\n\t\t\"lazy parent recovery not supported for fs_driver=%q. \"+\n\t\t\t\"Please clean up containerd's stale snapshot references with: \"+\n\t\t\t\"ctr snapshot --snapshotter nydus rm %s\",\n\t\tfsDriver, parent)\n}\n\n// createPlaceholderSnapshot creates a minimal committed snapshot entry in the local\n// BoltDB for recovery purposes. This is used in proxy mode where no actual filesystem\n// content is stored locally.\nfunc (o *snapshotter) createPlaceholderSnapshot(ctx context.Context, key string) error {\n\t// Use a fresh context to avoid any transaction context pollution\n\tcleanCtx := context.Background()\n\n\t// First check if the snapshot already exists (from a previous partial recovery)\n\t// nolint:dogsled\n\t_, _, _, existErr := snapshot.GetSnapshotInfo(cleanCtx, o.ms, key)\n\tif existErr == nil {\n\t\tlog.G(ctx).Infof(\"Placeholder snapshot %q already exists, skipping creation\", key)\n\t\treturn nil\n\t}\n\n\ttxCtx, t, err := o.ms.TransactionContext(cleanCtx, true)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"begin transaction for placeholder snapshot\")\n\t}\n\trollback := true\n\tdefer func() {\n\t\tif rollback {\n\t\t\tif rerr := t.Rollback(); rerr != nil {\n\t\t\t\tlog.G(ctx).WithError(rerr).Warn(\"failed to rollback placeholder transaction\")\n\t\t\t}\n\t\t}\n\t}()\n\n\t// Prepare the snapshot directory\n\ttd, err := o.prepareDirectory(o.snapshotRoot(), snapshots.KindCommitted)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"prepare directory for placeholder snapshot\")\n\t}\n\n\t// Create a placeholder with minimal labels indicating it was recovered\n\topts := []snapshots.Opt{\n\t\tsnapshots.WithLabels(map[string]string{\n\t\t\t\"nydus.recovered\":    \"true\",\n\t\t\t\"nydus.recovered.at\": fmt.Sprintf(\"%d\", time.Now().Unix()),\n\t\t}),\n\t}\n\n\t// Create as active first (no parent)\n\t// Use a unique key to avoid conflicts with retries\n\tactiveKey := fmt.Sprintf(\"recovery-%d-%s\", time.Now().UnixNano(), key)\n\ts, err := storage.CreateSnapshot(txCtx, snapshots.KindActive, activeKey, \"\", opts...)\n\tif err != nil {\n\t\tif err1 := o.cleanupSnapshotDirectory(cleanCtx, td); err1 != nil {\n\t\t\tlog.G(ctx).WithError(err1).Warn(\"failed to clean up temp directory\")\n\t\t}\n\t\treturn errors.Wrapf(err, \"create placeholder snapshot entry for %q\", key)\n\t}\n\n\t// Move temp directory to final location\n\tpath := o.snapshotDir(s.ID)\n\tif err = os.Rename(td, path); err != nil {\n\t\treturn errors.Wrap(err, \"rename placeholder snapshot directory\")\n\t}\n\n\t// Commit the active snapshot to create the final committed snapshot\n\t// CommitActive(ctx, key, name) commits active snapshot `key` as committed snapshot `name`\n\tif _, err := storage.CommitActive(txCtx, activeKey, key, snapshots.Usage{}, opts...); err != nil {\n\t\tif err1 := o.cleanupSnapshotDirectory(cleanCtx, path); err1 != nil {\n\t\t\tlog.G(ctx).WithError(err1).Warn(\"failed to clean up snapshot directory\")\n\t\t}\n\t\treturn errors.Wrapf(err, \"commit placeholder snapshot %q\", key)\n\t}\n\n\trollback = false\n\tif err = t.Commit(); err != nil {\n\t\treturn errors.Wrap(err, \"commit placeholder transaction\")\n\t}\n\n\tlog.G(ctx).Infof(\"Successfully created placeholder snapshot %q for lazy recovery\", key)\n\treturn nil\n}\n\nfunc (o *snapshotter) mergeTarfs(ctx context.Context, s storage.Snapshot, pID string, pInfo snapshots.Info) error {\n\tif err := o.fs.MergeTarfsLayers(s, func(id string) string { return o.upperPath(id) }); err != nil {\n\t\treturn errors.Wrapf(err, \"tarfs merge fail %s\", pID)\n\t}\n\tif config.GetTarfsExportEnabled() {\n\t\tupdateFields, err := o.fs.ExportBlockData(s, false, pInfo.Labels, func(id string) string { return o.upperPath(id) })\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"export tarfs as block image\")\n\t\t}\n\t\tif len(updateFields) > 0 {\n\t\t\t_, err = o.Update(ctx, pInfo, updateFields...)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"update snapshot label information\")\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc bindMount(source, roFlag string) []mount.Mount {\n\treturn []mount.Mount{\n\t\t{\n\t\t\tType:   \"bind\",\n\t\t\tSource: source,\n\t\t\tOptions: []string{\n\t\t\t\troFlag,\n\t\t\t\t\"rbind\",\n\t\t\t},\n\t\t},\n\t}\n}\n\nfunc overlayMount(options []string) []mount.Mount {\n\treturn []mount.Mount{\n\t\t{\n\t\t\tType:    \"overlay\",\n\t\t\tSource:  \"overlay\",\n\t\t\tOptions: options,\n\t\t},\n\t}\n}\n\n// Handle proxy mount which the snapshot has been prepared by other snapshotter, mainly used for pause image in containerd\nfunc (o *snapshotter) mountProxy(ctx context.Context, s storage.Snapshot) ([]mount.Mount, error) {\n\tvar overlayOptions []string\n\tif s.Kind == snapshots.KindActive {\n\t\toverlayOptions = append(overlayOptions,\n\t\t\tfmt.Sprintf(\"workdir=%s\", o.workPath(s.ID)),\n\t\t\tfmt.Sprintf(\"upperdir=%s\", o.upperPath(s.ID)),\n\t\t)\n\t}\n\n\tlog.G(ctx).Debugf(\"len(s.ParentIDs) = %v\", len(s.ParentIDs))\n\tparentPaths := make([]string, 0, len(s.ParentIDs)+1)\n\tif len(s.ParentIDs) == 0 {\n\t\tparentPaths = append(parentPaths, config.GetSnapshotsRootDir())\n\t} else {\n\t\tfor _, id := range s.ParentIDs {\n\t\t\tparentPaths = append(parentPaths, o.upperPath(id))\n\t\t}\n\t}\n\n\tlowerDirOption := fmt.Sprintf(\"lowerdir=%s\", strings.Join(parentPaths, \":\"))\n\toverlayOptions = append(overlayOptions, lowerDirOption)\n\tlog.G(ctx).Infof(\"proxy mount options %v\", overlayOptions)\n\toptions, err := o.mountWithProxyVolume(rafs.Rafs{\n\t\tFsDriver:    config.GetFsDriver(),\n\t\tAnnotations: make(map[string]string),\n\t})\n\tif err != nil {\n\t\treturn []mount.Mount{}, errors.Wrapf(err, \"create kata volume for proxy\")\n\t}\n\tif len(options) > 0 {\n\t\toverlayOptions = append(overlayOptions, options...)\n\t}\n\tlog.G(ctx).Debugf(\"fuse.nydus-overlayfs mount options %v\", overlayOptions)\n\n\tmountType := \"fuse.nydus-overlayfs\"\n\tif o.nydusOverlayFSPath != \"\" {\n\t\tlog.G(ctx).Debugf(\"Using nydus-overlayfs from path: %s\", o.nydusOverlayFSPath)\n\t\tmountType = fmt.Sprintf(\"fuse.%s\", o.nydusOverlayFSPath)\n\t}\n\n\tmounts := []mount.Mount{\n\t\t{\n\t\t\tType:    mountType,\n\t\t\tSource:  \"overlay\",\n\t\t\tOptions: overlayOptions,\n\t\t},\n\t}\n\treturn mounts, nil\n}\n\n// `s` is the upmost snapshot and `id` refers to the nydus meta snapshot\n// `s` and `id` can represent a different layer, it's useful when View an image\nfunc (o *snapshotter) mountRemote(ctx context.Context, labels map[string]string, s storage.Snapshot, id, key string) ([]mount.Mount, error) {\n\tvar overlayOptions []string\n\tif _, ok := labels[label.OverlayfsVolatileOpt]; ok || o.enableOverlayfsVolatile {\n\t\toverlayOptions = append(overlayOptions, \"volatile\")\n\t}\n\n\tlowerPaths := make([]string, 0, 8)\n\tif o.fs.ReferrerDetectEnabled() || o.fs.IndexDetectEnabled() {\n\t\t// From the parent list, we want to add all the layers\n\t\t// between the upmost snapshot and the nydus meta snapshot.\n\t\t// On the other hand, we consider that all the layers below\n\t\t// the nydus meta snapshot will be included in its mount.\n\t\tfor i := range s.ParentIDs {\n\t\t\tif s.ParentIDs[i] == id {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tlowerPaths = append(lowerPaths, o.upperPath(s.ParentIDs[i]))\n\t\t}\n\t}\n\n\tlowerPathNydus, err := o.lowerPath(id)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to locate overlay lowerdir\")\n\t}\n\tlowerPaths = append(lowerPaths, lowerPathNydus)\n\n\tswitch s.Kind {\n\tcase snapshots.KindActive:\n\t\toverlayOptions = append(overlayOptions,\n\t\t\tfmt.Sprintf(\"workdir=%s\", o.workPath(s.ID)),\n\t\t\tfmt.Sprintf(\"upperdir=%s\", o.upperPath(s.ID)),\n\t\t)\n\tcase snapshots.KindView:\n\t\tlowerPathNormal, err := o.lowerPath(s.ID)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"failed to locate overlay lowerdir for view snapshot\")\n\t\t}\n\t\tlowerPaths = append(lowerPaths, lowerPathNormal)\n\tdefault:\n\t\t// KindUnknown or KindCommitted - no additional options needed\n\t}\n\n\tlowerDirOption := fmt.Sprintf(\"lowerdir=%s\", strings.Join(lowerPaths, \":\"))\n\toverlayOptions = append(overlayOptions, lowerDirOption)\n\tlog.G(ctx).Infof(\"remote mount options %v\", overlayOptions)\n\n\tif o.enableKataVolume {\n\t\treturn o.mountWithKataVolume(ctx, id, overlayOptions, key)\n\t}\n\t// Add `extraoption` if NydusOverlayFS is enable or daemonMode is `None`\n\tif o.enableNydusOverlayFS || config.GetDaemonMode() == config.DaemonModeNone {\n\t\treturn o.remoteMountWithExtraOptions(ctx, s, id, overlayOptions)\n\t}\n\treturn overlayMount(overlayOptions), nil\n}\n\nfunc (o *snapshotter) mountNative(ctx context.Context, labels map[string]string, s storage.Snapshot) ([]mount.Mount, error) {\n\tif len(s.ParentIDs) == 0 {\n\t\t// if we only have one layer/no parents then just return a bind mount as overlay will not work\n\t\troFlag := \"rw\"\n\t\tif s.Kind == snapshots.KindView {\n\t\t\troFlag = \"ro\"\n\t\t}\n\t\treturn bindMount(o.upperPath(s.ID), roFlag), nil\n\t}\n\n\tvar options []string\n\tif s.Kind == snapshots.KindActive {\n\t\toptions = append(options,\n\t\t\tfmt.Sprintf(\"workdir=%s\", o.workPath(s.ID)),\n\t\t\tfmt.Sprintf(\"upperdir=%s\", o.upperPath(s.ID)),\n\t\t)\n\t\tif _, ok := labels[label.OverlayfsVolatileOpt]; ok || o.enableOverlayfsVolatile {\n\t\t\toptions = append(options, \"volatile\")\n\t\t}\n\t} else if len(s.ParentIDs) == 1 {\n\t\tparentPath := o.upperPath(s.ParentIDs[0])\n\t\t// if we only have one parent then just return a bind mount\n\t\tlog.G(ctx).Debugf(\"bind mount on %s\", parentPath)\n\t\treturn bindMount(parentPath, \"ro\"), nil\n\t}\n\n\tparentPaths := make([]string, len(s.ParentIDs))\n\tfor i := range s.ParentIDs {\n\t\tparentPaths[i] = o.upperPath(s.ParentIDs[i])\n\t}\n\toptions = append(options, fmt.Sprintf(\"lowerdir=%s\", strings.Join(parentPaths, \":\")))\n\n\tlog.G(ctx).Debugf(\"overlayfs mount options %s\", options)\n\treturn overlayMount(options), nil\n}\n\nfunc (o *snapshotter) prepareDirectory(snapshotDir string, kind snapshots.Kind) (string, error) {\n\ttd, err := os.MkdirTemp(snapshotDir, \"new-\")\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to create temp dir\")\n\t}\n\n\tif err := os.Mkdir(filepath.Join(td, \"fs\"), 0755); err != nil {\n\t\treturn td, err\n\t}\n\n\tif kind == snapshots.KindActive {\n\t\tif err := os.Mkdir(filepath.Join(td, \"work\"), 0711); err != nil {\n\t\t\treturn td, err\n\t\t}\n\t}\n\n\treturn td, nil\n}\n\nfunc (o *snapshotter) getCleanupDirectories(ctx context.Context) ([]string, error) {\n\tids, err := storage.IDMap(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// For example:\n\t// 23:default/24/sha256:8c2ed532dce363da2d08489f385c432f7c0ee4509ab4e20eb2778803916adc93\n\t// 24:sha256:c858413d9e5162c287028d630128ea4323d5029bf8a093af783480b38cf8d44e\n\t// 25:sha256:fcb51e3c865d96542718beba0bb247376e4c78e039412c5d30c989872e66b6d5\n\n\tfd, err := os.Open(o.snapshotRoot())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer fd.Close()\n\n\tdirs, err := fd.Readdirnames(0)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcleanup := make([]string, 0, 16)\n\tfor _, d := range dirs {\n\t\tif _, ok := ids[d]; ok {\n\t\t\tcontinue\n\t\t}\n\t\t// When it quits, there will be nothing inside\n\t\t// TODO: try to clean up config/sockets/logs directories\n\t\tcleanup = append(cleanup, o.snapshotDir(d))\n\t}\n\treturn cleanup, nil\n}\n\nfunc (o *snapshotter) cleanupDirectories(ctx context.Context) ([]string, error) {\n\t// Get a write transaction to ensure no other write transaction can be entered\n\t// while the cleanup is scanning.\n\tctx, t, err := o.ms.TransactionContext(ctx, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdefer func() {\n\t\tif err := t.Rollback(); err != nil {\n\t\t\tlog.L.WithError(err)\n\t\t}\n\t}()\n\n\treturn o.getCleanupDirectories(ctx)\n}\n\nfunc (o *snapshotter) cleanupSnapshotDirectory(ctx context.Context, dir string) error {\n\t// For example: cleanupSnapshotDirectory /var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/34\" dir=/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/34\n\n\tsnapshotID := filepath.Base(dir)\n\tif err := o.fs.Umount(ctx, snapshotID); err != nil && !os.IsNotExist(err) {\n\t\tlog.G(ctx).WithError(err).WithField(\"dir\", dir).Error(\"failed to unmount\")\n\t}\n\n\tif o.fs.TarfsEnabled() {\n\t\tif err := o.fs.DetachTarfsLayer(snapshotID); err != nil && !os.IsNotExist(err) {\n\t\t\tlog.G(ctx).WithError(err).Errorf(\"failed to detach tarfs layer for snapshot %s\", snapshotID)\n\t\t}\n\t}\n\n\tif err := os.RemoveAll(dir); err != nil {\n\t\treturn errors.Wrapf(err, \"remove directory %q\", dir)\n\t}\n\n\treturn nil\n}\n\nfunc (o *snapshotter) getUnusedCacheBlobs(ctx context.Context) ([]string, error) {\n\t// Get a write transaction to ensure no other write transaction can be entered\n\t// while the cleanup is scanning.\n\t_, t, err := o.ms.TransactionContext(ctx, true)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdefer func() {\n\t\tif err := t.Rollback(); err != nil {\n\t\t\tlog.L.WithError(err)\n\t\t}\n\t}()\n\n\t// Collect all used blob IDs from all daemons\n\tusedBlobIDs := make(map[string]bool)\n\tif err := o.fs.WalkManagers(func(mgr *mgr.Manager) error {\n\t\tfor _, d := range mgr.ListDaemons() {\n\t\t\t// Get all rafs instances for this daemon\n\t\t\tfor _, rafs := range d.RafsCache.List() {\n\t\t\t\t// Extract blob IDs from underlying files and mark as used\n\t\t\t\tfor _, filePath := range rafs.UnderlyingFiles {\n\t\t\t\t\t// Extract blob ID from the file path\n\t\t\t\t\tfilename := filepath.Base(filePath)\n\t\t\t\t\tblobID := cache.ExtractBlobIDFromFilename(filename)\n\t\t\t\t\tif blobID != \"\" {\n\t\t\t\t\t\tusedBlobIDs[blobID] = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}); err != nil {\n\t\treturn nil, errors.Wrap(err, \"walk managers to collect used blobs\")\n\t}\n\n\tlog.L.Debugf(\"[getUnusedCacheBlobs] found %d used blob IDs\", len(usedBlobIDs))\n\n\t// Update metrics for blobs in use\n\tdata.CacheBlobsInUse.Set(float64(len(usedBlobIDs)))\n\n\tcacheDir, err := o.fs.GetCacheDir()\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"get cache directory\")\n\t}\n\n\t// List all files in cache directory\n\tentries, err := os.ReadDir(cacheDir)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"read cache directory %s\", cacheDir)\n\t}\n\n\t// Track which blob IDs we've already processed to avoid duplicate RemoveCache calls\n\tstoredBlobIDs := map[string]interface{}{}\n\tfor _, entry := range entries {\n\t\tif entry.IsDir() {\n\t\t\tcontinue\n\t\t}\n\n\t\tblobID := cache.ExtractBlobIDFromFilename(entry.Name())\n\t\tif blobID == \"\" {\n\t\t\tlog.L.Debugf(\"[getUnusedCacheBlobs] skipping file with unknown format: %s\", entry.Name())\n\t\t\tcontinue\n\t\t}\n\n\t\tstoredBlobIDs[blobID] = nil\n\t}\n\tlog.L.Debugf(\"[getUnusedCacheBlobs] found %d stored blob IDs\", len(storedBlobIDs))\n\n\tvar unusedBlobIDs []string\n\tfor blobID := range storedBlobIDs {\n\t\tif _, ok := usedBlobIDs[blobID]; !ok {\n\t\t\tunusedBlobIDs = append(unusedBlobIDs, blobID)\n\t\t}\n\t}\n\n\treturn unusedBlobIDs, nil\n}\n\nfunc (o *snapshotter) snapshotRoot() string {\n\treturn filepath.Join(o.root, \"snapshots\")\n}\n\nfunc (o *snapshotter) snapshotDir(id string) string {\n\treturn filepath.Join(o.snapshotRoot(), id)\n}\n\nfunc treatAsProxyDriver(labels map[string]string) bool {\n\tisProxyDriver := config.GetFsDriver() == config.FsDriverProxy\n\tisProxyLabel := label.IsNydusProxyMode(labels)\n\t_, isProxyImage := labels[label.CRIImageRef]\n\tlog.G(context.Background()).Debugf(\"isProxyDriver = %t, isProxyLabel = %t, isProxyImage = %t\", isProxyDriver, isProxyLabel, isProxyImage)\n\tswitch {\n\tcase isProxyDriver && isProxyImage:\n\t\treturn false\n\tcase isProxyDriver != isProxyLabel:\n\t\tlog.G(context.Background()).Warnf(\"check Labels With Driver failed, driver = %q, labels = %q\", config.GetFsDriver(), labels)\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n"
  },
  {
    "path": "snapshot/snapshot_test.go",
    "content": "/*\n * Copyright (c) 2025. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage snapshot\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/containerd/containerd/v2/core/mount\"\n\t\"github.com/containerd/containerd/v2/core/snapshots\"\n\t\"github.com/containerd/containerd/v2/core/snapshots/storage\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/label\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestMountNative(t *testing.T) {\n\t// Create a minimal snapshotter instance for testing\n\tsnapshotterRoot := \"/var/lib/containerd/snapshotter\"\n\ts := &snapshotter{\n\t\troot: snapshotterRoot,\n\t}\n\n\ttests := []struct {\n\t\tname           string\n\t\tsnapshot       storage.Snapshot\n\t\tlabels         map[string]string\n\t\texpectedMounts []mount.Mount\n\n\t\tvalidate func(t *testing.T, mounts []mount.Mount, s *snapshotter)\n\t}{\n\t\t{\n\t\t\tname: \"no parents, active snapshot - rw bind mount\",\n\t\t\tsnapshot: storage.Snapshot{\n\t\t\t\tID:        \"snap1\",\n\t\t\t\tKind:      snapshots.KindActive,\n\t\t\t\tParentIDs: []string{},\n\t\t\t},\n\t\t\texpectedMounts: []mount.Mount{\n\t\t\t\t{\n\t\t\t\t\tType:   \"bind\",\n\t\t\t\t\tSource: s.upperPath(\"snap1\"),\n\t\t\t\t\tOptions: []string{\n\t\t\t\t\t\t\"rw\",\n\t\t\t\t\t\t\"rbind\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"no parents, view snapshot - ro bind mount\",\n\t\t\tsnapshot: storage.Snapshot{\n\t\t\t\tID:        \"snap2\",\n\t\t\t\tKind:      snapshots.KindView,\n\t\t\t\tParentIDs: []string{},\n\t\t\t},\n\t\t\texpectedMounts: []mount.Mount{\n\t\t\t\t{\n\t\t\t\t\tType:   \"bind\",\n\t\t\t\t\tSource: s.upperPath(\"snap2\"),\n\t\t\t\t\tOptions: []string{\n\t\t\t\t\t\t\"ro\",\n\t\t\t\t\t\t\"rbind\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"one parent, committed snapshot - ro bind mount of parent\",\n\t\t\tsnapshot: storage.Snapshot{\n\t\t\t\tID:        \"snap3\",\n\t\t\t\tKind:      snapshots.KindCommitted,\n\t\t\t\tParentIDs: []string{\"parent1\"},\n\t\t\t},\n\t\t\texpectedMounts: []mount.Mount{\n\t\t\t\t{\n\t\t\t\t\tType:   \"bind\",\n\t\t\t\t\tSource: s.upperPath(\"parent1\"),\n\t\t\t\t\tOptions: []string{\n\t\t\t\t\t\t\"ro\",\n\t\t\t\t\t\t\"rbind\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"one parent, view snapshot - ro bind mount of parent\",\n\t\t\tsnapshot: storage.Snapshot{\n\t\t\t\tID:        \"snap4\",\n\t\t\t\tKind:      snapshots.KindView,\n\t\t\t\tParentIDs: []string{\"parent1\"},\n\t\t\t},\n\t\t\texpectedMounts: []mount.Mount{\n\t\t\t\t{\n\t\t\t\t\tType:   \"bind\",\n\t\t\t\t\tSource: s.upperPath(\"parent1\"),\n\t\t\t\t\tOptions: []string{\n\t\t\t\t\t\t\"ro\",\n\t\t\t\t\t\t\"rbind\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"multiple parents, active snapshot - overlay with work and upper dirs\",\n\t\t\tsnapshot: storage.Snapshot{\n\t\t\t\tID:        \"snap5\",\n\t\t\t\tKind:      snapshots.KindActive,\n\t\t\t\tParentIDs: []string{\"parent1\", \"parent2\"},\n\t\t\t},\n\t\t\texpectedMounts: []mount.Mount{\n\t\t\t\t{\n\t\t\t\t\tType:   \"overlay\",\n\t\t\t\t\tSource: \"overlay\",\n\t\t\t\t\tOptions: []string{\n\t\t\t\t\t\tfmt.Sprintf(\"workdir=%s\", s.workPath(\"snap5\")),\n\t\t\t\t\t\tfmt.Sprintf(\"upperdir=%s\", s.upperPath(\"snap5\")),\n\t\t\t\t\t\tfmt.Sprintf(\"lowerdir=%s:%s\", s.upperPath(\"parent1\"), s.upperPath(\"parent2\")),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"multiple parents, active snapshot with volatile option\",\n\t\t\tsnapshot: storage.Snapshot{\n\t\t\t\tID:        \"snap6\",\n\t\t\t\tKind:      snapshots.KindActive,\n\t\t\t\tParentIDs: []string{\"parent1\", \"parent2\"},\n\t\t\t},\n\t\t\tlabels: map[string]string{\n\t\t\t\tlabel.OverlayfsVolatileOpt: \"true\",\n\t\t\t},\n\t\t\texpectedMounts: []mount.Mount{\n\t\t\t\t{\n\t\t\t\t\tType:   \"overlay\",\n\t\t\t\t\tSource: \"overlay\",\n\t\t\t\t\tOptions: []string{\n\t\t\t\t\t\tfmt.Sprintf(\"workdir=%s\", s.workPath(\"snap6\")),\n\t\t\t\t\t\tfmt.Sprintf(\"upperdir=%s\", s.upperPath(\"snap6\")),\n\t\t\t\t\t\tfmt.Sprintf(\"lowerdir=%s:%s\", s.upperPath(\"parent1\"), s.upperPath(\"parent2\")),\n\t\t\t\t\t\t\"volatile\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"multiple parents, committed snapshot - overlay with only lowerdir\",\n\t\t\tsnapshot: storage.Snapshot{\n\t\t\t\tID:        \"snap7\",\n\t\t\t\tKind:      snapshots.KindCommitted,\n\t\t\t\tParentIDs: []string{\"parent1\", \"parent2\", \"parent3\"},\n\t\t\t},\n\t\t\texpectedMounts: []mount.Mount{\n\t\t\t\t{\n\t\t\t\t\tType:   \"overlay\",\n\t\t\t\t\tSource: \"overlay\",\n\t\t\t\t\tOptions: []string{\n\t\t\t\t\t\tfmt.Sprintf(\"lowerdir=%s:%s:%s\", s.upperPath(\"parent1\"), s.upperPath(\"parent2\"), s.upperPath(\"parent3\")),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"multiple parents, view snapshot - overlay with only lowerdir\",\n\t\t\tsnapshot: storage.Snapshot{\n\t\t\t\tID:        \"snap8\",\n\t\t\t\tKind:      snapshots.KindView,\n\t\t\t\tParentIDs: []string{\"parent1\", \"parent2\"},\n\t\t\t},\n\t\t\texpectedMounts: []mount.Mount{\n\t\t\t\t{\n\t\t\t\t\tType:   \"overlay\",\n\t\t\t\t\tSource: \"overlay\",\n\t\t\t\t\tOptions: []string{\n\t\t\t\t\t\tfmt.Sprintf(\"lowerdir=%s:%s\", s.upperPath(\"parent1\"), s.upperPath(\"parent2\")),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"no parents, committed snapshot - rw bind mount\",\n\t\t\tsnapshot: storage.Snapshot{\n\t\t\t\tID:        \"snap9\",\n\t\t\t\tKind:      snapshots.KindCommitted,\n\t\t\t\tParentIDs: []string{},\n\t\t\t},\n\t\t\texpectedMounts: []mount.Mount{\n\t\t\t\t{\n\t\t\t\t\tType:   \"bind\",\n\t\t\t\t\tSource: filepath.Join(s.root, \"snapshots\", \"snap9\", \"fs\"),\n\t\t\t\t\tOptions: []string{\n\t\t\t\t\t\t\"rw\",\n\t\t\t\t\t\t\"rbind\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tt.Run(tt.name, func(t *testing.T) {\n\t\t\tctx := context.Background()\n\n\t\t\t// Call the mountNative function\n\t\t\tmounts, err := s.mountNative(ctx, tt.labels, tt.snapshot)\n\n\t\t\t// Verify no error occurred\n\t\t\trequire.NoError(t, err)\n\n\t\t\t// Verify expected number of mounts\n\t\t\trequire.Len(t, mounts, len(tt.expectedMounts))\n\t\t\tfor i, expectedMount := range tt.expectedMounts {\n\t\t\t\t// Verify expected mount\n\t\t\t\tassert.Equal(t, expectedMount.Type, mounts[i].Type)\n\t\t\t\tassert.Equal(t, expectedMount.Source, mounts[i].Source)\n\t\t\t\tassert.ElementsMatch(t, expectedMount.Options, mounts[i].Options)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc TestMountNativeConfigVolatile(t *testing.T) {\n\tsnapshotterRoot := \"/var/lib/containerd/snapshotter\"\n\ts := &snapshotter{\n\t\troot:                    snapshotterRoot,\n\t\tenableOverlayfsVolatile: true,\n\t}\n\n\tctx := context.Background()\n\n\tt.Run(\"active snapshot gets volatile from config\", func(t *testing.T) {\n\t\tsnap := storage.Snapshot{\n\t\t\tID:        \"snap1\",\n\t\t\tKind:      snapshots.KindActive,\n\t\t\tParentIDs: []string{\"parent1\", \"parent2\"},\n\t\t}\n\t\tmounts, err := s.mountNative(ctx, nil, snap)\n\t\trequire.NoError(t, err)\n\t\trequire.Len(t, mounts, 1)\n\t\tassert.Contains(t, mounts[0].Options, \"volatile\")\n\t})\n\n\tt.Run(\"view snapshot does not get volatile from config\", func(t *testing.T) {\n\t\tsnap := storage.Snapshot{\n\t\t\tID:        \"snap2\",\n\t\t\tKind:      snapshots.KindView,\n\t\t\tParentIDs: []string{\"parent1\", \"parent2\"},\n\t\t}\n\t\tmounts, err := s.mountNative(ctx, nil, snap)\n\t\trequire.NoError(t, err)\n\t\trequire.Len(t, mounts, 1)\n\t\tassert.NotContains(t, mounts[0].Options, \"volatile\")\n\t})\n\n\tt.Run(\"committed snapshot does not get volatile from config\", func(t *testing.T) {\n\t\tsnap := storage.Snapshot{\n\t\t\tID:        \"snap3\",\n\t\t\tKind:      snapshots.KindCommitted,\n\t\t\tParentIDs: []string{\"parent1\", \"parent2\"},\n\t\t}\n\t\tmounts, err := s.mountNative(ctx, nil, snap)\n\t\trequire.NoError(t, err)\n\t\trequire.Len(t, mounts, 1)\n\t\tassert.NotContains(t, mounts[0].Options, \"volatile\")\n\t})\n}\n"
  },
  {
    "path": "snapshot/utils.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage snapshot\n\nimport (\n\t\"os\"\n\t\"syscall\"\n\n\t\"github.com/containerd/continuity/fs\"\n)\n\nfunc getSupportsDType(dir string) (bool, error) {\n\treturn fs.SupportsDType(dir)\n}\n\nfunc lchown(target string, st os.FileInfo) error {\n\tstat := st.Sys().(*syscall.Stat_t)\n\treturn os.Lchown(target, int(stat.Uid), int(stat.Gid))\n}\n"
  },
  {
    "path": "tests/converter_test.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage tests\n\nimport (\n\t\"archive/tar\"\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"context\"\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/user\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/aws/aws-sdk-go-v2/aws\"\n\tawscfg \"github.com/aws/aws-sdk-go-v2/config\"\n\t\"github.com/aws/aws-sdk-go-v2/credentials\"\n\t\"github.com/aws/aws-sdk-go-v2/service/s3\"\n\tcontainerd \"github.com/containerd/containerd/v2/client\"\n\t\"github.com/containerd/containerd/v2/core/content\"\n\t\"github.com/containerd/containerd/v2/pkg/namespaces\"\n\t\"github.com/containerd/containerd/v2/plugins/content/local\"\n\t\"github.com/containerd/log\"\n\t\"github.com/containerd/platforms\"\n\t\"github.com/opencontainers/go-digest\"\n\t\"github.com/sirupsen/logrus\"\n\t\"github.com/stretchr/testify/require\"\n\n\tcontainerdConverter \"github.com/containerd/containerd/v2/core/images/converter\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/backend\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/converter\"\n\t\"github.com/containerd/nydus-snapshotter/pkg/encryption\"\n\tocispec \"github.com/opencontainers/image-spec/specs-go/v1\"\n)\n\nconst envNydusdPath = \"NYDUS_NYDUSD\"\n\nvar (\n\tprivateKey = []byte(`-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAw8mbbvEiQ6BSfsjSq8XEz9ZOS5lOzI2Up3zXlKU9mZN/JBc2\n0TGQp0SnSCXYHmzJ9UrXqX2MDU2UFsQpVF0vTrvj+PURYHO5K2NIo8Dqj9uUTq5q\nylwYLWWcuUQPLHeShOWDOeiVycaSP2dnSKwZOyhiQc/TvRXZ5oooFBHzMOrKhACv\nZOfVxYNrrhwdsIX5+TRL8isxT4y8bkdzhY0R4J6z3aVhOAQhrp7fKtNtEA1edkIE\nVd+F7k72qdTCSCNAhjy1Dyom3A9Yii2wNafcEtEr8D3dgnQMnkgpDhPCqLeeecmX\nn2BmELmBOW9Nio/tR8dc/wpW3OqB5ycmgnGu+QIDAQABAoIBAQCaAJUQmP/Yrdz1\n+UUs9C0xRmLjuD1xTNRnQh3YwHlJuelCHDh0KEaeK7RhXdM3a18YYLxuh2CIfkND\n/Rx9TacOiWByzWHTunMmm7vhgrd+XLu1gCBj+DjUTJ8QY2aEFbHccyPbgwV/Z4BV\n+yIU2bom/Eb9eVoV24BAhN+tmcju6f6PtGDQciV3QJqnzn+YUpl+e1+qjs1UnvSH\nfYRDWdoKIeBr9C4NYMh9qMxuduKErld+01aJvthSdxC6E2GKyQNj726IZm5cYQPL\ntbGc+Om+tR3mI3uK1MJZ00yoThuG216SB2hFqGCqgW4gpXpWGZVyGlh/JiQDDuSL\nsSFiLqYBAoGBAPXUgX+eIOfwh88tUy+VNKkAQvazv/KF+/eosU2aazJQBxvLRIWL\nqm1pjEU0ZzUP3a2rEsnZxHh2SYERGGJQVBVUlITQSaeW+XbEZbGCh5x9dTnY0hvc\nBjRLOk8jGYxAVtvXl88zfhS+c8jNM5M0ECRCP/yFkGE99DzWhXLf/D4ZAoGBAMvj\nHoZZvNaku3ruNgmI/Kp3Gx3aUiMwXIKXjQ0xc3f0A1Ccc5SAgYXLmLvqB+ZNJ+Sd\nFd/87Zpb8kEy+JC5UE4ZwZo2SnL1wDyMZWRw3cTsf8mhvQ1kCpj5fPWUrGzUs/bh\nImL6w5sh5IB3BYN5nAtZiRyrqQCHxqW2HK+EJVPhAoGAXLevuABeDNzNfDhuHY46\n9Fri5sVY6hHavMflR42sTKeeZr89stjAiM+8VgWzv3GifHP/fB4kWgLTKljWR45g\niEMEWStt/EWXBVKBwHeoyj8PTagXZuaPeH2/GkX0xs8lc3lXCpEzRoOmi9/JSgXi\n6KoMFCQUFnkVezS11GPicVECgYEAhacXrniK+qW4JIidMbjz8IbtZq9kIp8kNZNF\nKn3dNKfnuGMmvRVUUrG5KI3sqcKwQQPcgB1cYFCfyK+yE6T3CIuHxyCJwzxnzQk3\nuhTmu51Q04tL08hdzhPWH2JbeWghpNfGY94AdeRM1w2utpX0fdgusnWw7qESzjRI\nL6JPmeECgYBUkLNcEyrNMc90tk5jdQqCQb/frT6K5k04LjvXe+TlJPHBO3XJun0H\nOYrCC8EcKknH6jkHejHUdDTG/XjHvohzKI43xg61touKtgFOVpoq79vUBRVOuH85\n6vNEksKyKXUKYya19LJS/EpfC2uHUENPSmq/Bh7TDb4y70JWnGTVWA==\n-----END RSA PRIVATE KEY-----`)\n\n\tpublicKey = []byte(`-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw8mbbvEiQ6BSfsjSq8XE\nz9ZOS5lOzI2Up3zXlKU9mZN/JBc20TGQp0SnSCXYHmzJ9UrXqX2MDU2UFsQpVF0v\nTrvj+PURYHO5K2NIo8Dqj9uUTq5qylwYLWWcuUQPLHeShOWDOeiVycaSP2dnSKwZ\nOyhiQc/TvRXZ5oooFBHzMOrKhACvZOfVxYNrrhwdsIX5+TRL8isxT4y8bkdzhY0R\n4J6z3aVhOAQhrp7fKtNtEA1edkIEVd+F7k72qdTCSCNAhjy1Dyom3A9Yii2wNafc\nEtEr8D3dgnQMnkgpDhPCqLeeecmXn2BmELmBOW9Nio/tR8dc/wpW3OqB5ycmgnGu\n+QIDAQAB\n-----END PUBLIC KEY-----`)\n)\n\nfunc hugeString(mb int) string {\n\tvar buf strings.Builder\n\tsize := mb * 1024 * 1024\n\tseqSize := 512 * 1024\n\tbuf.Grow(size)\n\n\tseq := size / seqSize\n\n\tfor i := 0; i < seq; i++ {\n\t\tdata := make([]byte, seqSize)\n\t\tif i%2 == 0 {\n\t\t\t_, err := rand.Read(data)\n\t\t\tif err != nil {\n\t\t\t\tlog.L.WithError(err)\n\t\t\t}\n\t\t}\n\t\tbuf.Write(data)\n\t}\n\n\treturn buf.String()\n}\n\nfunc dropCache(t *testing.T) {\n\tcmd := exec.Command(\"sh\", \"-c\", \"echo 3 > /proc/sys/vm/drop_caches\")\n\tcmd.Stdout = os.Stdout\n\tcmd.Stderr = os.Stderr\n\trequire.NoError(t, cmd.Run())\n}\n\nfunc ensureFile(t *testing.T, name string) {\n\t_, err := os.Stat(name)\n\trequire.NoError(t, err)\n}\n\nfunc ensureNoFile(t *testing.T, name string) {\n\t_, err := os.Stat(name)\n\trequire.True(t, errors.Is(err, os.ErrNotExist))\n}\n\nfunc writeFileToTar(t *testing.T, tw *tar.Writer, name string, data string) {\n\tu, err := user.Current()\n\trequire.NoError(t, err)\n\tg, err := user.LookupGroupId(u.Uid)\n\trequire.NoError(t, err)\n\n\thdr := &tar.Header{\n\t\tName:  name,\n\t\tMode:  0444,\n\t\tSize:  int64(len(data)),\n\t\tUname: u.Username,\n\t\tGname: g.Name,\n\t}\n\terr = tw.WriteHeader(hdr)\n\trequire.NoError(t, err)\n\n\t_, err = io.Copy(tw, bytes.NewReader([]byte(data)))\n\trequire.Nil(t, err)\n\trequire.NoError(t, err)\n}\n\nfunc writeDirToTar(t *testing.T, tw *tar.Writer, name string) {\n\tu, err := user.Current()\n\trequire.NoError(t, err)\n\tg, err := user.LookupGroupId(u.Uid)\n\trequire.NoError(t, err)\n\n\thdr := &tar.Header{\n\t\tName:     name,\n\t\tMode:     0444,\n\t\tTypeflag: tar.TypeDir,\n\t\tUname:    u.Username,\n\t\tGname:    g.Name,\n\t}\n\terr = tw.WriteHeader(hdr)\n\trequire.NoError(t, err)\n}\n\nfunc writeToFile(t *testing.T, reader io.Reader, fileName string) {\n\tfile, err := os.Create(fileName)\n\trequire.NoError(t, err)\n\tdefer file.Close()\n\n\t_, err = io.Copy(file, reader)\n\trequire.NoError(t, err)\n}\n\nfunc buildChunkDictTar(t *testing.T, n int) io.ReadCloser {\n\tpr, pw := io.Pipe()\n\ttw := tar.NewWriter(pw)\n\n\tgo func() {\n\t\tdefer pw.Close()\n\n\t\twriteDirToTar(t, tw, \"dir-1\")\n\n\t\tfor i := 1; i < n; i++ {\n\t\t\twriteFileToTar(t, tw, fmt.Sprintf(\"dir-1/file-%d\", i), fmt.Sprintf(\"lower-file-%d\", i))\n\t\t}\n\n\t\trequire.NoError(t, tw.Close())\n\t}()\n\n\treturn pr\n}\n\nfunc buildOCILowerTar(t *testing.T, n int) (io.ReadCloser, map[string]string) {\n\tfileTree := map[string]string{}\n\n\tpr, pw := io.Pipe()\n\ttw := tar.NewWriter(pw)\n\n\tgo func() {\n\t\tdefer pw.Close()\n\n\t\twriteDirToTar(t, tw, \"dir-1\")\n\t\tfileTree[\"dir-1\"] = \"\"\n\n\t\tfor i := 1; i < n; i++ {\n\t\t\twriteFileToTar(t, tw, fmt.Sprintf(\"dir-1/file-%d\", i), fmt.Sprintf(\"lower-file-%d\", i))\n\t\t\tfileTree[fmt.Sprintf(\"dir-1/file-%d\", i)] = fmt.Sprintf(\"lower-file-%d\", i)\n\t\t}\n\n\t\twriteDirToTar(t, tw, \"dir-2\")\n\t\tfileTree[\"dir-2\"] = \"\"\n\n\t\twriteFileToTar(t, tw, \"dir-2/file-1\", \"lower-file-1\")\n\t\tfileTree[\"dir-2/file-1\"] = \"lower-file-1\"\n\n\t\trequire.NoError(t, tw.Close())\n\t}()\n\n\treturn pr, fileTree\n}\n\nfunc buildOCIUpperTar(t *testing.T, teePath string, lowerFileTree map[string]string, tarSize int) (io.ReadCloser, map[string]string) {\n\tif lowerFileTree == nil {\n\t\tlowerFileTree = map[string]string{}\n\t}\n\n\thugeStr := hugeString(tarSize)\n\tpr, pw := io.Pipe()\n\n\tgo func() {\n\t\ttw := tar.NewWriter(pw)\n\t\tdefer pw.Close()\n\n\t\tif len(teePath) > 0 {\n\t\t\tteew, err := os.OpenFile(teePath, os.O_WRONLY|os.O_CREATE, 0644)\n\t\t\trequire.NoError(t, err)\n\t\t\tdefer teew.Close()\n\n\t\t\ttw = tar.NewWriter(io.MultiWriter(pw, teew))\n\t\t}\n\n\t\twriteDirToTar(t, tw, \"dir-1\")\n\t\tlowerFileTree[\"dir-1\"] = \"\"\n\n\t\twriteFileToTar(t, tw, \"dir-1/.wh.file-1\", \"\")\n\t\tdelete(lowerFileTree, \"dir-1/file-1\")\n\n\t\twriteDirToTar(t, tw, \"dir-2\")\n\t\tlowerFileTree[\"dir-2\"] = \"\"\n\n\t\twriteFileToTar(t, tw, \"dir-2/.wh..wh..opq\", \"\")\n\t\tfor k := range lowerFileTree {\n\t\t\tif strings.HasPrefix(k, \"dir-2/\") {\n\t\t\t\tdelete(lowerFileTree, k)\n\t\t\t}\n\t\t}\n\n\t\twriteFileToTar(t, tw, \"dir-2/file-1\", hugeStr)\n\t\tlowerFileTree[\"dir-2/file-1\"] = hugeStr\n\n\t\twriteFileToTar(t, tw, \"dir-2/file-2\", \"upper-file-2\")\n\t\tlowerFileTree[\"dir-2/file-2\"] = \"upper-file-2\"\n\n\t\twriteFileToTar(t, tw, \"dir-2/file-3\", \"upper-file-3\")\n\t\tlowerFileTree[\"dir-2/file-3\"] = \"upper-file-3\"\n\n\t\trequire.NoError(t, tw.Close())\n\t}()\n\n\treturn pr, lowerFileTree\n}\n\nfunc packLayer(t *testing.T, source io.ReadCloser, chunkDict, workDir string, fsVersion string) (string, digest.Digest) {\n\tvar data bytes.Buffer\n\twriter := io.Writer(&data)\n\n\ttwc, err := converter.Pack(context.TODO(), writer, converter.PackOption{\n\t\tChunkDictPath: chunkDict,\n\t\tFsVersion:     fsVersion,\n\t})\n\trequire.NoError(t, err)\n\n\t_, err = io.Copy(twc, source)\n\trequire.NoError(t, err)\n\terr = twc.Close()\n\trequire.NoError(t, err)\n\n\tblobDigester := digest.Canonical.Digester()\n\t_, err = blobDigester.Hash().Write(data.Bytes())\n\trequire.NoError(t, err)\n\tblobDigest := blobDigester.Digest()\n\n\ttarBlobFilePath := filepath.Join(workDir, blobDigest.Hex())\n\twriteToFile(t, bytes.NewReader(data.Bytes()), tarBlobFilePath)\n\n\treturn tarBlobFilePath, blobDigest\n}\n\nfunc packLayerRef(t *testing.T, gzipSource io.ReadCloser, workDir string) (string, digest.Digest, digest.Digest) {\n\tvar blobMetaData bytes.Buffer\n\tblobMetaWriter := io.Writer(&blobMetaData)\n\n\tpr, pw := io.Pipe()\n\tgzipBlobDigester := digest.Canonical.Digester()\n\thw := io.MultiWriter(pw, gzipBlobDigester.Hash())\n\tgo func() {\n\t\tdefer pw.Close()\n\t\t_, err := io.Copy(hw, gzipSource)\n\t\trequire.NoError(t, err)\n\t}()\n\n\ttwc, err := converter.Pack(context.TODO(), blobMetaWriter, converter.PackOption{\n\t\tOCIRef: true,\n\t})\n\trequire.NoError(t, err)\n\n\t_, err = io.Copy(twc, pr)\n\trequire.NoError(t, err)\n\terr = twc.Close()\n\trequire.NoError(t, err)\n\n\tblobMetaDigester := digest.Canonical.Digester()\n\t_, err = blobMetaDigester.Hash().Write(blobMetaData.Bytes())\n\trequire.NoError(t, err)\n\tblobMetaDigest := blobMetaDigester.Digest()\n\n\ttarBlobMetaFilePath := filepath.Join(workDir, blobMetaDigest.Hex())\n\twriteToFile(t, bytes.NewReader(blobMetaData.Bytes()), tarBlobMetaFilePath)\n\n\tgzipBlobDigest := gzipBlobDigester.Digest()\n\n\treturn tarBlobMetaFilePath, blobMetaDigest, gzipBlobDigest\n}\n\nfunc unpackLayer(t *testing.T, workDir string, ra content.ReaderAt, stream bool) (string, digest.Digest) {\n\tvar data bytes.Buffer\n\twriter := io.Writer(&data)\n\n\terr := converter.Unpack(context.TODO(), ra, writer, converter.UnpackOption{\n\t\tStream: stream,\n\t})\n\trequire.NoError(t, err)\n\n\tdigester := digest.Canonical.Digester()\n\t_, err = digester.Hash().Write(data.Bytes())\n\trequire.NoError(t, err)\n\tdigest := digester.Digest()\n\n\ttarPath := filepath.Join(workDir, digest.Hex())\n\twriteToFile(t, bytes.NewReader(data.Bytes()), tarPath)\n\n\treturn tarPath, digest\n}\n\nfunc verify(t *testing.T, workDir string, expectedFileTree map[string]string) {\n\tmountDir := filepath.Join(workDir, \"mnt\")\n\tblobDir := filepath.Join(workDir, \"blobs\")\n\tnydusdPath := os.Getenv(envNydusdPath)\n\tif nydusdPath == \"\" {\n\t\tnydusdPath = \"nydusd\"\n\t}\n\tconfig := NydusdConfig{\n\t\tEnablePrefetch: false,\n\t\tNydusdPath:     nydusdPath,\n\t\tBootstrapPath:  filepath.Join(workDir, \"bootstrap\"),\n\t\tConfigPath:     filepath.Join(workDir, \"nydusd-config.fusedev.json\"),\n\t\tBackendType:    \"localfs\",\n\t\tBackendConfig:  fmt.Sprintf(`{\"dir\": \"%s\"}`, blobDir),\n\t\tBlobCacheDir:   filepath.Join(workDir, \"cache\"),\n\t\tAPISockPath:    filepath.Join(workDir, \"nydusd-api.sock\"),\n\t\tMountPath:      mountDir,\n\t\tMode:           \"direct\",\n\t\tDigestValidate: false,\n\t}\n\n\tnydusd, err := NewNydusd(config)\n\trequire.NoError(t, err)\n\terr = nydusd.Mount()\n\trequire.NoError(t, err)\n\tdefer func() {\n\t\tif err := nydusd.Umount(); err != nil {\n\t\t\tlog.L.WithError(err).Errorf(\"umount\")\n\t\t}\n\t}()\n\n\tactualFileTree := map[string]string{}\n\terr = filepath.WalkDir(mountDir, func(path string, entry fs.DirEntry, err error) error {\n\t\trequire.Nil(t, err)\n\t\tinfo, err := entry.Info()\n\t\trequire.NoError(t, err)\n\n\t\ttargetPath, err := filepath.Rel(mountDir, path)\n\t\trequire.NoError(t, err)\n\n\t\tif targetPath == \".\" {\n\t\t\treturn nil\n\t\t}\n\n\t\tdata := \"\"\n\t\tif !info.IsDir() {\n\t\t\tfile, err := os.Open(path)\n\t\t\trequire.NoError(t, err)\n\t\t\tdefer file.Close()\n\t\t\t_data, err := io.ReadAll(file)\n\t\t\trequire.NoError(t, err)\n\t\t\tdata = string(_data)\n\t\t}\n\t\tactualFileTree[targetPath] = data\n\n\t\treturn nil\n\t})\n\trequire.NoError(t, err)\n\n\trequire.Equal(t, expectedFileTree, actualFileTree)\n}\n\nfunc buildChunkDict(t *testing.T, workDir, fsVersion string, n int) (string, string) {\n\tdictOCITarReader := buildChunkDictTar(t, n)\n\n\tblobDir := filepath.Join(workDir, \"blobs\")\n\tnydusTarPath, lowerNydusBlobDigest := packLayer(t, dictOCITarReader, \"\", blobDir, fsVersion)\n\tra, err := local.OpenReader(nydusTarPath)\n\trequire.NoError(t, err)\n\tdefer ra.Close()\n\n\tlayers := []converter.Layer{\n\t\t{\n\t\t\tDigest:   lowerNydusBlobDigest,\n\t\t\tReaderAt: ra,\n\t\t},\n\t}\n\n\tbootstrapPath := filepath.Join(workDir, \"dict-bootstrap\")\n\tfile, err := os.Create(bootstrapPath)\n\trequire.NoError(t, err)\n\tdefer file.Close()\n\n\tblobDigests, err := converter.Merge(context.TODO(), layers, file, converter.MergeOption{})\n\trequire.NoError(t, err)\n\trequire.Equal(t, []digest.Digest{lowerNydusBlobDigest}, blobDigests)\n\n\tdictBlobPath := \"\"\n\terr = filepath.WalkDir(blobDir, func(path string, _ fs.DirEntry, err error) error {\n\t\trequire.NoError(t, err)\n\t\tif path == blobDir {\n\t\t\treturn nil\n\t\t}\n\t\tdictBlobPath = path\n\t\treturn nil\n\t})\n\trequire.NoError(t, err)\n\n\treturn bootstrapPath, filepath.Base(dictBlobPath)\n}\n\nfunc TestPack(t *testing.T) {\n\ttestPack(t, \"5\")\n\ttestPack(t, \"6\")\n}\n\nfunc testPack(t *testing.T, fsVersion string) {\n\tworkDir, err := os.MkdirTemp(\"\", \"nydus-converter-test-\")\n\trequire.NoError(t, err)\n\tdefer os.RemoveAll(workDir)\n\n\tlowerOCITarReader, expectedLowerFileTree := buildOCILowerTar(t, 100)\n\tupperOCITarReader, expectedOverlayFileTree := buildOCIUpperTar(t, \"\", expectedLowerFileTree, 3)\n\n\tblobDir := filepath.Join(workDir, \"blobs\")\n\terr = os.MkdirAll(blobDir, 0755)\n\trequire.NoError(t, err)\n\n\tcacheDir := filepath.Join(workDir, \"cache\")\n\terr = os.MkdirAll(cacheDir, 0755)\n\trequire.NoError(t, err)\n\n\tmountDir := filepath.Join(workDir, \"mnt\")\n\terr = os.MkdirAll(mountDir, 0755)\n\trequire.NoError(t, err)\n\n\tchunkDictBootstrapPath, chunkDictBlobHash := buildChunkDict(t, workDir, fsVersion, 100)\n\n\tlowerNydusTarPath, lowerNydusBlobDigest := packLayer(t, lowerOCITarReader, chunkDictBootstrapPath, blobDir, fsVersion)\n\tupperNydusTarPath, upperNydusBlobDigest := packLayer(t, upperOCITarReader, chunkDictBootstrapPath, blobDir, fsVersion)\n\n\tlowerTarRa, err := local.OpenReader(lowerNydusTarPath)\n\trequire.NoError(t, err)\n\tdefer lowerTarRa.Close()\n\n\tupperTarRa, err := local.OpenReader(upperNydusTarPath)\n\trequire.NoError(t, err)\n\tdefer upperTarRa.Close()\n\n\tlayers := []converter.Layer{\n\t\t{\n\t\t\tDigest:   lowerNydusBlobDigest,\n\t\t\tReaderAt: lowerTarRa,\n\t\t},\n\t\t{\n\t\t\tDigest:   upperNydusBlobDigest,\n\t\t\tReaderAt: upperTarRa,\n\t\t},\n\t}\n\n\tbootstrapPath := filepath.Join(workDir, \"bootstrap\")\n\tfile, err := os.Create(bootstrapPath)\n\trequire.NoError(t, err)\n\tdefer file.Close()\n\n\tblobDigests, err := converter.Merge(context.TODO(), layers, file, converter.MergeOption{\n\t\tChunkDictPath: chunkDictBootstrapPath,\n\t})\n\trequire.NoError(t, err)\n\tchunkDictBlobDigest := digest.NewDigestFromHex(string(digest.SHA256), chunkDictBlobHash)\n\texpectedBlobDigests := []digest.Digest{chunkDictBlobDigest, upperNydusBlobDigest}\n\trequire.Equal(t, expectedBlobDigests, blobDigests)\n\n\tverify(t, workDir, expectedOverlayFileTree)\n\tdropCache(t)\n\tverify(t, workDir, expectedOverlayFileTree)\n\n\tensureFile(t, filepath.Join(cacheDir, chunkDictBlobHash)+\".blob.data.chunk_map\")\n\tensureNoFile(t, filepath.Join(cacheDir, lowerNydusBlobDigest.Hex())+\".blob.data.chunk_map\")\n\tensureFile(t, filepath.Join(cacheDir, upperNydusBlobDigest.Hex())+\".blob.data.chunk_map\")\n}\n\n// sudo go test -v -count=1 -run TestPackRef ./tests\nfunc TestPackRef(t *testing.T) {\n\tif os.Getenv(\"TEST_PACK_REF\") == \"\" {\n\t\tt.Skip(\"skip TestPackRef test until new nydus-image/nydusd release\")\n\t}\n\n\tworkDir, err := os.MkdirTemp(\"\", \"nydus-converter-test-\")\n\trequire.NoError(t, err)\n\tdefer os.RemoveAll(workDir)\n\n\tblobDir := filepath.Join(workDir, \"blobs\")\n\terr = os.MkdirAll(blobDir, 0755)\n\trequire.NoError(t, err)\n\n\tcacheDir := filepath.Join(workDir, \"cache\")\n\terr = os.MkdirAll(cacheDir, 0755)\n\trequire.NoError(t, err)\n\n\tmountDir := filepath.Join(workDir, \"mnt\")\n\terr = os.MkdirAll(mountDir, 0755)\n\trequire.NoError(t, err)\n\n\tlowerOCITarReader, expectedLowerFileTree := buildOCILowerTar(t, 500)\n\tdefer lowerOCITarReader.Close()\n\n\tvar gzipData bytes.Buffer\n\tgzipWriter := gzip.NewWriter(&gzipData)\n\t_, err = io.Copy(gzipWriter, lowerOCITarReader)\n\trequire.NoError(t, err)\n\tgzipWriter.Close()\n\tdupGzipData := gzipData\n\n\tgzipReader := io.NopCloser(&gzipData)\n\tlowerNydusBlobPath, lowerNydusBlobDigest, lowerGzipBlobDigest := packLayerRef(t, gzipReader, blobDir)\n\n\twriteToFile(t, &dupGzipData, path.Join(blobDir, lowerGzipBlobDigest.Hex()))\n\n\tlowerNydusBlobRa, err := local.OpenReader(lowerNydusBlobPath)\n\trequire.NoError(t, err)\n\tdefer lowerNydusBlobRa.Close()\n\n\t// Check uncompressed bootstrap digest in TOC\n\tbootstrapDigester := digest.Canonical.Digester()\n\tbootstrapTOC, err := converter.UnpackEntry(lowerNydusBlobRa, converter.EntryBootstrap, bootstrapDigester.Hash())\n\trequire.NoError(t, err)\n\trequire.Equal(t, bootstrapTOC.GetUncompressedDigest(), bootstrapDigester.Digest().Hex())\n\n\t// Check uncompressed blob meta digest in TOC\n\tblobMetaDigester := digest.Canonical.Digester()\n\tblobMetaTOC, err := converter.UnpackEntry(lowerNydusBlobRa, converter.EntryBlobMeta, blobMetaDigester.Hash())\n\trequire.NoError(t, err)\n\trequire.Equal(t, blobMetaTOC.GetUncompressedDigest(), blobMetaDigester.Digest().Hex())\n\n\tlayers := []converter.Layer{\n\t\t{\n\t\t\tDigest:         lowerNydusBlobDigest,\n\t\t\tOriginalDigest: &lowerGzipBlobDigest,\n\t\t\tReaderAt:       lowerNydusBlobRa,\n\t\t},\n\t}\n\n\tbootstrapPath := filepath.Join(workDir, \"bootstrap\")\n\tfile, err := os.Create(bootstrapPath)\n\trequire.NoError(t, err)\n\tdefer file.Close()\n\n\tblobDigests, err := converter.Merge(context.TODO(), layers, file, converter.MergeOption{\n\t\tOCIRef: true,\n\t})\n\trequire.NoError(t, err)\n\n\trequire.Equal(t, []digest.Digest{lowerGzipBlobDigest}, blobDigests)\n\n\tverify(t, workDir, expectedLowerFileTree)\n}\n\n// sudo go test -v -count=1 -run TestUnpack ./tests\nfunc TestUnpack(t *testing.T) {\n\ttestUnpack(t, \"5\", 3)\n\ttestUnpack(t, \"6\", 3)\n}\n\nfunc testUnpack(t *testing.T, fsVersion string, tarSize int) {\n\tworkDir, err := os.MkdirTemp(\"\", \"nydus-converter-test-\")\n\trequire.NoError(t, err)\n\tdefer os.RemoveAll(workDir)\n\n\tociTar := filepath.Join(workDir, \"oci.tar\")\n\tociTarReader, _ := buildOCIUpperTar(t, ociTar, nil, tarSize)\n\tnydusTar, _ := packLayer(t, ociTarReader, \"\", workDir, fsVersion)\n\n\ttarTa, err := local.OpenReader(nydusTar)\n\trequire.NoError(t, err)\n\tdefer tarTa.Close()\n\n\tociTarReader, err = os.OpenFile(ociTar, os.O_RDONLY, 0644)\n\trequire.NoError(t, err)\n\tociTarDigest, err := digest.Canonical.FromReader(ociTarReader)\n\trequire.NoError(t, err)\n\n\tfor _, stream := range []bool{true, false} {\n\t\ttarPath, newTarDigest := unpackLayer(t, workDir, tarTa, stream)\n\t\tos.RemoveAll(tarPath)\n\t\trequire.Equal(t, ociTarDigest, newTarDigest)\n\t}\n}\n\ntype ConvertTestOption struct {\n\tt                    *testing.T\n\tfsVersion            string\n\tbackend              converter.Backend\n\tdisableCheck         bool\n\tencryptRecipients    []string\n\tdecryptKeys          []string\n\tbeforeConversionHook func() error\n\tafterConversionHook  func() error\n}\n\ntype ReConvertTestOption struct {\n\tt                    *testing.T\n\tbackend              converter.Backend\n\tencryptRecipients    []string\n\tbeforeConversionHook func() error\n\tafterConversionHook  func() error\n}\n\n// sudo go test -v -count=1 -run TestImageConvert ./tests\nfunc TestImageConvert(t *testing.T) {\n\tfor _, fsVersion := range []string{\"5\", \"6\"} {\n\t\ttestImageConvertNoBackend(t, fsVersion)\n\t\ttestImageConvertS3Backend(t, fsVersion)\n\t\ttestImageConvertWithCrypt(t, fsVersion)\n\t}\n}\n\nfunc testImageConvertNoBackend(t *testing.T, fsVersion string) {\n\ttestImageConvertBasic(&ConvertTestOption{\n\t\tt:         t,\n\t\tfsVersion: fsVersion,\n\t})\n}\n\nfunc testImageConvertS3Backend(t *testing.T, fsVersion string) {\n\ttestOpt := &ConvertTestOption{\n\t\tt:         t,\n\t\tfsVersion: fsVersion,\n\t}\n\trawConfig := []byte(`{\n\t\t  \"endpoint\": \"localhost:9000\",\n\t\t  \"scheme\": \"http\",\n\t\t  \"bucket_name\": \"nydus\",\n\t\t  \"region\": \"us-east-1\",\n\t\t  \"object_prefix\": \"path/to/my-registry/\",\n\t\t  \"access_key_id\": \"minio\",\n\t\t  \"access_key_secret\": \"minio123\"\n\t  }`)\n\tbackend, err := backend.NewBackend(\"s3\", rawConfig, true)\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create s3 backend: %v\", err)\n\t}\n\ttestOpt.backend = backend\n\n\tminioContainerName := fmt.Sprintf(\"minio-%d\", time.Now().UnixNano())\n\ttestOpt.beforeConversionHook = func() error {\n\t\t// setup minio server\n\t\tif err := exec.Command(\"docker\", \"run\", \"-d\", \"-p\", \"9000:9000\", \"--name\", minioContainerName, \"-e\", \"MINIO_ACCESS_KEY=minio\", \"-e\", \"MINIO_SECRET_KEY=minio123\", \"minio/minio\", \"server\", \"/data\").Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to start minio server: %v\", err)\n\t\t\treturn err\n\t\t}\n\t\ttime.Sleep(5 * time.Second)\n\t\t// create nydus bucket\n\t\ts3AWSConfig, err := awscfg.LoadDefaultConfig(context.TODO())\n\t\tif err != nil {\n\t\t\tt.Errorf(\"failed to load aws config\")\n\t\t}\n\t\tendpoint := \"http://localhost:9000\"\n\t\tclient := s3.NewFromConfig(s3AWSConfig, func(o *s3.Options) {\n\t\t\to.BaseEndpoint = &endpoint\n\t\t\to.Region = \"us-east-1\"\n\t\t\to.UsePathStyle = true\n\t\t\to.Credentials = credentials.NewStaticCredentialsProvider(\"minio\", \"minio123\", \"\")\n\t\t\to.UsePathStyle = true\n\t\t})\n\t\t_, err = client.CreateBucket(context.Background(), &s3.CreateBucketInput{Bucket: aws.String(\"nydus\")})\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlogrus.Info(\"create s3 bucket successfully\")\n\t\treturn nil\n\t}\n\n\ttestOpt.afterConversionHook = func() error {\n\t\tif err := exec.Command(\"docker\", \"rm\", \"-f\", minioContainerName).Run(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t}\n\n\t// TODO by now, the last release of nydusify doesn't support s3 backend\n\t// so skip the check\n\ttestOpt.disableCheck = true\n\n\ttestImageConvertBasic(testOpt)\n}\n\nfunc testImageConvertWithCrypt(t *testing.T, fsVersion string) {\n\tworkDir, err := os.MkdirTemp(\"\", fmt.Sprintf(\"nydus-bootstrap-crypt-test-%d\", time.Now().UnixNano()))\n\trequire.NoError(t, err)\n\tdefer os.RemoveAll(workDir)\n\n\tencryptRecipient, err := os.Create(filepath.Join(workDir, \"pubkey.pem\"))\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create pubkey.pem: %v\", err)\n\t\treturn\n\t}\n\tdefer encryptRecipient.Close()\n\t_, err = encryptRecipient.WriteString(string(publicKey))\n\tif err != nil {\n\t\tt.Fatalf(\"failed to write into pubkey.pem: %v\", err)\n\t\treturn\n\t}\n\tdecryptKey, err := os.Create(filepath.Join(workDir, \"key.pem\"))\n\tif err != nil {\n\t\tt.Fatalf(\"failed to create key.pem: %v\", err)\n\t\treturn\n\t}\n\tdefer decryptKey.Close()\n\t_, err = decryptKey.WriteString(string(privateKey))\n\tif err != nil {\n\t\tt.Fatalf(\"failed to write into key.pem: %v\", err)\n\t\treturn\n\t}\n\n\ttestImageConvertBasic(&ConvertTestOption{\n\t\tt:         t,\n\t\tfsVersion: fsVersion,\n\t\t// TODO set false when nydusify ready\n\t\tdisableCheck:      true,\n\t\tencryptRecipients: []string{fmt.Sprint(\"jwe:\", encryptRecipient.Name())},\n\t\tdecryptKeys:       []string{decryptKey.Name()},\n\t})\n}\n\nfunc testImageConvertBasic(testOpt *ConvertTestOption) {\n\tconst (\n\t\tsrcImageRef    = \"docker.io/library/nginx:latest\"\n\t\ttargetImageRef = \"localhost:5000/nydus/nginx:nydus-latest\"\n\t)\n\tt := testOpt.t\n\t// setup docker registry\n\tif err := exec.Command(\"docker\", \"run\", \"-d\", \"-p\", \"5000:5000\", \"--restart=always\", \"--name\", \"registry\", \"registry:2\").Run(); err != nil {\n\t\tt.Fatalf(\"failed to start docker registry: %v\", err)\n\t\treturn\n\t}\n\tdefer func() {\n\t\tif err := exec.Command(\"docker\", \"stop\", \"registry\").Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to stop docker registry: %v\", err)\n\t\t}\n\t\tif err := exec.Command(\"docker\", \"rm\", \"registry\").Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to remove docker registry: %v\", err)\n\t\t}\n\t}()\n\n\tif testOpt.beforeConversionHook != nil {\n\t\tif err := testOpt.beforeConversionHook(); err != nil {\n\t\t\tt.Fatalf(\"failed to run before conversion hook: %v\", err)\n\t\t\treturn\n\t\t}\n\t\tdefer func() {\n\t\t\tif err := testOpt.afterConversionHook(); err != nil {\n\t\t\t\tt.Fatalf(\"failed to run after conversion hook: %v\", err)\n\t\t\t}\n\t\t}()\n\t}\n\n\tif err := exec.Command(\"ctr\", \"images\", \"pull\", srcImageRef).Run(); err != nil {\n\t\tt.Fatalf(\"failed to pull image %s: %v\", srcImageRef, err)\n\t\treturn\n\t}\n\tdefer func() {\n\t\tif err := exec.Command(\"ctr\", \"images\", \"rm\", srcImageRef).Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to remove image %s: %v\", srcImageRef, err)\n\t\t}\n\t}()\n\tworkDir, err := os.MkdirTemp(\"\", fmt.Sprintf(\"nydus-containerd-converter-test-%d\", time.Now().UnixNano()))\n\trequire.NoError(t, err)\n\tdefer os.RemoveAll(workDir)\n\tnydusOpts := &converter.PackOption{\n\t\tWorkDir:   workDir,\n\t\tFsVersion: testOpt.fsVersion,\n\t\tBackend:   testOpt.backend,\n\t}\n\tconvertFunc := converter.LayerConvertFunc(*nydusOpts)\n\tvar encrypter converter.Encrypter\n\tif len(testOpt.encryptRecipients) > 0 {\n\t\tencrypter = func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (ocispec.Descriptor, error) {\n\t\t\treturn encryption.EncryptNydusBootstrap(ctx, cs, desc, testOpt.encryptRecipients)\n\t\t}\n\t}\n\tconvertHooks := containerdConverter.ConvertHooks{\n\t\tPostConvertHook: converter.ConvertHookFunc(converter.MergeOption{\n\t\t\tWorkDir:          nydusOpts.WorkDir,\n\t\t\tBuilderPath:      nydusOpts.BuilderPath,\n\t\t\tFsVersion:        nydusOpts.FsVersion,\n\t\t\tChunkDictPath:    nydusOpts.ChunkDictPath,\n\t\t\tBackend:          testOpt.backend,\n\t\t\tPrefetchPatterns: nydusOpts.PrefetchPatterns,\n\t\t\tEncrypt:          encrypter,\n\t\t}),\n\t}\n\tconvertFuncOpt := containerdConverter.WithIndexConvertFunc(\n\t\tcontainerdConverter.IndexConvertFuncWithHook(\n\t\t\tconvertFunc,\n\t\t\ttrue,\n\t\t\tplatforms.DefaultStrict(),\n\t\t\tconvertHooks,\n\t\t),\n\t)\n\tclient, err := containerd.New(\"/run/containerd/containerd.sock\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t\treturn\n\t}\n\tctx := namespaces.WithNamespace(context.Background(), \"default\")\n\tif _, err = containerdConverter.Convert(ctx, client, targetImageRef, srcImageRef, convertFuncOpt); err != nil {\n\t\tt.Fatal(err)\n\t\treturn\n\t}\n\tdefer func() {\n\t\tif err := exec.Command(\"ctr\", \"images\", \"rm\", targetImageRef).Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to remove image %s: %v\", targetImageRef, err)\n\t\t}\n\t}()\n\t// push target image\n\tif output, err := exec.Command(\"ctr\", \"images\", \"push\", \"--plain-http\", targetImageRef).CombinedOutput(); err != nil {\n\t\tt.Fatalf(\"failed to push image %s: %v, output:\\n%s\", targetImageRef, err, string(output))\n\t\treturn\n\t}\n\t// check whether the converted image is valid\n\tif testOpt.disableCheck {\n\t\treturn\n\t}\n\tif len(testOpt.decryptKeys) != 0 {\n\t\tif output, err := exec.Command(\"nydusify\", \"check\",\n\t\t\t\"--source\", srcImageRef,\n\t\t\t\"--target\", targetImageRef,\n\t\t\t\"--decrypt-keys\", strings.Join(testOpt.decryptKeys, \",\"),\n\t\t\t\"--target-insecure\").CombinedOutput(); err != nil {\n\t\t\tt.Fatalf(\"failed to check image %s: %v, \\noutput:\\n%s\", targetImageRef, err, output)\n\t\t\treturn\n\t\t}\n\t\treturn\n\t}\n\tif output, err := exec.Command(\"nydusify\", \"check\", \"--source\", srcImageRef, \"--target\", targetImageRef, \"--target-insecure\").CombinedOutput(); err != nil {\n\t\tt.Fatalf(\"failed to check image %s: %v, \\noutput:\\n%s\", targetImageRef, err, output)\n\t\treturn\n\t}\n}\n\n// sudo go test -v -count=1 -run TestImageReConvert ./tests\nfunc TestImageReConvert(t *testing.T) {\n\ttestImageReConvertNoBackend(t)\n}\n\nfunc testImageReConvertNoBackend(t *testing.T) {\n\ttestImageReConvertBasic(&ReConvertTestOption{\n\t\tt: t,\n\t})\n}\n\nfunc testImageReConvertBasic(testOpt *ReConvertTestOption) {\n\tconst (\n\t\tpreSrcImageRef = \"docker.io/library/nginx:latest\"\n\t\tsrcImageRef    = \"localhost:5000/nydus/nginx:nydus-latest\"\n\t\ttargetImageRef = \"localhost:5000/nydus/nginx:oci\"\n\t)\n\tt := testOpt.t\n\t// setup docker registry\n\tif err := exec.Command(\"docker\", \"run\", \"-d\", \"-p\", \"5000:5000\", \"--restart=always\", \"--name\", \"registry\", \"registry:2\").Run(); err != nil {\n\t\tt.Fatalf(\"failed to start docker registry: %v\", err)\n\t\treturn\n\t}\n\tdefer func() {\n\t\tif err := exec.Command(\"docker\", \"stop\", \"registry\").Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to stop docker registry: %v\", err)\n\t\t}\n\t\tif err := exec.Command(\"docker\", \"rm\", \"registry\").Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to remove docker registry: %v\", err)\n\t\t}\n\t}()\n\tif testOpt.beforeConversionHook != nil {\n\t\tif err := testOpt.beforeConversionHook(); err != nil {\n\t\t\tt.Fatalf(\"failed to run before conversion hook: %v\", err)\n\t\t\treturn\n\t\t}\n\t\tdefer func() {\n\t\t\tif err := testOpt.afterConversionHook(); err != nil {\n\t\t\t\tt.Fatalf(\"failed to run after conversion hook: %v\", err)\n\t\t\t}\n\t\t}()\n\t}\n\n\t// use convert to create nydus format srcImager\n\tif err := exec.Command(\"ctr\", \"images\", \"pull\", preSrcImageRef).Run(); err != nil {\n\t\tt.Fatalf(\"failed to pull image %s: %v\", preSrcImageRef, err)\n\t\treturn\n\t}\n\tdefer func() {\n\t\tif err := exec.Command(\"ctr\", \"images\", \"rm\", preSrcImageRef).Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to remove image %s: %v\", preSrcImageRef, err)\n\t\t}\n\t}()\n\n\tworkDir, err := os.MkdirTemp(\"\", fmt.Sprintf(\"nydus-containerd-converter-test-%d\", time.Now().UnixNano()))\n\trequire.NoError(t, err)\n\tdefer os.RemoveAll(workDir)\n\tnydusOpts := &converter.PackOption{\n\t\tWorkDir: workDir,\n\t\tBackend: testOpt.backend,\n\t}\n\tconvertFunc := converter.LayerConvertFunc(*nydusOpts)\n\tvar encrypter converter.Encrypter\n\tif len(testOpt.encryptRecipients) > 0 {\n\t\tencrypter = func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (ocispec.Descriptor, error) {\n\t\t\treturn encryption.EncryptNydusBootstrap(ctx, cs, desc, testOpt.encryptRecipients)\n\t\t}\n\t}\n\tconvertHooks := containerdConverter.ConvertHooks{\n\t\tPostConvertHook: converter.ConvertHookFunc(converter.MergeOption{\n\t\t\tWorkDir:          nydusOpts.WorkDir,\n\t\t\tBuilderPath:      nydusOpts.BuilderPath,\n\t\t\tFsVersion:        nydusOpts.FsVersion,\n\t\t\tChunkDictPath:    nydusOpts.ChunkDictPath,\n\t\t\tBackend:          testOpt.backend,\n\t\t\tPrefetchPatterns: nydusOpts.PrefetchPatterns,\n\t\t\tEncrypt:          encrypter,\n\t\t}),\n\t}\n\tconvertFuncOpt := containerdConverter.WithIndexConvertFunc(\n\t\tcontainerdConverter.IndexConvertFuncWithHook(\n\t\t\tconvertFunc,\n\t\t\ttrue,\n\t\t\tplatforms.DefaultStrict(),\n\t\t\tconvertHooks,\n\t\t),\n\t)\n\n\tclient, err := containerd.New(\"/run/containerd/containerd.sock\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t\treturn\n\t}\n\tctx := namespaces.WithNamespace(context.Background(), \"default\")\n\tif _, err = containerdConverter.Convert(ctx, client, srcImageRef, preSrcImageRef, convertFuncOpt); err != nil {\n\t\tt.Fatal(err)\n\t\treturn\n\t}\n\tdefer func() {\n\t\tif err = exec.Command(\"ctr\", \"images\", \"rm\", srcImageRef).Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to remove image %s: %v\", srcImageRef, err)\n\t\t}\n\t}()\n\n\tnydusReconvertOpts := &converter.UnpackOption{\n\t\tWorkDir: workDir,\n\t\tBackend: testOpt.backend,\n\t}\n\treconvertFunc := converter.LayerReconvertFunc(*nydusReconvertOpts)\n\treconvertHook := containerdConverter.ConvertHooks{\n\t\tPostConvertHook: converter.ReconvertHookFunc(),\n\t}\n\treConvertFuncOpt := containerdConverter.WithIndexConvertFunc(\n\t\tcontainerdConverter.IndexConvertFuncWithHook(\n\t\t\treconvertFunc,\n\t\t\tfalse,\n\t\t\tplatforms.DefaultStrict(),\n\t\t\treconvertHook,\n\t\t),\n\t)\n\n\tif _, err = containerdConverter.Convert(ctx, client, targetImageRef, srcImageRef, reConvertFuncOpt); err != nil {\n\t\tt.Fatal(err)\n\t\treturn\n\t}\n\tdefer func() {\n\t\tif err := exec.Command(\"ctr\", \"images\", \"rm\", targetImageRef).Run(); err != nil {\n\t\t\tt.Fatalf(\"failed to remove image %s: %v\", targetImageRef, err)\n\t\t}\n\t}()\n}\n"
  },
  {
    "path": "tests/e2e/k8s/kind.yaml",
    "content": "kind: Cluster\napiVersion: kind.x-k8s.io/v1alpha4\nnetworking:\n  ipFamily: dual\ncontainerdConfigPatches:\n  - |-\n    [plugins.\"io.containerd.grpc.v1.cri\".containerd]\n    discard_unpacked_layers = false\n    disable_snapshot_annotations = false\nnodes:\n  - role: control-plane\n    extraMounts:\n      - hostPath: /dev/fuse\n        containerPath: /dev/fuse\n"
  },
  {
    "path": "tests/e2e/k8s/snapshotter-cri.yaml",
    "content": "---\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: nydus-system\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: nydus-snapshotter-sa\n  namespace: nydus-system\n---\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: nydus-snapshotter-role\nrules:\n  - apiGroups: \n    - \"\"\n    resources: \n    - nodes\n    verbs:\n    - get\n    - patch\n\n---\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: nydus-snapshotter-role-binding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: nydus-snapshotter-role\nsubjects:\n  - kind: ServiceAccount\n    name: nydus-snapshotter-sa\n    namespace: nydus-system\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: nydus-snapshotter\n  namespace: nydus-system\n  labels:\n    app: nydus-snapshotter\nspec:\n  serviceAccountName: nydus-snapshotter-sa\n  hostNetwork: true\n  hostPID: true\n  containers:\n    - name: nydus-snapshotter\n      image: \"local-dev:e2e\"\n      imagePullPolicy: IfNotPresent\n      env:\n        - name: NODE_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: spec.nodeName\n        - name: FS_DRIVER\n          valueFrom:\n            configMapKeyRef:\n              name: nydus-snapshotter-configs\n              key: FS_DRIVER\n              optional: true\n        - name: ENABLE_CONFIG_FROM_VOLUME\n          valueFrom:\n            configMapKeyRef:\n              name: nydus-snapshotter-configs\n              key: ENABLE_CONFIG_FROM_VOLUME\n              optional: true\n        - name: ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER\n          valueFrom:\n            configMapKeyRef:\n              name: nydus-snapshotter-configs\n              key: ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER\n              optional: true\n        - name: ENABLE_SYSTEMD_SERVICE\n          valueFrom:\n            configMapKeyRef:\n              name: nydus-snapshotter-configs\n              key: ENABLE_SYSTEMD_SERVICE\n              optional: true\n      lifecycle:\n        preStop:\n          exec:\n            command:\n              - \"bash\"\n              - \"-c\"\n              - |\n                /opt/nydus-artifacts/opt/nydus/snapshotter.sh cleanup\n      command:\n        - bash\n        - -c\n        - |-\n          /opt/nydus-artifacts/opt/nydus/snapshotter.sh deploy\n      volumeMounts:\n        - name: config-volume\n          mountPath: \"/etc/nydus-snapshotter\"\n        - name: nydus-lib\n          mountPath: \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\"\n          mountPropagation: Bidirectional\n        - name: nydus-run\n          mountPath: \"/run/containerd-nydus\"\n          mountPropagation: Bidirectional\n        - name: nydus-opt\n          mountPath: \"/opt/nydus\"\n          mountPropagation: Bidirectional\n        - name: nydus-etc\n          mountPath: \"/etc/nydus\"\n          mountPropagation: Bidirectional\n        - name: containerd-conf\n          mountPath: \"/etc/containerd/\"\n        - name: local-bin\n          mountPath: \"/usr/local/bin/\"\n        - name: etc-systemd-system\n          mountPath: \"/etc/systemd/system/\"\n        - name: fuse\n          mountPath: /dev/fuse\n      securityContext:\n        privileged: true\n\n  volumes:\n    - name: config-volume\n      configMap:\n        name: nydus-snapshotter-configs\n        optional: true\n    - name: nydus-run\n      hostPath:\n        path: /run/containerd-nydus\n        type: DirectoryOrCreate\n    - name: nydus-lib\n      hostPath:\n        path: /var/lib/containerd/io.containerd.snapshotter.v1.nydus\n        type: DirectoryOrCreate\n    - name: nydus-etc\n      hostPath:\n          path: /etc/nydus\n          type: DirectoryOrCreate\n    - name: nydus-opt\n      hostPath:\n        path: /opt/nydus\n        type: DirectoryOrCreate\n    - name: containerd-conf\n      hostPath:\n        path: /etc/containerd/\n    - name: local-bin\n      hostPath:\n        path: /usr/local/bin/\n    - name: etc-systemd-system\n      hostPath:\n        path: /etc/systemd/system/\n    - name: fuse\n      hostPath:\n        path: /dev/fuse\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: nydus-snapshotter-configs\n  labels:\n    app: nydus-snapshotter\n  namespace: nydus-system\ndata:\n  FS_DRIVER: \"fusedev\"\n  ENABLE_CONFIG_FROM_VOLUME: \"true\"\n  ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER: \"false\"\n  ENABLE_SYSTEMD_SERVICE: \"true\"\n  config.toml: |-\n    version = 1\n    root = \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\"\n    address = \"/run/containerd-nydus/containerd-nydus-grpc.sock\"\n    daemon_mode = \"multiple\"\n    # Whether snapshotter should try to clean up resources when it is closed\n    cleanup_on_close = false\n    \n    [system]\n    # Snapshotter's debug and trace HTTP server interface\n    enable = true\n    # Unix domain socket path where system controller is listening on\n    address = \"/run/containerd-nydus/system.sock\"\n    \n    [metrics]\n    # Enable by assigning an address, empty indicates metrics server is disabled\n    address = \":9110\"\n    # The maximum duration an I/O operation can be pending before it's considered hung.\n    hung_io_interval = \"30s\"\n    # The interval at which metrics are collected and updated.\n    collect_interval = \"1m\"\n    \n    [experimental]\n    # Whether tp enable stargz support\n    enable_stargz = false\n    \n    [daemon]\n    nydusd_path = \"/usr/local/bin/nydusd\"\n    nydusimage_path = \"/usr/local/bin/nydus-image\"\n    # fusedev or fscache\n    fs_driver = \"fusedev\"\n    # Specify nydusd log level\n    log_level = \"info\"\n    # How to process when daemon dies: \"none\", \"restart\" or \"failover\"\n    recover_policy = \"restart\"\n    # Specify a configuration file for nydusd\n    nydusd_config = \"/etc/nydus/nydusd.json\"\n    # The fuse or fscache IO working threads started by nydusd\n    threads_number = 4\n    \n    [log]\n    # Snapshotter's log level\n    level = \"info\"\n    log_rotation_compress = true\n    log_rotation_local_time = true\n    # Max number of days to retain logs\n    log_rotation_max_age = 7\n    log_rotation_max_backups = 5\n    # In unit MB(megabytes)\n    log_rotation_max_size = 1\n    log_to_stdout = false\n    \n    [remote]\n    convert_vpc_registry = false\n    \n    [remote.auth]\n    # Fetch the private registry auth by listening to K8s API server\n    enable_kubeconfig_keychain = false\n    # synchronize `kubernetes.io/dockerconfigjson` secret from kubernetes API server with specified kubeconfig (default `$KUBECONFIG` or `~/.kube/config`)\n    kubeconfig_path = \"\"\n    # Fetch the private registry auth as CRI image service proxy\n    enable_cri_keychain = true\n    # the target image service when using image proxy\n    image_service_address = \"\"\n    \n    [snapshot]\n    enable_nydus_overlayfs = false\n    # Whether to remove resources when a snapshot is removed\n    sync_remove = false\n    \n    [cache_manager]\n    disable = false\n    gc_period = \"24h\"\n    cache_dir = \"\"\n    \n    [image]\n    public_key_file = \"\"\n    validate_signature = false\n\n  nydusd.json: |-\n    {\n      \"device\": {\n        \"backend\": {\n          \"type\": \"registry\",\n          \"config\": {\n            \"scheme\": \"\",\n            \"skip_verify\": true,\n            \"timeout\": 10,\n            \"connect_timeout\": 10,\n            \"retry_limit\": 2\n          }\n        },\n        \"cache\": {\n          \"type\": \"blobcache\",\n          \"config\": {\n            \"work_dir\": \"/var/lib/nydus/cache/\"\n          }\n        }\n      },\n      \"mode\": \"direct\",\n      \"digest_validate\": false,\n      \"iostats_files\": false,\n      \"enable_xattr\": true,\n      \"amplify_io\": 1048576,\n      \"fs_prefetch\": {\n        \"enable\": true,\n        \"threads_count\": 10,\n        \"merging_size\": 131072,\n        \"bandwidth_rate\": 1048576\n      }\n    }\n"
  },
  {
    "path": "tests/e2e/k8s/snapshotter-kubeconf.yaml",
    "content": "---\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: nydus-system\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: nydus-snapshotter-sa\n  namespace: nydus-system\n---\nkind: ClusterRole\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: nydus-snapshotter-role\nrules:\n  - apiGroups:\n      - \"\"\n    resources:\n      - secrets\n    verbs:\n      - get\n      - list\n      - watch\n  - apiGroups:\n    - \"\"\n    resources:\n    - nodes\n    verbs:\n    - get\n    - patch\n\n---\nkind: ClusterRoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: nydus-snapshotter-role-binding\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: nydus-snapshotter-role\nsubjects:\n  - kind: ServiceAccount\n    name: nydus-snapshotter-sa\n    namespace: nydus-system\n\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: nydus-snapshotter\n  namespace: nydus-system\n  labels:\n    app: nydus-snapshotter\nspec:\n  serviceAccountName: nydus-snapshotter-sa\n  hostNetwork: true\n  hostPID: true\n  containers:\n    - name: nydus-snapshotter\n      image: \"local-dev:e2e\"\n      imagePullPolicy: IfNotPresent\n      env:\n        - name: NODE_NAME\n          valueFrom:\n            fieldRef:\n              fieldPath: spec.nodeName\n        - name: FS_DRIVER\n          valueFrom:\n            configMapKeyRef:\n              name: nydus-snapshotter-configs\n              key: FS_DRIVER\n              optional: true\n        - name: ENABLE_CONFIG_FROM_VOLUME\n          valueFrom:\n            configMapKeyRef:\n              name: nydus-snapshotter-configs\n              key: ENABLE_CONFIG_FROM_VOLUME\n              optional: true\n        - name: ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER\n          valueFrom:\n            configMapKeyRef:\n              name: nydus-snapshotter-configs\n              key: ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER\n              optional: true\n        - name: ENABLE_SYSTEMD_SERVICE\n          valueFrom:\n            configMapKeyRef:\n              name: nydus-snapshotter-configs\n              key: ENABLE_SYSTEMD_SERVICE\n              optional: true\n      lifecycle:\n        preStop:\n          exec:\n            command:\n              - \"bash\"\n              - \"-c\"\n              - |\n                /opt/nydus-artifacts/opt/nydus/snapshotter.sh cleanup\n      command:\n        - bash\n        - -c\n        - |-\n          /opt/nydus-artifacts/opt/nydus/snapshotter.sh deploy\n      volumeMounts:\n        - name: config-volume\n          mountPath: \"/etc/nydus-snapshotter\"\n        - name: nydus-lib\n          mountPath: \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\"\n          mountPropagation: Bidirectional\n        - name: nydus-run\n          mountPath: \"/run/containerd-nydus\"\n          mountPropagation: Bidirectional\n        - name: nydus-opt\n          mountPath: \"/opt/nydus\"\n          mountPropagation: Bidirectional\n        - name: nydus-etc\n          mountPath: \"/etc/nydus\"\n          mountPropagation: Bidirectional\n        - name: containerd-conf\n          mountPath: \"/etc/containerd/\"\n        - name: local-bin\n          mountPath: \"/usr/local/bin/\"\n        - name: etc-systemd-system\n          mountPath: \"/etc/systemd/system/\"\n        - name: fuse\n          mountPath: /dev/fuse\n      securityContext:\n        privileged: true\n\n  volumes:\n    - name: config-volume\n      configMap:\n        name: nydus-snapshotter-configs\n        optional: true\n    - name: nydus-run\n      hostPath:\n        path: /run/containerd-nydus\n        type: DirectoryOrCreate\n    - name: nydus-lib\n      hostPath:\n        path: /var/lib/containerd/io.containerd.snapshotter.v1.nydus\n        type: DirectoryOrCreate\n    - name: nydus-etc\n      hostPath:\n          path: /etc/nydus\n          type: DirectoryOrCreate\n    - name: nydus-opt\n      hostPath:\n        path: /opt/nydus\n        type: DirectoryOrCreate\n    - name: containerd-conf\n      hostPath:\n        path: /etc/containerd/\n    - name: local-bin\n      hostPath:\n        path: /usr/local/bin/\n    - name: etc-systemd-system\n      hostPath:\n        path: /etc/systemd/system/\n    - name: fuse\n      hostPath:\n        path: /dev/fuse\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: nydus-snapshotter-configs\n  labels:\n    app: nydus-snapshotter\n  namespace: nydus-system\ndata:\n  FS_DRIVER: \"fusedev\"\n  ENABLE_CONFIG_FROM_VOLUME: \"true\"\n  ENABLE_RUNTIME_SPECIFIC_SNAPSHOTTER: \"false\"\n  ENABLE_SYSTEMD_SERVICE: \"false\"\n  config.toml: |-\n    version = 1\n    root = \"/var/lib/containerd/io.containerd.snapshotter.v1.nydus\"\n    address = \"/run/containerd-nydus/containerd-nydus-grpc.sock\"\n    daemon_mode = \"multiple\"\n    # Whether snapshotter should try to clean up resources when it is closed\n    cleanup_on_close = false\n    \n    [system]\n    # Snapshotter's debug and trace HTTP server interface\n    enable = true\n    # Unix domain socket path where system controller is listening on\n    address = \"/run/containerd-nydus/system.sock\"\n    \n    [metrics]\n    # Enable by assigning an address, empty indicates metrics server is disabled\n    address = \":9110\"\n    # The maximum duration an I/O operation can be pending before it's considered hung.\n    hung_io_interval = \"30s\"\n    # The interval at which metrics are collected and updated.\n    collect_interval = \"1m\"\n    \n    [experimental]\n    # Whether tp enable stargz support\n    enable_stargz = false\n    enable_index_detect = true\n    \n    [daemon]\n    nydusd_path = \"/usr/local/bin/nydusd\"\n    nydusimage_path = \"/usr/local/bin/nydus-image\"\n    # fusedev or fscache\n    fs_driver = \"fusedev\"\n    # Specify nydusd log level\n    log_level = \"info\"\n    # How to process when daemon dies: \"none\", \"restart\" or \"failover\"\n    recover_policy = \"restart\"\n    # Specify a configuration file for nydusd\n    nydusd_config = \"/etc/nydus/nydusd.json\"\n    # The fuse or fscache IO working threads started by nydusd\n    threads_number = 4\n    \n    [log]\n    # Snapshotter's log level\n    level = \"info\"\n    log_rotation_compress = true\n    log_rotation_local_time = true\n    # Max number of days to retain logs\n    log_rotation_max_age = 7\n    log_rotation_max_backups = 5\n    # In unit MB(megabytes)\n    log_rotation_max_size = 1\n    log_to_stdout = false\n    \n    [remote]\n    convert_vpc_registry = false\n    [remote.auth]\n    # Fetch the private registry auth by listening to K8s API server\n    enable_kubeconfig_keychain = true\n    # synchronize `kubernetes.io/dockerconfigjson` secret from kubernetes API server with specified kubeconfig (default `$KUBECONFIG` or `~/.kube/config`)\n    kubeconfig_path = \"\"\n    # Fetch the private registry auth as CRI image service proxy\n    enable_cri_keychain = false\n    # the target image service when using image proxy\n    image_service_address = \"\"\n    \n    [snapshot]\n    enable_nydus_overlayfs = false\n    # Whether to remove resources when a snapshot is removed\n    sync_remove = false\n    \n    [cache_manager]\n    disable = false\n    gc_period = \"24h\"\n    cache_dir = \"\"\n    \n    [image]\n    public_key_file = \"\"\n    validate_signature = false\n\n  nydusd.json: |-\n    {\n      \"device\": {\n        \"backend\": {\n          \"type\": \"registry\",\n          \"config\": {\n            \"scheme\": \"\",\n            \"skip_verify\": true,\n            \"timeout\": 10,\n            \"connect_timeout\": 10,\n            \"retry_limit\": 2\n          }\n        },\n        \"cache\": {\n          \"type\": \"blobcache\",\n          \"config\": {\n            \"work_dir\": \"/var/lib/nydus/cache/\"\n          }\n        }\n      },\n      \"mode\": \"direct\",\n      \"digest_validate\": false,\n      \"iostats_files\": false,\n      \"enable_xattr\": true,\n      \"amplify_io\": 1048576,\n      \"fs_prefetch\": {\n        \"enable\": true,\n        \"threads_count\": 10,\n        \"merging_size\": 131072,\n        \"bandwidth_rate\": 1048576\n      }\n    }\n"
  },
  {
    "path": "tests/e2e/k8s/test-pod.yaml.tpl",
    "content": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: test-pod\n  namespace: nydus-system\nspec:\n  containers:\n    - name: busybox\n      image: REGISTRY_URL/busybox:nydus-v6-latest\n      imagePullPolicy: Always\n      command: [\"sh\", \"-c\"]\n      args:\n        - tail -f /dev/null\n  imagePullSecrets:\n    - name: regcred\n"
  },
  {
    "path": "tests/helpers/helpers.sh",
    "content": "#!/usr/bin/env bash\n\n#   Copyright The containerd Authors.\n\n#   Licensed under the Apache License, Version 2.0 (the \"License\");\n#   you may not use this file except in compliance with the License.\n#   You may obtain a copy of the License at\n\n#       http://www.apache.org/licenses/LICENSE-2.0\n\n#   Unless required by applicable law or agreed to in writing, software\n#   distributed under the License is distributed on an \"AS IS\" BASIS,\n#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#   See the License for the specific language governing permissions and\n#   limitations under the License.\n\nset -o errexit -o errtrace -o functrace -o nounset -o pipefail\n\n## Helpers specific to nydus\n\n_rootful=\n\nconfigure::rootful(){\n  log::debug \"Configuring rootful to: ${1:+true}\"\n  _rootful=\"${1:+true}\"\n}\n\nconfigure::dockerd(){\n  local config=\"$1\"\n\n  log::debug \"Reconfiguring docker and restarting\"\n  log::debug \"$config\"\n  sudo touch /etc/docker/daemon.json\n  printf \"%s\" \"$config\" | sudo tee /etc/docker/daemon.json >/dev/null\n  sudo systemctl restart docker\n}\n\nexec::docker(){\n  local args=()\n  [ ! \"$_rootful\" ] || args=(sudo)\n  args+=(docker)\n\n  log::debug \"${args[*]} $*\"\n  \"${args[@]}\" \"$@\"\n}\n\nexec::kind(){\n  local args=()\n  [ ! \"$_rootful\" ] || args=(sudo)\n  args+=(kind)\n\n  log::debug \"${args[*]} $*\"\n  \"${args[@]}\" \"$@\"\n}\n\nexec::kubectl(){\n  local args=()\n  [ ! \"$_rootful\" ] || args=(sudo)\n  args+=(kubectl)\n\n  log::debug \"${args[*]} $*\"\n  \"${args[@]}\" \"$@\"\n}\n\nexec::nydusify(){\n  local args=()\n  [ ! \"$_rootful\" ] || args=(sudo)\n  args+=(nydusify)\n\n  log::debug \"${args[*]} $*\"\n  \"${args[@]}\" \"$@\"\n}\n\ndocker::configpath(){\n  [ \"$_rootful\" ] && printf \"/root/.docker/config.json\" || printf \"%s/.docker/config.json\" \"$HOME\"\n}\n\ndocker::login(){\n  local user=\"$1\"\n  local password=\"$2\"\n  local registry_url=\"$3\"\n\n  local args=()\n  [ ! \"$_rootful\" ] || args=(sudo)\n  args+=(docker login --password-stdin)\n\n  log::debug \"${args[*]} --username=$user $registry_url\"\n  \"${args[@]}\" --username=\"$user\" \"$registry_url\" <<<\"$password\" >/dev/null\n}\n\n# Installation helpers\ninstall::kind(){\n  local version=\"$1\"\n  local temp\n  temp=\"$(fs::mktemp \"install\")\"\n\n  http::get \"$temp\"/kind \"https://kind.sigs.k8s.io/dl/$version/kind-linux-${GOARCH:-amd64}\"\n  host::install \"$temp\"/kind\n}\n\ninstall::kubectl(){\n  local version=\"${1:-v1.30.0}\"\n  [ \"$version\" ] || version=\"$(http::get /dev/stdout https://dl.k8s.io/release/stable.txt)\"\n  local temp\n  temp=\"$(fs::mktemp \"install\")\"\n\n  http::get \"$temp\"/kubectl \"https://dl.k8s.io/release/$version/bin/linux/${GOARCH:-amd64}/kubectl\"\n  host::install \"$temp\"/kubectl\n}\n\ninstall::nydus(){\n  local version=\"$1\"\n  local temp\n  temp=\"$(fs::mktemp \"install\")\"\n\n  http::get \"$temp\"/nydus-static.tgz \"https://github.com/dragonflyoss/nydus/releases/download/$version/nydus-static-$version-linux-${GOARCH:-amd64}.tgz\"\n  tar::expand \"$temp\" \"$temp\"/nydus-static.tgz\n  host::install \"$temp\"/nydus-static/nydus-image\n  host::install \"$temp\"/nydus-static/nydusify\n  host::install \"$temp\"/nydus-static/nydusd\n  host::install \"$temp\"/nydus-static/nydusctl\n}\n\ninstall::nerdctl(){\n  local version=\"$1\"\n  local temp\n  temp=\"$(fs::mktemp \"install\")\"\n\n  http::get \"$temp\"/nerdctl.tar.gz \"https://github.com/containerd/nerdctl/releases/download/v$version/nerdctl-$version-linux-${GOARCH:-amd64}.tar.gz\"\n  tar::expand \"$temp\" \"$temp\"/nerdctl.tar.gz\n  host::install \"$temp\"/nerdctl\n}\n\nstart::registry(){\n  local user=\"$1\"\n  local password=\"$2\"\n  local tempdir\n  tempdir=\"$(fs::mktemp registry)\"\n  local port=5000\n  local ip\n\n  exec::docker rm -f registry-auth-\"$port\" >/dev/null 2>&1 || true\n\n  exec::docker run \\\n    --rm \\\n    --entrypoint htpasswd \\\n    httpd:2 -Bbn \"$user\" \"$password\" > \"$tempdir\"/htpasswd\n\n  exec::docker run -d \\\n    -p \"$port\":5000 \\\n    --restart=always \\\n    --name registry-auth-\"$port\" \\\n    -v \"$tempdir\":/auth \\\n    -e \"REGISTRY_AUTH=htpasswd\" \\\n    -e \"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm\" \\\n    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \\\n    registry:2 >/dev/null\n\n  ip=\"$(ip addr show eth0 | grep 'inet ' | awk '{print $2}' | cut -d/ -f1)\"\n  printf \"%s:%s\" \"$ip\" \"$port\"\n}\n"
  },
  {
    "path": "tests/helpers/kind.sh",
    "content": "#!/usr/bin/env bash\nset -o errexit -o errtrace -o functrace -o nounset -o pipefail\n\nAUTH_TYPE=\"${AUTH_TYPE:-kubeconf}\"\nINDEX_DETECT=\"${INDEX_DETECT:-false}\"\n[ \"$(uname -m)\" == \"aarch64\" ] && GOARCH=arm64 || GOARCH=amd64\nROOTFUL=\"${ROOTFUL:-}\"\n\nroot=\"$(cd \"$(dirname \"${BASH_SOURCE[0]:-$PWD}\")\" 2>/dev/null 1>&2 && pwd)\"\nreadonly root\n# shellcheck source=/dev/null\n. \"$root/lib.sh\"\n# shellcheck source=/dev/null\n. \"$root/helpers.sh\"\n\n\nKIND_VERSION=v0.23.0\nKUBE_VERSION=v1.30.2\nNYDUS_VERSION=v2.3.0\nDOCKER_USER=testuser\nDOCKER_PASSWORD=testpassword\nNAMESPACE=nydus-system\n\nADDITIONAL_NYDUS_CONVERT_ARGS=\"\"\nif [ \"$INDEX_DETECT\" == \"true\" ]; then\n  ADDITIONAL_NYDUS_CONVERT_ARGS=\"--merge-platform\"\nfi\n\nlog::info \"Configuring rootful and github\"\nconfigure::rootful \"${ROOTFUL:-}\"\ngithub::settoken '${{ secrets.GITHUB_TOKEN }}'\n\nNYDUS_VERSION=\"$(github::releases::latest dragonflyoss/nydus | jq -rc 'select(.tag_name != null) | .tag_name' || printf \"%s\" \"$NYDUS_VERSION\")\"\nlog::info \"Get latest nydus version $NYDUS_VERSION\"\n\n# Build\nlog::info \"Building... make\"\n# Binaries are going to be copied over inside the kind container that likely has a different glibc we do not control.\n# So, build static\nif [ \"$LOG_LEVEL\" == debug ]; then\n  make -d static\nelse\n  make -s static\nfi\ncp bin/containerd-nydus-grpc ./\ncp bin/nydus-overlayfs ./\ncp -r misc/snapshotter/* ./\n\nlog::info \"Building... docker image\"\npwd\nexec::docker build --build-arg NYDUS_VER=\"$NYDUS_VERSION\" --build-arg KUBE_VER=\"$KUBE_VERSION\" -t local-dev:e2e .\n\n# Start local registry, and configure docker\nlog::info \"Starting registry\"\nregistry_url=\"$(start::registry \"$DOCKER_USER\" \"$DOCKER_PASSWORD\")\"\n# Configure template\nsed -e \"s|REGISTRY_URL|$registry_url|\" tests/e2e/k8s/test-pod.yaml.tpl > tests/e2e/k8s/test-pod.yaml\nconfigure::dockerd '{\n  \"exec-opts\": [\"native.cgroupdriver=cgroupfs\"],\n  \"cgroup-parent\": \"/actions_job\",\n  \"insecure-registries\" : [ \"'\"$registry_url\"'\" ]\n}'\nhttp::healthcheck \"$registry_url\"/v2/ 10 2 \"$DOCKER_USER\" \"$DOCKER_PASSWORD\"\nlog::info \"Login\"\ndocker::login \"$DOCKER_USER\" \"$DOCKER_PASSWORD\" \"$registry_url\"\n\n# Install dependencies\nlog::info \"Installing host dependencies\"\ninstall::kind \"$KIND_VERSION\"\ninstall::kubectl \"$KUBE_VERSION\"\ninstall::nydus \"$NYDUS_VERSION\"\n\n# Convert a nydus image and push it\nlog::info \"Converting test image to nydus and push\"\nexec::nydusify convert \\\n   --source busybox:latest \\\n   --target $registry_url/busybox:nydus-v6-latest \\\n   --fs-version 6 \\\n   ${ADDITIONAL_NYDUS_CONVERT_ARGS}\n\n# Create fresh cluster\nlog::info \"Creating new cluster\"\nexec::kind delete cluster 2>/dev/null || true\nexec::kind create cluster --config tests/e2e/k8s/kind.yaml --image \"kindest/node:$KUBE_VERSION\"\nexec::kind load docker-image local-dev:e2e\n\n# Deploy nydus\nlog::info \"Deploying nydus\"\nexec::kubectl create -f tests/e2e/k8s/snapshotter-\"$AUTH_TYPE\".yaml\npod=\"$(exec::kubectl --namespace \"$NAMESPACE\" get pods --no-headers -o custom-columns=NAME:metadata.name)\"\nexec::kubectl --namespace \"$NAMESPACE\" wait po \"$pod\" --for=condition=ready --timeout=1m\n\n# Reconfigure and restart kind containerd\nlog::info \"Restarting containerd\"\necho '[plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"'\"$registry_url\"'\"]\n          endpoint = [\"http://'\"$registry_url\"'\"]' |\n  exec::docker exec -i kind-control-plane sh -c 'cat /dev/stdin >> /etc/containerd/config.toml'\n\nexec::docker exec kind-control-plane systemctl restart containerd\n\n# Actual testing\nexec::kubectl delete --namespace \"$NAMESPACE\" secret generic regcred 2>/dev/null || true\nexec::kubectl create --namespace \"$NAMESPACE\" secret generic regcred \\\n  --from-file=.dockerconfigjson=\"$(docker::configpath)\" \\\n  --type=kubernetes.io/dockerconfigjson\n\nif [ \"$AUTH_TYPE\" == \"cri\" ]; then\n  exec::docker exec kind-control-plane sh -c 'echo \" --image-service-endpoint=unix:///run/containerd-nydus/containerd-nydus-grpc.sock\" >> /etc/default/kubelet'\n  exec::docker exec kind-control-plane sh -c 'systemctl daemon-reload && systemctl restart kubelet'\n  # The API server may become briefly unavailable after the kubelet\n  # restart. Wait for it to recover before issuing kubectl commands.\n  log::info \"Waiting for API server to recover\"\n  for _ in $(seq 1 10); do\n    kubectl get --raw /healthz &>/dev/null && break\n    sleep 2\n  done\n  kubectl get --raw /healthz &>/dev/null || {\n    log::error \"API server did not recover within 20s\"\n    exit 1\n  }\nfi\n\nexec::kubectl apply -f tests/e2e/k8s/test-pod.yaml\nexec::kubectl wait po test-pod --namespace nydus-system --for=condition=ready --timeout=1m || {\n  exec::kubectl --namespace nydus-system get pods\n  exec::kubectl --namespace nydus-system get events\n  exec::kubectl --namespace nydus-system logs nydus-snapshotter\n  exec::kubectl --namespace nydus-system logs test-pod\n  exit 1\n}\n\nif [ \"$INDEX_DETECT\" == \"true\" ]; then\n  snapshotter_logs=\"$(exec::kubectl --namespace nydus-system exec nydus-snapshotter -- cat /var/lib/containerd/io.containerd.snapshotter.v1.nydus/logs/nydus-snapshotter.log)\"\n  echo \"$snapshotter_logs\" | grep -q \"Found nydus alternative image in index for image\" || {\n    log::error \"Nydus snapshotter did not detect nydus image in index. Logs:\"\n    log::error \"$snapshotter_logs\"\n    exit 1\n  }\nfi\n\nexec::kubectl delete -f tests/e2e/k8s/test-pod.yaml\n"
  },
  {
    "path": "tests/helpers/lib.sh",
    "content": "#!/usr/bin/env bash\n\n#   Copyright The containerd Authors.\n\n#   Licensed under the Apache License, Version 2.0 (the \"License\");\n#   you may not use this file except in compliance with the License.\n#   You may obtain a copy of the License at\n\n#       http://www.apache.org/licenses/LICENSE-2.0\n\n#   Unless required by applicable law or agreed to in writing, software\n#   distributed under the License is distributed on an \"AS IS\" BASIS,\n#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#   See the License for the specific language governing permissions and\n#   limitations under the License.\n\n# shellcheck disable=SC2034\nset -o errexit -o errtrace -o functrace -o nounset -o pipefail\n\n## This is a library of generic helpers that can be used accross many different projects\n\n# Simple logger\nreadonly LOG_LEVEL_DEBUG=0\nreadonly LOG_LEVEL_INFO=1\nreadonly LOG_LEVEL_WARNING=2\nreadonly LOG_LEVEL_ERROR=3\n\nreadonly LOG_COLOR_BLACK=0\nreadonly LOG_COLOR_RED=1\nreadonly LOG_COLOR_GREEN=2\nreadonly LOG_COLOR_YELLOW=3\nreadonly LOG_COLOR_BLUE=4\nreadonly LOG_COLOR_MAGENTA=5\nreadonly LOG_COLOR_CYAN=6\nreadonly LOG_COLOR_WHITE=7\nreadonly LOG_COLOR_DEFAULT=9\n\nreadonly LOG_STYLE_DEBUG=( setaf \"$LOG_COLOR_WHITE\" )\nreadonly LOG_STYLE_INFO=( setaf \"$LOG_COLOR_GREEN\" )\nreadonly LOG_STYLE_WARNING=( setaf \"$LOG_COLOR_YELLOW\" )\nreadonly LOG_STYLE_ERROR=( setaf \"$LOG_COLOR_RED\" )\n\n_log::log(){\n  local level\n  local style\n  local numeric_level\n  local message=\"$2\"\n\n  level=\"$(printf \"%s\" \"$1\" | tr '[:lower:]' '[:upper:]')\"\n  numeric_level=\"$(printf \"LOG_LEVEL_%s\" \"$level\")\"\n  style=\"LOG_STYLE_${level}[@]\"\n\n  [ \"${!numeric_level}\" -ge \"$LOG_LEVEL\" ] || return 0\n\n  [ ! \"$TERM\" ] || [ ! -t 2 ] || >&2 tput \"${!style}\" 2>/dev/null || true\n  >&2 printf \"[%s] %s: %s\\n\" \"$(date 2>/dev/null || true)\" \"$(printf \"%s\" \"$level\" | tr '[:lower:]' '[:upper:]')\" \"$message\"\n  [ ! \"$TERM\" ] || [ ! -t 2 ] || >&2 tput op 2>/dev/null || true\n}\n\nlog::init(){\n  local _ll\n  # Default log to warning if unspecified\n  _ll=\"$(printf \"LOG_LEVEL_%s\" \"${LOG_LEVEL:-warning}\" | tr '[:lower:]' '[:upper:]')\"\n  # Default to 3 (warning) if unrecognized\n  LOG_LEVEL=\"${!_ll:-3}\"\n}\n\nlog::debug(){\n  _log::log debug \"$@\"\n}\n\nlog::info(){\n  _log::log info \"$@\"\n}\n\nlog::warning(){\n  _log::log warning \"$@\"\n}\n\nlog::error(){\n  _log::log error \"$@\"\n}\n\n# Helpers\nhost::require(){\n  local binary=\"$1\"\n\n  log::debug \"Checking presence of $binary\"\n  command -v \"$binary\" >/dev/null || {\n    log::error \"You need $binary for this script to work, and it cannot be found in your path\"\n    return 1\n  }\n}\n\nhost::install(){\n  local binary\n\n  for binary in \"$@\"; do\n    log::debug \"sudo install -D -m 755 $binary /usr/local/bin/$(basename \"$binary\")\"\n    sudo install -D -m 755 \"$binary\" /usr/local/bin/\"$(basename \"$binary\")\"\n  done\n}\n\nfs::mktemp(){\n  local prefix=\"${1:-temporary}\"\n\n  mktemp -dq \"${TMPDIR:-/tmp}/$prefix.XXXXXX\" 2>/dev/null || mktemp -dq || {\n    log::error \"Failed to create temporary directory\"\n    return 1\n  }\n}\n\ntar::expand(){\n  local dir=\"$1\"\n  local arc=\"$2\"\n\n  log::debug \"tar -C $dir -xzf $arc\"\n  tar -C \"$dir\" -xzf \"$arc\"\n}\n\n_http::get(){\n  local url=\"$1\"\n  local output=\"$2\"\n  local retry=\"$3\"\n  local delay=\"$4\"\n  local user=\"${5:-}\"\n  local password=\"${6:-}\"\n  shift\n  shift\n  shift\n  shift\n  shift\n  shift\n\n  local header\n  local command=(curl -fsSL --retry-connrefused --retry \"$retry\" --retry-delay \"$delay\" -o \"$output\")\n  # Add a basic auth user if necessary\n  [ \"$user\" == \"\" ] || command+=(--user \"$user:$password\")\n  # Force tls v1.2 and no redirect to http if url scheme is https\n  [ \"${url:0:5}\" != \"https\" ] || command+=(--proto '=https' --tlsv1.2)\n  # Stuff in any additional arguments as headers\n  for header in \"$@\"; do\n    command+=(-H \"$header\")\n  done\n  # Debug\n  log::debug \"${command[*]} $url\"\n  # Exec\n  \"${command[@]}\" \"$url\" || {\n    log::error \"Failed to connect to $url with $retry retries every $delay seconds\"\n    return 1\n  }\n}\n\nhttp::get(){\n  local output=\"$1\"\n  local url=\"$2\"\n  shift\n  shift\n\n  _http::get \"$url\" \"$output\" \"2\" \"1\" \"\" \"\" \"$@\"\n}\n\nhttp::healthcheck(){\n  local url=\"$1\"\n  local retry=\"${2:-5}\"\n  local delay=\"${3:-1}\"\n  local user=\"${4:-}\"\n  local password=\"${5:-}\"\n  shift\n  shift\n  shift\n  shift\n  shift\n  _http::get \"$url\" /dev/null \"$retry\" \"$delay\" \"$user\" \"$password\" \"$@\"\n}\n\nhttp::checksum(){\n  local urls=(\"$@\")\n  local url\n\n  local temp\n  temp=\"$(fs::mktemp \"http-checksum\")\"\n\n  for url in \"${urls[@]}\"; do\n    http::get -o \"$temp/${url##*/}\" \"$url\"\n  done\n\n  cd \"$temp\"\n  shasum -a 256 ./*\n  cd - >/dev/null || true\n}\n\n# Github API helpers\n# Set GITHUB_TOKEN to use authenticated requests to workaround limitations\n\ngithub::settoken(){\n  local token=\"$1\"\n  # If passed token is a github action pattern replace, and we are NOT on github, ignore it\n  [ \"${token:0:3}\" == '${{' ] || GITHUB_TOKEN=\"$token\"\n}\n\ngithub::request(){\n  local endpoint=\"$1\"\n  local args=(\n    \"Accept: application/vnd.github+json\"\n    \"X-GitHub-Api-Version: 2022-11-28\"\n  )\n\n  [ \"${GITHUB_TOKEN:-}\" == \"\" ] || args+=(\"Authorization: Bearer $GITHUB_TOKEN\")\n\n  http::get /dev/stdout https://api.github.com/\"$endpoint\" \"${args[@]}\"\n}\n\ngithub::tags::latest(){\n  local repo=\"$1\"\n  github::request \"repos/$repo/tags\" | jq -rc .[0].name\n}\n\ngithub::releases::latest(){\n  local repo=\"$1\"\n  github::request \"repos/$repo/releases/latest\" | jq -rc .\n}\n\nlog::init\nhost::require jq\nhost::require tar\nhost::require curl\nhost::require shasum\n"
  },
  {
    "path": "tests/nydusd.go",
    "content": "/*\n * Copyright (c) 2022. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage tests\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/exec\"\n\t\"text/template\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n)\n\ntype NydusdConfig struct {\n\tEnablePrefetch bool\n\tNydusdPath     string\n\tBootstrapPath  string\n\tConfigPath     string\n\tBackendType    string\n\tBackendConfig  string\n\tBlobCacheDir   string\n\tAPISockPath    string\n\tMountPath      string\n\tMode           string\n\tDigestValidate bool\n}\n\n// Nydusd runs nydusd binary.\ntype Nydusd struct {\n\tNydusdConfig\n}\n\ntype daemonInfo struct {\n\tState string `json:\"state\"`\n}\n\nvar configTpl = `\n{\n\t\"device\": {\n\t\t\"backend\": {\n\t\t\t\"type\": \"{{.BackendType}}\",\n\t\t\t\"config\": {{.BackendConfig}}\n\t\t},\n\t\t\"cache\": {\n\t\t\t\"type\": \"blobcache\",\n\t\t\t\"config\": {\n\t\t\t\t\"work_dir\": \"{{.BlobCacheDir}}\"\n\t\t\t}\n\t\t}\n\t},\n\t\"mode\": \"{{.Mode}}\",\n\t\"iostats_files\": false,\n\t\"fs_prefetch\": {\n\t\t\"enable\": {{.EnablePrefetch}},\n\t\t\"threads_count\": 10,\n\t\t\"merging_size\": 131072\n\t},\n\t\"digest_validate\": {{.DigestValidate}},\n\t\"enable_xattr\": true,\n\t\"amplify_io\": 1048576\n}\n`\n\nfunc makeConfig(conf NydusdConfig) error {\n\ttpl := template.Must(template.New(\"\").Parse(configTpl))\n\n\tvar ret bytes.Buffer\n\tif err := tpl.Execute(&ret, conf); err != nil {\n\t\treturn errors.New(\"prepare config template for Nydusd\")\n\t}\n\n\tif err := os.WriteFile(conf.ConfigPath, ret.Bytes(), 0600); err != nil {\n\t\treturn errors.New(\"write config file for Nydusd\")\n\t}\n\n\treturn nil\n}\n\n// Wait until Nydusd ready by checking daemon state RUNNING\nfunc checkReady(ctx context.Context, sock string) <-chan bool {\n\tready := make(chan bool)\n\n\ttransport := &http.Transport{\n\t\tMaxIdleConns:          10,\n\t\tIdleConnTimeout:       10 * time.Second,\n\t\tExpectContinueTimeout: 1 * time.Second,\n\t\tDialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {\n\t\t\tdialer := &net.Dialer{\n\t\t\t\tTimeout:   5 * time.Second,\n\t\t\t\tKeepAlive: 5 * time.Second,\n\t\t\t}\n\t\t\treturn dialer.DialContext(ctx, \"unix\", sock)\n\t\t},\n\t}\n\n\tclient := &http.Client{\n\t\tTimeout:   30 * time.Second,\n\t\tTransport: transport,\n\t}\n\n\tgo func() {\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn\n\t\t\tdefault:\n\t\t\t}\n\n\t\t\tresp, err := client.Get(fmt.Sprintf(\"http://unix%s\", \"/api/v1/daemon\"))\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tdefer resp.Body.Close()\n\n\t\t\tbody, err := io.ReadAll(resp.Body)\n\t\t\tif err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvar info daemonInfo\n\t\t\tif err = json.Unmarshal(body, &info); err != nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif info.State == \"RUNNING\" {\n\t\t\t\tready <- true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}()\n\n\treturn ready\n}\n\nfunc NewNydusd(conf NydusdConfig) (*Nydusd, error) {\n\tif err := makeConfig(conf); err != nil {\n\t\treturn nil, errors.New(\"create config file for Nydusd\")\n\t}\n\treturn &Nydusd{\n\t\tNydusdConfig: conf,\n\t}, nil\n}\n\nfunc (nydusd *Nydusd) Mount() error {\n\t// Ignore the error since the nydusd may not ever start\n\t_ = nydusd.Umount()\n\n\targs := []string{\n\t\t\"--config\",\n\t\tnydusd.ConfigPath,\n\t\t\"--mountpoint\",\n\t\tnydusd.MountPath,\n\t\t\"--bootstrap\",\n\t\tnydusd.BootstrapPath,\n\t\t\"--apisock\",\n\t\tnydusd.APISockPath,\n\t\t\"--log-level\",\n\t\t\"error\",\n\t}\n\n\tcmd := exec.Command(nydusd.NydusdPath, args...)\n\tcmd.Stdout = os.Stdout\n\tcmd.Stderr = os.Stderr\n\n\trunErr := make(chan error)\n\tgo func() {\n\t\trunErr <- cmd.Run()\n\t}()\n\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tready := checkReady(ctx, nydusd.APISockPath)\n\n\tselect {\n\tcase err := <-runErr:\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"run Nydusd binary\")\n\t\t}\n\tcase <-ready:\n\t\treturn nil\n\tcase <-time.After(10 * time.Second):\n\t\treturn errors.New(\"timeout to wait Nydusd ready\")\n\t}\n\n\treturn nil\n}\n\nfunc (nydusd *Nydusd) Umount() error {\n\tif _, err := os.Stat(nydusd.MountPath); err == nil {\n\t\tcmd := exec.Command(\"umount\", nydusd.MountPath)\n\t\tcmd.Stdout = os.Stdout\n\t\tcmd.Stderr = os.Stderr\n\t\tif err := cmd.Run(); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "tools/optimizer-server/Cargo.toml",
    "content": "[package]\nname = \"optimizer-server\"\nversion = \"0.1.0\"\nedition = \"2021\"\ndescription = \"Optimizer server to generate accessed files in target mount namespace\"\nauthors = [\"The Nydus Developers\"]\nlicense = \"Apache-2.0 OR BSD-3-Clause\"\n\n[dependencies]\nclap = \"4.1.8\"\nlazy_static = \"1.4.0\"\nlibc = \"0.2.140\"\nnix = \"0.26.2\"\nserde = { version=\"1.0.198\", features = [\"derive\"] }\nserde_json = \"1.0.116\"\nsignal-hook = \"0.3.15\"\n"
  },
  {
    "path": "tools/optimizer-server/Makefile",
    "content": "OS ?= linux\nARCH ?= amd64\n\narch_amd64 := x86_64\narch_arm64 := aarch64\narch_ppc64le := powerpc64le\narch_riscv64 := riscv64gc\n\nlinker_amd64 := x86_64\nlinker_arm64 := aarch64\nlinker_ppc64le := powerpc64le\n\nifneq ($(arch_$(ARCH)),)\n    RUST_ARCH := $(arch_$(ARCH))\nelse\n    RUST_ARCH := $(ARCH)\nendif\n\nifneq ($(linker_$(ARCH)),)\n    RUST_LINKER := $(linker_$(ARCH))\nelse\n    RUST_LINKER := $(ARCH)\nendif\n\nRUST_TARGET := $(RUST_ARCH)-unknown-$(OS)-gnu\nRUST_LINKER := $(RUST_LINKER)-$(OS)-gnu-gcc\nRUST_TYPE := debug\n\nall: build\n\n.PHONY: .release_version .format build release\n\n.release_version:\n\t$(eval CARGO_BUILD_FLAGS += --release)\n\t$(eval RUST_TYPE := release)\n\t$(eval RUST_FLAGS += -C target-feature=+crt-static -C strip=symbols)\n\n.format:\n\tcargo fmt -- --check\n\nbuild: .format\n\trustup target add $(RUST_TARGET)\n\tRUSTFLAGS=\"-C linker=$(RUST_LINKER) $(RUST_FLAGS)\" cargo build $(CARGO_BUILD_FLAGS) --target $(RUST_TARGET)\n\tcargo clippy $(CARGO_BUILD_FLAGS) -- -Dwarnings\n\tinstall -D -m 755 target/$(RUST_TARGET)/$(RUST_TYPE)/optimizer-server bin/optimizer-server\n\nrelease: .format .release_version build\n\nstatic-release: .format \n\tcargo clippy $(CARGO_BUILD_FLAGS) -- -Dwarnings\n\tRUSTFLAGS=\"-C linker=$(RUST_LINKER) -C target-feature=+crt-static -C target-feature=+crt-static -C strip=symbols\" cargo build --release --target $(RUST_TARGET)\n\tinstall -D -m 755 target/$(RUST_TARGET)/release/optimizer-server bin/optimizer-server\n\nclean:\n\tcargo clean\n\trm -rf bin/*"
  },
  {
    "path": "tools/optimizer-server/src/main.rs",
    "content": "/*\n * Copyright (c) 2023. Nydus Developers. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\nuse std::{\n    env, ffi, fs, io,\n    io::Write,\n    mem,\n    os::unix::{io::AsRawFd, net::UnixStream},\n    path::{Path, PathBuf},\n    slice,\n    time::Instant,\n};\n\nuse nix::{\n    poll::{poll, PollFd, PollFlags},\n    sched::{setns, CloneFlags},\n    sys::wait::{waitpid, WaitStatus},\n    unistd::{fork, getpgid, ForkResult},\n};\nuse serde::Serialize;\n\nuse lazy_static::lazy_static;\nuse signal_hook::{consts::SIGTERM, low_level::pipe};\n\n#[derive(Debug, Clone, Copy)]\n#[repr(C)]\nstruct FanotifyEvent {\n    event_len: u32,\n    vers: u8,\n    reserved: u8,\n    metadata_len: u16,\n    mask: u64,\n    fd: i32,\n    pid: i32,\n}\n\n#[derive(Serialize, Debug)]\nstruct EventInfo {\n    path: String,\n    size: u64,\n    elapsed: u128,\n}\n\nimpl PartialEq for EventInfo {\n    fn eq(&self, target: &EventInfo) -> bool {\n        self.path == target.path\n    }\n}\n\nlazy_static! {\n    static ref FAN_EVENT_METADATA_LEN: usize = mem::size_of::<FanotifyEvent>();\n    static ref BEGIN_TIME: Instant = Instant::now();\n}\n\nconst DEFAULT_TARGET: &str = \"/\";\n\nconst FAN_CLOEXEC: u32 = 0x0000_0001;\nconst FAN_NONBLOCK: u32 = 0x0000_0002;\nconst FAN_CLASS_CONTENT: u32 = 0x0000_0004;\n\nconst O_RDONLY: u32 = 0;\nconst O_LARGEFILE: u32 = 0;\n\nconst FAN_MARK_ADD: u32 = 0x0000_0001;\nconst FAN_MARK_MOUNT: u32 = 0x0000_0010;\n\nconst FAN_ACCESS: u64 = 0x0000_0001;\nconst FAN_OPEN: u64 = 0x0000_0020;\nconst FAN_OPEN_EXEC: u64 = 0x00001000;\nconst AT_FDCWD: i32 = -100;\n\n#[allow(dead_code)]\n#[derive(Debug)]\nenum SetnsError {\n    IO(io::Error),\n    Nix(nix::Error),\n}\n\n#[allow(dead_code)]\n#[derive(Debug)]\nenum SendError {\n    IO(io::Error),\n    Serde(serde_json::Error),\n}\n\nfn get_pid() -> Option<String> {\n    env::var(\"_MNTNS_PID\").ok()\n}\n\nfn get_target() -> String {\n    env::var(\"_TARGET\").map_or(DEFAULT_TARGET.to_string(), |str| str)\n}\n\nfn get_fd_path(fd: i32) -> io::Result<PathBuf> {\n    let fd_path = format!(\"/proc/self/fd/{fd}\");\n    fs::read_link(fd_path)\n}\n\nfn set_ns(ns_path: String, flags: CloneFlags) -> Result<(), SetnsError> {\n    let file = fs::File::open(Path::new(ns_path.as_str())).map_err(SetnsError::IO)?;\n    setns(file.as_raw_fd(), flags).map_err(SetnsError::Nix)\n}\n\nfn init_fanotify() -> Result<i32, io::Error> {\n    unsafe {\n        match libc::fanotify_init(\n            FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,\n            O_RDONLY | O_LARGEFILE,\n        ) {\n            -1 => Err(io::Error::last_os_error()),\n            fd => Ok(fd),\n        }\n    }\n}\n\nfn mark_fanotify(fd: i32, path: &str) -> Result<(), io::Error> {\n    let path = ffi::CString::new(path)?;\n    unsafe {\n        match libc::fanotify_mark(\n            fd,\n            FAN_MARK_ADD | FAN_MARK_MOUNT,\n            FAN_OPEN | FAN_ACCESS | FAN_OPEN_EXEC,\n            AT_FDCWD,\n            path.as_ptr(),\n        ) {\n            0 => Ok(()),\n            _ => Err(io::Error::last_os_error()),\n        }\n    }\n}\n\nfn read_fanotify(fanotify_fd: i32) -> Vec<FanotifyEvent> {\n    let mut vec = Vec::new();\n    unsafe {\n        let buffer = libc::malloc(*FAN_EVENT_METADATA_LEN * 1024);\n        let sizeof = libc::read(fanotify_fd, buffer, *FAN_EVENT_METADATA_LEN * 1024);\n        let src = slice::from_raw_parts(\n            buffer as *mut FanotifyEvent,\n            sizeof as usize / *FAN_EVENT_METADATA_LEN,\n        );\n        vec.extend_from_slice(src);\n        libc::free(buffer);\n    }\n    vec\n}\n\nfn close_fd(fd: i32) {\n    unsafe {\n        libc::close(fd);\n    }\n}\n\nfn generate_event_info(path: &Path) -> Result<EventInfo, io::Error> {\n    fs::metadata(path).map(|metadata| EventInfo {\n        path: path.to_string_lossy().to_string(),\n        size: metadata.len(),\n        elapsed: BEGIN_TIME.elapsed().as_micros(),\n    })\n}\n\nfn send_event(event: &EventInfo) -> Result<(), SendError> {\n    let mut writer = io::stdout();\n    let event_string = serde_json::to_string(event).map_err(SendError::Serde)?;\n    writer\n        .write_all(format!(\"{event_string}\\n\").as_bytes())\n        .map_err(SendError::IO)?;\n    writer.flush().map_err(SendError::IO)\n}\n\nfn handle_event(event: &FanotifyEvent, event_duplicate: &mut Vec<String>) -> Result<(), SendError> {\n    let path = get_fd_path(event.fd).map_err(SendError::IO)?;\n    let info = generate_event_info(&path).map_err(SendError::IO)?;\n    if !event_duplicate.contains(&info.path) {\n        send_event(&info)?;\n        event_duplicate.push(info.path);\n    }\n    Ok(())\n}\n\nfn handle_fanotify_event(fd: i32) {\n    let mut event_duplicate = Vec::new();\n    let (reader, writer) = match UnixStream::pair() {\n        Ok((reader, writer)) => (reader, writer),\n        Err(e) => {\n            eprintln!(\"failed to create a pair of sockets: {e:?}\");\n            return;\n        }\n    };\n    if let Err(e) = pipe::register(SIGTERM, writer) {\n        eprintln!(\"failed to set SIGTERM signal handler {e:?}\");\n        return;\n    }\n    let mut fds = [\n        PollFd::new(fd.as_raw_fd(), PollFlags::POLLIN),\n        PollFd::new(reader.as_raw_fd(), PollFlags::POLLIN),\n    ];\n\n    loop {\n        match poll(&mut fds, -1) {\n            Ok(polled_num) => {\n                if polled_num <= 0 {\n                    eprintln!(\"polled_num <= 0!\");\n                    break;\n                }\n\n                if let Some(flag) = fds[0].revents() {\n                    if flag.contains(PollFlags::POLLIN) {\n                        let events = read_fanotify(fd);\n                        for event in events {\n                            if let Err(e) = handle_event(&event, &mut event_duplicate) {\n                                eprintln!(\"failed to handle event {event:?} {e:?}\")\n                            };\n                            // No matter the target path is valid or not, we should close the fd\n                            close_fd(event.fd);\n                        }\n                    }\n                }\n\n                if let Some(flag) = fds[1].revents() {\n                    if flag.contains(PollFlags::POLLIN) {\n                        println!(\"received SIGTERM signal\");\n                        break;\n                    }\n                }\n            }\n            Err(e) => {\n                if e == nix::Error::EINTR {\n                    continue;\n                }\n                eprintln!(\"Poll error {e:?}\");\n                break;\n            }\n        }\n    }\n}\n\nfn start_fanotify() -> Result<(), io::Error> {\n    let fd = init_fanotify()?;\n    mark_fanotify(fd, get_target().as_str())?;\n    handle_fanotify_event(fd);\n    Ok(())\n}\n\nfn join_namespace(pid: String) -> Result<(), SetnsError> {\n    set_ns(format!(\"/proc/{pid}/ns/pid\"), CloneFlags::CLONE_NEWPID)?;\n    set_ns(format!(\"/proc/{pid}/ns/mnt\"), CloneFlags::CLONE_NEWNS)?;\n    Ok(())\n}\n\nfn main() {\n    if let Some(pid) = get_pid() {\n        if let Err(e) = join_namespace(pid) {\n            eprintln!(\"join namespace failed {e:?}\");\n            return;\n        }\n    }\n\n    match unsafe { fork() } {\n        Ok(ForkResult::Child) => {\n            if let Err(e) = start_fanotify() {\n                eprintln!(\"failed to start fanotify server {e:?}\");\n            }\n        }\n        Ok(ForkResult::Parent { child }) => {\n            if let Err(e) = getpgid(Some(child)).map(|pgid| {\n                eprintln!(\"forked optimizer server subprocess, pid: {child}, pgid: {pgid}\");\n            }) {\n                eprintln!(\"failed to get pgid of {child} {e:?}\");\n            }\n\n            match waitpid(child, None) {\n                Ok(WaitStatus::Signaled(pid, signal, _)) => {\n                    eprintln!(\"child process {pid} was killed by signal {signal}\");\n                }\n                Ok(WaitStatus::Stopped(pid, signal)) => {\n                    eprintln!(\"child process {pid} was stopped by signal {signal}\");\n                }\n                Err(e) => {\n                    eprintln!(\"failed to wait for child process: {e}\");\n                }\n                _ => {}\n            }\n        }\n        Err(e) => {\n            eprintln!(\"fork failed: unable to create child process: {e:?}\");\n        }\n    }\n}\n"
  },
  {
    "path": "version/version.go",
    "content": "/*\n * Copyright (c) 2020. Ant Group. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\npackage version\n\nimport \"runtime\"\n\nvar (\n\t// Version holds the complete version number. Filled in at linking time.\n\tVersion = \"unknown\"\n\n\t// Revision is filled with the VCS (e.g. git) revision being used to build\n\t// the program at linking time.\n\tRevision = \"unknown\"\n\n\t// GoVersion is Go tree's version.\n\tGoVersion = runtime.Version()\n\n\t// BuildTimestamp is timestamp of building.\n\tBuildTimestamp = \"unknown\"\n)\n"
  }
]