Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 133 additions & 53 deletions internal/winapi/cimfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,140 @@
package winapi

import (
"unsafe"

"github.com/Microsoft/go-winio/pkg/guid"
"golang.org/x/sys/windows"

"github.com/Microsoft/hcsshim/internal/winapi/cimfs"
"github.com/Microsoft/hcsshim/internal/winapi/cimwriter"
"github.com/Microsoft/hcsshim/internal/winapi/types"
)

type g = guid.GUID
type FsHandle uintptr
type StreamHandle uintptr

type CimFsFileMetadata struct {
Attributes uint32
FileSize int64

CreationTime windows.Filetime
LastWriteTime windows.Filetime
ChangeTime windows.Filetime
LastAccessTime windows.Filetime

SecurityDescriptorBuffer unsafe.Pointer
SecurityDescriptorSize uint32

ReparseDataBuffer unsafe.Pointer
ReparseDataSize uint32

ExtendedAttributes unsafe.Pointer
EACount uint32
}

type CimFsImagePath struct {
ImageDir *uint16
ImageName *uint16
}

//sys CimMountImage(imagePath string, fsName string, flags uint32, volumeID *g) (hr error) = cimfs.CimMountImage?
//sys CimDismountImage(volumeID *g) (hr error) = cimfs.CimDismountImage?

//sys CimCreateImage(imagePath string, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) = cimwriter.CimCreateImage?
//sys CimCreateImage2(imagePath string, flags uint32, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) = cimwriter.CimCreateImage2?
//sys CimCloseImage(cimFSHandle FsHandle) = cimwriter.CimCloseImage?
//sys CimCommitImage(cimFSHandle FsHandle) (hr error) = cimwriter.CimCommitImage?

//sys CimCreateFile(cimFSHandle FsHandle, path string, file *CimFsFileMetadata, cimStreamHandle *StreamHandle) (hr error) = cimwriter.CimCreateFile?
//sys CimCloseStream(cimStreamHandle StreamHandle) (hr error) = cimwriter.CimCloseStream?
//sys CimWriteStream(cimStreamHandle StreamHandle, buffer uintptr, bufferSize uint32) (hr error) = cimwriter.CimWriteStream?
//sys CimDeletePath(cimFSHandle FsHandle, path string) (hr error) = cimwriter.CimDeletePath?
//sys CimCreateHardLink(cimFSHandle FsHandle, newPath string, oldPath string) (hr error) = cimwriter.CimCreateHardLink?
//sys CimCreateAlternateStream(cimFSHandle FsHandle, path string, size uint64, cimStreamHandle *StreamHandle) (hr error) = cimwriter.CimCreateAlternateStream?
//sys CimAddFsToMergedImage(cimFSHandle FsHandle, path string) (hr error) = cimwriter.CimAddFsToMergedImage?
//sys CimAddFsToMergedImage2(cimFSHandle FsHandle, path string, flags uint32) (hr error) = cimwriter.CimAddFsToMergedImage2?
//sys CimMergeMountImage(numCimPaths uint32, backingImagePaths *CimFsImagePath, flags uint32, volumeID *g) (hr error) = cimfs.CimMergeMountImage?
//sys CimTombstoneFile(cimFSHandle FsHandle, path string) (hr error) = cimwriter.CimTombstoneFile?
//sys CimCreateMergeLink(cimFSHandle FsHandle, newPath string, oldPath string) (hr error) = cimwriter.CimCreateMergeLink?
//sys CimSealImage(blockCimPath string, hashSize *uint64, fixedHeaderSize *uint64, hash *byte) (hr error) = cimwriter.CimSealImage?
//sys CimGetVerificationInformation(blockCimPath string, isSealed *uint32, hashSize *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte) (hr error) = cimfs.CimGetVerificationInformation?
//sys CimMountVerifiedImage(imagePath string, fsName string, flags uint32, volumeID *g, hashSize uint16, hash *byte) (hr error) = cimfs.CimMountVerifiedImage?
//sys CimMergeMountVerifiedImage(numCimPaths uint32, backingImagePaths *CimFsImagePath, flags uint32, volumeID *g, hashSize uint16, hash *byte) (hr error) = cimfs.CimMergeMountVerifiedImage

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could probably do something like the below to simplify a lot the boilerplate for picking between the cimfs and cimwriter (playground):

func pick[F any](cwFn, cFn F) F {
	if cimwriter.CimWriterSupported() {
		return cwFn
	}
	return cFn
}

func CimCreateImage(imagePath string, oldFSName *uint16, newFSName *uint16, cimFSHandle *types.FsHandle) error {
	return pick(
		cimwriter.CimCreateImage,
		cimfs.CimCreateImage,
	)(imagePath, oldFSName, newFSName, cimFSHandle)
}

func CimMountImage(imagePath string, fsName string, flags uint32, volumeID *guid.GUID) error {
return cimfs.CimMountImage(imagePath, fsName, flags, volumeID)
}

