/** * Return a pointer to the extension, including the dot, or NULL. * Same as dcc_find_extension(), but the argument and return * value are both pointers to const. **/ const char * dcc_find_extension_const(const char *sfile) { #if 0 return dcc_find_extension((char *) sfile); #else /* The following intermediate variable works around a bug in gcc 4.2.3 where * for the code above gcc spuriously reports "warning: passing argument 1 * of 'dcc_find_extension' discards qualifiers from pointer target type", * despite the explicit cast. */ char *sfile_nonconst = (char *)sfile; return dcc_find_extension(sfile_nonconst); #endif }
static int dcc_set_file_extension(const char *sfile, const char *new_ext, char **ofile) { char *dot, *o; o = strdup(sfile); if (!o) { rs_log_error("strdup failed (out of memory?)"); return EXIT_DISTCC_FAILED; } dot = dcc_find_extension(o); if (!dot) { rs_log_error("couldn't find extension in \"%s\"", o); return EXIT_DISTCC_FAILED; } if (strlen(dot) < strlen(new_ext)) { rs_log_error("not enough space for new extension"); return EXIT_DISTCC_FAILED; } strcpy(dot, new_ext); *ofile = o; return 0; }
static int dcc_input_tmpnam(char * orig_input, char **tmpnam_ret) { const char *input_exten; rs_trace("input file %s", orig_input); input_exten = dcc_find_extension(orig_input); if (input_exten) input_exten = dcc_preproc_exten(input_exten); if (!input_exten) /* previous line might return NULL */ input_exten = ".tmp"; return dcc_make_tmpnam("distccd", input_exten, tmpnam_ret); }
/* Go through arguments (in @p argv), and relevant environment variables, and * find out where the dependencies output should go. Return that location in a * newly allocated string in @p dotd_fname. @p needs_dotd is set to true if the * compilation command line and environent imply that a .d file must be * produced. @p sets_dotd_target is set to true if there is a -MQ or -MT * option. This is to be used on the client, so that the client knows where to * put the .d file it gets from the server. @p dotd_target is set only if * @needs_dotd is true and @sets_dotd_target is false and the target is given in * the DEPENDENCIES_OUTPUT environment variable. * * Note: -M is not handled here, because this option implies -E. * * TODO(manos): it does not support SUNPRO_DEPENDENCIES. */ int dcc_get_dotd_info(char **argv, char **dotd_fname, int *needs_dotd, int *sets_dotd_target, char **dotd_target) { char *deps_output = 0; char *input_file; char *output_file; char **new_args; /* will throw this away */ int has_dash_o = 0; char *env_var = 0; int ret; int i; char *a; *needs_dotd = 0; *sets_dotd_target = 0; *dotd_target = NULL; env_var = getenv("DEPENDENCIES_OUTPUT"); if (env_var != NULL) { *needs_dotd = 1; } for (i = 0; (a = argv[i]); i++) { if (strcmp(a, "-MT") == 0) { *sets_dotd_target = 1; ++i; continue; } if (strcmp(a, "-MQ") == 0) { *sets_dotd_target = 1; ++i; continue; } /* Catch-all for all -MD, -MMD, etc, options. * -MQ and -MT do not imply a deps file is expected. */ if (strncmp(a, "-M", 2) == 0) { *needs_dotd = 1; } if (strcmp(a, "-MF") == 0) { ++i; deps_output = argv[i]; } else if (strncmp(a, "-MF", 3) == 0) { deps_output = argv[i] + 3; } else if (strcmp(a, "-o") == 0) { has_dash_o = 1; } } /* TODO(csilvers): we also need to parse -Wp,-x,-y,-z, in the same * way we do gcc flags in the for loop above. Note that the -Wp * flags are passed to cpp, with slightly different semantics than * gcc flags (eg -Wp,-MD takes a filename argument, while -MD does * not). */ if (deps_output) { *dotd_fname = strdup(deps_output); if (*dotd_fname == NULL) { return EXIT_OUT_OF_MEMORY; } else { return 0; } } /* ok, so there is no explicit setting of the deps filename. */ deps_output = env_var; if (deps_output) { char *space; *dotd_fname = strdup(deps_output); if (*dotd_fname == NULL) { return EXIT_OUT_OF_MEMORY; } space = strchr(*dotd_fname, ' '); if (space != NULL) { *space = '\0'; *dotd_target = space + 1; } return 0; } /* and it's not set explicitly in the variable */ { /* Call dcc_scan_args to find the input/output files in order to calculate a name for the .d file.*/ char *extension; char *tmp_dotd_fname; ret = dcc_scan_args(argv, &input_file, &output_file, &new_args, NULL); if (ret) return ret; /* if .o is set, just append .d. * otherwise, take the basename of the input, and set the suffix to .d */ if (has_dash_o) tmp_dotd_fname = strdup(output_file); else tmp_dotd_fname = strdup(input_file); if (tmp_dotd_fname == NULL) return EXIT_OUT_OF_MEMORY; extension = dcc_find_extension(tmp_dotd_fname); /* Whether derived from input or output filename, we peel the extension off (if it exists). */ if (extension) { /* dcc_find_extension guarantees that there is space for 'd'. */ extension[1] = 'd'; extension[2] = '\0'; *dotd_fname = tmp_dotd_fname; } else { /* There is no extension (or name ends with a "."). */ if (tmp_dotd_fname[strlen(tmp_dotd_fname) - 1] == '.') checked_asprintf(dotd_fname, "%s%s", tmp_dotd_fname, "d"); else checked_asprintf(dotd_fname, "%s%s", tmp_dotd_fname, ".d"); if (*dotd_fname == NULL) { return EXIT_OUT_OF_MEMORY; } free(tmp_dotd_fname); } return 0; } }
int dcc_r_many_files(int in_fd, const char *dirname, enum dcc_compress compr) { int ret = 0; unsigned int n_files; unsigned int i; char *name = NULL; char *link_target = NULL; char token[5]; #ifdef XCODE_INTEGRATION /* NOTE: If this function is ever used for something besides pump * mode support for receiving things to be compiled, then it should * take another argument to include/exclude this fixup. */ char *xci_name, *xci_link_target, *extension; #endif if ((ret = dcc_r_token_int(in_fd, "NFIL", &n_files))) return ret; for (i = 0; i < n_files; ++i) { /* like dcc_r_argv */ unsigned int link_or_file_len; if ((ret = dcc_r_token_string(in_fd, "NAME", &name))) goto out_cleanup; #ifdef XCODE_INTEGRATION xci_name = dcc_xci_unmask_developer_dir(name); if (xci_name) { free(name); name = xci_name; xci_name = NULL; } else { ret = EXIT_OUT_OF_MEMORY; goto out_cleanup; } #endif /* FIXME: verify that name starts with '/' and doesn't contain '..'. */ if ((ret = prepend_dir_to_name(dirname, &name))) goto out_cleanup; if ((ret = dcc_r_sometoken_int(in_fd, token, &link_or_file_len))) goto out_cleanup; /* Must prepend the dirname for the file name, a link's target name. */ if (strncmp(token, "LINK", 4) == 0) { if ((ret = dcc_r_str_alloc(in_fd, link_or_file_len, &link_target))){ goto out_cleanup; } rs_trace("got '%s'", link_target); #ifdef XCODE_INTEGRATION xci_link_target = dcc_xci_unmask_developer_dir(link_target); if (xci_link_target) { free(link_target); link_target = xci_link_target; xci_link_target = NULL; } else { ret = EXIT_OUT_OF_MEMORY; goto out_cleanup; } #endif /* FIXME: verify that link_target doesn't contain '..'. * But the include server uses '..' to reference system * directories (see _MakeLinkFromMirrorToRealLocation * in include_server/compiler_defaults.py), so we'll need to * modify that first. */ if (link_target[0] == '/') { if ((ret = prepend_dir_to_name(dirname, &link_target))) { goto out_cleanup; } } if ((ret = dcc_mk_tmp_ancestor_dirs(name))) { goto out_cleanup; } if (symlink(link_target, name) != 0) { rs_log_error("failed to create path for %s: %s", name, strerror(errno)); ret = 1; goto out_cleanup; } if ((ret = dcc_add_cleanup(name))) { /* bailing out */ unlink(name); goto out_cleanup; } } else if (strncmp(token, "FILE", 4) == 0) { if ((ret = dcc_r_file(in_fd, name, link_or_file_len, compr))) { goto out_cleanup; } #ifdef XCODE_INTEGRATION if ((extension = dcc_find_extension(name)) && !strcmp(extension, ".hmap") && (ret = dcc_xci_headermap_fix(name, dirname))) { unlink(name); goto out_cleanup; } #endif if ((ret = dcc_add_cleanup(name))) { /* bailing out */ unlink(name); goto out_cleanup; } } else { char buf[4 + sizeof(link_or_file_len)]; /* unexpected token */ rs_log_error("protocol derailment: expected token FILE or LINK"); /* We should explain what happened here, but we have already read * a few more bytes. */ strncpy(buf, token, 4); /* TODO(manos): this is probably not kosher */ memcpy(&buf[4], &link_or_file_len, sizeof(link_or_file_len)); dcc_explain_mismatch(buf, 12, in_fd); ret = EXIT_PROTOCOL_ERROR; goto out_cleanup; } out_cleanup: if (name) { free(name); name = NULL; } if (link_target) { free(link_target); link_target = NULL; } if (ret) break; } return ret; }