diff --git a/checkin_notes b/checkin_notes index 0a64f4cea3d33291e36ed11ba1c5090f3abb1c4a..864aab0c3f90f43aceb95188c8553d981e23f393 100644 --- a/checkin_notes +++ b/checkin_notes @@ -3076,4 +3076,11 @@ Charlie 17 Mar 2009 mac_build/ boinc.xcodeproj/ project.pbxproj - \ No newline at end of file + +Eric K 17 Mar 2009 + - Linux: client: Added code to detect capability to run 64-bit binaries + from 32-bit BOINC client, and capability to run 32-bit binaries on + a 64-bit linux system. + + client/ + cs_platforms.cpp diff --git a/client/cs_platforms.cpp b/client/cs_platforms.cpp index a34849612fc0078b3e75ba9016a3986ae43c636f..02d803943d01ed0d13fc07543cae28fc0d5067ed 100644 --- a/client/cs_platforms.cpp +++ b/client/cs_platforms.cpp @@ -46,6 +46,7 @@ LPFN_ISWOW64PROCESS fnIsWow64Process; #include "client_state.h" #include "error_numbers.h" #include "log_flags.h" +#include "filesys.h" #include "str_util.h" #include "util.h" @@ -103,6 +104,105 @@ void CLIENT_STATE::detect_platforms() { // Supported on all 3 Mac architectures add_platform("powerpc-apple-darwin"); +#elif defined(__linux__) && ( defined(__i386__) || defined(__x86_64__) ) + // Let's try to support both 32 and 64 bit applications in one client + // regardless of whether it is a 32 or 64 bit client + const char *uname[]={"/bin/uname","/usr/bin/uname",0}; + int eno=0, support64=0, support32=0; + FILE *f; + char cmdline[256]; + cmdline[0]=0; + + // find the 'uname' executable + do { + if (boinc_file_exists(uname[eno])) break; + } while (uname[++eno] != 0); + // run it and check the kernel machine architecture. + if ( uname[eno] != 0 ) { + strlcpy(cmdline,uname[eno],256); + strlcat(cmdline," -m",256); + if ((f=popen(cmdline,"r"))) { + while (!std::feof(f)) { + fgets(cmdline,256,f); + if (strstr(cmdline,"x86_64")) support64=1; + } + pclose(f); + } + if (!support64) { + // we're running on a 32 bit kernel, so we will assume + // we are i686-pc-linux-gnu only. + support32=1; + } else { + // we're running on a 64 bit kernel. + // Now comes the hard part. How to tell whether we can run + // 32-bit binaries. +#if defined(__i386__) && !defined(__x86_64__) + // If we're a 32 bit binary, then we obviously can. + support32=1; +#else + // If we're a 64 bit binary, the check is a bit harder. + // We'll use the file command to check installation of + // 32 bit libraries or executables. + const char *file[]={"/usr/bin/file","/bin/file",0}; + const char *libdir[]={"/lib","/lib32","/lib/32","/usr/lib","/usr/lib32","/usr/lib/32"}; + const int nlibdirs=sizeof(libdir)/sizeof(char *); + + + // find 'file' + eno=0; + do { + if (boinc_file_exists(file[eno])) break; + } while (file[++eno] != 0); + // now try to find a 32-bit C library. + if (file[eno] != 0) { + int i; + for (i=0;i<nlibdirs;i++) { + struct dirent *entry; + DIR *a=opendir(libdir[i]); + // if dir doesn't exist, do to the next one + if ( a == 0 ) continue; + // dir exists. read each entry until you find a 32bit lib + while ((support32 == 0) && ((entry=readdir(a)) != 0)) { + strlcpy(cmdline,file[eno],256); + strlcat(cmdline," -L ",256); + strlcat(cmdline,libdir[i],256); + strlcat(cmdline,"/",256); + strlcat(cmdline,entry->d_name,256); + if ((f=popen(cmdline,"r"))) { + while (!std::feof(f)) { + fgets(cmdline,256,f); + // If the library is 32-bit ELF, then we're + // golden. + if (strstr(cmdline,"ELF") && + strstr(cmdline,"32-bit")) support32=1; + } + pclose(f); + } + } + closedir(a); + if (support32) break; + } + } +#endif + } + } + + if (support64) { + add_platform("x86_64-pc-linux-gnu"); + } + if (support32) { + add_platform("i686-pc-linux-gnu"); + } + + if (!(support64 || support32)) { + // Something went wrong. Assume HOSTTYPE and HOSTTYPEALT + // are correct + add_platform(HOSTTYPE); +#ifdef HOSTTYPEALT + add_platform(HOSTTYPEALT); +#endif + } + #elif defined(sun) // Check if we can run 64-bit binaries... // this assumes there isn't a 64-bit only solaris. (Every 64-bit solaris can run 32 bit binaries) @@ -169,7 +269,7 @@ void CLIENT_STATE::detect_platforms() { #endif // !defined(UNKNOWN_SOLARIS_PROCESSOR) -#else // defined(sun) +#else // Any other platform, fall back to the previous method add_platform(HOSTTYPE); #ifdef HOSTTYPEALT