diff --git a/sysutils/mpifileutils/Makefile b/sysutils/mpifileutils/Makefile new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/Makefile @@ -0,0 +1,34 @@ +PORTNAME= mpifileutils +DISTVERSIONPREFIX= v +DISTVERSION= 0.10.1 +CATEGORIES= sysutils parallel + +MAINTAINER= rikka.goering@outlook.de +COMMENT= MPI-based parallel file utilities (dcp, dcmp, ddup, dtar, etc.) +WWW= https://hpc.github.io/mpifileutils/ + +LICENSE= BSD3CLAUSE +LICENSE_FILE= ${WRKSRC}/LICENSE + +LIB_DEPENDS= libcircle.so:devel/libcircle \ + libdtcmp.so:devel/dtcmp + +USES= cmake localbase:ldflags mpi pkgconfig ssl +USE_GITHUB= yes +GH_ACCOUNT= hpc + +USE_LDCONFIG= yes + +CMAKE_ARGS+= -DCMAKE_C_COMPILER=${MPICC} \ + -DCMAKE_CXX_COMPILER=${MPICXX} +CMAKE_ON= BUILD_SHARED_LIBS +CMAKE_OFF= ENABLE_GPFS ENABLE_LUSTRE + +do-test: + @${ECHO_MSG} "Tests are MPI-run and disabled by default." + +# Upstream CMake installs a pkgconfig file for libmfu (if provided); stage plist automatically. +# If you prefer a static plist, run 'make makeplist > pkg-plist' after a first build. + +.include + diff --git a/sysutils/mpifileutils/distinfo b/sysutils/mpifileutils/distinfo new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1757163741 +SHA256 (hpc-mpifileutils-v0.10.1_GH0.tar.gz) = 4c8409ef4140f6f557d0e93f0c1267baf5d893c203b29fb7a33d9bc3c5a5d25c +SIZE (hpc-mpifileutils-v0.10.1_GH0.tar.gz) = 319389 diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__bz2.h b/sysutils/mpifileutils/files/patch-src_common_mfu__bz2.h new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__bz2.h @@ -0,0 +1,10 @@ +--- src/common/mfu_bz2.h.orig 2025-12-15 01:37:35 UTC ++++ src/common/mfu_bz2.h +@@ -1,6 +1,7 @@ + #ifndef MFU_BZ2_H + #define MFU_BZ2_H + ++int mfu_compress_bz2_static(const char* src_name, const char* dst_name, int b_size); + int mfu_compress_bz2(const char* src_name, const char* dst_name, int b_size); + int mfu_decompress_bz2(const char* src_name, const char* dst_name); + diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__bz2.c b/sysutils/mpifileutils/files/patch-src_common_mfu__bz2.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__bz2.c @@ -0,0 +1,21 @@ +--- src/common/mfu_bz2.c.orig 2025-12-07 16:58:47 UTC ++++ src/common/mfu_bz2.c +@@ -5,13 +5,14 @@ + #include + #include + +-/* for statfs */ +-#include ++#if defined(__linux__) ++#include /* for statfs */ ++#endif + ++#if defined(__linux__) && LUSTRE_SUPPORT + /* for LL_SUPER_MAGIC */ +-#if LUSTRE_SUPPORT + #include +-#endif /* LUSTRE_SUPPORT */ ++#endif /* __linux__ && LUSTRE_SUPPORT */ + + #include "mpi.h" + #include "mfu.h" diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__bz2__static.c b/sysutils/mpifileutils/files/patch-src_common_mfu__bz2__static.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__bz2__static.c @@ -0,0 +1,101 @@ +--- src/common/mfu_bz2_static.c.orig 2025-12-14 21:30:29 UTC ++++ src/common/mfu_bz2_static.c +@@ -5,7 +5,9 @@ + #include + #include + #include ++#if defined(__linux__) + #include ++#endif + #include + #include + #include +@@ -23,6 +25,11 @@ + #include "mfu.h" + #include "mfu_bz2.h" + ++/* FreeBSD does not define O_LARGEFILE; large file support is implicit. */ ++#ifndef O_LARGEFILE ++#define O_LARGEFILE 0 ++#endif ++ + #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) + + int mfu_compress_bz2_static(const char* src_name, const char* dst_name, int b_size) +@@ -268,21 +275,6 @@ int mfu_compress_bz2_static(const char* src_name, cons + /* End of all waves */ + MPI_Barrier(MPI_COMM_WORLD); + +-/* +- size_t footer_offset_size = 10 * 1024 * 1024; +- size_t single_pair_size = 16 * ranks; +- if (footer_offset_size < single_pair_size) { +- footer_offset_size = single_pair_size; +- } +- int64_t pairs_per_gather_step = footer_offset_size / single_pair_size; +- for (i = 0; i < pairs_per_gather_step; i++) { +- } +-*/ +- +- /* TODO: gather these in larger blocks to rank 0 for writing, +- * tight interleaving as written will not perform well with +- * byte range locking on lustre */ +- + /* Each process writes the offset of all blocks processed by it at corect location in trailer */ + for (int k = 0; k < my_blocks; k++) { + /* seek to metadata location for this block */ +@@ -543,7 +535,7 @@ int mfu_decompress_bz2_static(const char* src_name, co + rc = MFU_FAILURE; + break; + } +- ++ + /* read offset of block */ + uint64_t net_offset; + ssize_t nread = mfu_read(src_name, fd, &net_offset, 8); +@@ -563,15 +555,15 @@ int mfu_decompress_bz2_static(const char* src_name, co + rc = MFU_FAILURE; + break; + } +- ++ + /* convert values from network to host order */ + int64_t offset = mfu_ntoh64(net_offset); + int64_t length = mfu_ntoh64(net_length); +- ++ + /* compute max size of buffer to hold uncompressed data: + * BZ2 scheme requires block_size + 1% + 600 bytes */ + unsigned int outSize = (unsigned int)block_size; +- ++ + /* seek to start of compressed block in source file */ + lseek_rc = mfu_lseek(src_name, fd, offset, SEEK_SET); + if (lseek_rc == (off_t)-1) { +@@ -589,7 +581,7 @@ int mfu_decompress_bz2_static(const char* src_name, co + rc = MFU_FAILURE; + break; + } +- ++ + /* Perform decompression */ + int ret = BZ2_bzBuffToBuffDecompress(obuf, &outSize, ibuf, inSize, 0, 0); + if (ret != 0) { +@@ -597,10 +589,10 @@ int mfu_decompress_bz2_static(const char* src_name, co + rc = MFU_FAILURE; + break; + } +- ++ + /* compute offset to start of uncompressed block in target file */ + int64_t in_offset = block_no * block_size; +- ++ + /* seek to position to write block in target file */ + lseek_rc = mfu_lseek(dst_name, fd_out, in_offset, SEEK_SET); + if (lseek_rc == (off_t)-1) { +@@ -658,3 +650,4 @@ int mfu_decompress_bz2_static(const char* src_name, co + + return rc; + } ++ diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__compress__bz2__libcircle.c b/sysutils/mpifileutils/files/patch-src_common_mfu__compress__bz2__libcircle.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__compress__bz2__libcircle.c @@ -0,0 +1,562 @@ +--- src/common/mfu_compress_bz2_libcircle.c.orig 2020-07-06 23:31:07 UTC ++++ src/common/mfu_compress_bz2_libcircle.c +@@ -1,534 +1,36 @@ +-#ifndef _GNU_SOURCE +-#define _GNU_SOURCE +-#endif +-#define _LARGEFILE64_SOURCE + #include + #include + #include +-#include +-#include +-#include +-#include +-#include "mpi.h" +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include + +-#include "libcircle.h" ++#include "mpi.h" + #include "mfu.h" + #include "mfu_bz2.h" + +-#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) ++/* ++ * FreeBSD / non-Linux fallback implementation. ++ * ++ * The original libcircle-based implementation of ++ * mfu_compress_bz2_libcircle() ++ * relies on Linux-specific sysinfo()/struct sysinfo from ++ * to size buffers and manage a dynamic work queue. ++ * ++ * FreeBSD does not provide a compatible sysinfo(2) API, so that code ++ * does not compile here. ++ * ++ * On non-Linux platforms, this wrapper forwards the call to the existing ++ * portable static implementation: ++ * ++ * mfu_compress_bz2_static() ++ * ++ * This preserves the public interface while using the MPI-based compressor ++ * that is already known to work everywhere. ++ */ + +-struct block_info { +- unsigned int length; +- int rank; +- int64_t offset; +- int64_t sno; +-}; +- +-static struct block_info* my_blocks; +-static int64_t blocks_processed = 0; +-static char** a; +-static int64_t my_prev_blocks = 0; +-static int64_t blocks_pn_pw; +-static int64_t block_size; +-static int64_t comp_buff_size; +-static int64_t blocks_done = 0; +-static int64_t wave_blocks; +-static int64_t tot_blocks; +-static int bc_size; +-static int64_t filesize; +-static char* src_name; +-static char* dst_name; +-static int fd; +-static int fd_out; +-static int64_t my_tot_blocks = 0; +- +-/* To use libcircle, this function creates work for compression. +- * It simply puts the all the block numbers for the file in the queue. */ +-static void DBz2_Enqueue(CIRCLE_handle* handle) ++int mfu_compress_bz2_libcircle(const char* src_name, ++ const char* dst_name, ++ int b_size) + { +- char* newop; +- for (int i = 0; i < wave_blocks; i++) { +- /* compute block id */ +- int64_t block_no = (int64_t)i + (int64_t)blocks_done; +- if (block_no >= tot_blocks) { +- break; +- } +- +- /* encode block id as string */ +- newop = (char*)MFU_MALLOC(sizeof(char) * 10); +- sprintf(newop, "%" PRId64, block_no); +- +- /* enqueue this block */ +- handle->enqueue(newop); +- +- MFU_LOG(MFU_LOG_INFO, "Blocks queued=%" PRId64 "\n", block_no); +- +- mfu_free(&newop); +- } ++ /* Reuse the static compressor implementation. */ ++ return mfu_compress_bz2_static(src_name, dst_name, b_size); + } + +-/* process each compression block */ +-static void DBz2_Dequeue(CIRCLE_handle* handle) +-{ +- /* used to check whether memory is full because the number of blocks +- to be processed in a wave have been completed for this wave */ +- +- int rank; +- MPI_Comm_rank(MPI_COMM_WORLD, &rank); +- +- /* dequeue an item */ +- char newop[10]; +- handle->dequeue(newop); +- +- /* extract block id */ +- int64_t block_no; +- sscanf(newop, "%" PRId64, &block_no); +- +- /* compute starting offset in source file to read from */ +- off_t pos = block_no * block_size; +- +- /* seek to offset in source file for this block */ +- off_t lseek_rc = mfu_lseek(src_name, fd, pos, SEEK_SET); +- if (lseek_rc == (off_t)-1) { +- MFU_LOG(MFU_LOG_ERR, "Failed to seek in source file: %s offset=%lx errno=%d (%s)", +- src_name, pos, errno, strerror(errno)); +- //rc = MFU_FAILURE; +- //continue; +- MPI_Abort(MPI_COMM_WORLD, 1); +- } +- +- /* compute number of bytes to read from input file */ +- size_t nread = (size_t) block_size; +- size_t remainder = (size_t) (filesize - pos); +- if (remainder < nread) { +- nread = remainder; +- } +- +- /* allocate a buffer to hold data from file */ +- char* ibuf = MFU_MALLOC(nread); +- +- /* read block from input file */ +- ssize_t inSize = mfu_read(src_name, fd, ibuf, nread); +- if (inSize != nread) { +- MFU_LOG(MFU_LOG_ERR, "Failed to read from source file: %s offset=%lx got=%d expected=%d errno=%d (%s)", +- src_name, pos, inSize, nread, errno, strerror(errno)); +- //rc = MFU_FAILURE; +- //continue; +- MPI_Abort(MPI_COMM_WORLD, 1); +- } +- +- /* Guaranteed max output size after compression for bz2 */ +- unsigned int outSize = (unsigned int)comp_buff_size; +- +- /* compress block from read buffer into next compression buffer */ +- int ret = BZ2_bzBuffToBuffCompress(a[blocks_processed], &outSize, ibuf, (int)inSize, bc_size, 0, 30); +- if (ret != 0) { +- MFU_LOG(MFU_LOG_ERR, "Error in compression for rank %d", rank); +- //rc = MFU_FAILURE; +- //continue; +- MPI_Abort(MPI_COMM_WORLD, 1); +- } +- +- /* set metadata for the compressed block */ +- my_blocks[my_tot_blocks].sno = block_no; +- my_blocks[my_tot_blocks].length = outSize; +- my_blocks[my_tot_blocks].rank = rank; +- +- /* increment count of blocks we have processed */ +- blocks_processed++; +- my_tot_blocks++; +- MFU_LOG(MFU_LOG_INFO, "Processed block %" PRId64 ",num processed=%" PRId64 ",rank=%d, blocks per wave=%" PRId64 "\n", block_no, blocks_processed, rank, blocks_pn_pw); +- +- /* free read buffer */ +- mfu_free(&ibuf); +-} +- +-static void find_wave_size(int64_t size, int opts_memory) +-{ +- /* get process memory limit from rlimit, if one is set */ +- struct rlimit limit; +- getrlimit(RLIMIT_DATA, &limit); +- MFU_LOG(MFU_LOG_INFO, "The limit is %lld %lld\n", (long long)limit.rlim_cur, (long long)limit.rlim_max); +- +- /* identify free memory on the node */ +- struct sysinfo info; +- sysinfo(&info); +- MFU_LOG(MFU_LOG_INFO, "The free and total ram are:%lu,%lu", info.freeram, info.totalram); +- MFU_LOG(MFU_LOG_INFO, "The block size is:%" PRId64, size); +- +- /* TODO: what about other procs on the same node? */ +- +- /* set our memory limit to minimum of rlimit and free memory */ +- int64_t mem_limit = info.freeram; +- if ((unsigned long)limit.rlim_cur < info.freeram) { +- mem_limit = (int64_t)limit.rlim_cur; +- } +- +- /* go lower still if user gave us a lower limit */ +- if (opts_memory > 0 && opts_memory < mem_limit) { +- mem_limit = (int64_t)opts_memory; +- } +- +- /* memory is computed as the mem_limit is max memory for a process. +- * We leave 2% of totalram free, then 8*size +400*1024 is the +- * memory required to do compression, keep 128B for variables,etc. +- * The block itself must be in memory before compression. */ +- int64_t wave_size_approx = mem_limit - (int64_t)info.totalram * 2 / 100 - 8 * size - 400 * 1024 - 128 - size; +- int64_t waves_blocks_approx = wave_size_approx / comp_buff_size; +- int64_t wave_size = wave_size_approx - 2 * tot_blocks * sizeof(struct block_info); +- blocks_pn_pw = (int64_t)(0.4 * wave_size / comp_buff_size); +- if (blocks_pn_pw > 800) { +- blocks_pn_pw = 800; +- } +- //int blocks_n_w=(int)blocks_pn_pw; +- +- /* find minimum across all processes */ +- MPI_Allreduce(&blocks_pn_pw, &wave_blocks, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD); +-} +- +-int mfu_compress_bz2_libcircle(const char* src, const char* dst, int b_size, ssize_t opts_memory) +-{ +- int rc = MFU_SUCCESS; +- +- /* copy source and target file names */ +- src_name = MFU_STRDUP(src); +- dst_name = MFU_STRDUP(dst); +- +- /* get rank and size of the communicator */ +- int rank, size; +- MPI_Comm_rank(MPI_COMM_WORLD, &rank); +- MPI_Comm_size(MPI_COMM_WORLD, &size); +- +- /* read stat info for source file */ +- struct stat st; +- int stat_flag = 1; +- filesize = 0; +- if (rank == 0) { +- /* stat file to get file size */ +- int lstat_rc = mfu_lstat(src_name, &st); +- if (lstat_rc == 0) { +- filesize = (int64_t) st.st_size; +- } else { +- /* failed to stat file for file size */ +- stat_flag = 0; +- MFU_LOG(MFU_LOG_ERR, "Failed to stat file: %s errno=%d (%s)", +- src_name, errno, strerror(errno)); +- } +- } +- +- /* broadcast filesize to all ranks */ +- MPI_Bcast(&stat_flag, 1, MPI_INT, 0, MPI_COMM_WORLD); +- MPI_Bcast(&filesize, 1, MPI_INT64_T, 0, MPI_COMM_WORLD); +- +- /* check that we could stat file */ +- if (! stat_flag) { +- mfu_free(&src_name); +- mfu_free(&dst_name); +- return MFU_FAILURE; +- } +- +- /* open the source file for reading */ +- fd = mfu_open(src_name, O_RDONLY); +- if (fd < 0) { +- MFU_LOG(MFU_LOG_ERR, "Failed to open file for reading: %s errno=%d (%s)", +- src_name, errno, strerror(errno)); +- } +- +- /* check that all processes were able to open the file */ +- if (! mfu_alltrue(fd >= 0, MPI_COMM_WORLD)) { +- /* some process failed to open so bail with error, +- * if we opened ok, close file */ +- if (fd >= 0) { +- mfu_close(src_name, fd); +- } +- mfu_free(&src_name); +- mfu_free(&dst_name); +- return MFU_FAILURE; +- } +- +- /* open destination file for writing */ +- fd_out = mfu_create_fully_striped(dst_name, FILE_MODE); +- if (fd_out < 0) { +- MFU_LOG(MFU_LOG_ERR, "Failed to open file for writing: %s errno=%d (%s)", +- dst_name, errno, strerror(errno)); +- } +- +- /* check that all processes were able to open the file */ +- if (! mfu_alltrue(fd_out >= 0, MPI_COMM_WORLD)) { +- /* some process failed to open so bail with error, +- * if we opened ok, close file */ +- if (fd_out >= 0) { +- mfu_close(dst_name, fd_out); +- } +- mfu_free(&src_name); +- mfu_free(&dst_name); +- mfu_close(src_name, fd); +- return MFU_FAILURE; +- } +- +- /* ensure that b_size is in range of [1,9] */ +- if (b_size < 1) { +- b_size = 1; +- } +- if (b_size > 9) { +- b_size = 9; +- } +- bc_size = b_size; +- +- /* compute block size in bytes */ +- block_size = (int64_t)b_size * 100 * 1000; +- +- /* compute total number of blocks in the file */ +- tot_blocks = filesize / block_size; +- if (tot_blocks * block_size < filesize) { +- tot_blocks++; +- } +- +- /* given original data of size B, BZ2 compressed data can take up to B * 1.01 + 600 bytes, +- * we use 2% to be on safe side */ +- comp_buff_size = (int64_t) (1.02 * (double)block_size + 600.0); +- +- /* compute number of blocks we can handle in a wave +- * based on allowed memory per process */ +- find_wave_size(block_size, opts_memory); +- +- blocks_processed = 0; +- my_prev_blocks = 0; +- blocks_done = 0; +- my_tot_blocks = 0; +- +- /* compute number of waves to finish file */ +- int64_t num_waves = tot_blocks / wave_blocks; +- if (num_waves * wave_blocks < tot_blocks) { +- num_waves += 1; +- } +- +- /* stores metadata of all blocks processed by this process */ +- my_blocks = (struct block_info*)MFU_MALLOC(sizeof(struct block_info) * blocks_pn_pw * num_waves); +- struct block_info** this_wave_blocks = (struct block_info**)MFU_MALLOC(sizeof(struct block_info*)*wave_blocks); +- +- MPI_Datatype metatype, oldtypes[3]; +- MPI_Aint offsets[3], extent, lb; +- int blockcounts[3]; +- +- offsets[0] = 0; +- oldtypes[0] = MPI_UNSIGNED; +- blockcounts[0] = 1; +- MPI_Type_get_extent(MPI_UNSIGNED, &lb, &extent); +- +- offsets[1] = extent; +- oldtypes[1] = MPI_INT; +- blockcounts[1] = 1; +- MPI_Type_get_extent(MPI_INT, &lb, &extent); +- +- offsets[2] = extent + offsets[1]; +- oldtypes[2] = MPI_INT64_T; +- blockcounts[2] = 2; +- +- MPI_Type_create_struct(3, blockcounts, offsets, oldtypes, &metatype); +- MPI_Type_commit(&metatype); +- +- struct block_info rbuf[wave_blocks]; +- +- /* allocate a compression buffer for each block */ +- a = (char**)MFU_MALLOC(sizeof(char*) * wave_blocks); +- for (int i = 0; i < wave_blocks; i++) { +- a[i] = (char*)MFU_MALLOC(comp_buff_size); +- //memset(a[i],1,comp_buff_size*sizeof(char)); +- } +- +- /* Call libcircle in a loop to work each wave as a single instance of libcircle */ +- int64_t last_offset = 0; +- for (blocks_done = 0; blocks_done < tot_blocks; blocks_done += wave_blocks) { +- /* compute number of blocks in this wave */ +- int blocks_for_wave = wave_blocks; +- int blocks_remaining = tot_blocks - blocks_done; +- if (blocks_remaining < blocks_for_wave) { +- blocks_for_wave = blocks_remaining; +- } +- +- /* execute libcircle to compress blocks */ +- CIRCLE_init(0, NULL, CIRCLE_DEFAULT_FLAGS); +- CIRCLE_cb_create(&DBz2_Enqueue); +- CIRCLE_cb_process(&DBz2_Dequeue); +- CIRCLE_begin(); +- CIRCLE_finalize(); +- +- /* gather the number of blocks processed by each process in this wave */ +- int rcount[size]; +- MPI_Gather(&blocks_processed, 1, MPI_INT, rcount, 1, MPI_INT, 0, MPI_COMM_WORLD); +- +- /* actual number of blocks processed by all processes in this wave */ +- int64_t actual_wave_blocks = 0; +- for (int k = 0; k < size; k++) { +- actual_wave_blocks += (int64_t)rcount[k]; +- } +- +- /* compute displacements array for gatherv */ +- int displs[size]; +- displs[0] = 0; +- for (int k = 1; k < size; k++) { +- displs[k] = displs[k - 1] + rcount[k - 1]; +- } +- +- /* Gather metadata of all blocks processed in this wave */ +- MPI_Gatherv(&my_blocks[my_prev_blocks], blocks_processed, metatype, rbuf, rcount, displs, metatype, 0, MPI_COMM_WORLD); +- +- /* compute the offset of all blocks processed in current wave */ +- if (rank == 0) { +- for (int k = 0; k < actual_wave_blocks; k++) { +- this_wave_blocks[rbuf[k].sno - blocks_done] = &rbuf[k]; +- } +- +- this_wave_blocks[0]->offset = last_offset; +- +- for (int k = 1; k < actual_wave_blocks; k++) { +- this_wave_blocks[k]->offset = this_wave_blocks[k - 1]->offset + this_wave_blocks[k - 1]->length; +- } +- +- last_offset = this_wave_blocks[actual_wave_blocks - 1]->offset + this_wave_blocks[actual_wave_blocks - 1]->length; +- } +- +- /* provide info about the offset of coressponding blocks to process that processed it */ +- MPI_Scatterv(&rbuf, rcount, displs, metatype, &my_blocks[my_prev_blocks], blocks_processed, metatype, 0, MPI_COMM_WORLD); +- +- /* Each process writes out the blocks it processed in current wave at the correct offset */ +- for (int k = 0; k < blocks_processed; k++) { +- /* compute offset into compressed file for our block */ +- off_t pos = my_blocks[my_prev_blocks + k].offset; +- +- /* seek to position in destination file for this block */ +- off_t lseek_rc = mfu_lseek(dst_name, fd_out, pos, SEEK_SET); +- if (lseek_rc == (off_t)-1) { +- MFU_LOG(MFU_LOG_ERR, "Failed to seek to compressed block in target file: %s offset=%lx errno=%d (%s)", +- dst_name, pos, errno, strerror(errno)); +- rc = MFU_FAILURE; +- } +- +- /* write out block */ +- size_t my_length = (size_t) my_blocks[my_prev_blocks + k].length; +- ssize_t nwritten = mfu_write(dst_name, fd_out, a[k], my_length); +- if (nwritten != my_length) { +- MFU_LOG(MFU_LOG_ERR, "Failed to write compressed block to target file: %s offset=%lx got=%d expected=%d errno=%d (%s)", +- dst_name, pos, nwritten, my_length, errno, strerror(errno)); +- rc = MFU_FAILURE; +- } +- } +- +- my_prev_blocks = my_tot_blocks; +- blocks_processed = 0; +- } +- +- /* free buffers used to hold compressed data */ +- for (int i = 0; i < wave_blocks; i++) { +- mfu_free(&a[i]); +- } +- mfu_free(&a); +- +- /* End of all waves */ +- MPI_Barrier(MPI_COMM_WORLD); +- +- /* Broadcast offset of start of trailer */ +- MPI_Bcast(&last_offset, 1, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD); +- +- /* Each process writes the offset of all blocks processed by it at corect location in trailer */ +- for (int k = 0; k < my_tot_blocks; k++) { +- /* seek to metadata location for this block */ +- off_t pos = last_offset + my_blocks[k].sno * 16; +- off_t lseek_rc = mfu_lseek(dst_name, fd_out, pos, SEEK_SET); +- if (lseek_rc == (off_t)-1) { +- MFU_LOG(MFU_LOG_ERR, "Failed to seek to block metadata in target file: %s offset=%lx errno=%d (%s)", +- dst_name, pos, errno, strerror(errno)); +- rc = MFU_FAILURE; +- } +- +- /* write offset of block in destination file */ +- int64_t my_offset = my_blocks[k].offset; +- int64_t net_offset = mfu_hton64(my_offset); +- ssize_t nwritten = mfu_write(dst_name, fd_out, &net_offset, 8); +- if (nwritten != 8) { +- MFU_LOG(MFU_LOG_ERR, "Failed to write block offset to target file: %s pos=%lx got=%d expected=%d errno=%d (%s)", +- dst_name, pos, nwritten, 8, errno, strerror(errno)); +- rc = MFU_FAILURE; +- } +- +- /* write length of block in destination file */ +- int64_t my_length = my_blocks[k].length; +- int64_t net_length = mfu_hton64(my_length); +- nwritten = mfu_write(dst_name, fd_out, &net_length, 8); +- if (nwritten != 8) { +- MFU_LOG(MFU_LOG_ERR, "Failed to write block length to target file: %s pos=%lx got=%d expected=%d errno=%d (%s)", +- dst_name, pos+8, nwritten, 8, errno, strerror(errno)); +- rc = MFU_FAILURE; +- } +- } +- +- /* root writes the locaion of trailer start to last 8 bytes of the file */ +- if (rank == 0) { +- /* convert header fields to network order */ +- uint64_t footer[6]; +- footer[0] = mfu_hton64(last_offset); /* offset to start of block metadata */ +- footer[1] = mfu_hton64(tot_blocks); /* number of blocks in the file */ +- footer[2] = mfu_hton64(block_size); /* max size of uncompressed block */ +- footer[3] = mfu_hton64(filesize); /* size with all blocks decompressed */ +- footer[4] = mfu_hton64(1); /* file version number */ +- footer[5] = mfu_hton64(0x3141314131413141); /* magic number (repeating pi: 3.141) */ +- +- /* seek to position to write footer */ +- off_t pos = last_offset + tot_blocks * 16; +- off_t lseek_rc = mfu_lseek(dst_name, fd_out, pos, SEEK_SET); +- if (lseek_rc == (off_t)-1) { +- MFU_LOG(MFU_LOG_ERR, "Failed to seek to footer in target file: %s offset=%lx errno=%d (%s)", +- dst_name, pos, errno, strerror(errno)); +- rc = MFU_FAILURE; +- } +- +- /* write footer */ +- size_t footer_size = 6 * 8; +- ssize_t nwritten = mfu_write(dst_name, fd_out, footer, footer_size); +- if (nwritten != footer_size) { +- MFU_LOG(MFU_LOG_ERR, "Failed to write footer to target file: %s pos=%lx got=%d expected=%d errno=%d (%s)", +- dst_name, pos, nwritten, footer_size, errno, strerror(errno)); +- rc = MFU_FAILURE; +- } +- } +- +- MPI_Barrier(MPI_COMM_WORLD); +- +- /* free memory for compress blocks */ +- mfu_free(&this_wave_blocks); +- mfu_free(&my_blocks); +- +- /* close source and target files */ +- mfu_fsync(dst_name, fd_out); +- mfu_close(dst_name, fd_out); +- mfu_close(src_name, fd); +- +- /* ensure that everyone has closed and synced before updating timestamps */ +- MPI_Barrier(MPI_COMM_WORLD); +- +- if (rank == 0) { +- /* set mode and group */ +- mfu_chmod(dst_name, st.st_mode); +- mfu_lchown(dst_name, st.st_uid, st.st_gid); +- +- /* set timestamps, mode, and group */ +- struct utimbuf uTimBuf; +- uTimBuf.actime = st.st_atime; +- uTimBuf.modtime = st.st_mtime; +- utime(dst_name, &uTimBuf); +- } +- +- mfu_free(&src_name); +- mfu_free(&dst_name); +- +- return rc; +-} diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__decompress__bz2__libcircle.c b/sysutils/mpifileutils/files/patch-src_common_mfu__decompress__bz2__libcircle.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__decompress__bz2__libcircle.c @@ -0,0 +1,12 @@ +--- src/common/mfu_decompress_bz2_libcircle.c.orig 2025-12-14 21:18:33 UTC ++++ src/common/mfu_decompress_bz2_libcircle.c +@@ -5,7 +5,9 @@ + #include + #include + #include ++#if defined(__linux__) + #include ++#endif + #include + #include + #include diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__flist.h b/sysutils/mpifileutils/files/patch-src_common_mfu__flist.h new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__flist.h @@ -0,0 +1,11 @@ +--- src/common/mfu_flist.h.orig 2025-12-07 17:14:40 UTC ++++ src/common/mfu_flist.h +@@ -44,7 +44,7 @@ extern "C" { + #include + #include "mpi.h" + +-#if DCOPY_USE_XATTRS ++#if defined(__linux__) && DCOPY_USE_XATTRS + #include + /* + * Newer versions of attr deprecated attr/xattr.h which defines ENOATTR as a diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__flist.c b/sysutils/mpifileutils/files/patch-src_common_mfu__flist.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__flist.c @@ -0,0 +1,84 @@ +--- src/common/mfu_flist.c.orig 2020-07-06 23:31:07 UTC ++++ src/common/mfu_flist.c +@@ -12,6 +12,14 @@ + #include + #include + #include ++/* FreeBSD does not provide the Linux sys/xattr.h API. To keep the ++ * build portable, disable xattr support on non-Linux platforms by ++ * un-defining DCOPY_USE_XATTRS before the header is pulled in. This ++ * preserves core functionality while simply skipping xattr copy/preserve ++ * logic on FreeBSD. */ ++#if !defined(__linux__) ++#undef DCOPY_USE_XATTRS ++#endif + #include + #include + #include +@@ -35,8 +43,13 @@ + #include + #include + ++/* Linux-specific file flag ioctls live in ; ++ * not available (and not used) on FreeBSD. ++ */ ++#ifdef __linux__ + #include + #include ++#endif + + #include /* dirname */ + #include "libcircle.h" +@@ -773,46 +786,15 @@ uint64_t mfu_flist_file_get_perm(mfu_flist bflist, uin + return mode & (S_IRWXU | S_IRWXG | S_IRWXO); + } + +-#if DCOPY_USE_XATTRS ++#if !defined(__linux__) + void *mfu_flist_file_get_acl(mfu_flist bflist, uint64_t idx, ssize_t *acl_size, char *type) + { +- flist_t* flist = (flist_t*) bflist; +- const char* filename = mfu_flist_file_get_name(flist, idx); +- size_t val_bufsize = 1024; +- void* val = (void*) MFU_MALLOC(val_bufsize); +- ssize_t val_size; +- int retries = 0; ++ (void)bflist; ++ (void)idx; ++ (void)type; ++ (void)acl_size; + +- *acl_size = 0; +- +- while(retries < 3) { +- val_size = lgetxattr(filename, type, val, val_bufsize); +- if(val_size < 0) { +- if(errno == ERANGE) { +- mfu_free(&val); +- val_bufsize = 0; +- retries++; +- } else if(errno == ENOATTR) { +- break; +- } else { +- /* this is a real error */ +- MFU_LOG(MFU_LOG_ERR, "Failed to get value for name=%s on `%s' lgetxattr() (errno=%d %s)", +- type, filename, errno, strerror(errno) +- ); +- break; +- } +- } else { +- if(val_size > 0 && val_bufsize == 0) { +- val_bufsize = (size_t) val_size; +- val = (void*) MFU_MALLOC(val_bufsize); +- } else { +- *acl_size = val_size; +- break; +- } +- } +- } +- +- return val; ++ return NULL; + } + #endif + diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__flist__copy.c b/sysutils/mpifileutils/files/patch-src_common_mfu__flist__copy.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__flist__copy.c @@ -0,0 +1,137 @@ +--- src/common/mfu_flist_copy.c.orig 2020-07-06 23:31:07 UTC ++++ src/common/mfu_flist_copy.c +@@ -35,8 +35,10 @@ + #include + #include + ++#ifdef __linux__ + #include + #include ++#endif + + /* define PRI64 */ + #include +@@ -81,6 +83,55 @@ typedef struct { + int fd; /* file descriptor */ + } mfu_copy_file_cache_t; + ++/* ----- Linux xattr compatibility stubs for non-Linux ----- */ ++ ++#if DCOPY_USE_XATTRS && !defined(__linux__) ++ ++#include ++#include ++ ++/* ++ * FreeBSD / non-Linux stub versions of the Linux xattr API. ++ * These functions always report ENOTSUP so mfu_copy_xattrs() will skip ++ * xattrs gracefully (it already has special handling for ENOTSUP). ++ */ ++ ++static inline ssize_t ++llistxattr(const char *path, char *list, size_t size) ++{ ++ (void)path; ++ (void)list; ++ (void)size; ++ errno = ENOTSUP; ++ return -1; ++} ++ ++static inline ssize_t ++lgetxattr(const char *path, const char *name, void *value, size_t size) ++{ ++ (void)path; ++ (void)name; ++ (void)value; ++ (void)size; ++ errno = ENOTSUP; ++ return -1; ++} ++ ++static inline int ++lsetxattr(const char *path, const char *name, ++ const void *value, size_t size, int flags) ++{ ++ (void)path; ++ (void)name; ++ (void)value; ++ (void)size; ++ (void)flags; ++ errno = ENOTSUP; ++ return -1; ++} ++ ++#endif /* DCOPY_USE_XATTRS && !__linux__ */ ++ + /**************************************** + * Define globals + ***************************************/ +@@ -1725,6 +1776,7 @@ static int mfu_copy_file_normal( + return 0; + } + ++#ifdef __linux__ + static int mfu_copy_file_fiemap( + const char* src, + const char* dest, +@@ -1762,10 +1814,12 @@ static int mfu_copy_file_fiemap( + goto fail_normal_copy; + } + ++ #ifdef __linux__ + if (ioctl(in_fd, FS_IOC_FIEMAP, fiemap) < 0) { + MFU_LOG(MFU_LOG_ERR, "fiemap ioctl() failed for src `%s'", src); + goto fail_normal_copy; + } ++ #endif /* __linux__ */ + + size_t extents_size = sizeof(struct fiemap_extent) * (fiemap->fm_mapped_extents); + +@@ -1780,10 +1834,12 @@ static int mfu_copy_file_fiemap( + fiemap->fm_extent_count = fiemap->fm_mapped_extents; + fiemap->fm_mapped_extents = 0; + ++ #ifdef __linux__ + if (ioctl(in_fd, FS_IOC_FIEMAP, fiemap) < 0) { + MFU_LOG(MFU_LOG_ERR, "fiemap ioctl() failed for src `%s'", src); + goto fail_normal_copy; + } ++ #endif /* __linux__ */ + + uint64_t last_byte = offset + length; + +@@ -1900,6 +1956,7 @@ fail_normal_copy: + fail_normal_copy: + return -1; + } ++#endif + + static int mfu_copy_file( + const char* src, +@@ -1910,7 +1967,9 @@ static int mfu_copy_file( + mfu_copy_opts_t* mfu_copy_opts) + { + int ret; ++ #ifdef __linux__ + bool normal_copy_required; ++ #endif + + /* open the input file */ + int in_fd = mfu_copy_open_file(src, 1, &mfu_copy_src_cache, mfu_copy_opts); +@@ -1928,6 +1987,7 @@ static int mfu_copy_file( + return -1; + } + ++ #ifdef __linux__ + if (mfu_copy_opts->sparse) { + ret = mfu_copy_file_fiemap(src, dest, in_fd, out_fd, offset, + length, file_size, +@@ -1936,6 +1996,7 @@ static int mfu_copy_file( + return ret; + } + } ++ #endif + + ret = mfu_copy_file_normal(src, dest, in_fd, out_fd, + offset, length, file_size, mfu_copy_opts); diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__flist__walk.c b/sysutils/mpifileutils/files/patch-src_common_mfu__flist__walk.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__flist__walk.c @@ -0,0 +1,30 @@ +--- src/common/mfu_flist_walk.c.orig 2025-12-07 22:27:53 UTC ++++ src/common/mfu_flist_walk.c +@@ -162,7 +162,17 @@ static void walk_getdents_process_dir(const char* dir, + /* Read all directory entries */ + while (1) { + /* execute system call to get block of directory entries */ +- int nread = syscall(SYS_getdents, fd, buf, (int) BUF_SIZE); ++ int nread; ++#ifdef __linux__ ++ /* On Linux, call the raw getdents syscall as before */ ++ nread = syscall(SYS_getdents, fd, buf, (int) BUF_SIZE); ++#else ++ /* ++ * On FreeBSD and other non-Linux systems, use the getdents(2) ++ * libc wrapper instead of the Linux-specific SYS_getdents. ++ */ ++ nread = getdents(fd, (char *)buf, (size_t)BUF_SIZE); ++#endif + if (nread == -1) { + MFU_LOG(MFU_LOG_ERR, "syscall to getdents failed when reading `%s' (errno=%d %s)", dir, errno, strerror(errno)); + break; +@@ -736,7 +746,7 @@ void mfu_flist_stat( + /* check whether we should skip this item */ + if (skip_fn != NULL && skip_fn(name, skip_args)) { + /* skip this file, don't include it in new list */ +- MFU_LOG(MFU_LOG_INFO, "skip %s"); ++ MFU_LOG(MFU_LOG_INFO, "skip %s", name); + continue; + } + diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__io.h b/sysutils/mpifileutils/files/patch-src_common_mfu__io.h new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__io.h @@ -0,0 +1,20 @@ +--- src/common/mfu_io.h.orig 2020-07-06 23:31:07 UTC ++++ src/common/mfu_io.h +@@ -34,12 +34,15 @@ extern "C" { + #include + #include + ++#ifdef __FreeBSD__ ++#define stat64 stat ++#define lstat64 lstat ++#endif ++ + /* Intent is to wrap all POSIX I/O routines used by mfu tools. May + * abort on fatal conditions to avoid checking condition at every call. + * May also automatically retry on things like EINTR. */ + +-/* TODO: fix this */ +-/* do this to avoid warning about undefined stat64 struct */ + struct stat64; + + /***************************** diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__io.c b/sysutils/mpifileutils/files/patch-src_common_mfu__io.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__io.c @@ -0,0 +1,15 @@ +--- src/common/mfu_io.c.orig 2020-07-06 23:31:07 UTC ++++ src/common/mfu_io.c +@@ -12,6 +12,12 @@ + + #include "mfu.h" + ++/* FreeBSD does not provide lstat64, only lstat. Map it accordingly. */ ++#ifdef __FreeBSD__ ++#undef lstat64 ++#define lstat64(path, buf) lstat((path), (struct stat *)(buf)) ++#endif ++ + #define MFU_IO_TRIES (5) + #define MFU_IO_USLEEP (100) + diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__param__path.c b/sysutils/mpifileutils/files/patch-src_common_mfu__param__path.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__param__path.c @@ -0,0 +1,27 @@ +--- src/common/mfu_param_path.c.orig 2020-07-06 23:31:07 UTC ++++ src/common/mfu_param_path.c +@@ -4,9 +4,15 @@ + #include + #include + #include ++#include ++#include + #include + #include + ++#ifndef S_ISLNK ++#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) ++#endif ++ + /* initialize fields in param */ + static void mfu_param_path_init(mfu_param_path* param) + { +@@ -469,7 +475,7 @@ void mfu_param_path_check_copy(uint64_t num, const mfu + /* dest is a file */ + dest_is_file = true; + } +- else if(S_ISLNK(destpath->path_stat.st_mode)) { ++ else if (S_ISLNK(destpath->path_stat.st_mode)) { + /* dest is a symlink, but to what? */ + if (destpath->target_stat_valid) { + /* target of the symlink exists, determine what it is */ diff --git a/sysutils/mpifileutils/files/patch-src_common_mfu__util.c b/sysutils/mpifileutils/files/patch-src_common_mfu__util.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_common_mfu__util.c @@ -0,0 +1,41 @@ +--- src/common/mfu_util.c.orig 2020-07-06 23:31:07 UTC ++++ src/common/mfu_util.c +@@ -14,8 +14,20 @@ + + #include + #include ++#include + #include + ++int posix_memalign(void **memptr, size_t alignment, size_t size); ++int posix_fadvise(int fd, off_t offset, off_t len, int advice); ++ ++#ifndef POSIX_FADV_SEQUENTIAL ++#define POSIX_FADV_SEQUENTIAL 2 ++#endif ++ ++#ifndef S_ISLNK ++#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) ++#endif ++ + #ifndef ULLONG_MAX + #define ULLONG_MAX (__LONG_LONG_MAX__ * 2UL + 1UL) + #endif +@@ -826,7 +838,7 @@ int mfu_compare_contents( + if (mfu_lseek(dst_name, dst_fd, pos, SEEK_SET) == (off_t)-1) { + /* log error if there is an lseek failure on the dst side */ + MFU_LOG(MFU_LOG_ERR, "Failed to lseek `%s', offset: %llx (errno=%d %s)", +- dst_name, (unsigned long long)pos, strerror(errno)); ++ dst_name, (unsigned long long)pos, errno, strerror(errno)); + rc = -1; + break; + } +@@ -837,7 +849,7 @@ int mfu_compare_contents( + if (bytes_written < 0) { + /* hit a write error */ + MFU_LOG(MFU_LOG_ERR, "Failed to write `%s' at offset %llx (errno=%d %s)", +- dst_name, (unsigned long long)pos, strerror(errno)); ++ dst_name, (unsigned long long)pos, errno, strerror(errno)); + rc = -1; + break; + } diff --git a/sysutils/mpifileutils/files/patch-src_dbcast_dbcast.c b/sysutils/mpifileutils/files/patch-src_dbcast_dbcast.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_dbcast_dbcast.c @@ -0,0 +1,73 @@ +--- src/dbcast/dbcast.c.orig 2020-07-06 23:31:07 UTC ++++ src/dbcast/dbcast.c +@@ -16,7 +16,12 @@ + #include + #include + ++#ifdef __linux__ + #include ++#else ++#include ++#include ++#endif + + // mmap and friends for shared memory + #include +@@ -32,6 +37,14 @@ + * and send data to each other. The writer flow controls these worker + * processes with messages. */ + ++#ifndef HOST_NAME_MAX ++# ifdef MAXHOSTNAMELEN ++# define HOST_NAME_MAX MAXHOSTNAMELEN ++# else ++# define HOST_NAME_MAX 256 ++# endif ++#endif ++ + #define GCS_SUCCESS (0) + + static int gcs_shm_file_key = MPI_KEYVAL_INVALID; +@@ -803,7 +816,7 @@ int main (int argc, char *argv[]) + /* check whether we have space to write the file */ + if (file_size > free_size) { + /* not enough space for file */ +- MFU_LOG(MFU_LOG_ERR, "Insufficient space for file `%s` filesize=%llu free=%llu", out_file_path, file_size, free_size); ++ MFU_LOG(MFU_LOG_ERR, "Insufficient space for file `%s` filesize=%llu free=%llu", out_file_path, (unsigned long long)file_size, (unsigned long long)free_size); + write_error = 1; + } + } +@@ -1118,14 +1131,14 @@ if (node_rank == 0) { + * a file by the same name but of different size than a previous copy */ + errno = 0; + if (mfu_truncate(out_file_path, (off_t) file_size) != 0) { +- MFU_LOG(MFU_LOG_ERR, "Failed to truncate file `%s`", out_file_path, strerror(errno)); ++ MFU_LOG(MFU_LOG_ERR, "Failed to truncate file `%s`: %s", out_file_path, strerror(errno)); + write_error = 1; + } + + /* have every writer update file mode */ + errno = 0; + if (mfu_chmod(out_file_path, (mode_t) mode) != 0) { +- MFU_LOG(MFU_LOG_ERR, "Failed to chmod file `%s`", out_file_path, strerror(errno)); ++ MFU_LOG(MFU_LOG_ERR, "Failed to chmod file `%s`: %s", out_file_path, strerror(errno)); + write_error = 1; + } + +@@ -1133,14 +1146,14 @@ if (node_rank == 0) { + if (write_error) { + errno = 0; + if (mfu_unlink(out_file_path) != 0) { +- MFU_LOG(MFU_LOG_ERR, "Failed to unlink file `%s`", out_file_path, strerror(errno)); ++ MFU_LOG(MFU_LOG_ERR, "Failed to unlink file `%s`: %s", out_file_path, strerror(errno)); + } + } + } else { + /* readers close input file */ + errno = 0; + if (mfu_close(in_file_path, in_file) != 0) { +- MFU_LOG(MFU_LOG_ERR, "Failed to close file `%s`", in_file_path, strerror(errno)); ++ MFU_LOG(MFU_LOG_ERR, "Failed to close file `%s`: %s", in_file_path, strerror(errno)); + } + } + diff --git a/sysutils/mpifileutils/files/patch-src_dbz2_dbz2.c b/sysutils/mpifileutils/files/patch-src_dbz2_dbz2.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_dbz2_dbz2.c @@ -0,0 +1,15 @@ +--- src/dbz2/dbz2.c.orig 2025-12-14 21:29:41 UTC ++++ src/dbz2/dbz2.c +@@ -1,7 +1,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -248,3 +247,4 @@ int main(int argc, char** argv) + + return 0; + } ++ diff --git a/sysutils/mpifileutils/files/patch-src_dcmp_dcmp.c b/sysutils/mpifileutils/files/patch-src_dcmp_dcmp.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_dcmp_dcmp.c @@ -0,0 +1,15 @@ +--- src/dcmp/dcmp.c.orig 2025-12-08 09:21:51 UTC ++++ src/dcmp/dcmp.c +@@ -4,7 +4,12 @@ + #include + #include + #include ++#ifdef __linux__ + #include ++#else ++#include ++#include ++#endif + #include + #include + #include diff --git a/sysutils/mpifileutils/files/patch-src_dcp1_cleanup.c b/sysutils/mpifileutils/files/patch-src_dcp1_cleanup.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_dcp1_cleanup.c @@ -0,0 +1,13 @@ +--- src/dcp1/cleanup.c.orig 2025-12-11 05:20:58 UTC ++++ src/dcp1/cleanup.c +@@ -51,8 +51,8 @@ static void DCOPY_truncate_file(DCOPY_operation_t* op, + * Try the recursive file before file-to-file. The cast below requires us + * to have a maximum file_size of 2^63, not 2^64. + */ +- if(truncate64(dest_path_recursive, op->file_size) < 0) { +- if(truncate64(dest_path_file_to_file, op->file_size) < 0) { ++ if(mfu_truncate(dest_path_recursive, op->file_size) < 0) { ++ if(mfu_truncate(dest_path_file_to_file, op->file_size) < 0) { + MFU_LOG(MFU_LOG_ERR, "Failed to truncate destination file: %s (errno=%d %s)", + dest_path_recursive, errno, strerror(errno)); + diff --git a/sysutils/mpifileutils/files/patch-src_dcp1_common.h b/sysutils/mpifileutils/files/patch-src_dcp1_common.h new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_dcp1_common.h @@ -0,0 +1,19 @@ +--- src/dcp1/common.h.orig 2020-07-06 23:31:07 UTC ++++ src/dcp1/common.h +@@ -45,7 +45,16 @@ + #include + + #if DCOPY_USE_XATTRS ++#if defined(__linux__) + #include ++#else ++/* FreeBSD and other non-Linux systems: no Linux xattr API available. ++ * Disable xattr-related code paths by clearing DCOPY_USE_XATTRS. */ ++#ifdef DCOPY_USE_XATTRS ++#undef DCOPY_USE_XATTRS ++#endif ++#endif ++ + /* + * Newer versions of attr deprecated attr/xattr.h which defines ENOATTR as a + * ENODATA. Add the definition to keep compatibility. diff --git a/sysutils/mpifileutils/files/patch-src_dsync_dsync.c b/sysutils/mpifileutils/files/patch-src_dsync_dsync.c new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/files/patch-src_dsync_dsync.c @@ -0,0 +1,22 @@ +--- src/dsync/dsync.c.orig 2025-12-15 01:38:57 UTC ++++ src/dsync/dsync.c +@@ -24,7 +24,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -32,6 +32,10 @@ + #define _XOPEN_SOURCE 600 + #include + #include ++ ++#ifndef PATH_MAX ++#define PATH_MAX 4096 ++#endif + + /* for bool type, true/false macros */ + #include diff --git a/sysutils/mpifileutils/pkg-descr b/sysutils/mpifileutils/pkg-descr new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/pkg-descr @@ -0,0 +1,4 @@ +mpiFileUtils provides a library (libmfu) and a suite of MPI-parallel file +utilities such as dcp (parallel copy), dcmp (compare), ddup (duplicate finder), +dfind, dtar/dbz2, dchmod, and more. Designed for high scalability on large +filesystems. diff --git a/sysutils/mpifileutils/pkg-plist b/sysutils/mpifileutils/pkg-plist new file mode 100644 --- /dev/null +++ b/sysutils/mpifileutils/pkg-plist @@ -0,0 +1,38 @@ +bin/dbcast +bin/dbz2 +bin/dchmod +bin/dcmp +bin/dcp +bin/dcp1 +bin/ddup +bin/dfilemaker1 +bin/dfind +bin/dreln +bin/drm +bin/dstripe +bin/dsync +bin/dwalk +include/mfu.h +include/mfu_bz2.h +include/mfu_flist.h +include/mfu_flist_internal.h +include/mfu_io.h +include/mfu_param_path.h +include/mfu_path.h +include/mfu_pred.h +include/mfu_progress.h +include/mfu_util.h +lib/libmfu.a +lib/libmfu.so +share/man/man1/dbcast.1.gz +share/man/man1/dbz2.1.gz +share/man/man1/dchmod.1.gz +share/man/man1/dcmp.1.gz +share/man/man1/dcp.1.gz +share/man/man1/ddup.1.gz +share/man/man1/dfind.1.gz +share/man/man1/dreln.1.gz +share/man/man1/drm.1.gz +share/man/man1/dstripe.1.gz +share/man/man1/dsync.1.gz +share/man/man1/dwalk.1.gz