From ea4affb2a248f10b00f276d5ee91acb80e653af1 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 2 Feb 2021 15:58:00 -0500 Subject: [PATCH] Add FreeBSD support --- ApfsLib/Device.cpp | 5 ++ ApfsLib/DeviceBSD.cpp | 125 ++++++++++++++++++++++++++++++++++++++++++ ApfsLib/DeviceBSD.h | 46 ++++++++++++++++ ApfsLib/Endian.h | 8 +++ CMakeLists.txt | 6 ++ apfsfuse/ApfsFuse.cpp | 9 ++- 6 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 ApfsLib/DeviceBSD.cpp create mode 100644 ApfsLib/DeviceBSD.h 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;