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; }
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; }
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; }
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; }