Page MenuHomeFreeBSD

D54230.id168035.diff
No OneTemporary

D54230.id168035.diff

diff --git a/sysutils/mpifileutils/Makefile b/sysutils/mpifileutils/Makefile
new file mode 100644
--- /dev/null
+++ b/sysutils/mpifileutils/Makefile
@@ -0,0 +1,36 @@
+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
+GH_PROJECT= mpifileutils
+GH_TAGNAME= ${DISTVERSIONPREFIX}${DISTVERSION}
+
+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 <bsd.port.mk>
+
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 <string.h>
+ #include <errno.h>
+
+-/* for statfs */
+-#include <sys/vfs.h>
++#if defined(__linux__)
++#include <sys/vfs.h> /* for statfs */
++#endif
+
++#if defined(__linux__) && LUSTRE_SUPPORT
+ /* for LL_SUPER_MAGIC */
+-#if LUSTRE_SUPPORT
+ #include <lustre/lustre_user.h>
+-#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 <unistd.h>
+ #include <stdio.h>
+ #include <stdlib.h>
++#if defined(__linux__)
+ #include <sys/sysinfo.h>
++#endif
+ #include <string.h>
+ #include <sys/time.h>
+ #include <sys/resource.h>
+@@ -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 <unistd.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+-#include <sys/sysinfo.h>
+-#include <string.h>
+-#include <sys/time.h>
+-#include <sys/resource.h>
+-#include "mpi.h"
+-#include <unistd.h>
+-#include <stdint.h>
+-#include <fcntl.h>
+-#include <sys/stat.h>
+-#include <utime.h>
+-#include <bzlib.h>
+-#include <inttypes.h>
+-#include <errno.h>
+
+-#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 <sys/sysinfo.h>
++ * 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 <unistd.h>
+ #include <stdio.h>
+ #include <stdlib.h>
++#if defined(__linux__)
+ #include <sys/sysinfo.h>
++#endif
+ #include <string.h>
+ #include <sys/time.h>
+ #include <sys/resource.h>
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 <stdbool.h>
+ #include "mpi.h"
+
+-#if DCOPY_USE_XATTRS
++#if defined(__linux__) && DCOPY_USE_XATTRS
+ #include <sys/xattr.h>
+ /*
+ * 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 <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
++/* 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 <string.h>
+ #include <unistd.h>
+ #include <getopt.h>
+@@ -35,8 +43,13 @@
+ #include <sys/ioctl.h>
+ #include <sys/param.h>
+
++/* Linux-specific file flag ioctls live in <linux/fs.h>;
++ * not available (and not used) on FreeBSD.
++ */
++#ifdef __linux__
+ #include <linux/fs.h>
+ #include <linux/fiemap.h>
++#endif
+
+ #include <libgen.h> /* 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 <sys/ioctl.h>
+ #include <sys/param.h>
+
++#ifdef __linux__
+ #include <linux/fs.h>
+ #include <linux/fiemap.h>
++#endif
+
+ /* define PRI64 */
+ #include <inttypes.h>
+@@ -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 <errno.h>
++#include <sys/types.h>
++
++/*
++ * 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 <fcntl.h>
+ #include <dirent.h>
+
++#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 <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <sys/stat.h>
++#include <sys/types.h>
+ #include <stdarg.h>
+ #include <errno.h>
+
++#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 <sys/types.h>
+ #include <sys/stat.h>
++#include <fcntl.h>
+ #include <unistd.h>
+
++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 <string.h>
+ #include <getopt.h>
+
++#ifdef __linux__
+ #include <sys/vfs.h>
++#else
++#include <sys/param.h>
++#include <sys/mount.h>
++#endif
+
+ // mmap and friends for shared memory
+ #include <sys/mman.h>
+@@ -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 <unistd.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+-#include <sys/sysinfo.h>
+ #include <string.h>
+ #include <sys/time.h>
+ #include <sys/resource.h>
+@@ -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 <stdlib.h>
+ #include <mpi.h>
+ #include <libcircle.h>
++#ifdef __linux__
+ #include <linux/limits.h>
++#else
++#include <limits.h>
++#include <sys/param.h>
++#endif
+ #include <libgen.h>
+ #include <errno.h>
+ #include <dtcmp.h>
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 <utime.h>
+
+ #if DCOPY_USE_XATTRS
++#if defined(__linux__)
+ #include <sys/xattr.h>
++#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 <stdlib.h>
+ #include <mpi.h>
+ #include <libcircle.h>
+-#include <linux/limits.h>
++#include <limits.h>
+ #include <libgen.h>
+ #include <errno.h>
+ #include <dtcmp.h>
+@@ -32,6 +32,10 @@
+ #define _XOPEN_SOURCE 600
+ #include <fcntl.h>
+ #include <string.h>
++
++#ifndef PATH_MAX
++#define PATH_MAX 4096
++#endif
+
+ /* for bool type, true/false macros */
+ #include <stdbool.h>
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,6 @@
+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.
+
+Homepage: https://hpc.github.io/mpifileutils/
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

File Metadata

Mime Type
text/plain
Expires
Thu, Jan 15, 11:40 AM (7 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27648403
Default Alt Text
D54230.id168035.diff (48 KB)

Event Timeline