Esempio n. 1
0
int git_futils_mmap_ro_file(git_map *out, const char *path)
{
	git_file fd = git_futils_open_ro(path);
	git_off_t len;
	int result;

	if (fd < 0)
		return fd;

	if ((len = git_futils_filesize(fd)) < 0) {
		result = -1;
		goto out;
	}

	if (!git__is_sizet(len)) {
		giterr_set(GITERR_OS, "file `%s` too large to mmap", path);
		result = -1;
		goto out;
	}

	result = git_futils_mmap_ro(out, fd, 0, (size_t)len);
out:
	p_close(fd);
	return result;
}
Esempio n. 2
0
static int diff_file_content_load_workdir_file(
	git_diff_file_content *fc,
	git_buf *path,
	git_diff_options *diff_opts)
{
	int error = 0;
	git_filter_list *fl = NULL;
	git_file fd = git_futils_open_ro(git_buf_cstr(path));
	git_buf raw = GIT_BUF_INIT;

	if (fd < 0)
		return fd;

	if (!fc->file->size &&
		!(fc->file->size = git_futils_filesize(fd)))
		goto cleanup;

	if ((diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0 &&
		diff_file_content_binary_by_size(fc))
		goto cleanup;

	if ((error = git_filter_list_load(
			&fl, fc->repo, NULL, fc->file->path,
			GIT_FILTER_TO_ODB, GIT_FILTER_ALLOW_UNSAFE)) < 0)
		goto cleanup;

	/* if there are no filters, try to mmap the file */
	if (fl == NULL) {
		if (!(error = git_futils_mmap_ro(
				&fc->map, fd, 0, (size_t)fc->file->size))) {
			fc->flags |= GIT_DIFF_FLAG__UNMAP_DATA;
			goto cleanup;
		}

		/* if mmap failed, fall through to try readbuffer below */
		giterr_clear();
	}

	if (!(error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size))) {
		git_buf out = GIT_BUF_INIT;

		error = git_filter_list_apply_to_data(&out, fl, &raw);

		if (out.ptr != raw.ptr)
			git_buf_dispose(&raw);

		if (!error) {
			fc->map.len  = out.size;
			fc->map.data = out.ptr;
			fc->flags |= GIT_DIFF_FLAG__FREE_DATA;
		}
	}

cleanup:
	git_filter_list_free(fl);
	p_close(fd);

	return error;
}
Esempio n. 3
0
static int diff_file_content_load_workdir_file(
	git_diff_file_content *fc, git_buf *path)
{
	int error = 0;
	git_vector filters = GIT_VECTOR_INIT;
	git_buf raw = GIT_BUF_INIT, filtered = GIT_BUF_INIT;
	git_file fd = git_futils_open_ro(git_buf_cstr(path));

	if (fd < 0)
		return fd;

	if (!fc->file->size &&
		!(fc->file->size = git_futils_filesize(fd)))
		goto cleanup;

	if (diff_file_content_binary_by_size(fc))
		goto cleanup;

	if ((error = git_filters_load(
			&filters, fc->repo, fc->file->path, GIT_FILTER_TO_ODB)) < 0)
		goto cleanup;
	/* error >= is a filter count */

	if (error == 0) {
		if (!(error = git_futils_mmap_ro(
				&fc->map, fd, 0, (size_t)fc->file->size)))
			fc->flags |= GIT_DIFF_FLAG__UNMAP_DATA;
		else /* fall through to try readbuffer below */
			giterr_clear();
	}

	if (error != 0) {
		error = git_futils_readbuffer_fd(&raw, fd, (size_t)fc->file->size);
		if (error < 0)
			goto cleanup;

		if (!filters.length)
			git_buf_swap(&filtered, &raw);
		else
			error = git_filters_apply(&filtered, &raw, &filters);

		if (!error) {
			fc->map.len  = git_buf_len(&filtered);
			fc->map.data = git_buf_detach(&filtered);
			fc->flags |= GIT_DIFF_FLAG__FREE_DATA;
		}

		git_buf_free(&raw);
		git_buf_free(&filtered);
	}

cleanup:
	git_filters_free(&filters);
	p_close(fd);

	return error;
}
Esempio n. 4
0
static git_mwindow *new_window(git_mwindow_file *mwf, git_file fd, git_off_t size, git_off_t offset)
{
	size_t walign = ctl.window_size / 2;
	git_off_t len;
	git_mwindow *w;

	w = git__malloc(sizeof(*w));
	if (w == NULL)
		return w;

	memset(w, 0x0, sizeof(*w));
	w->offset = (offset / walign) * walign;

	len = size - w->offset;
	if (len > (git_off_t)ctl.window_size)
		len = (git_off_t)ctl.window_size;

	ctl.mapped += (size_t)len;

	while(ctl.mapped_limit < ctl.mapped &&
			git_mwindow_close_lru(mwf) == GIT_SUCCESS) {}

	/* FIXME: Shouldn't we error out if there's an error in closing lru? */

	if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < GIT_SUCCESS)
		goto cleanup;

	ctl.mmap_calls++;
	ctl.open_windows++;

	if (ctl.mapped > ctl.peak_mapped)
		ctl.peak_mapped = ctl.mapped;

	if (ctl.open_windows > ctl.peak_open_windows)
		ctl.peak_open_windows = ctl.open_windows;

	return w;

cleanup:
	free(w);
	return NULL;
}