From 1d53783253adbdcddabcdd8404f7369eb6aa7f92 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Tue, 30 Mar 2021 04:10:37 +0100 Subject: [PATCH] Try to use fcntl to create sparse files in Darwin. --- setter/src/darwin/CMakeLists.txt | 4 +- setter/src/darwin/darwin.h | 1 + setter/src/darwin/sparse.c | 151 +++++++++++++++++++++++++++++++ setter/src/unix/sparse.c | 11 ++- 4 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 setter/src/darwin/sparse.c diff --git a/setter/src/darwin/CMakeLists.txt b/setter/src/darwin/CMakeLists.txt index f63e4cf..776cca0 100644 --- a/setter/src/darwin/CMakeLists.txt +++ b/setter/src/darwin/CMakeLists.txt @@ -32,11 +32,11 @@ project(fssetter-darwin find_library(CARBON_LIBRARY NAMES Carbon) -set(PLATFORM_SOURCES os.c darwin.h volume.c volume.h attr.c attr.h rsrcfork.c rsrcfork.h) +set(PLATFORM_SOURCES os.c darwin.h volume.c volume.h attr.c attr.h rsrcfork.c rsrcfork.h sparse.c xattr.c xattr.h) if(CARBON_LIBRARY) add_definitions("-DHAVE_CARBON") - set(PLATFORM_SOURCES ${PLATFORM_SOURCES} carbon.c carbon.h xattr.c xattr.h) + set(PLATFORM_SOURCES ${PLATFORM_SOURCES} carbon.c carbon.h) endif() set(EXECUTABLE_NAME "fssetter-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") diff --git a/setter/src/darwin/darwin.h b/setter/src/darwin/darwin.h index e6bd131..5f5c1cb 100644 --- a/setter/src/darwin/darwin.h +++ b/setter/src/darwin/darwin.h @@ -13,5 +13,6 @@ void DarwinResourceFork(const char* path); void DarwinFileAttributes(const char* path); void DarwinExtendedAttributes(const char* path); void DarwinVolumeAttributes(const char* path); +int DarwinSparse(const char* path); #endif // SETTER_SRC_DARWIN_DARWIN_H_ diff --git a/setter/src/darwin/sparse.c b/setter/src/darwin/sparse.c new file mode 100644 index 0000000..51c969f --- /dev/null +++ b/setter/src/darwin/sparse.c @@ -0,0 +1,151 @@ +/**************************************************************************** +Aaru Data Preservation Suite +----------------------------------------------------------------------------- + + Author(s) : Natalia Portillo + +--[ License ] --------------------------------------------------------------- + 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 . + +----------------------------------------------------------------------------- +Copyright (C) 2011-2021 Natalia Portillo +*****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "../include/consts.h" +#include "../log.h" + +int DarwinSparse(const char* path) +{ + int ret; + int rc, wRc, cRc, sRc; + FILE* h; + int i; + int fd; + int done = -1; + fpunchhole_t fphole; + memset(&fphole, 0, sizeof(fpunchhole_t)); + + ret = chdir(path); + + if(ret) + { + log_write("Error %d changing to specified path.\n", errno); + return done; + } + + ret = mkdir("SPARSE", 0755); + + if(ret) + { + log_write("Error %d creating working directory.\n", errno); + return done; + } + + ret = chdir("SPARSE"); + + if(ret) + { + log_write("Error %d changing to working directory.\n", errno); + return done; + } + + done = 0; + + log_write("Creating sparse files.\n"); + + h = fopen("SMALL", "w+"); + rc = 0; + wRc = 0; + cRc = 0; + sRc = 0; + if(h == NULL) { rc = errno; } + else + { + for(i = 0; i < 4096 * 3; i += CLAUNIA_SIZE) + { + ret = fwrite(clauniaBytes, CLAUNIA_SIZE, 1, h); + if(ret < 0) + { + wRc = errno; + break; + } + } + + fd = fileno(h); + fphole.fp_offset = 4096; + fphole.fp_length = 8192; + ret = fcntl(fd, F_PUNCHHOLE, &fphole); + if(ret) sRc = errno; + else + done++; + + ret = fclose(h); + if(ret) cRc = errno; + } + + log_write("\tFile name = \"%s\", size = %d, rc = %d, wRc = %d, cRc = %d, sRc = %d\n", + "SMALL", + 4096 * 4, + rc, + wRc, + cRc, + sRc); + + h = fopen("BIG", "w+"); + rc = 0; + wRc = 0; + cRc = 0; + sRc = 0; + if(h == NULL) { rc = errno; } + else + { + for(i = 0; i < 4096 * 30; i += CLAUNIA_SIZE) + { + ret = fwrite(clauniaBytes, CLAUNIA_SIZE, 1, h); + if(ret < 0) + { + wRc = errno; + break; + } + } + + fd = fileno(h); + fphole.fp_offset = 32768; + fphole.fp_length = 81920; + ret = fcntl(fd, F_PUNCHHOLE, &fphole); + if(ret) sRc = errno; + else + done++; + + ret = fclose(h); + if(ret) cRc = errno; + } + + log_write("\tFile name = \"%s\", size = %d, rc = %d, wRc = %d, cRc = %d, sRc = %d\n", + "BIG", + 4096 * 30, + rc, + wRc, + cRc, + sRc); + + return done; +} diff --git a/setter/src/unix/sparse.c b/setter/src/unix/sparse.c index 6908991..37a18cb 100644 --- a/setter/src/unix/sparse.c +++ b/setter/src/unix/sparse.c @@ -23,11 +23,11 @@ Copyright (C) 2011-2021 Natalia Portillo *****************************************************************************/ #if defined(__linux__) || defined(__LINUX__) || defined(__gnu_linux) -#define _GNU_SOURCE - #include #include "../linux/linux.h" +#elif defined(__APPLE__) && defined(__MACH__) +#include "../darwin/darwin.h" #endif #include @@ -57,6 +57,13 @@ void Sparse(const char* path) return; } +#elif defined(__APPLE__) && defined(__MACH__) + ret = DarwinSparse(path); + + if(ret > 0) return; + + ret = chdir(path); + rmdir("SPARSE"); #endif ret = chdir(path);