3030#include <sys/proc_info.h>
3131#include <sys/stat.h>
3232#include <unistd.h>
33- #elif defined(__linux__ )
33+ #elif defined(__linux__ ) || defined( __FreeBSD__ )
3434#include <fcntl.h>
3535#include <sys/stat.h>
3636#include <unistd.h>
37+ #if defined(__FreeBSD__ )
38+ #include <sys/types.h>
39+ #include <sys/sysctl.h>
40+ #endif
3741#endif
3842
3943enum {
@@ -135,7 +139,7 @@ typedef struct {
135139 HANDLE file ;
136140 BY_HANDLE_FILE_INFORMATION information ;
137141 LARGE_INTEGER size ;
138- #elif defined(__APPLE__ ) || defined(__linux__ )
142+ #elif defined(__APPLE__ ) || defined(__linux__ ) || defined( __FreeBSD__ )
139143 int fd ;
140144 struct stat status ;
141145#endif
@@ -490,7 +494,7 @@ static bool runtime_activation_response_decode(
490494static uint64_t runtime_current_process_id (void ) {
491495#ifdef _WIN32
492496 return (uint64_t )GetCurrentProcessId ();
493- #elif defined(__APPLE__ ) || defined(__linux__ )
497+ #elif defined(__APPLE__ ) || defined(__linux__ ) || defined( __FreeBSD__ )
494498 return (uint64_t )getpid ();
495499#else
496500 return 0 ;
@@ -504,7 +508,7 @@ static void runtime_process_image_reference_init(runtime_process_image_reference
504508 memset (reference , 0 , sizeof (* reference ));
505509#ifdef _WIN32
506510 reference -> file = INVALID_HANDLE_VALUE ;
507- #elif defined(__APPLE__ ) || defined(__linux__ )
511+ #elif defined(__APPLE__ ) || defined(__linux__ ) || defined( __FreeBSD__ )
508512 reference -> fd = -1 ;
509513#endif
510514}
@@ -518,7 +522,7 @@ static bool runtime_process_image_reference_release(runtime_process_image_refere
518522 if (reference -> file != INVALID_HANDLE_VALUE && !CloseHandle (reference -> file )) {
519523 ok = false;
520524 }
521- #elif defined(__APPLE__ ) || defined(__linux__ )
525+ #elif defined(__APPLE__ ) || defined(__linux__ ) || defined( __FreeBSD__ )
522526 if (reference -> fd >= 0 && close (reference -> fd ) != 0 ) {
523527 ok = false;
524528 }
@@ -658,9 +662,9 @@ static bool runtime_mac_process_maps_file_executable(int process_id, const struc
658662 return false;
659663}
660664
661- #elif defined(__linux__ )
665+ #elif defined(__linux__ ) || defined( __FreeBSD__ )
662666
663- static bool runtime_linux_stat_same_image (const struct stat * first , const struct stat * second ) {
667+ static bool runtime_posix_stat_same_image (const struct stat * first , const struct stat * second ) {
664668 return first && second && S_ISREG (first -> st_mode ) && S_ISREG (second -> st_mode ) &&
665669 first -> st_dev == second -> st_dev && first -> st_ino == second -> st_ino &&
666670 first -> st_size == second -> st_size && first -> st_mtim .tv_sec == second -> st_mtim .tv_sec &&
@@ -769,11 +773,11 @@ static bool runtime_process_image_reference_acquire(
769773 (!fingerprint ||
770774 cbm_daemon_build_fingerprint_native_file ((uintptr_t )image_fd , fingerprint )) &&
771775 fstat (image_fd , & image_after ) == 0 &&
772- runtime_linux_stat_same_image (& image_before , & image_after );
776+ runtime_posix_stat_same_image (& image_before , & image_after );
773777 int verify_fd = ok ? openat (process_fd , "exe" , O_RDONLY | O_CLOEXEC ) : -1 ;
774778 struct stat verify_status ;
775779 ok = ok && verify_fd >= 0 && fstat (verify_fd , & verify_status ) == 0 &&
776- runtime_linux_stat_same_image (& image_after , & verify_status );
780+ runtime_posix_stat_same_image (& image_after , & verify_status );
777781 if (verify_fd >= 0 && close (verify_fd ) != 0 ) {
778782 ok = false;
779783 }
@@ -787,6 +791,33 @@ static bool runtime_process_image_reference_acquire(
787791 } else if (image_fd >= 0 ) {
788792 (void )close (image_fd );
789793 }
794+ #elif defined(__FreeBSD__ )
795+ if (process_id > INT_MAX ) {
796+ return false;
797+ }
798+ int pid = (int )process_id ;
799+ int mib [4 ] = {CTL_KERN , KERN_PROC , KERN_PROC_PATHNAME , pid };
800+ char path [PATH_MAX ];
801+ size_t path_length = sizeof (path );
802+ bool ok = sysctl (mib , 4 , path , & path_length , NULL , 0 ) == 0 && path_length > 0 ;
803+ if (ok ) {
804+ path [path_length < sizeof (path ) ? path_length : sizeof (path ) - 1 ] = '\0' ;
805+ }
806+ int image_fd = ok ? open (path , O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK ) : -1 ;
807+ struct stat image_before ;
808+ struct stat image_after ;
809+ ok = image_fd >= 0 && fstat (image_fd , & image_before ) == 0 && S_ISREG (image_before .st_mode ) &&
810+ (!fingerprint ||
811+ cbm_daemon_build_fingerprint_native_file ((uintptr_t )image_fd , fingerprint )) &&
812+ fstat (image_fd , & image_after ) == 0 &&
813+ runtime_posix_stat_same_image (& image_before , & image_after );
814+ if (ok ) {
815+ reference -> held = true;
816+ reference -> fd = image_fd ;
817+ reference -> status = image_after ;
818+ } else if (image_fd >= 0 ) {
819+ (void )close (image_fd );
820+ }
790821#else
791822 (void )process_id ;
792823 bool ok = false;
@@ -827,14 +858,14 @@ static bool runtime_process_image_reference_matches_process(
827858 runtime_mac_stat_same (& active -> status , & peer .status );
828859 bool released = runtime_process_image_reference_release (& peer );
829860 return same && released ;
830- #elif defined(__linux__ )
861+ #elif defined(__linux__ ) || defined( __FreeBSD__ )
831862 runtime_process_image_reference_t peer ;
832863 runtime_process_image_reference_init (& peer );
833864 bool same = runtime_process_image_reference_acquire (process_id , & peer , NULL );
834865 struct stat active_now ;
835866 same = same && fstat (active -> fd , & active_now ) == 0 &&
836- runtime_linux_stat_same_image (& active -> status , & active_now ) &&
837- runtime_linux_stat_same_image (& active -> status , & peer .status );
867+ runtime_posix_stat_same_image (& active -> status , & active_now ) &&
868+ runtime_posix_stat_same_image (& active -> status , & peer .status );
838869 bool released = runtime_process_image_reference_release (& peer );
839870 return same && released ;
840871#else
0 commit comments