func CimDismountImage(volumeID *guid.GUID) error {
return cimfs.CimDismountImage(volumeID)
}

func CimCreateImage(imagePath string, oldFSName *uint16, newFSName *uint16, cimFSHandle *types.FsHandle) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimCreateImage(imagePath, oldFSName, newFSName, cimFSHandle)
}
return cimfs.CimCreateImage(imagePath, oldFSName, newFSName, cimFSHandle)
}

func CimCreateImage2(imagePath string, flags uint32, oldFSName *uint16, newFSName *uint16, cimFSHandle *types.FsHandle) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimCreateImage2(imagePath, flags, oldFSName, newFSName, cimFSHandle)
}
return cimfs.CimCreateImage2(imagePath, flags, oldFSName, newFSName, cimFSHandle)
}

func CimCloseImage(cimFSHandle types.FsHandle) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimCloseImage(cimFSHandle)
}
return cimfs.CimCloseImage(cimFSHandle)
}

func CimCommitImage(cimFSHandle types.FsHandle) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimCommitImage(cimFSHandle)
}
return cimfs.CimCommitImage(cimFSHandle)
}

func CimCreateFile(cimFSHandle types.FsHandle, path string, file *types.CimFsFileMetadata, cimStreamHandle *types.StreamHandle) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimCreateFile(cimFSHandle, path, file, cimStreamHandle)
}
return cimfs.CimCreateFile(cimFSHandle, path, file, cimStreamHandle)
}

func CimCloseStream(cimStreamHandle types.StreamHandle) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimCloseStream(cimStreamHandle)
}
return cimfs.CimCloseStream(cimStreamHandle)
}

func CimWriteStream(cimStreamHandle types.StreamHandle, buffer uintptr, bufferSize uint32) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimWriteStream(cimStreamHandle, buffer, bufferSize)
}
return cimfs.CimWriteStream(cimStreamHandle, buffer, bufferSize)
}

func CimDeletePath(cimFSHandle types.FsHandle, path string) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimDeletePath(cimFSHandle, path)
}
return cimfs.CimDeletePath(cimFSHandle, path)
}

func CimCreateHardLink(cimFSHandle types.FsHandle, newPath string, oldPath string) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimCreateHardLink(cimFSHandle, newPath, oldPath)
}
return cimfs.CimCreateHardLink(cimFSHandle, newPath, oldPath)
}

func CimCreateAlternateStream(cimFSHandle types.FsHandle, path string, size uint64, cimStreamHandle *types.StreamHandle) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimCreateAlternateStream(cimFSHandle, path, size, cimStreamHandle)
}
return cimfs.CimCreateAlternateStream(cimFSHandle, path, size, cimStreamHandle)
}

func CimAddFsToMergedImage(cimFSHandle types.FsHandle, path string) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimAddFsToMergedImage(cimFSHandle, path)
}
return cimfs.CimAddFsToMergedImage(cimFSHandle, path)
}

func CimAddFsToMergedImage2(cimFSHandle types.FsHandle, path string, flags uint32) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimAddFsToMergedImage2(cimFSHandle, path, flags)
}
return cimfs.CimAddFsToMergedImage2(cimFSHandle, path, flags)
}

func CimMergeMountImage(numCimPaths uint32, backingImagePaths *types.CimFsImagePath, flags uint32, volumeID *guid.GUID) error {
return cimfs.CimMergeMountImage(numCimPaths, backingImagePaths, flags, volumeID)
}

func CimTombstoneFile(cimFSHandle types.FsHandle, path string) error {
if cimwriter.CimWriterSupported() {
return cimwriter.CimTombstoneFile(cimFSHandle, path)
}
return cimfs.CimTombstoneFile(cimFSHandle, path)
}

func CimCreateMergeLink(cimFSHandle types.FsHandle, newPath string, oldPath string) (hr error) {
if cimwriter.CimWriterSupported() {
return cimwriter.CimCreateMergeLink(cimFSHandle, newPath, oldPath)
}
return cimfs.CimCreateMergeLink(cimFSHandle, newPath, oldPath)
}

func CimSealImage(blockCimPath string, hashSize *uint64, fixedHeaderSize *uint64, hash *byte) (hr error) {
if cimwriter.CimWriterSupported() {
return cimwriter.CimSealImage(blockCimPath, hashSize, fixedHeaderSize, hash)
}
return cimfs.CimSealImage(blockCimPath, hashSize, fixedHeaderSize, hash)
}

func CimGetVerificationInformation(blockCimPath string, isSealed *uint32, hashSize *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte) (hr error) {
return cimfs.CimGetVerificationInformation(blockCimPath, isSealed, hashSize, signatureSize, fixedHeaderSize, hash, signature)
}

func CimMountVerifiedImage(imagePath string, fsName string, flags uint32, volumeID *guid.GUID, hashSize uint16, hash *byte) error {
return cimfs.CimMountVerifiedImage(imagePath, fsName, flags, volumeID, hashSize, hash)
}

