diff --git a/osspecifics/osspecifics_cross.go b/osspecifics/osspecifics_cross.go new file mode 100644 index 0000000..d2cc31f --- /dev/null +++ b/osspecifics/osspecifics_cross.go @@ -0,0 +1,44 @@ +// Linsk - A utility to access Linux-native file systems on non-Linux operating systems. +// Copyright (c) 2023 The Linsk Authors. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package osspecifics + +import ( + "fmt" + "os" + + "github.com/pkg/errors" +) + +func GetDeviceLogicalBlockSize(devPath string) (uint64, error) { + fd, err := os.Open(devPath) + if err != nil { + return 0, errors.Wrap(err, "open device") + } + + defer func() { _ = fd.Close() }() + + bs, err := getDeviceLogicalBlockSizeInner(fd.Fd()) + if err != nil { + return 0, errors.Wrap(err, "get block size inner") + } + + if bs <= 0 { + return 0, fmt.Errorf("retrieved block size is zero (or negative): '%v'", bs) + } + + return uint64(bs), nil +} diff --git a/osspecifics/osspecifics_darwin.go b/osspecifics/osspecifics_darwin.go new file mode 100644 index 0000000..bc77ea4 --- /dev/null +++ b/osspecifics/osspecifics_darwin.go @@ -0,0 +1,26 @@ +// Linsk - A utility to access Linux-native file systems on non-Linux operating systems. +// Copyright (c) 2023 The Linsk Authors. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// go:build darwin + +func getDeviceLogicalBlockSizeInner(fd uintptr) (int64, error) { + bs, err := unix.IoctlGetInt(int(fd.Fd()), 0x40046418) // Syscall code for DKIOGETBLOCKSIZE + if err != nil { + return 0, errors.Wrap(err, "ioctl get logical block size") + } + + return int64(bs), nil +} diff --git a/osspecifics/osspecifics_linux.go b/osspecifics/osspecifics_linux.go new file mode 100644 index 0000000..ce44f32 --- /dev/null +++ b/osspecifics/osspecifics_linux.go @@ -0,0 +1,36 @@ +// Linsk - A utility to access Linux-native file systems on non-Linux operating systems. +// Copyright (c) 2023 The Linsk Authors. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// go:build linux + +package osspecifics + +import ( + "unsafe" + + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +func getDeviceLogicalBlockSizeInner(fd uintptr) (int64, error) { + var bs int64 + _, _, serr := unix.Syscall(unix.SYS_IOCTL, fd, unix.BLKSSZGET, uintptr(unsafe.Pointer(&bs))) + if serr != 0 { + return 0, errors.Wrap(serr, "syscall get logical block size") + } + + return int64(bs), nil +}