Files
overlayfs/overlayfs_windows.go
Matheus Sampaio Queiroga 35846fe633
Some checks failed
Golang test / go-test (ubuntu-latest) (push) Successful in 11s
Golang test / go-test (windows-latest) (push) Has been cancelled
Remove FreeBSD support and clean up related code; update Linux test to use consistent temp directories.
Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
2025-07-12 22:50:58 -03:00

117 lines
3.1 KiB
Go

//go:build windows && (amd64 || 386 || arm64)
package overlayfs
import (
"os"
"path/filepath"
"runtime"
"syscall"
"unsafe"
"github.com/aegistudio/go-winfsp"
"github.com/aegistudio/go-winfsp/gofs"
)
// Check if winfsp is available on the system
func OverlayfsAvaible() bool {
var dllName string
switch runtime.GOARCH {
case "386":
dllName = "winfsp-x86.dll"
case "amd64":
dllName = "winfsp-x64.dll"
case "arm64":
dllName = "winfsp-a64.dll"
default:
return false
}
dll, _ := syscall.LoadDLL(dllName)
if dll != nil {
_ = dll.Release()
return true
}
var keyReg syscall.Handle // HKLM\\Software\\WinFSP
keyName, err := syscall.UTF16PtrFromString("Software\\WinFsp")
if err != nil {
return false
} else if err := syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, keyName, 0, syscall.KEY_READ|syscall.KEY_WOW64_32KEY, &keyReg); err != nil {
return false
}
defer syscall.RegCloseKey(keyReg)
valueName, err := syscall.UTF16PtrFromString("InstallDir")
if err != nil {
return false
}
var pathBuf [syscall.MAX_PATH]uint16
var valueType, valueSize uint32
valueSize = uint32(len(pathBuf)) * 2
if err := syscall.RegQueryValueEx(keyReg, valueName, nil, &valueType, (*byte)(unsafe.Pointer(&pathBuf)), &valueSize); err != nil {
return false
} else if valueType != syscall.REG_SZ {
return false
}
path := pathBuf[:int(valueSize/2)]
if len(path) > 0 && path[len(path)-1] == 0 {
path = path[:len(path)-1]
}
installPath := syscall.UTF16ToString(path)
// Attempt to load the DLL that we have found.
dll, err = syscall.LoadDLL(filepath.Join(installPath, "bin", dllName))
if err != nil {
return false
}
_ = dll.Release()
return true
}
type winfspMerge struct{ *Overlayfs }
func (winfsp winfspMerge) OpenFile(name string, flag int, perm os.FileMode) (gofs.File, error) {
return winfsp.Overlayfs.OpenFile(name, flag, perm)
}
func (fsp *Overlayfs) getWinfsp() (*winfsp.FileSystem, error) {
if fssp, ok := fsp.ProcessInternal.(*winfsp.FileSystem); ok {
return fssp, nil
}
return nil, ErrUnmounted
}
// Mount go-mergefs with winfsp
//
// This function supports drive letters (X:) or directories as mount points:
//
// - Drive letters: Refer to the documentation of the DefineDosDevice Windows API to better understand how they are created.
//
// - Directories: They can be used as mount points for disk based file systems. They cannot be used for network file systems. This is a limitation that Windows imposes on junctions.
func (overlay *Overlayfs) Mount() error {
_, err := overlay.getWinfsp()
if err != nil && err != ErrUnmounted {
return err
}
// Clean folder path to mount
if !filepath.IsAbs(overlay.Target) {
if overlay.Target, err = filepath.Abs(overlay.Target); err != nil {
return err
}
}
overlay.ProcessInternal, err = winfsp.Mount(gofs.New(&winfspMerge{Overlayfs: overlay}), overlay.Target, winfsp.FileSystemName("go-mergefs"))
return err
}
// Umount winfsp filesystem if mounted
func (overlay *Overlayfs) Unmount() error {
fssp, err := overlay.getWinfsp()
if err == nil && fssp != nil {
fssp.Unmount()
overlay.ProcessInternal = nil
}
return nil
}