diff --git a/ApfsLib/Device.cpp b/ApfsLib/Device.cpp
index 2934c12..eaba5c8 100644
--- a/ApfsLib/Device.cpp
+++ b/ApfsLib/Device.cpp
@@ -25,6 +25,7 @@
#include "DeviceWinPhys.h"
#include "DeviceLinux.h"
#include "DeviceMac.h"
+#include "DeviceBSD.h"
#include "DeviceDMG.h"
#include "DeviceSparseImage.h"
#include "DeviceVDI.h"
@@ -97,6 +98,10 @@ Device * Device::OpenDevice(const char * name)
#ifdef __APPLE__
dev = new DeviceMac();
#endif
+#if defined (__FreeBSD__)
+ dev = new DeviceBSD();
+#endif
+
rc = dev->Open(name);
if (!rc)
diff --git a/ApfsLib/DeviceBSD.cpp b/ApfsLib/DeviceBSD.cpp
new file mode 100644
index 0000000..3305560
--- /dev/null
+++ b/ApfsLib/DeviceBSD.cpp
@@ -0,0 +1,125 @@
+/*
+This file is part of apfs-fuse, a read-only implementation of APFS
+(Apple File System) for FUSE.
+Copyright (C) 2017 Simon Gander
+Copyright (C) 2021 John Othwolo
+
+Apfs-fuse 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 2 of the License, or
+(at your option) any later version.
+
+Apfs-fuse 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 apfs-fuse. If not, see .
+*/
+
+#if defined (__FreeBSD__) // check other BSDs
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "DeviceBSD.h"
+#include "Global.h"
+
+DeviceBSD::DeviceBSD()
+{
+ m_device = -1;
+ m_size = 0;
+}
+
+DeviceBSD::~DeviceBSD()
+{
+ Close();
+}
+
+bool DeviceBSD::Open(const char* name)
+{
+ m_device = open(name, O_RDONLY);
+
+ if (m_device == -1)
+ {
+ std::cout << "Opening device " << name << " failed with error " << strerror(errno) << std::endl;
+ return false;
+ }
+
+ struct stat st;
+
+ fstat(m_device, &st);
+
+ std::cout << "st_mode = " << st.st_mode << std::endl;
+
+ if (S_ISREG(st.st_mode))
+ {
+ m_size = st.st_size;
+ }
+ else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))
+ {
+ // uint64_t sector_count = 0;
+ uint32_t sector_size = 0;
+ uint32_t media_size = 0;
+
+ ioctl(m_device, DIOCGMEDIASIZE, &media_size);
+ // ioctl(m_device, DKIOCGETBLOCKCOUNT, §or_count);
+ ioctl(m_device, DIOCGSECTORSIZE, §or_size);
+
+ // m_size = sector_size * sector_count;
+ m_size = media_size;
+
+ if ((media_size%sector_size) != 0)
+ {
+ std::cerr << "Something is really wrong!!";
+ }
+ // std::cout << "Sector count = " << sector_count << std::endl;
+ std::cout << "Sector size = " << sector_size << std::endl;
+ std::cout << "Media size = " << media_size << std::endl;
+ }
+ else
+ {
+ std::cout << "File mode unknown!" << std::endl;
+ }
+
+ if (g_debug & Dbg_Info)
+ std::cout << "Device " << name << " opened. Size is " << m_size << std::endl;
+
+ return m_device != -1;
+}
+
+void DeviceBSD::Close()
+{
+ if (m_device != -1)
+ close(m_device);
+ m_device = -1;
+ m_size = 0;
+}
+
+bool DeviceBSD::Read(void* data, uint64_t offs, uint64_t len)
+{
+ size_t nread;
+
+ nread = pread(m_device, data, len, offs);
+
+ // TODO: Better error handling ...
+ return nread == len;
+}
+
+bool DeviceBSD::Write(void* data, uint64_t offs, uint64_t len)
+{
+ // TODO: Better error handling ...
+ return len == static_cast(pwrite(m_device, data, len, offs));
+}
+
+#endif
+
diff --git a/ApfsLib/DeviceBSD.h b/ApfsLib/DeviceBSD.h
new file mode 100644
index 0000000..117ddf9
--- /dev/null
+++ b/ApfsLib/DeviceBSD.h
@@ -0,0 +1,46 @@
+/*
+This file is part of apfs-fuse, a read-only implementation of APFS
+(Apple File System) for FUSE.
+Copyright (C) 2017 Simon Gander
+Copyright (C) 2021 John Othwolo
+
+Apfs-fuse 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 2 of the License, or
+(at your option) any later version.
+
+Apfs-fuse 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 apfs-fuse. If not, see .
+*/
+
+#pragma once
+
+#if defined (__FreeBSD__)
+
+#include "Device.h"
+
+class DeviceBSD : public Device
+{
+public:
+ DeviceBSD();
+ ~DeviceBSD();
+
+ bool Open(const char *name) override;
+ void Close() override;
+
+ bool Read(void *data, uint64_t offs, uint64_t len) override;
+ bool Write(void *data, uint64_t offs, uint64_t len);
+
+ uint64_t GetSize() const override { return m_size; }
+
+private:
+ int m_device;
+ uint64_t m_size;
+};
+
+#endif
diff --git a/ApfsLib/Endian.h b/ApfsLib/Endian.h
index 5c461c8..c3b6b3c 100644
--- a/ApfsLib/Endian.h
+++ b/ApfsLib/Endian.h
@@ -57,6 +57,14 @@ Also helps making the driver run on big-endian architectures.
// Definitions for Linux
#include
#include
+#endif
+#ifdef __FreeBSD__
+#include
+
+#define bswap_16 bswap16
+#define bswap_32 bswap32
+#define bswap_64 bswap64
+
#endif
#ifdef __APPLE__
// Definitions for macOS
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3ad571e..cc0562b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -73,6 +73,8 @@ add_library(apfs
ApfsLib/DeviceLinux.h
ApfsLib/DeviceMac.cpp
ApfsLib/DeviceMac.h
+ ApfsLib/DeviceBSD.h
+ ApfsLib/DeviceBSD.cpp
ApfsLib/DeviceSparseImage.cpp
ApfsLib/DeviceSparseImage.h
ApfsLib/DeviceWinFile.cpp
@@ -121,6 +123,10 @@ target_include_directories(apfs-fuse PRIVATE /usr/local/include/osxfuse/)
# link_directories(/usr/local/lib/)
target_link_libraries(apfs-fuse apfs /usr/local/lib/libosxfuse.dylib)
else()
+if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+target_include_directories(apfs-fuse PRIVATE /usr/local/include/)
+link_directories(/usr/local/lib/)
+endif()
if (USE_FUSE3)
target_link_libraries(apfs-fuse apfs fuse3)
else()
diff --git a/apfsfuse/ApfsFuse.cpp b/apfsfuse/ApfsFuse.cpp
index 372fd3c..fca829f 100644
--- a/apfsfuse/ApfsFuse.cpp
+++ b/apfsfuse/ApfsFuse.cpp
@@ -23,7 +23,7 @@
#define FUSE_USE_VERSION 30
#endif
-#ifdef __linux__
+#if defined (__linux__)
#ifdef USE_FUSE2
#include
#include
@@ -33,7 +33,7 @@
#endif
#include
#endif
-#ifdef __APPLE__
+#if defined (__APPLE__) || defined (__FreeBSD__)
#include
#include
#endif
@@ -49,6 +49,7 @@
#include
#include
#include
+#include
#include
#include
@@ -57,6 +58,10 @@
#include
+#ifdef __FreeBSD__
+#include
+#endif
+
static_assert(sizeof(fuse_ino_t) == 8, "Sorry, on 32-bit systems, you need to use FUSE-3.");
constexpr double FUSE_TIMEOUT = 86400.0;