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; }
int git_futils_readbuffer_updated(git_fbuffer *obj, const char *path, time_t *mtime, int *updated) { git_file fd; size_t len; struct stat st; unsigned char *buff; assert(obj && path && *path); if (updated != NULL) *updated = 0; if (p_stat(path, &st) < 0) return git__throw(GIT_ENOTFOUND, "Failed to stat file %s", path); if (S_ISDIR(st.st_mode)) return git__throw(GIT_ERROR, "Can't read a dir into a buffer"); /* * If we were given a time, we only want to read the file if it * has been modified. */ if (mtime != NULL && *mtime >= st.st_mtime) return GIT_SUCCESS; if (mtime != NULL) *mtime = st.st_mtime; if (!git__is_sizet(st.st_size+1)) return git__throw(GIT_ERROR, "Failed to read file `%s`. An error occured while calculating its size", path); len = (size_t) st.st_size; if ((fd = p_open(path, O_RDONLY)) < 0) return git__throw(GIT_EOSERR, "Failed to open %s for reading", path); if ((buff = git__malloc(len + 1)) == NULL) { p_close(fd); return GIT_ENOMEM; } if (p_read(fd, buff, len) < 0) { p_close(fd); free(buff); return git__throw(GIT_ERROR, "Failed to read file `%s`", path); } buff[len] = '\0'; p_close(fd); if (mtime != NULL) *mtime = st.st_mtime; if (updated != NULL) *updated = 1; obj->data = buff; obj->len = len; return GIT_SUCCESS; }
int git_futils_readbuffer_updated( git_buf *buf, const char *path, time_t *mtime, size_t *size, int *updated) { git_file fd; struct stat st; bool changed = false; assert(buf && path && *path); if (updated != NULL) *updated = 0; if ((fd = git_futils_open_ro(path)) < 0) return fd; if (p_fstat(fd, &st) < 0 || S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) { p_close(fd); giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path); return -1; } /* * If we were given a time and/or a size, we only want to read the file * if it has been modified. */ if (size && *size != (size_t)st.st_size) changed = true; if (mtime && *mtime != st.st_mtime) changed = true; if (!size && !mtime) changed = true; if (!changed) { p_close(fd); return 0; } if (mtime != NULL) *mtime = st.st_mtime; if (size != NULL) *size = (size_t)st.st_size; if (git_futils_readbuffer_fd(buf, fd, (size_t)st.st_size) < 0) { p_close(fd); return -1; } p_close(fd); if (updated != NULL) *updated = 1; return 0; }
int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path) { int error, fd; char full_path[GIT_PATH_MAX]; char buffer[2048]; git_off_t size; git_odb_stream *stream; if (repo->path_workdir == NULL) return GIT_ENOTFOUND; git__joinpath(full_path, repo->path_workdir, path); if ((fd = gitfo_open(full_path, O_RDONLY)) < 0) return GIT_ENOTFOUND; if ((size = gitfo_size(fd)) < 0 || !git__is_sizet(size)) { gitfo_close(fd); return GIT_EOSERR; } if ((error = git_odb_open_wstream(&stream, repo->db, (size_t)size, GIT_OBJ_BLOB)) < GIT_SUCCESS) { gitfo_close(fd); return error; } while (size > 0) { ssize_t read_len; read_len = read(fd, buffer, sizeof(buffer)); if (read_len < 0) { gitfo_close(fd); stream->free(stream); return GIT_EOSERR; } stream->write(stream, buffer, read_len); size -= read_len; } error = stream->finalize_write(oid, stream); stream->free(stream); return error; }
int git_odb_hashfile(git_oid *out, const char *path, git_otype type) { git_off_t size; int result, fd = git_futils_open_ro(path); if (fd < 0) return fd; if ((size = git_futils_filesize(fd)) < 0 || !git__is_sizet(size)) { giterr_set(GITERR_OS, "File size overflow for 32-bit systems"); p_close(fd); return -1; } result = git_odb__hashfd(out, fd, (size_t)size, type); p_close(fd); return result; }
/* * Open a new window, closing the least recenty used until we have * enough space. Don't forget to add it to your list */ unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, git_off_t offset, int extra, unsigned int *left) { git_mwindow *w = *cursor; if (!w || !git_mwindow_contains(w, offset + extra)) { if (w) { w->inuse_cnt--; } for (w = mwf->windows; w; w = w->next) { if (git_mwindow_contains(w, offset + extra)) break; } /* * If there isn't a suitable window, we need to create a new * one. */ if (!w) { w = new_window(mwf, mwf->fd, mwf->size, offset); if (w == NULL) return NULL; w->next = mwf->windows; mwf->windows = w; } } /* If we changed w, store it in the cursor */ if (w != *cursor) { w->last_used = ctl.used_ctr++; w->inuse_cnt++; *cursor = w; } offset -= w->offset; assert(git__is_sizet(offset)); if (left) *left = (unsigned int)(w->window_map.len - offset); return (unsigned char *) w->window_map.data + offset; }
int git_odb__hashlink(git_oid *out, const char *path) { struct stat st; git_off_t size; int result; if (git_path_lstat(path, &st) < 0) return -1; size = st.st_size; if (!git__is_sizet(size)) { giterr_set(GITERR_OS, "File size overflow for 32-bit systems"); return -1; } if (S_ISLNK(st.st_mode)) { char *link_data; ssize_t read_len; link_data = (char*) git__malloc((size_t)(size + 1)); GITERR_CHECK_ALLOC(link_data); read_len = p_readlink(path, link_data, (size_t)size); link_data[size] = '\0'; if (read_len != (ssize_t)size) { giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", path); git__free(link_data); return -1; } result = git_odb_hash(out, link_data, (size_t)size, GIT_OBJ_BLOB); git__free(link_data); } else { int fd = git_futils_open_ro(path); if (fd < 0) return -1; result = git_odb__hashfd(out, fd, (size_t)size, GIT_OBJ_BLOB); p_close(fd); } return result; }
static int has_cr_in_index(const git_filter_source *src) { git_repository *repo = git_filter_source_repo(src); const char *path = git_filter_source_path(src); git_index *index; const git_index_entry *entry; git_blob *blob; const void *blobcontent; git_off_t blobsize; bool found_cr; if (!path) return false; if (git_repository_index__weakptr(&index, repo) < 0) { giterr_clear(); return false; } if (!(entry = git_index_get_bypath(index, path, 0)) && !(entry = git_index_get_bypath(index, path, 1))) return false; if (!S_ISREG(entry->mode)) /* don't crlf filter non-blobs */ return true; if (git_blob_lookup(&blob, repo, &entry->id) < 0) return false; blobcontent = git_blob_rawcontent(blob); blobsize = git_blob_rawsize(blob); if (!git__is_sizet(blobsize)) blobsize = (size_t)-1; found_cr = (blobcontent != NULL && blobsize > 0 && memchr(blobcontent, '\r', (size_t)blobsize) != NULL); git_blob_free(blob); return found_cr; }
static int pack_openidx_map(git_pack *p) { char pb[GIT_PATH_MAX]; off_t len; if (git__fmt(pb, sizeof(pb), "%s/pack/%s.idx", p->backend->objects_dir, p->pack_name) < 0) return GIT_ERROR; if ((p->idx_fd = gitfo_open(pb, O_RDONLY)) < 0) return GIT_ERROR; if ((len = gitfo_size(p->idx_fd)) < 0 || !git__is_sizet(len) || gitfo_map_ro(&p->idx_map, p->idx_fd, 0, (size_t)len)) { gitfo_close(p->idx_fd); return GIT_ERROR; } return GIT_SUCCESS; }
int gitfo_read_file(gitfo_buf *obj, const char *path) { git_file fd; size_t len; git_off_t size; unsigned char *buff; assert(obj && path && *path); if ((fd = gitfo_open(path, O_RDONLY)) < 0) return GIT_ERROR; if (((size = gitfo_size(fd)) < 0) || !git__is_sizet(size+1)) { gitfo_close(fd); return GIT_ERROR; } len = (size_t) size; if ((buff = git__malloc(len + 1)) == NULL) { gitfo_close(fd); return GIT_ERROR; } if (gitfo_read(fd, buff, len) < 0) { gitfo_close(fd); free(buff); return GIT_ERROR; } buff[len] = '\0'; gitfo_close(fd); obj->data = buff; obj->len = len; return GIT_SUCCESS; }
static int open_pack(git_pack *p) { char pb[GIT_PATH_MAX]; struct stat sb; if (p->pack_fd != -1) return GIT_SUCCESS; if (git__fmt(pb, sizeof(pb), "%s/pack/%s.pack", p->backend->objects_dir, p->pack_name) < 0) return GIT_ERROR; if (pack_openidx(p)) return GIT_ERROR; if ((p->pack_fd = gitfo_open(pb, O_RDONLY)) < 0) goto error_cleanup; if (gitfo_fstat(p->pack_fd, &sb) || !S_ISREG(sb.st_mode) || p->pack_size != sb.st_size || check_pack_hdr(p) || check_pack_sha1(p)) goto error_cleanup; if (!git__is_sizet(p->pack_size) || gitfo_map_ro(&p->pack_map, p->pack_fd, 0, (size_t)p->pack_size) < 0) goto error_cleanup; pack_decidx(p); return GIT_SUCCESS; error_cleanup: gitfo_close(p->pack_fd); p->pack_fd = -1; pack_decidx(p); return GIT_ERROR; }
int git_futils_readbuffer_updated( git_buf *out, const char *path, git_oid *checksum, int *updated) { int error; git_file fd; struct stat st; git_buf buf = GIT_BUF_INIT; git_oid checksum_new; assert(out && path && *path); if (updated != NULL) *updated = 0; if (p_stat(path, &st) < 0) return git_path_set_error(errno, path, "stat"); if (S_ISDIR(st.st_mode)) { giterr_set(GITERR_INVALID, "requested file is a directory"); return GIT_ENOTFOUND; } if (!git__is_sizet(st.st_size+1)) { giterr_set(GITERR_OS, "invalid regular file stat for '%s'", path); return -1; } if ((fd = git_futils_open_ro(path)) < 0) return fd; if (git_futils_readbuffer_fd(&buf, fd, (size_t)st.st_size) < 0) { p_close(fd); return -1; } p_close(fd); if (checksum) { if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) { git_buf_free(&buf); return error; } /* * If we were given a checksum, we only want to use it if it's different */ if (!git_oid__cmp(checksum, &checksum_new)) { git_buf_free(&buf); if (updated) *updated = 0; return 0; } git_oid_cpy(checksum, &checksum_new); } /* * If we're here, the file did change, or the user didn't have an old version */ if (updated != NULL) *updated = 1; git_buf_swap(out, &buf); git_buf_free(&buf); return 0; }
int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime, int *updated) { git_file fd; size_t len; struct stat st; assert(buf && path && *path); if (updated != NULL) *updated = 0; if ((fd = git_futils_open_ro(path)) < 0) return fd; if (p_fstat(fd, &st) < 0 || S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) { p_close(fd); giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path); return -1; } /* * If we were given a time, we only want to read the file if it * has been modified. */ if (mtime != NULL && *mtime >= st.st_mtime) { p_close(fd); return 0; } if (mtime != NULL) *mtime = st.st_mtime; len = (size_t) st.st_size; git_buf_clear(buf); if (git_buf_grow(buf, len + 1) < 0) { p_close(fd); return -1; } buf->ptr[len] = '\0'; while (len > 0) { ssize_t read_size = p_read(fd, buf->ptr, len); if (read_size < 0) { p_close(fd); giterr_set(GITERR_OS, "Failed to read descriptor for '%s'", path); return -1; } len -= read_size; buf->size += read_size; } p_close(fd); if (updated != NULL) *updated = 1; return 0; }