From f4660651684ca9863c009386938e44c42f43d6bf Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Wed, 1 Apr 2026 20:36:27 -0700 Subject: [PATCH] all: add macOS build support Replace Linux-specific headers and ioctls with portable alternatives so that mkudffs, udfinfo, udflabel, udffsck, and libudffs build on macOS. Block device size and sector size queries use DKIOCGETBLOCKSIZE and DKIOCGETBLOCKCOUNT from on macOS instead of BLKGETSIZE64 and BLKSSZGET from . Disk geometry (HDIO_GETGEO) and CD-ROM ioctls (CDROMMULTISESSION, CDROM_LAST_WRITTEN, CDROM_SEND_PACKET) are guarded behind #ifdef __linux__ since they have no macOS equivalent and the code already has working fallback paths. fdatasync() is replaced with fcntl(F_FULLFSYNC) on macOS. The build system now probes for and only builds cdrwtool, pktsetup, and wrudf when it is present, as these tools are inherently Linux-specific. --- Makefile.am | 5 ++++- configure.ac | 8 +++++++- mkudffs/main.c | 25 ++++++++++++++++++++++++- mkudffs/mkudffs.c | 6 ++++++ mkudffs/options.c | 4 ++++ udfinfo/main.c | 26 ++++++++++++++++++++++++-- udfinfo/readdisc.c | 12 ++++++++++-- udflabel/main.c | 30 ++++++++++++++++++++++++++++-- 8 files changed, 107 insertions(+), 9 deletions(-) diff --git a/Makefile.am b/Makefile.am index ad5966e6..2c3841fb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,6 @@ -SUBDIRS = libudffs mkudffs cdrwtool pktsetup udffsck udfinfo udflabel wrudf doc +SUBDIRS = libudffs mkudffs udffsck udfinfo udflabel doc +if LINUX_TOOLS +SUBDIRS += cdrwtool pktsetup wrudf +endif dist_doc_DATA = AUTHORS COPYING NEWS README EXTRA_DIST = autogen.sh Doxyfile diff --git a/configure.ac b/configure.ac index 30aa6565..328eb09d 100644 --- a/configure.ac +++ b/configure.ac @@ -41,6 +41,12 @@ AC_SUBST(LTLIBOBJS) AM_CONDITIONAL(USE_READLINE, test "$readline_found" = "yes") -AC_CONFIG_FILES(Makefile libudffs/Makefile mkudffs/Makefile cdrwtool/Makefile pktsetup/Makefile udffsck/Makefile udfinfo/Makefile udflabel/Makefile wrudf/Makefile doc/Makefile) +dnl Check for Linux-only tools (cdrwtool, pktsetup, wrudf depend on linux/cdrom.h) +AC_CHECK_HEADER([linux/cdrom.h], [have_linux_cdrom=yes], [have_linux_cdrom=no]) +AM_CONDITIONAL(LINUX_TOOLS, [test "$have_linux_cdrom" = "yes"]) + +AC_CONFIG_FILES(Makefile libudffs/Makefile mkudffs/Makefile udffsck/Makefile udfinfo/Makefile udflabel/Makefile doc/Makefile) +AS_IF([test "$have_linux_cdrom" = "yes"], + [AC_CONFIG_FILES(cdrwtool/Makefile pktsetup/Makefile wrudf/Makefile)]) AC_OUTPUT diff --git a/mkudffs/main.c b/mkudffs/main.c index 92919d4c..9a4fdf10 100644 --- a/mkudffs/main.c +++ b/mkudffs/main.c @@ -41,9 +41,13 @@ #include #include #include +#ifdef __linux__ #include #include #include +#elif defined(__APPLE__) +#include +#endif #include "mkudffs.h" #include "defaults.h" @@ -71,6 +75,10 @@ static uint32_t get_blocks(int fd, int blocksize, uint32_t opt_blocks) #endif #ifdef FDGETPRM struct floppy_struct this_floppy; +#endif +#ifdef __APPLE__ + uint32_t dk_block_size; + uint64_t dk_block_count; #endif struct stat buf; @@ -80,6 +88,12 @@ static uint32_t get_blocks(int fd, int blocksize, uint32_t opt_blocks) if (fd <= 0) return 0; +#ifdef __APPLE__ + if (ioctl(fd, DKIOCGETBLOCKSIZE, &dk_block_size) >= 0 && + ioctl(fd, DKIOCGETBLOCKCOUNT, &dk_block_count) >= 0) + blocks = (uint64_t)dk_block_size * dk_block_count / blocksize; + else +#endif #ifdef BLKGETSIZE64 if (ioctl(fd, BLKGETSIZE64, &size64) >= 0) blocks = size64 / blocksize; @@ -128,11 +142,20 @@ static uint32_t get_blocks(int fd, int blocksize, uint32_t opt_blocks) static void detect_blocksize(int fd, struct udf_disc *disc, int *blocksize) { -#ifdef BLKSSZGET +#if defined(BLKSSZGET) || defined(__APPLE__) int size; +#ifdef __APPLE__ + { + uint32_t dk_size; + if (ioctl(fd, DKIOCGETBLOCKSIZE, &dk_size) != 0 || dk_size <= 0) + return; + size = dk_size; + } +#else if (ioctl(fd, BLKSSZGET, &size) != 0 || size <= 0) return; +#endif if (!disc->blkssz) disc->blkssz = size; diff --git a/mkudffs/mkudffs.c b/mkudffs/mkudffs.c index e704e94e..aee69f6b 100644 --- a/mkudffs/mkudffs.c +++ b/mkudffs/mkudffs.c @@ -40,7 +40,9 @@ #include #include #include +#ifdef __linux__ #include +#endif #include "mkudffs.h" #include "file.h" @@ -614,7 +616,9 @@ static void fill_mbr(struct udf_disc *disc, struct mbr *mbr, uint32_t start) struct mbr old_mbr; uint64_t lba_blocks; struct stat st; +#ifdef __linux__ struct hd_geometry geometry; +#endif unsigned int heads, sectors; struct mbr_partition *mbr_partition; unsigned int blkssz = disc->blkssz ? disc->blkssz : 512; @@ -643,12 +647,14 @@ static void fill_mbr(struct udf_disc *disc, struct mbr *mbr, uint32_t start) lba_blocks = ((uint64_t)disc->blocks * disc->blocksize + blkssz - 1) / blkssz; +#ifdef __linux__ if (fd >= 0 && fstat(fd, &st) == 0 && S_ISBLK(st.st_mode) && ioctl(fd, HDIO_GETGEO, &geometry) == 0) { heads = geometry.heads; sectors = geometry.sectors; } else +#endif { /* Use LBA-Assist Translation for calculating CHS when disk geometry is not available */ sectors = 63; diff --git a/mkudffs/options.c b/mkudffs/options.c index e2acd111..1c7a5885 100644 --- a/mkudffs/options.c +++ b/mkudffs/options.c @@ -40,7 +40,9 @@ #include #include #include +#ifdef __linux__ #include +#endif #include "mkudffs.h" #include "defaults.h" @@ -741,6 +743,7 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in * pktcdvd.ko accepts only these ioctls: * CDROMEJECT CDROMMULTISESSION CDROMREADTOCENTRY * CDROM_LAST_WRITTEN CDROM_SEND_PACKET SCSI_IOCTL_SEND_COMMAND */ +#ifdef __linux__ if (fd >= 0 && fstat(fd, &st) == 0 && S_ISBLK(st.st_mode) && ioctl(fd, CDROM_LAST_WRITTEN, &last) == 0) { struct cdrom_generic_command cgc; @@ -808,6 +811,7 @@ void parse_args(int argc, char *argv[], struct udf_disc *disc, char **device, in } } } +#endif if (fd >= 0) close(fd); diff --git a/udfinfo/main.c b/udfinfo/main.c index 03a70416..49fb86b6 100644 --- a/udfinfo/main.c +++ b/udfinfo/main.c @@ -31,8 +31,12 @@ #include #include -#include #include +#ifdef __linux__ +#include +#elif defined(__APPLE__) +#include +#endif #include "libudffs.h" #include "options.h" @@ -46,9 +50,20 @@ static uint64_t get_size(int fd) if (fstat(fd, &st) == 0) { +#ifdef __linux__ if (S_ISBLK(st.st_mode) && ioctl(fd, BLKGETSIZE64, &size) == 0) return size; - else if (S_ISREG(st.st_mode)) +#elif defined(__APPLE__) + if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) + { + uint32_t block_size; + uint64_t block_count; + if (ioctl(fd, DKIOCGETBLOCKSIZE, &block_size) == 0 && + ioctl(fd, DKIOCGETBLOCKCOUNT, &block_count) == 0) + return (uint64_t)block_size * block_count; + } +#endif + if (S_ISREG(st.st_mode)) return st.st_size; } @@ -72,8 +87,15 @@ static int get_sector_size(int fd) { int size; +#ifdef __linux__ if (ioctl(fd, BLKSSZGET, &size) != 0) return 0; +#elif defined(__APPLE__) + if (ioctl(fd, DKIOCGETBLOCKSIZE, &size) != 0) + return 0; +#else + return 0; +#endif if (size < 512 || size > 32768 || (size & (size - 1))) { diff --git a/udfinfo/readdisc.c b/udfinfo/readdisc.c index 7b4e2f5c..4248e78c 100644 --- a/udfinfo/readdisc.c +++ b/udfinfo/readdisc.c @@ -29,8 +29,10 @@ #include #include -#include #include +#ifdef __linux__ +#include +#endif #include "libudffs.h" #include "readdisc.h" @@ -349,16 +351,20 @@ static int detect_udf(int fd, struct udf_disc *disc) int found_vrs = 0; uint64_t start = 0; uint64_t last = 0; +#ifdef __linux__ long last_written; - struct stat st; struct cdrom_multisession multisession; +#endif + struct stat st; if (disc->start_block == (uint32_t)-1) { +#ifdef __linux__ memset(&multisession, 0, sizeof(multisession)); multisession.addr_format = CDROM_LBA; if (fstat(fd, &st) == 0 && S_ISBLK(st.st_mode) && ioctl(fd, CDROMMULTISESSION, &multisession) == 0 && multisession.xa_flag) start = (uint64_t)multisession.addr.lba * (disc->blkssz ? disc->blkssz : 2048); +#endif if (!start) disc->start_block = 0; } @@ -367,8 +373,10 @@ static int detect_udf(int fd, struct udf_disc *disc) { if (disc->vat_block) disc->last_block = disc->vat_block; +#ifdef __linux__ else if (fstat(fd, &st) == 0 && S_ISBLK(st.st_mode) && ioctl(fd, CDROM_LAST_WRITTEN, &last_written) == 0) last = (uint64_t)last_written * (disc->blkssz ? disc->blkssz : 2048); +#endif else last = (uint64_t)-1; } diff --git a/udflabel/main.c b/udflabel/main.c index d2c9af45..ac89b814 100644 --- a/udflabel/main.c +++ b/udflabel/main.c @@ -31,8 +31,12 @@ #include #include -#include #include +#ifdef __linux__ +#include +#elif defined(__APPLE__) +#include +#endif #include "libudffs.h" #include "options.h" @@ -46,9 +50,20 @@ static uint64_t get_size(int fd) if (fstat(fd, &st) == 0) { +#ifdef __linux__ if (S_ISBLK(st.st_mode) && ioctl(fd, BLKGETSIZE64, &size) == 0) return size; - else if (S_ISREG(st.st_mode)) +#elif defined(__APPLE__) + if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) + { + uint32_t block_size; + uint64_t block_count; + if (ioctl(fd, DKIOCGETBLOCKSIZE, &block_size) == 0 && + ioctl(fd, DKIOCGETBLOCKCOUNT, &block_count) == 0) + return (uint64_t)block_size * block_count; + } +#endif + if (S_ISREG(st.st_mode)) return st.st_size; } @@ -72,8 +87,15 @@ static int get_sector_size(int fd) { int size; +#ifdef __linux__ if (ioctl(fd, BLKSSZGET, &size) != 0) return 0; +#elif defined(__APPLE__) + if (ioctl(fd, DKIOCGETBLOCKSIZE, &size) != 0) + return 0; +#else + return 0; +#endif if (size < 512 || size > 32768 || (size & (size - 1))) { @@ -779,7 +801,11 @@ int main(int argc, char *argv[]) printf("Synchronizing...\n"); if (!(disc.flags & FLAG_NO_WRITE)) { +#ifdef __APPLE__ + if (fcntl(fd, F_FULLFSYNC) != 0) +#else if (fdatasync(fd) != 0) +#endif { fprintf(stderr, "%s: Error: Synchronization to device '%s' failed: %s\n", appname, filename, strerror(errno)); exit(1);