/** * Search executable within the user's PATH. * * @return full path if found, NULL otherwise. * The returned string is allocated with halloc(). */ char * file_locate_from_path(const char *argv0) { static bool already_done; char *path; char *tok; char filepath[MAX_PATH_LEN + 1]; char *result = NULL; char *ext = ""; if (is_running_on_mingw() && !is_strsuffix(argv0, (size_t) -1, ".exe")) { ext = ".exe"; } if (filepath_basename(argv0) != argv0) { if (!already_done) { s_warning("can't locate \"%s\" in PATH: name contains '%c' already", argv0, strchr(argv0, G_DIR_SEPARATOR) != NULL ? G_DIR_SEPARATOR : '/'); } goto done; } path = getenv("PATH"); if (NULL == path) { if (!already_done) { s_warning("can't locate \"%s\" in PATH: " "no such environment variable", argv0); } goto done; } path = h_strdup(path); tok = strtok(path, G_SEARCHPATH_SEPARATOR_S); while (NULL != tok) { const char *dir = tok; filestat_t buf; if ('\0' == *dir) dir = "."; concat_strings(filepath, sizeof filepath, dir, G_DIR_SEPARATOR_S, argv0, ext, NULL); if (-1 != stat(filepath, &buf)) { if (S_ISREG(buf.st_mode) && -1 != access(filepath, X_OK)) { result = h_strdup(filepath); break; } } tok = strtok(NULL, G_SEARCHPATH_SEPARATOR_S); } hfree(path); done: already_done = TRUE; /* No warning on subsequent invocation */ return result; }
int main(int argc, char **argv) { int c; int fd; SHA1Context ctx; struct sha1 digest; bool done; /* getopt() variables: */ extern int optind; extern char *optarg; mingw_early_init(); progname = filepath_basename(argv[0]); while ((c = getopt(argc, argv, "h")) != EOF) { switch (c) { case 'h': /* show help */ default: usage(); break; } } if ((argc -= optind) != 1) usage(); argv += optind; fd = file_open(argv[0], O_RDONLY, 0); if (-1 == fd) exit(EXIT_FAILURE); SHA1Reset(&ctx); for (done = FALSE; !done; /* empty */) { char buf[512]; int r; r = read(fd, buf, sizeof buf); if (-1 == r) s_fatal_exit(EXIT_FAILURE, "read() error: %m"); done = r != sizeof buf; SHA1Input(&ctx, buf, r); } SHA1Result(&ctx, &digest); close(fd); printf("%s\n", sha1_base16(&digest)); return 0; }
/** * Initialize the bfd context. * * @return TRUE if OK. */ static bool bfd_util_open(bfd_ctx_t *bc, const char *path) { static mutex_t bfd_library_mtx = MUTEX_INIT; bfd *b; void *symbols = NULL; unsigned size = 0; long count; int fd = -1; const char *libpath = path; /* * On Debian systems, there is a debugging version of libraries held * under /usr/lib/debug. We'll get better symbol resolution by * opening these instead of the usually stripped runtime versions * that will only contain externally visible symbols. */ if (!is_running_on_mingw() && is_absolute_path(path)) { static char debugpath[MAX_PATH_LEN]; const char *base = filepath_basename(path); concat_strings(debugpath, sizeof debugpath, "/usr/lib/debug/", base, NULL_PTR); fd = open(debugpath, O_RDONLY); if (-1 == fd) { concat_strings(debugpath, sizeof debugpath, "/usr/lib/debug", path, NULL_PTR); fd = open(debugpath, O_RDONLY); } if (-1 != fd) libpath = debugpath; } if (-1 == fd) fd = open(libpath, O_RDONLY); if (-1 == fd) { s_miniwarn("%s: can't open %s: %m", G_STRFUNC, libpath); return FALSE; } /* * Protect calls to BFD opening: they don't appear to be fully * thread-safe and we could enter here concurrently. */ mutex_lock_fast(&bfd_library_mtx); b = bfd_fdopenr(libpath, NULL, fd); if (NULL == b) { mutex_unlock_fast(&bfd_library_mtx); close(fd); return FALSE; } if (!bfd_util_check_format(b, bfd_object, libpath)) { s_miniwarn("%s: %s is not an object", G_STRFUNC, libpath); goto failed; } if (0 == (bfd_get_file_flags(b) & HAS_SYMS)) { s_miniwarn("%s: %s has no symbols", G_STRFUNC, libpath); goto failed; } count = bfd_read_minisymbols(b, FALSE, &symbols, &size); if (count <= 0) { bc->dynamic = TRUE; count = bfd_read_minisymbols(b, TRUE, &symbols, &size); } if (count >= 0) goto done; s_miniwarn("%s: unable to load symbols from %s ", G_STRFUNC, libpath); symbols = NULL; /* FALL THROUGH */ /* * We keep the context on errors to avoid logging them over and over * each time we attempt to access the same file. The BFD and system * resources are released though. */ failed: bfd_close(b); b = NULL; count = 0; /* FALL THROUGH */ done: mutex_unlock_fast(&bfd_library_mtx); bc->magic = BFD_CTX_MAGIC; bc->handle = b; bc->symbols = symbols; /* Allocated by the bfd library */ bc->count = count; bc->symsize = size; mutex_init(&bc->lock); return TRUE; }
/** * Search executable within the user's PATH. * * @return full path if found, NULL otherwise. * The returned string is allocated with halloc(). */ char * file_locate_from_path(const char *argv0) { static bool already_done; char *path; char *tok; char filepath[MAX_PATH_LEN + 1]; char *result = NULL; char *ext = ""; if (is_running_on_mingw() && !is_strsuffix(argv0, (size_t) -1, ".exe")) { ext = ".exe"; } if (filepath_basename(argv0) != argv0) { if (!already_done) { s_warning("can't locate \"%s\" in PATH: name contains '%c' already", argv0, strchr(argv0, G_DIR_SEPARATOR) != NULL ? G_DIR_SEPARATOR : '/'); } result = h_strdup(argv0); goto done; } path = getenv("PATH"); if (NULL == path) { if (!already_done) { s_warning("can't locate \"%s\" in PATH: " "no such environment variable", argv0); } goto done; } /* * On Windows, we need to implicitly add "." to the path if not already * present -- this is done by appending a separator and a dot, not by * checking whether "." is already part of the path. * * The reason is that "." is implied, and also because one may omit the * ".exe" extension when launching a program. This means checks done * in crash_init() for instance to see whether the file listed in * argv[0] exists and which do not account for a missing ".exe" will * attempt to locate the program in the PATH to get a full name and will * fail if we do not add ".". * * On UNIX this cannot happen because there is no hidden extension and * the "." is never made part of the PATH implictly. * * --RAM, 2015-12-06 */ if (is_running_on_mingw()) path = h_strdup_printf("%s%c.", path, *G_SEARCHPATH_SEPARATOR_S); else path = h_strdup(path); path = h_strdup(path); /* FIXME: strtok() is not thread-safe --RAM, 2015-12-06 */ tok = strtok(path, G_SEARCHPATH_SEPARATOR_S); while (NULL != tok) { const char *dir = tok; filestat_t buf; if ('\0' == *dir) dir = "."; concat_strings(filepath, sizeof filepath, dir, G_DIR_SEPARATOR_S, argv0, ext, NULL_PTR); if (-1 != stat(filepath, &buf)) { if (S_ISREG(buf.st_mode) && -1 != access(filepath, X_OK)) { result = h_strdup(filepath); break; } } tok = strtok(NULL, G_SEARCHPATH_SEPARATOR_S); } hfree(path); done: already_done = TRUE; /* No warning on subsequent invocation */ return result; }
G_GNUC_COLD void upload_stats_load_history(void) { FILE *upload_stats_file; file_path_t fp; char line[FILENAME_MAX + 64]; guint lineno = 0; gcu_upload_stats_gui_freeze(); file_path_set(&fp, settings_config_dir(), ul_stats_file); /* open file for reading */ upload_stats_file = file_config_open_read(ul_stats_what, &fp, 1); if (upload_stats_file == NULL) goto done; /* parse, insert names into ul_stats_clist */ while (fgets(line, sizeof(line), upload_stats_file)) { static const struct ul_stats zero_item; struct ul_stats item; struct sha1 sha1_buf; const char *p; size_t i; lineno++; if (line[0] == '#' || line[0] == '\n') continue; p = strchr(line, '\t'); if (NULL == p) goto corrupted; line[p - line] = '\0'; /* line is now the URL-escaped file name */ p++; /* URL-unescape in-place */ if (!url_unescape(line, TRUE)) goto corrupted; item = zero_item; item.pathname = line; for (i = 0; i < 8; i++) { guint64 v; int error; const char *endptr; p = skip_ascii_spaces(p); /* SVN versions up to 15322 had only 6 fields in the history */ if (5 == i && '\0' == *p) break; switch (i) { case 7: /* We have a SHA1 or '*' if none known */ if ('*' != *p) { size_t len = clamp_strlen(p, SHA1_BASE32_SIZE); error = !parse_base32_sha1(p, len, &sha1_buf); item.sha1 = error ? NULL : &sha1_buf; } else { error = FALSE; } p = skip_ascii_non_spaces(p); v = 0; break; default: v = parse_uint64(p, &endptr, 10, &error); p = deconstify_gchar(endptr); } if (error || !is_ascii_space(*endptr)) goto corrupted; switch (i) { case 0: item.size = v; break; case 1: item.attempts = v; break; case 2: item.complete = v; break; case 3: item.bytes_sent |= ((guint64) (guint32) v) << 32; break; case 4: item.bytes_sent |= (guint32) v; break; case 5: item.rtime = MIN(v + (time_t) 0, TIME_T_MAX + (guint64) 0); case 6: item.dtime = MIN(v + (time_t) 0, TIME_T_MAX + (guint64) 0); case 7: break; /* Already stored above */ default: g_assert_not_reached(); goto corrupted; } } /* * We store the filenames UTF-8 encoded but the file might have been * edited or corrupted. */ if (is_absolute_path(item.pathname)) { item.filename = lazy_filename_to_utf8_normalized( filepath_basename(item.pathname), UNI_NORM_NFC); } else { item.filename = lazy_unknown_to_utf8_normalized( filepath_basename(item.pathname), UNI_NORM_NFC, NULL); } if (upload_stats_find(NULL, item.pathname, item.size)) { g_warning("upload_stats_load_history():" " Ignoring line %u due to duplicate file.", lineno); } else if (upload_stats_find(item.sha1, item.pathname, item.size)) { g_warning("upload_stats_load_history():" " Ignoring line %u due to duplicate file.", lineno); } else { upload_stats_add(item.pathname, item.size, item.filename, item.attempts, item.complete, item.bytes_sent, item.rtime, item.dtime, item.sha1); } continue; corrupted: g_warning("upload statistics file corrupted at line %u.", lineno); } /* close file */ fclose(upload_stats_file); done: gcu_upload_stats_gui_thaw(); return; }