From b6db185e79141d9e9ffdb7f35ce154ffad3357b8 Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Fri, 14 Oct 2022 16:57:03 +0900 Subject: [PATCH 1/2] removed white space --- virtualization.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virtualization.m b/virtualization.m index 331cbf0..5a782aa 100644 --- a/virtualization.m +++ b/virtualization.m @@ -45,7 +45,7 @@ - (BOOL)listener:(VZVirtioSocketListener *)listener shouldAcceptNewConnection:(V /*! @abstract Create a VZLinuxBootLoader with the Linux kernel passed as URL. - @param kernelPath Path of Linux kernel on the local file system. + @param kernelPath Path of Linux kernel on the local file system. */ void *newVZLinuxBootLoader(const char *kernelPath) { From 117c12a5820925a3e7117b1a547af37ef845f085 Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Fri, 14 Oct 2022 16:57:41 +0900 Subject: [PATCH 2/2] fixed issue #43 --- bootloader.go | 19 +++++++++--- console.go | 9 ++++-- issues_arm64_test.go | 34 ++++++++++++++++++++ issues_test.go | 69 ++++++++++++++++++++++++++++++++++++++--- osversion_arm64_test.go | 3 ++ shared_folder.go | 11 ++++++- storage.go | 8 ++++- virtualization_arm64.go | 10 ++++++ 8 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 issues_arm64_test.go diff --git a/bootloader.go b/bootloader.go index 7f74141..69d613d 100644 --- a/bootloader.go +++ b/bootloader.go @@ -8,6 +8,7 @@ package vz import "C" import ( "fmt" + "os" "runtime" ) @@ -44,26 +45,31 @@ func (b *LinuxBootLoader) String() string { ) } -type LinuxBootLoaderOption func(b *LinuxBootLoader) +type LinuxBootLoaderOption func(b *LinuxBootLoader) error // WithCommandLine sets the command-line parameters. // see: https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html func WithCommandLine(cmdLine string) LinuxBootLoaderOption { - return func(b *LinuxBootLoader) { + return func(b *LinuxBootLoader) error { b.cmdLine = cmdLine cs := charWithGoString(cmdLine) defer cs.Free() C.setCommandLineVZLinuxBootLoader(b.Ptr(), cs.CString()) + return nil } } // WithInitrd sets the optional initial RAM disk. func WithInitrd(initrdPath string) LinuxBootLoaderOption { - return func(b *LinuxBootLoader) { + return func(b *LinuxBootLoader) error { + if _, err := os.Stat(initrdPath); err != nil { + return fmt.Errorf("invalid initial RAM disk path: %w", err) + } b.initrdPath = initrdPath cs := charWithGoString(initrdPath) defer cs.Free() C.setInitialRamdiskURLVZLinuxBootLoader(b.Ptr(), cs.CString()) + return nil } } @@ -75,6 +81,9 @@ func NewLinuxBootLoader(vmlinuz string, opts ...LinuxBootLoaderOption) (*LinuxBo if macosMajorVersionLessThan(11) { return nil, ErrUnsupportedOSVersion } + if _, err := os.Stat(vmlinuz); err != nil { + return nil, fmt.Errorf("invalid linux kernel path: %w", err) + } vmlinuzPath := charWithGoString(vmlinuz) defer vmlinuzPath.Free() @@ -90,7 +99,9 @@ func NewLinuxBootLoader(vmlinuz string, opts ...LinuxBootLoaderOption) (*LinuxBo self.Release() }) for _, opt := range opts { - opt(bootLoader) + if err := opt(bootLoader); err != nil { + return nil, err + } } return bootLoader, nil } diff --git a/console.go b/console.go index 02ca601..9085d8f 100644 --- a/console.go +++ b/console.go @@ -78,9 +78,9 @@ type FileSerialPortAttachment struct { // NewFileSerialPortAttachment initialize the FileSerialPortAttachment from a path of a file. // If error is not nil, used to report errors if intialization fails. // -// - path of the file for the attachment on the local file system. -// - shouldAppend True if the file should be opened in append mode, false otherwise. -// When a file is opened in append mode, writing to that file will append to the end of it. +// - path of the file for the attachment on the local file system. +// - shouldAppend True if the file should be opened in append mode, false otherwise. +// When a file is opened in append mode, writing to that file will append to the end of it. // // This is only supported on macOS 11 and newer, ErrUnsupportedOSVersion will // be returned on older versions. @@ -88,6 +88,9 @@ func NewFileSerialPortAttachment(path string, shouldAppend bool) (*FileSerialPor if macosMajorVersionLessThan(11) { return nil, ErrUnsupportedOSVersion } + if _, err := os.Stat(path); err != nil { + return nil, err + } cpath := charWithGoString(path) defer cpath.Free() diff --git a/issues_arm64_test.go b/issues_arm64_test.go new file mode 100644 index 0000000..37354fb --- /dev/null +++ b/issues_arm64_test.go @@ -0,0 +1,34 @@ +//go:build darwin && arm64 +// +build darwin,arm64 + +package vz + +import ( + "errors" + "os" + "testing" +) + +func TestIssue43Arm64(t *testing.T) { + const doesNotExists = "/non/existing/path" + t.Run("does not throw NSInvalidArgumentException", func(t *testing.T) { + cases := map[string]func() error{ + // This is also fixed issue #71 + "NewMacAuxiliaryStorage": func() error { + _, err := NewMacAuxiliaryStorage(doesNotExists) + return err + }, + } + for name, run := range cases { + t.Run(name, func(t *testing.T) { + err := run() + if err == nil { + t.Fatal("expected returns error") + } + if !errors.Is(err, os.ErrNotExist) { + t.Errorf("want underlying error %q but got %q", os.ErrNotExist, err) + } + }) + } + }) +} diff --git a/issues_test.go b/issues_test.go index b36ba18..50883a0 100644 --- a/issues_test.go +++ b/issues_test.go @@ -1,7 +1,9 @@ package vz import ( + "errors" "os" + "strings" "testing" ) @@ -55,9 +57,66 @@ func TestIssue50(t *testing.T) { }) } -func TestIssue71(t *testing.T) { - _, err := NewFileSerialPortAttachment("/non/existing/path", false) - if err == nil { - t.Error("NewFileSerialPortAttachment should have returned an error") - } +func TestIssue43(t *testing.T) { + const doesNotExists = "/non/existing/path" + t.Run("does not throw NSInvalidArgumentException", func(t *testing.T) { + t.Run("NewLinuxBootLoader", func(t *testing.T) { + _, err := NewLinuxBootLoader(doesNotExists) + if err == nil { + t.Fatal("expected returns error") + } + if !strings.HasPrefix(err.Error(), "invalid linux kernel") { + t.Error(err) + } + if !errors.Is(err, os.ErrNotExist) { + t.Errorf("want underlying error %q but got %q", os.ErrNotExist, err) + } + + f, err := os.CreateTemp("", "vmlinuz") + if err != nil { + t.Fatal(err) + } + if err := f.Close(); err != nil { + t.Fatal(err) + } + + _, err = NewLinuxBootLoader(f.Name(), WithInitrd(doesNotExists)) + if err == nil { + t.Fatal("expected returns error") + } + if !strings.HasPrefix(err.Error(), "invalid initial RAM disk") { + t.Error(err) + } + if !errors.Is(err, os.ErrNotExist) { + t.Errorf("want underlying error %q but got %q", os.ErrNotExist, err) + } + }) + + cases := map[string]func() error{ + // This is also fixed issue #71 + "NewFileSerialPortAttachment": func() error { + _, err := NewFileSerialPortAttachment(doesNotExists, false) + return err + }, + "NewSharedDirectory": func() error { + _, err := NewFileSerialPortAttachment(doesNotExists, false) + return err + }, + "NewDiskImageStorageDeviceAttachment": func() error { + _, err := NewDiskImageStorageDeviceAttachment(doesNotExists, false) + return err + }, + } + for name, run := range cases { + t.Run(name, func(t *testing.T) { + err := run() + if err == nil { + t.Fatal("expected returns error") + } + if !errors.Is(err, os.ErrNotExist) { + t.Errorf("want underlying error %q but got %q", os.ErrNotExist, err) + } + }) + } + }) } diff --git a/osversion_arm64_test.go b/osversion_arm64_test.go index 319fedc..2ef89f0 100644 --- a/osversion_arm64_test.go +++ b/osversion_arm64_test.go @@ -1,3 +1,6 @@ +//go:build darwin && arm64 +// +build darwin,arm64 + package vz import ( diff --git a/shared_folder.go b/shared_folder.go index 32ccab1..a43a61a 100644 --- a/shared_folder.go +++ b/shared_folder.go @@ -6,7 +6,10 @@ package vz # include "virtualization.h" */ import "C" -import "runtime" +import ( + "os" + "runtime" +) // DirectorySharingDeviceConfiguration for a directory sharing device configuration. type DirectorySharingDeviceConfiguration interface { @@ -69,6 +72,10 @@ func NewSharedDirectory(dirPath string, readOnly bool) (*SharedDirectory, error) if macosMajorVersionLessThan(12) { return nil, ErrUnsupportedOSVersion } + if _, err := os.Stat(dirPath); err != nil { + return nil, err + } + dirPathChar := charWithGoString(dirPath) defer dirPathChar.Free() sd := &SharedDirectory{ @@ -125,6 +132,8 @@ type MultipleDirectoryShare struct { *baseDirectoryShare } +var _ DirectoryShare = (*MultipleDirectoryShare)(nil) + // NewMultipleDirectoryShare creates a new multiple directories share. func NewMultipleDirectoryShare(shares map[string]*SharedDirectory) (*MultipleDirectoryShare, error) { if macosMajorVersionLessThan(12) { diff --git a/storage.go b/storage.go index b78690d..910aeed 100644 --- a/storage.go +++ b/storage.go @@ -6,7 +6,10 @@ package vz # include "virtualization.h" */ import "C" -import "runtime" +import ( + "os" + "runtime" +) type baseStorageDeviceAttachment struct{} @@ -47,6 +50,9 @@ func NewDiskImageStorageDeviceAttachment(diskPath string, readOnly bool) (*DiskI if macosMajorVersionLessThan(11) { return nil, ErrUnsupportedOSVersion } + if _, err := os.Stat(diskPath); err != nil { + return nil, err + } nserr := newNSErrorAsNil() nserrPtr := nserr.Ptr() diff --git a/virtualization_arm64.go b/virtualization_arm64.go index ab704aa..3aa0a18 100644 --- a/virtualization_arm64.go +++ b/virtualization_arm64.go @@ -198,6 +198,9 @@ func NewMacAuxiliaryStorage(storagePath string, opts ...NewMacAuxiliaryStorageOp if macosMajorVersionLessThan(12) { return nil, ErrUnsupportedOSVersion } + if _, err := os.Stat(storagePath); err != nil { + return nil, err + } storage := &MacAuxiliaryStorage{storagePath: storagePath} for _, opt := range opts { @@ -205,6 +208,7 @@ func NewMacAuxiliaryStorage(storagePath string, opts ...NewMacAuxiliaryStorageOp return nil, err } } + if storage.pointer.ptr == nil { cpath := charWithGoString(storagePath) defer cpath.Free() @@ -423,6 +427,9 @@ func LoadMacOSRestoreImageFromPath(imagePath string) (retImage *MacOSRestoreImag if macosMajorVersionLessThan(12) { return nil, ErrUnsupportedOSVersion } + if _, err := os.Stat(imagePath); err != nil { + return nil, err + } waitCh := make(chan struct{}) handler := macOSRestoreImageHandler(func(restoreImage *MacOSRestoreImage, err error) { @@ -462,6 +469,9 @@ func NewMacOSInstaller(vm *VirtualMachine, restoreImageIpsw string) (*MacOSInsta if macosMajorVersionLessThan(12) { return nil, ErrUnsupportedOSVersion } + if _, err := os.Stat(restoreImageIpsw); err != nil { + return nil, err + } cs := charWithGoString(restoreImageIpsw) defer cs.Free()