From 6ba8928537d0b6a665913facf13d6ff7aec7e869 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 19 Mar 2008 16:54:36 +0000 Subject: [PATCH] - client (Unix): use symbolic links instead of XML link files. This will allow applications to access shared libraries by their logical names, which simplifies things when you have multiple platforms, and the apps (or libraries) refer to shared libraries by names that don't include the platform. This shouldn't impact the API - boinc_resolve_filename() will open the file, see that it's not an XML link file, and the symbolic link will be used directly. At some point we can change boinc_resolve_filename() on Unix to be a no-op if the client is 6.2+ - client (Unix): Append the slot dir to LD_LIBRARY_PATH. svn path=/trunk/boinc/; revision=14944 --- checkin_notes | 26 +++++++++ client/app_start.C | 119 +++++++++++++++++++++--------------------- client/client_types.C | 5 -- client/client_types.h | 5 +- lib/boinc_cmd.C | 2 - lib/error_numbers.h | 1 + py/Boinc/tools.py | 14 +++-- tools/update_versions | 19 ++++--- 8 files changed, 108 insertions(+), 83 deletions(-) diff --git a/checkin_notes b/checkin_notes index 3059b81b14..3738152edc 100644 --- a/checkin_notes +++ b/checkin_notes @@ -2504,3 +2504,29 @@ Charlie Mar 19 2008 mac_installer/ release_boinc.sh release_GridRepublic.sh + +David Mar 19 2008 + - client (Unix): use symbolic links instead of XML link files. + This will allow applications to access shared libraries + by their logical names, + which simplifies things when you have multiple platforms, + and the apps (or libraries) refer to shared libraries + by names that don't include the platform. + This shouldn't impact the API - boinc_resolve_filename() + will open the file, see that it's not an XML link file, + and the symbolic link will be used directly. + At some point we can change boinc_resolve_filename() on Unix + to be a no-op if the client is 6.2+ + - client (Unix): + Append the slot dir to LD_LIBRARY_PATH. + + client/ + app_start.C + client_types.C,h + lib/ + boinc_cmd.C + error_numbers.h + py/Boinc/ + tools.py + tools/ + update_versions diff --git a/client/app_start.C b/client/app_start.C index d45046ed77..a6c84dafbe 100644 --- a/client/app_start.C +++ b/client/app_start.C @@ -81,10 +81,8 @@ using std::vector; // #ifndef _WIN32 static void debug_print_argv(char** argv) { - int i; - msg_printf(0, MSG_INFO, "[task_debug] Arguments:"); - for (i=0; argv[i]; i++) { + for (int i=0; argv[i]; i++) { msg_printf(0, MSG_INFO, "[task_debug] argv[%d]: %s\n", i, argv[i] ); @@ -92,43 +90,6 @@ static void debug_print_argv(char** argv) { } #endif -// create a file (new_link) which contains an XML -// reference to existing file. -// -static int make_link(const char *existing, const char *new_link) { - FILE *fp; - - fp = boinc_fopen(new_link, "w"); - if (!fp) return ERR_FOPEN; - fprintf(fp, "%s\n", existing); - fclose(fp); -#ifdef SANDBOX - return set_to_project_group(new_link); -#endif - return 0; -} - -int ACTIVE_TASK::link_user_files() { - PROJECT* project = wup->project; - unsigned int i; - FILE_REF fref; - FILE_INFO* fip; - char link_path[1024], buf[256], file_path[1024]; - int retval; - - for (i=0; iuser_files.size(); i++) { - fref = project->user_files[i]; - fip = fref.file_info; - if (fip->status != FILE_PRESENT) continue; - get_pathname(fip, file_path, sizeof(file_path)); - sprintf(link_path, "%s/%s", slot_dir, strlen(fref.open_name)?fref.open_name:fip->name); - sprintf(buf, "../../%s", file_path); - retval = make_link(buf, link_path); - if (retval) return retval; - } - return 0; -} - // make a unique key for core/app shared memory segment // int ACTIVE_TASK::get_shmem_seg_name() { @@ -250,11 +211,14 @@ int ACTIVE_TASK::write_app_init_file() { return retval; } -// set up a 'symbolic link' in the slot dir to the given file -// (or copy the file to slot dir) +// set up a file reference, given a slot dir and project dir. +// This means: +// 1) copy the file to slot dir, if reference is by copy +// 2) (Unix) make a symbolic link +// 3) (Windows) make a // static int setup_file( - WORKUNIT* wup, FILE_INFO* fip, FILE_REF& fref, + PROJECT* project, FILE_INFO* fip, FILE_REF& fref, char* file_path, char* slot_dir, bool input ) { char link_path[256], buf[256]; @@ -266,11 +230,18 @@ static int setup_file( ); sprintf(buf, "../../%s", file_path ); + // if anonymous platform, this is called even if not first time, + // so link may already be there + // + if (input && project->anonymous_platform && boinc_file_exists(link_path)) { + return 0; + } + if (fref.copy_file) { if (input) { retval = boinc_copy(file_path, link_path); if (retval) { - msg_printf(wup->project, MSG_INTERNAL_ERROR, + msg_printf(project, MSG_INTERNAL_ERROR, "Can't copy %s to %s", file_path, link_path ); return retval; @@ -279,18 +250,46 @@ static int setup_file( return 0; } - // if anonymous platform, link may already be there - // - if (input && wup->project->anonymous_platform && boinc_file_exists(link_path)) { - return 0; - } - - retval = make_link(buf, link_path); - if (retval) { - msg_printf(wup->project, MSG_INTERNAL_ERROR, - "Can't link %s to %s", file_path, link_path +#ifdef _WIN32 + FILE *fp = boinc_fopen(link_path, "w"); + if (!fp) { + msg_printf(project, MSG_INTERNAL_ERROR, + "Can't open link file %s", link_path ); - return retval; + return ERR_FOPEN; + } + fprintf(fp, "%s\n", file_path); + fclose(fp); +#else + retval = symlink(file_path, link_path); + if (retval) { + msg_printf(project, MSG_INTERNAL_ERROR, + "Can't symlink %s to %s", file_path, link_path + ); + return ERR_SYMLINK; + } +#endif +#ifdef SANDBOX + return set_to_project_group(link_path); +#endif + return 0; +} + +int ACTIVE_TASK::link_user_files() { + PROJECT* project = wup->project; + unsigned int i; + FILE_REF fref; + FILE_INFO* fip; + char file_path[1024]; + int retval; + + for (i=0; iuser_files.size(); i++) { + fref = project->user_files[i]; + fip = fref.file_info; + if (fip->status != FILE_PRESENT) continue; + get_pathname(fip, file_path, sizeof(file_path)); + setup_file(project, fip, fref, file_path, slot_dir, true); + if (retval) return retval; } return 0; } @@ -415,10 +414,10 @@ int ACTIVE_TASK::start(bool first_time) { safe_strcpy(exec_path, file_path); } // anonymous platform may use different files than - // when the result was started + // when the result was started, so link files even if not first time // if (first_time || wup->project->anonymous_platform) { - retval = setup_file(wup, fip, fref, file_path, slot_dir, true); + retval = setup_file(result->project, fip, fref, file_path, slot_dir, true); if (retval) { strcpy(buf, "Can't link input file"); goto error; @@ -438,7 +437,7 @@ int ACTIVE_TASK::start(bool first_time) { fref = wup->input_files[i]; fip = fref.file_info; get_pathname(fref.file_info, file_path, sizeof(file_path)); - retval = setup_file(wup, fip, fref, file_path, slot_dir, true); + retval = setup_file(result->project, fip, fref, file_path, slot_dir, true); if (retval) { strcpy(buf, "Can't link input file"); goto error; @@ -449,7 +448,7 @@ int ACTIVE_TASK::start(bool first_time) { if (fref.copy_file) continue; fip = fref.file_info; get_pathname(fref.file_info, file_path, sizeof(file_path)); - retval = setup_file(wup, fip, fref, file_path, slot_dir, false); + retval = setup_file(result->project, fip, fref, file_path, slot_dir, false); if (retval) { strcpy(buf, "Can't link output file"); goto error; @@ -710,7 +709,7 @@ int ACTIVE_TASK::start(bool first_time) { // char libpath[8192]; get_project_dir(wup->project, buf, sizeof(buf)); - sprintf(libpath, "%s:%s", getenv("LD_LIBRARY_PATH"), buf); + sprintf(libpath, "%s:%s:%s", getenv("LD_LIBRARY_PATH"), buf, slot_dir); setenv("LD_LIBRARY_PATH", libpath, 1); retval = chdir(slot_dir); diff --git a/client/client_types.C b/client/client_types.C index 3e9517cb07..36738801d3 100644 --- a/client/client_types.C +++ b/client/client_types.C @@ -1177,7 +1177,6 @@ int FILE_REF::parse(MIOFILE& in) { strcpy(file_name, ""); strcpy(open_name, ""); - fd = -1; main_program = false; copy_file = false; optional = false; @@ -1185,7 +1184,6 @@ int FILE_REF::parse(MIOFILE& in) { if (match_tag(buf, "")) return 0; if (parse_str(buf, "", file_name, sizeof(file_name))) continue; if (parse_str(buf, "", open_name, sizeof(open_name))) continue; - if (parse_int(buf, "", fd)) continue; if (parse_bool(buf, "main_program", main_program)) continue; if (parse_bool(buf, "copy_file", copy_file)) continue; if (parse_bool(buf, "optional", optional)) continue; @@ -1208,9 +1206,6 @@ int FILE_REF::write(MIOFILE& out) { if (strlen(open_name)) { out.printf(" %s\n", open_name); } - if (fd >= 0) { - out.printf(" %d\n", fd); - } if (main_program) { out.printf(" \n"); } diff --git a/client/client_types.h b/client/client_types.h index 81d9d16e36..1ece334e55 100644 --- a/client/client_types.h +++ b/client/client_types.h @@ -122,9 +122,8 @@ public: // or the app will be connected by the given fd (in which case fd is nonzero) // struct FILE_REF { - char file_name[256]; - char open_name[256]; - int fd; + char file_name[256]; // physical name + char open_name[256]; // logical name bool main_program; FILE_INFO* file_info; bool copy_file; diff --git a/lib/boinc_cmd.C b/lib/boinc_cmd.C index 4435f53a86..9f48faa978 100644 --- a/lib/boinc_cmd.C +++ b/lib/boinc_cmd.C @@ -59,7 +59,6 @@ Commands:\n\ --project_attach URL auth attach to project\n\ --join_acct_mgr URL name passwd attach account manager\n\ --quit_acct_mgr quit current account manager\n\ -\n\ --get_state show entire state\n\ --get_results show results\n\ --get_simple_gui_info show status of projects and active results\n\ @@ -70,7 +69,6 @@ Commands:\n\ --get_messages seqno show messages > seqno\n\ --get_host_info\n\ --version, -V show core client version\n\ - \n\ --result url result_name op job operation\n\ op = suspend | resume | abort | graphics_window | graphics_fullscreen\n\ --project URL op project operation\n\ diff --git a/lib/error_numbers.h b/lib/error_numbers.h index b9cec8bd32..93503f3421 100644 --- a/lib/error_numbers.h +++ b/lib/error_numbers.h @@ -185,6 +185,7 @@ #define ERR_TOO_MANY_EXITS -226 #define ERR_RMDIR -227 #define ERR_CHILD_FAILED -228 +#define ERR_SYMLINK -229 // PLEASE: add a text description of your error to // the text description function boincerror() in str_util.C. diff --git a/py/Boinc/tools.py b/py/Boinc/tools.py index 95e6254c1a..bb1b96d6e5 100644 --- a/py/Boinc/tools.py +++ b/py/Boinc/tools.py @@ -132,6 +132,7 @@ def process_app_version( signature_files={}, file_ref_infos={}, api_version='', + extra_xml='', quiet=False ): """Return xml for application version @@ -157,10 +158,11 @@ def process_app_version( file_ref_infos is a dictionary mapping exec_file -> extra XML strings to include in , e.g. '' - exec_files[1:] and non_exec_files should be named like 'open_name=url_filename'. - (url_filename is the basename of file as copied to - download/) If there is no '=', then the entire filename is - used as both the open_name and the filename. + exec_files[1:] and non_exec_files should be named like + 'open_name=url_filename'. + (url_filename is the basename of file as copied to download/) + If there is no '=', then the entire filename is used as + both the open_name and the filename. """ assert(exec_files) @@ -191,7 +193,9 @@ def process_app_version( app.name, version_num) if (len(api_version)): - xml_doc += ' '+api_version+'\n'; + xml_doc += ' '+api_version+'\n' + if (len(extra_xml)): + xml_doc += extra_xml first = True for exec_file in exec_files + non_exec_files: diff --git a/tools/update_versions b/tools/update_versions index eeb8678db6..070fb9cdd1 100755 --- a/tools/update_versions +++ b/tools/update_versions @@ -59,7 +59,8 @@ def add_files( exec_files, # executable files; entry 0 is the main program non_exec_files=[], # non-executable files signature_files={}, - file_ref_infos = {} + file_ref_infos = {}, + extra_xml = '' ): ''' add files to app. ''' @@ -98,7 +99,8 @@ def add_files( non_exec_files = non_exec_files, signature_files = signature_files, file_ref_infos = file_ref_infos, - api_version = api_version + api_version = api_version, + extra_xml = extra_xml ) object = database.AppVersion( @@ -120,12 +122,8 @@ def re_match_exec_filename(filepath): def find_versions(app, dir): """Find application versions in DIR. - - If directory contains sub-directories, those are scanned (non-recursively) - for files. If an executable is found, the first one found - (alphabetically) is the main program and other files bundled as - non-executables. - + If directory contains sub-directories, + those are scanned (non-recursively) for files. """ for filepath in xlistdir(dir): @@ -184,6 +182,7 @@ def find_versions__process_bundle(app, match, dir): non_exec_files = [] signature_files = {} file_ref_infos = {} + extra_xml = '' dirname = os.path.basename(dir) found_main = False for filepath in xlistdir(dir): @@ -200,6 +199,9 @@ def find_versions__process_bundle(app, match, dir): s = filepath[:-4] signature_files[s] = filepath continue + if os.path.basename(filepath) == 'extra_xml': + extra_xml = open(filepath).read() + continue if filepath.endswith('.file_ref_info'): s = filepath[:-len('.file_ref_info')] file_ref_infos[s] = open(filepath).read() @@ -228,6 +230,7 @@ def find_versions__process_bundle(app, match, dir): non_exec_files = non_exec_files, signature_files = signature_files, file_ref_infos = file_ref_infos, + extra_xml = extra_xml, ) ####################