/* Initialize the defaults and run the system wgetrc and user's own wgetrc. */ void initialize (void) { char *file, *env_sysrc; bool ok = true; /* Run a non-standard system rc file when the according environment variable has been set. For internal testing purposes only! */ env_sysrc = getenv ("SYSTEM_WGETRC"); if (env_sysrc && file_exists_p (env_sysrc)) ok &= run_wgetrc (env_sysrc); /* Otherwise, if SYSTEM_WGETRC is defined, use it. */ #ifdef SYSTEM_WGETRC else if (file_exists_p (SYSTEM_WGETRC)) ok &= run_wgetrc (SYSTEM_WGETRC); #endif /* If there are any problems parsing the system wgetrc file, tell the user and exit */ if (! ok) { fprintf (stderr, _("\ Parsing system wgetrc file failed, please check '%s'. \ Or specify a different file using --config\n"), SYSTEM_WGETRC); exit (2); }
/* Return the path to the user's .wgetrc. This is either the value of `WGETRC' environment variable, or `$HOME/.wgetrc'. If the `WGETRC' variable exists but the file does not exist, the function will exit(). */ static char * wgetrc_file_name (void) { char *env, *home; char *file = NULL; /* Try the environment. */ env = getenv ("WGETRC"); if (env && *env) { if (!file_exists_p (env)) { fprintf (stderr, _("%s: WGETRC points to %s, which doesn't exist.\n"), exec_name, env); exit (1); } return xstrdup (env); } /* If that failed, try $HOME/.wgetrc. */ home = home_dir (); if (home) file = aprintf ("%s/.wgetrc", home); xfree_null (home); #ifdef WINDOWS /* Under Windows, if we still haven't found .wgetrc, look for the file `wget.ini' in the directory where `wget.exe' resides; we do this for backward compatibility with previous versions of Wget. SYSTEM_WGETRC should not be defined under WINDOWS. */ if (!file || !file_exists_p (file)) { xfree_null (file); file = NULL; home = ws_mypath (); if (home) file = aprintf ("%s/wget.ini", home); } #endif /* WINDOWS */ if (!file) return NULL; if (!file_exists_p (file)) { xfree (file); return NULL; } return file; }
/* Return the path to the user's .wgetrc. This is either the value of `WGETRC' environment variable, or `$HOME/.wgetrc'. Additionally, for windows, look in the directory where wget.exe resides. */ char * wgetrc_file_name (void) { char *file = wgetrc_env_file_name (); if (file && *file) return file; file = wgetrc_user_file_name (); #ifdef WINDOWS /* Under Windows, if we still haven't found .wgetrc, look for the file `wget.ini' in the directory where `wget.exe' resides; we do this for backward compatibility with previous versions of Wget. SYSTEM_WGETRC should not be defined under WINDOWS. */ if (!file) { char *home = home_dir (); xfree_null (file); file = NULL; home = ws_mypath (); if (home) { file = aprintf ("%s/wget.ini", home); if (!file_exists_p (file)) { xfree (file); file = NULL; } xfree (home); } } #endif /* WINDOWS */ return file; }
/* Create DIRECTORY. If some of the pathname components of DIRECTORY are missing, create them first. In case any mkdir() call fails, return its error status. Returns 0 on successful completion. The behaviour of this function should be identical to the behaviour of `mkdir -p' on systems where mkdir supports the `-p' option. */ int make_directory (const char *directory) { int quit = 0; int i; char *dir; /* Make a copy of dir, to be able to write to it. Otherwise, the function is unsafe if called with a read-only char *argument. */ STRDUP_ALLOCA (dir, directory); /* If the first character of dir is '/', skip it (and thus enable creation of absolute-pathname directories. */ for (i = (*dir == '/'); 1; ++i) { for (; dir[i] && dir[i] != '/'; i++) ; if (!dir[i]) quit = 1; dir[i] = '\0'; /* Check whether the directory already exists. */ if (!file_exists_p (dir)) { if (mkdir (dir, 0777) < 0) return -1; } if (quit) break; else dir[i] = '/'; } return 0; }
/* Check for the existance of '$HOME/.wgetrc' and return it's path if it exists and is set. */ char * wgetrc_user_file_name (void) { char *home; char *file = NULL; /* If that failed, try $HOME/.wgetrc (or equivalent). */ #ifdef __VMS file = "SYS$LOGIN:.wgetrc"; #else /* def __VMS */ home = home_dir (); if (home) file = aprintf ("%s/.wgetrc", home); xfree_null (home); #endif /* def __VMS [else] */ if (!file) return NULL; if (!file_exists_p (file)) { xfree (file); return NULL; } return file; }
/* Initialize the defaults and run the system wgetrc and user's own wgetrc. */ void initialize (void) { char *file; int ok = true; /* Load the hard-coded defaults. */ defaults (); /* If SYSTEM_WGETRC is defined, use it. */ #ifdef SYSTEM_WGETRC if (file_exists_p (SYSTEM_WGETRC)) ok &= run_wgetrc (SYSTEM_WGETRC); #endif /* Override it with your own, if one exists. */ file = wgetrc_file_name (); if (!file) return; /* #### We should canonicalize `file' and SYSTEM_WGETRC with something like realpath() before comparing them with `strcmp' */ #ifdef SYSTEM_WGETRC if (!strcmp (file, SYSTEM_WGETRC)) { fprintf (stderr, _("\ %s: Warning: Both system and user wgetrc point to `%s'.\n"), exec_name, file); }
time_t ar_member_date (const char *name) { char *arname; char *memname; long int val; ar_parse_name (name, &arname, &memname); /* Make sure we know the modtime of the archive itself because we are likely to be called just before commands to remake a member are run, and they will change the archive itself. But we must be careful not to enter_file the archive itself if it does not exist, because pattern_search assumes that files found in the data base exist or can be made. */ { struct file *arfile; arfile = lookup_file (arname); if (arfile == 0 && file_exists_p (arname)) arfile = enter_file (strcache_add (arname)); if (arfile != 0) (void) f_mtime (arfile, 0); } val = ar_scan (arname, ar_member_date_1, memname); free (arname); return (val <= 0 ? (time_t) -1 : (time_t) val); }
uerr_t retrieve_from_file (const char *file, bool html, int *count) { uerr_t status; struct urlpos *url_list, *cur_url; url_list = (html ? get_urls_html (file, NULL, NULL) : get_urls_file (file)); status = RETROK; /* Suppose everything is OK. */ *count = 0; /* Reset the URL count. */ for (cur_url = url_list; cur_url; cur_url = cur_url->next, ++*count) { char *filename = NULL, *new_file = NULL; int dt; if (cur_url->ignore_when_downloading) continue; if (opt.quota && total_downloaded_bytes > opt.quota) { status = QUOTEXC; break; } if ((opt.recursive || opt.page_requisites) && (cur_url->url->scheme != SCHEME_FTP || getproxy (cur_url->url))) { int old_follow_ftp = opt.follow_ftp; /* Turn opt.follow_ftp on in case of recursive FTP retrieval */ if (cur_url->url->scheme == SCHEME_FTP) opt.follow_ftp = 1; status = retrieve_tree (cur_url->url->url); opt.follow_ftp = old_follow_ftp; } else status = retrieve_url (cur_url->url->url, &filename, &new_file, NULL, &dt, opt.recursive); if (filename && opt.delete_after && file_exists_p (filename)) { DEBUGP (("\ Removing file due to --delete-after in retrieve_from_file():\n")); logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename); if (unlink (filename)) logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno)); dt &= ~RETROKF; } xfree_null (new_file); xfree_null (filename); }
static char *search_for(const char *evs, const char *file) { char *env; static char path[PATH_MAX]; struct stat _st; int i; #define file_exists_p(file) stat(file, &_st) == 0 env = getenv(evs); if(env) { if(file_exists_p(env)) return env; return NULL; } for(i = 0; search_path[i]; i++) { snprintf(path, PATH_MAX, "%s/%s", search_path[i], file); if(file_exists_p(path)) { return strdup(path); } } return NULL; }
/* Check the 'WGETRC' environment variable and return the file name if 'WGETRC' is set and is a valid file. If the `WGETRC' variable exists but the file does not exist, the function will exit(). */ char * wgetrc_env_file_name (void) { char *env = getenv ("WGETRC"); if (env && *env) { if (!file_exists_p (env)) { fprintf (stderr, _("%s: WGETRC points to %s, which doesn't exist.\n"), exec_name, env); exit (1); } return xstrdup (env); } return NULL; }
/* Find the URL-s in the file and call retrieve_url() for each of them. If HTML is non-zero, treat the file as HTML, and construct the URL-s accordingly. If opt.recursive is set, call recursive_retrieve() for each file. */ uerr_t retrieve_from_file (const char *file, int html, int *count) { uerr_t status; urlpos *url_list, *cur_url; /* If spider-mode is on, we do not want get_urls_html barfing errors on baseless links. */ url_list = (html ? get_urls_html (file, NULL, opt.spider) : get_urls_file (file)); status = RETROK; /* Suppose everything is OK. */ *count = 0; /* Reset the URL count. */ recursive_reset (); for (cur_url = url_list; cur_url; cur_url = cur_url->next, ++*count) { char *filename, *new_file; int dt; if (opt.quota && opt.downloaded > opt.quota) { status = QUOTEXC; break; } status = retrieve_url (cur_url->url, &filename, &new_file, NULL, &dt); if (opt.recursive && status == RETROK && (dt & TEXTHTML)) status = recursive_retrieve (filename, new_file ? new_file : cur_url->url); if (filename && opt.delete_after && file_exists_p (filename)) { logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename); if (unlink (filename)) logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno)); dt &= ~RETROKF; } FREE_MAYBE (new_file); FREE_MAYBE (filename); } /* Free the linked list of URL-s. */ free_urlpos (url_list); return status; }
int md_post_extract(void) { char kernelbin[100]; if (boardtype == BOARD_TYPE_NORMAL) return 0; if (boardtype == BOARD_TYPE_RPI) { snprintf(kernelbin, 100, "%s/netbsd.bin", targetroot_mnt); if (file_exists_p(kernelbin)) { run_program(RUN_DISPLAY, "/bin/cp %s /targetroot/boot/kernel.img", kernelbin); } else { msg_display(MSG_rpikernelmissing); process_menu(MENU_ok, NULL); return 1; } } return 0; }
/* Return a unique filename, given a prefix and count */ static char * unique_name_1 (const char *fileprefix, int count) { char *filename; if (count) { filename = (char *)xmalloc (strlen (fileprefix) + numdigit (count) + 2); sprintf (filename, "%s.%d", fileprefix, count); } else filename = xstrdup (fileprefix); if (!file_exists_p (filename)) return filename; else { free (filename); return NULL; } }
uerr_t retrieve_from_file (const char *file, bool html, int *count) { uerr_t status; struct urlpos *url_list, *cur_url; struct iri *iri = iri_new(); char *input_file, *url_file = NULL; const char *url = file; status = RETROK; /* Suppose everything is OK. */ *count = 0; /* Reset the URL count. */ /* sXXXav : Assume filename and links in the file are in the locale */ set_uri_encoding (iri, opt.locale, true); set_content_encoding (iri, opt.locale); if (url_valid_scheme (url)) { int dt,url_err; uerr_t status; struct url *url_parsed = url_parse (url, &url_err, iri, true); if (!url_parsed) { char *error = url_error (url, url_err); logprintf (LOG_NOTQUIET, "%s: %s.\n", url, error); xfree (error); return URLERROR; } if (!opt.base_href) opt.base_href = xstrdup (url); status = retrieve_url (url_parsed, url, &url_file, NULL, NULL, &dt, false, iri, true); url_free (url_parsed); if (!url_file || (status != RETROK)) return status; if (dt & TEXTHTML) html = true; /* If we have a found a content encoding, use it. * ( == is okay, because we're checking for identical object) */ if (iri->content_encoding != opt.locale) set_uri_encoding (iri, iri->content_encoding, false); /* Reset UTF-8 encode status */ iri->utf8_encode = opt.enable_iri; xfree_null (iri->orig_url); iri->orig_url = NULL; input_file = url_file; } else input_file = (char *) file; url_list = (html ? get_urls_html (input_file, NULL, NULL, iri) : get_urls_file (input_file)); xfree_null (url_file); for (cur_url = url_list; cur_url; cur_url = cur_url->next, ++*count) { char *filename = NULL, *new_file = NULL; int dt; struct iri *tmpiri = iri_dup (iri); struct url *parsed_url = NULL; if (cur_url->ignore_when_downloading) continue; if (opt.quota && total_downloaded_bytes > opt.quota) { status = QUOTEXC; break; } parsed_url = url_parse (cur_url->url->url, NULL, tmpiri, true); if ((opt.recursive || opt.page_requisites) && (cur_url->url->scheme != SCHEME_FTP || getproxy (cur_url->url))) { int old_follow_ftp = opt.follow_ftp; /* Turn opt.follow_ftp on in case of recursive FTP retrieval */ if (cur_url->url->scheme == SCHEME_FTP) opt.follow_ftp = 1; status = retrieve_tree (parsed_url ? parsed_url : cur_url->url, tmpiri); opt.follow_ftp = old_follow_ftp; } else status = retrieve_url (parsed_url ? parsed_url : cur_url->url, cur_url->url->url, &filename, &new_file, NULL, &dt, opt.recursive, tmpiri, true); if (parsed_url) url_free (parsed_url); if (filename && opt.delete_after && file_exists_p (filename)) { DEBUGP (("\ Removing file due to --delete-after in retrieve_from_file():\n")); logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename); if (unlink (filename)) logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno)); dt &= ~RETROKF; } xfree_null (new_file); xfree_null (filename); iri_free (tmpiri); }
int run_program(int argc, char **argv) { CommandLineArgument<int> number_of_list_files; int next_command_line_argument = 0; bool echo_commands = false; for (int i = 1; ((i < argc) && (!have_argument_p(number_of_list_files))); i++) { std::string argument(argv[i]); if (argument == "--help") { print_usage(); return 0; } else if (argument == "--echo") { echo_commands = true; } else if (!have_argument_p(number_of_list_files)) { number_of_list_files = argument; next_command_line_argument = i + 1; } } if (!have_argument_p(number_of_list_files)) { print_usage(); return -1; } if (*number_of_list_files == 0) return 0; const int minimum_number_of_arguments = 0 + *number_of_list_files + 1 // the command; + 0; if ((argc - next_command_line_argument) < minimum_number_of_arguments) throw make_runtime_error("Not enough arguments available for processing.\n"); std::list<std::string> standard_input_list; bool have_read_standard_input_list = false; std::vector<std::string> list_filenames(*number_of_list_files); std::vector<std::list<std::string> > lists(*number_of_list_files); for (int i = 0; i < *number_of_list_files; i++) { int argument_index = i + next_command_line_argument; std::string list_file = argv[argument_index]; std::list<std::string> l; if ((list_file == "-") && (have_read_standard_input_list)) { l = standard_input_list; } else if ((list_file == "-")) { standard_input_list = read_list(std::cin); have_read_standard_input_list = true; l = standard_input_list; } else if (!file_exists_p(list_file)) { throw make_runtime_error("List file %s does not exist.", list_file.c_str()); } else { l = read_list(list_file.c_str()); } list_filenames[i] = list_file; lists[i] = l; } next_command_line_argument += *number_of_list_files; // read the command and its options. std::string command(argv[next_command_line_argument]); std::list<std::string> command_arguments; std::copy(argv + next_command_line_argument + 1, argv + argc, std::back_inserter(command_arguments)); // check all lists are the same size. for (size_t i = 0; i < lists.size(); i++) { if (lists[i].size() != lists[0].size()) throw make_runtime_error("The number of entires in list %s (%d) differs to %s (%d).", list_filenames[i].c_str(), lists[i].size(), list_filenames[0].c_str(), lists[0].size()); } EchoRunner echo_runner(std::cout); ForkRunner fork_runner; Runner *runner = 0; if (echo_commands) runner = &echo_runner; else runner = &fork_runner; assert(runner); std::vector<std::list<std::string>::const_iterator> iterators(*number_of_list_files); for (int i = 0; i < *number_of_list_files; i++) iterators[i] = lists[i].begin(); for (size_t i = 0; i < lists[0].size(); i++) { std::string invocation_command = command; std::list<std::string> invocation_arguments; std::copy(command_arguments.begin(), command_arguments.end(), std::back_inserter(invocation_arguments)); for (size_t j = 0; j < iterators.size(); j++) { invocation_arguments.push_back(*iterators[j]); iterators[j]++; } runner->perform(invocation_command, invocation_arguments); } return 0; }
/* Search for an existing dSYM file as a possible separate debug file. Adapted from gdb. */ static Char * find_separate_debug_file (const Char *executable_name) { Char *basename_str; Char *dot_ptr; Char *slash_ptr; Char *dsymfile; /* Make sure the object file name itself doesn't contain ".dSYM" in it or we will end up with an infinite loop where after we add a dSYM symbol file, it will then enter this function asking if there is a debug file for the dSYM file itself. */ if (VG_(strcasestr) (executable_name, ".dSYM") == NULL) { /* Check for the existence of a .dSYM file for a given executable. */ basename_str = VG_(basename) (executable_name); dsymfile = ML_(dinfo_zalloc)("di.readmacho.dsymfile", VG_(strlen) (executable_name) + VG_(strlen) (APPLE_DSYM_EXT_AND_SUBDIRECTORY) + VG_(strlen) (basename_str) + 1 ); /* First try for the dSYM in the same directory as the original file. */ VG_(strcpy) (dsymfile, executable_name); VG_(strcat) (dsymfile, APPLE_DSYM_EXT_AND_SUBDIRECTORY); VG_(strcat) (dsymfile, basename_str); if (file_exists_p (dsymfile)) return dsymfile; /* Now search for any parent directory that has a '.' in it so we can find Mac OS X applications, bundles, plugins, and any other kinds of files. Mac OS X application bundles wil have their program in "/some/path/MyApp.app/Contents/MacOS/MyApp" (or replace ".app" with ".bundle" or ".plugin" for other types of bundles). So we look for any prior '.' character and try appending the apple dSYM extension and subdirectory and see if we find an existing dSYM file (in the above MyApp example the dSYM would be at either: "/some/path/MyApp.app.dSYM/Contents/Resources/DWARF/MyApp" or "/some/path/MyApp.dSYM/Contents/Resources/DWARF/MyApp". */ VG_(strcpy) (dsymfile, VG_(dirname) (executable_name)); while ((dot_ptr = VG_(strrchr) (dsymfile, '.'))) { /* Find the directory delimiter that follows the '.' character since we now look for a .dSYM that follows any bundle extension. */ slash_ptr = VG_(strchr) (dot_ptr, '/'); if (slash_ptr) { /* NULL terminate the string at the '/' character and append the path down to the dSYM file. */ *slash_ptr = '\0'; VG_(strcat) (slash_ptr, APPLE_DSYM_EXT_AND_SUBDIRECTORY); VG_(strcat) (slash_ptr, basename_str); if (file_exists_p (dsymfile)) return dsymfile; } /* NULL terminate the string at the '.' character and append the path down to the dSYM file. */ *dot_ptr = '\0'; VG_(strcat) (dot_ptr, APPLE_DSYM_EXT_AND_SUBDIRECTORY); VG_(strcat) (dot_ptr, basename_str); if (file_exists_p (dsymfile)) return dsymfile; /* NULL terminate the string at the '.' locatated by the strrchr() function again. */ *dot_ptr = '\0'; /* We found a previous extension '.' character and did not find a dSYM file so now find previous directory delimiter so we don't try multiple times on a file name that may have a version number in it such as "/some/path/MyApp.6.0.4.app". */ slash_ptr = VG_(strrchr) (dsymfile, '/'); if (!slash_ptr) break; /* NULL terminate the string at the previous directory character and search again. */ *slash_ptr = '\0'; } } return NULL; }
int fileutils___file_exists_p(char *filename) { return(file_exists_p(filename)); }
int run_program(int argc, char **argv) { CommandLineArgument<std::string> model_pathname; for (int i = 1; i < argc; i++) { std::string argument(argv[i]); if (argument == "--help") { print_usage(); return 0; } else if (!assign_argument(argument, model_pathname)) { throw make_runtime_error("Do not know how to process argument '%s'", argument.c_str()); } } if (!have_argument_p(model_pathname)) model_pathname = AVATAR::DefaultAvatarModelPathname(); if (!file_exists_p(model_pathname->c_str())) throw make_runtime_error("Model file '%s' does not exist", model_pathname->c_str()); AVATAR::Avatar *avatar = AVATAR::LoadAvatar(model_pathname->c_str()); if (avatar->numberOfAvatars() == 0) return 0; print_controls(); const int minimum_avatar = 0; const int maximum_avatar = avatar->numberOfAvatars() - 1; int index = 0; bool quit_application_p = false; printf("Number of avatars: %d\n", avatar->numberOfAvatars()); show_avatar(avatar, index); while (!quit_application_p) { char ch = cv::waitKey(10); switch (ch) { case 'a': case 2: index = std::max(minimum_avatar, index - 1); show_avatar(avatar, index); break; case 'd': case 3: index = std::min(maximum_avatar, index + 1); show_avatar(avatar, index); break; case 'q': case 27: quit_application_p = true; break; case -1: break; default: break; } } printf("\n"); delete avatar; return 0; }
/* Loop through all files in metalink structure and retrieve them. Returns RETROK if all files were downloaded. Returns last retrieval error (from retrieve_url) if some files could not be downloaded. */ uerr_t retrieve_from_metalink (const metalink_t* metalink) { metalink_file_t **mfile_ptr; uerr_t last_retr_err = RETROK; /* Store last encountered retrieve error. */ FILE *_output_stream = output_stream; bool _output_stream_regular = output_stream_regular; char *_output_document = opt.output_document; DEBUGP (("Retrieving from Metalink\n")); /* No files to download. */ if (!metalink->files) return RETROK; if (opt.output_document) { /* We cannot support output_document as we need to compute checksum of downloaded file, and to remove it if the checksum is bad. */ logputs (LOG_NOTQUIET, _("-O not supported for metalink download. Ignoring.\n")); } for (mfile_ptr = metalink->files; *mfile_ptr; mfile_ptr++) { metalink_file_t *mfile = *mfile_ptr; metalink_resource_t **mres_ptr; char *filename = NULL; bool hash_ok = false; uerr_t retr_err = METALINK_MISSING_RESOURCE; /* -1 -> file should be rejected 0 -> could not verify 1 -> verified successfully */ char sig_status = 0; output_stream = NULL; DEBUGP (("Processing metalink file %s...\n", quote (mfile->name))); /* Resources are sorted by priority. */ for (mres_ptr = mfile->resources; *mres_ptr; mres_ptr++) { metalink_resource_t *mres = *mres_ptr; metalink_checksum_t **mchksum_ptr, *mchksum; struct iri *iri; struct url *url; int url_err; if (!RES_TYPE_SUPPORTED (mres->type)) { logprintf (LOG_VERBOSE, _("Resource type %s not supported, ignoring...\n"), quote (mres->type)); continue; } retr_err = METALINK_RETR_ERROR; /* If output_stream is not NULL, then we have failed on previous resource and are retrying. Thus, remove the file. */ if (output_stream) { fclose (output_stream); output_stream = NULL; if (unlink (filename)) logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno)); xfree (filename); } /* Parse our resource URL. */ iri = iri_new (); set_uri_encoding (iri, opt.locale, true); url = url_parse (mres->url, &url_err, iri, false); if (!url) { char *error = url_error (mres->url, url_err); logprintf (LOG_NOTQUIET, "%s: %s.\n", mres->url, error); xfree (error); inform_exit_status (URLERROR); iri_free (iri); continue; } else { /* Avoid recursive Metalink from HTTP headers. */ bool _metalink_http = opt.metalink_over_http; /* Assure proper local file name regardless of the URL of particular Metalink resource. To do that we create the local file here and put it as output_stream. We restore the original configuration after we are finished with the file. */ output_stream = unique_create (mfile->name, true, &filename); output_stream_regular = true; /* Store the real file name for displaying in messages. */ opt.output_document = filename; opt.metalink_over_http = false; DEBUGP (("Storing to %s\n", filename)); retr_err = retrieve_url (url, mres->url, NULL, NULL, NULL, NULL, opt.recursive, iri, false); opt.metalink_over_http = _metalink_http; } url_free (url); iri_free (iri); if (retr_err == RETROK) { FILE *local_file; /* Check the digest. */ local_file = fopen (filename, "rb"); if (!local_file) { logprintf (LOG_NOTQUIET, _("Could not open downloaded file.\n")); continue; } for (mchksum_ptr = mfile->checksums; *mchksum_ptr; mchksum_ptr++) { char sha256[SHA256_DIGEST_SIZE]; char sha256_txt[2 * SHA256_DIGEST_SIZE + 1]; mchksum = *mchksum_ptr; /* I have seen both variants... */ if (strcasecmp (mchksum->type, "sha256") && strcasecmp (mchksum->type, "sha-256")) { DEBUGP (("Ignoring unsupported checksum type %s.\n", quote (mchksum->type))); continue; } logprintf (LOG_VERBOSE, _("Computing checksum for %s\n"), quote (mfile->name)); sha256_stream (local_file, sha256); wg_hex_to_string (sha256_txt, sha256, SHA256_DIGEST_SIZE); DEBUGP (("Declared hash: %s\n", mchksum->hash)); DEBUGP (("Computed hash: %s\n", sha256_txt)); if (!strcmp (sha256_txt, mchksum->hash)) { logputs (LOG_VERBOSE, _("Checksum matches.\n")); hash_ok = true; } else { logprintf (LOG_NOTQUIET, _("Checksum mismatch for file %s.\n"), quote (mfile->name)); hash_ok = false; } /* Stop as soon as we checked the supported checksum. */ break; } /* Iterate over available checksums. */ fclose (local_file); local_file = NULL; if (!hash_ok) continue; sig_status = 0; /* Not verified. */ #ifdef HAVE_GPGME /* Check the crypto signature. Note that the signtures from Metalink in XML will not be parsed when using libmetalink version older than 0.1.3. Metalink-over-HTTP is not affected by this problem. */ if (mfile->signature) { metalink_signature_t *msig = mfile->signature; gpgme_error_t gpgerr; gpgme_ctx_t gpgctx; gpgme_data_t gpgsigdata, gpgdata; gpgme_verify_result_t gpgres; gpgme_signature_t gpgsig; gpgme_protocol_t gpgprot = GPGME_PROTOCOL_UNKNOWN; int fd = -1; /* Initialize the library - as name suggests. */ gpgme_check_version (NULL); /* Open data file. */ fd = open (filename, O_RDONLY); if (fd == -1) { logputs (LOG_NOTQUIET, _("Could not open downloaded file for signature " "verification.\n")); goto gpg_skip_verification; } /* Assign file descriptor to GPG data structure. */ gpgerr = gpgme_data_new_from_fd (&gpgdata, fd); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, "GPGME data_new_from_fd: %s\n", gpgme_strerror (gpgerr)); goto gpg_skip_verification; } /* Prepare new GPGME context. */ gpgerr = gpgme_new (&gpgctx); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, "GPGME new: %s\n", gpgme_strerror (gpgerr)); gpgme_data_release (gpgdata); goto gpg_skip_verification; } DEBUGP (("Verifying signature %s:\n%s\n", quote (msig->mediatype), msig->signature)); /* Check signature type. */ if (!strcmp (msig->mediatype, "application/pgp-signature")) gpgprot = GPGME_PROTOCOL_OpenPGP; else /* Unsupported signature type. */ { gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } gpgerr = gpgme_set_protocol (gpgctx, gpgprot); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, "GPGME set_protocol: %s\n", gpgme_strerror (gpgerr)); gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } /* Load the signature. */ gpgerr = gpgme_data_new_from_mem (&gpgsigdata, msig->signature, strlen (msig->signature), 0); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, _("GPGME data_new_from_mem: %s\n"), gpgme_strerror (gpgerr)); gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } /* Verify the signature. */ gpgerr = gpgme_op_verify (gpgctx, gpgsigdata, gpgdata, NULL); if (gpgerr != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, _("GPGME op_verify: %s\n"), gpgme_strerror (gpgerr)); gpgme_data_release (gpgsigdata); gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } /* Check the results. */ gpgres = gpgme_op_verify_result (gpgctx); if (!gpgres) { logputs (LOG_NOTQUIET, _("GPGME op_verify_result: NULL\n")); gpgme_data_release (gpgsigdata); gpgme_release (gpgctx); gpgme_data_release (gpgdata); goto gpg_skip_verification; } /* The list is null-terminated. */ for (gpgsig = gpgres->signatures; gpgsig; gpgsig = gpgsig->next) { DEBUGP (("Checking signature %s\n", gpgsig->fpr)); if (gpgsig->summary & (GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN)) { logputs (LOG_VERBOSE, _("Signature validation suceeded.\n")); sig_status = 1; break; } if (gpgsig->summary & GPGME_SIGSUM_RED) { logputs (LOG_NOTQUIET, _("Invalid signature. Rejecting resource.\n")); sig_status = -1; break; } if (gpgsig->summary == 0 && (gpgsig->status & 0xFFFF) == GPG_ERR_NO_ERROR) { logputs (LOG_VERBOSE, _("Data matches signature, but signature " "is not trusted.\n")); } if ((gpgsig->status & 0xFFFF) != GPG_ERR_NO_ERROR) { logprintf (LOG_NOTQUIET, "GPGME: %s\n", gpgme_strerror (gpgsig->status & 0xFFFF)); } } gpgme_data_release (gpgsigdata); gpgme_release (gpgctx); gpgme_data_release (gpgdata); gpg_skip_verification: if (fd != -1) close (fd); } /* endif (mfile->signature) */ #endif /* Stop if file was downloaded with success. */ if (sig_status >= 0) break; } /* endif RETR_OK. */ } /* Iterate over resources. */ if (retr_err != RETROK) { logprintf (LOG_VERBOSE, _("Failed to download %s. Skipping resource.\n"), quote (mfile->name)); } else if (!hash_ok) { retr_err = METALINK_CHKSUM_ERROR; logprintf (LOG_NOTQUIET, _("File %s retrieved but checksum does not match. " "\n"), quote (mfile->name)); } #ifdef HAVE_GPGME /* Signature will be only validated if hash check was successful. */ else if (sig_status < 0) { retr_err = METALINK_SIG_ERROR; logprintf (LOG_NOTQUIET, _("File %s retrieved but signature does not match. " "\n"), quote (mfile->name)); } #endif last_retr_err = retr_err == RETROK ? last_retr_err : retr_err; /* Remove the file if error encountered or if option specified. Note: the file has been downloaded using *_loop. Therefore, it is not necessary to keep the file for continuated download. */ if ((retr_err != RETROK || opt.delete_after) && filename != NULL && file_exists_p (filename)) { logprintf (LOG_VERBOSE, _("Removing %s.\n"), quote (filename)); if (unlink (filename)) logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno)); } if (output_stream) { fclose (output_stream); output_stream = NULL; } xfree (filename); } /* Iterate over files. */ /* Restore original values. */ opt.output_document = _output_document; output_stream_regular = _output_stream_regular; output_stream = _output_stream; return last_retr_err; }