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,
)
####################