Example #1
0
/**
 * 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;
}
Example #2
0
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;
}
Example #3
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;
}
Example #4
0
/**
 * 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;
}
Example #5
0
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;
}