func CimMergeMountVerifiedImage(numCimPaths uint32, backingImagePaths *types.CimFsImagePath, flags uint32, volumeID *guid.GUID, hashSize uint16, hash *byte) error {
return cimfs.CimMergeMountVerifiedImage(numCimPaths, backingImagePaths, flags, volumeID, hashSize, hash)
}
45 changes: 45 additions & 0 deletions internal/winapi/cimfs/cimfs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//go:build windows

package cimfs

import (
"github.com/Microsoft/go-winio/pkg/guid"

"github.com/Microsoft/hcsshim/internal/winapi/types"
)

// Type aliases
type g = guid.GUID
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know its already called g elsewhere, but can we do

Suggested change
type g = guid.GUID
type GUID = guid.GUID

type FsHandle = types.FsHandle
type StreamHandle = types.StreamHandle
type FileMetadata = types.CimFsFileMetadata
type ImagePath = types.CimFsImagePath

//sys CimMountImage(imagePath string, fsName string, flags uint32, volumeID *g) (hr error) = cimfs.CimMountImage?
//sys CimDismountImage(volumeID *g) (hr error) = cimfs.CimDismountImage?

//sys CimCreateImage(imagePath string, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) = cimfs.CimCreateImage?
//sys CimCreateImage2(imagePath string, flags uint32, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) = cimfs.CimCreateImage2?
//sys CimCloseImage(cimFSHandle FsHandle) = cimfs.CimCloseImage?
//sys CimCommitImage(cimFSHandle FsHandle) (hr error) = cimfs.CimCommitImage?

//sys CimCreateFile(cimFSHandle FsHandle, path string, file *FileMetadata, cimStreamHandle *StreamHandle) (hr error) = cimfs.CimCreateFile?
//sys CimCloseStream(cimStreamHandle StreamHandle) (hr error) = cimfs.CimCloseStream?
//sys CimWriteStream(cimStreamHandle StreamHandle, buffer uintptr, bufferSize uint32) (hr error) = cimfs.CimWriteStream?
//sys CimDeletePath(cimFSHandle FsHandle, path string) (hr error) = cimfs.CimDeletePath?
//sys CimCreateHardLink(cimFSHandle FsHandle, newPath string, oldPath string) (hr error) = cimfs.CimCreateHardLink?
//sys CimCreateAlternateStream(cimFSHandle FsHandle, path string, size uint64, cimStreamHandle *StreamHandle) (hr error) = cimfs.CimCreateAlternateStream?
//sys CimAddFsToMergedImage(cimFSHandle FsHandle, path string) (hr error) = cimfs.CimAddFsToMergedImage?
//sys CimAddFsToMergedImage2(cimFSHandle FsHandle, path string, flags uint32) (hr error) = cimfs.CimAddFsToMergedImage2?
//sys CimMergeMountImage(numCimPaths uint32, backingImagePaths *ImagePath, flags uint32, volumeID *g) (hr error) = cimfs.CimMergeMountImage?
//sys CimTombstoneFile(cimFSHandle FsHandle, path string) (hr error) = cimfs.CimTombstoneFile?
//sys CimCreateMergeLink(cimFSHandle FsHandle, newPath string, oldPath string) (hr error) = cimfs.CimCreateMergeLink?
//sys CimSealImage(blockCimPath string, hashSize *uint64, fixedHeaderSize *uint64, hash *byte) (hr error) = cimfs.CimSealImage?
//sys CimGetVerificationInformation(blockCimPath string, isSealed *uint32, hashSize *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte) (hr error) = cimfs.CimGetVerificationInformation?
//sys CimMountVerifiedImage(imagePath string, fsName string, flags uint32, volumeID *g, hashSize uint16, hash *byte) (hr error) = cimfs.CimMountVerifiedImage?
//sys CimMergeMountVerifiedImage(numCimPaths uint32, backingImagePaths *ImagePath, flags uint32, volumeID *g, hashSize uint16, hash *byte) (hr error) = cimfs.CimMergeMountVerifiedImage
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

carried over from internal/winapi/cimfs.go, but CimMergeMountVerifiedImage is the declaration without a ?:

Suggested change
//sys CimMergeMountVerifiedImage(numCimPaths uint32, backingImagePaths *ImagePath, flags uint32, volumeID *g, hashSize uint16, hash *byte) (hr error) = cimfs.CimMergeMountVerifiedImage
//sys CimMergeMountVerifiedImage(numCimPaths uint32, backingImagePaths *ImagePath, flags uint32, volumeID *g, hashSize uint16, hash *byte) (hr error) = cimfs.CimMergeMountVerifiedImage?


// CimFsSupported checks if cimfs.dll is present on the system.
func CimFsSupported() bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: avoid stutter here (cimfs.CimFsSupported()) and with cimwriter (cimwriter.CimWriterSupported())

Suggested change
func CimFsSupported() bool {
func Supported() bool {

return modcimfs.Load() == nil
}
3 changes: 3 additions & 0 deletions internal/winapi/cimfs/syscall.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package cimfs

//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go
Loading