summaryrefslogtreecommitdiff
path: root/src/fileops.c
diff options
context:
space:
mode:
authorVicent Martí <tanoku@gmail.com>2012-02-27 04:28:31 +0100
committerVicent Martí <tanoku@gmail.com>2012-02-27 05:30:07 +0100
commit13224ea4aad9a1b3c9cc4c992ceaea9af623e047 (patch)
treeb5c3a503d1ef7ba6269bf4291530c4e8e5936bdb /src/fileops.c
parente07c2d225deec42e592133df49ad8c564d4d66c7 (diff)
downloadlibgit2-13224ea4aad9a1b3c9cc4c992ceaea9af623e047.tar.gz
buffer: Unify `git_fbuffer` and `git_buf`
This makes so much sense that I can't believe it hasn't been done before. Kill the old `git_fbuffer` and read files straight into `git_buf` objects. Also: In order to fully support 4GB files in 32-bit systems, the `git_buf` implementation has been changed from using `ssize_t` for storage and storing negative values on allocation failure, to using `size_t` and changing the buffer pointer to a magical pointer on allocation failure. Hopefully this won't break anything.
Diffstat (limited to 'src/fileops.c')
-rw-r--r--src/fileops.c74
1 files changed, 32 insertions, 42 deletions
diff --git a/src/fileops.c b/src/fileops.c
index 3241c68b1..d2b4af51e 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -97,87 +97,77 @@ mode_t git_futils_canonical_mode(mode_t raw_mode)
return 0;
}
-int git_futils_readbuffer_updated(git_fbuffer *obj, const char *path, time_t *mtime, int *updated)
+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;
- unsigned char *buff;
- assert(obj && path && *path);
+ assert(buf && 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 ((fd = p_open(path, O_RDONLY)) < 0) {
+ return git__throw(GIT_ENOTFOUND, "Failed to read file '%s': %s", path, strerror(errno));
+ }
- if (S_ISDIR(st.st_mode))
- return git__throw(GIT_ERROR, "Can't read a dir into a buffer");
+ if (p_fstat(fd, &st) < 0 || S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) {
+ close(fd);
+ return git__throw(GIT_EOSERR, "Failed to stat file '%s'", path);
+ }
/*
* 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) {
+ close(fd);
+ return 0;
+ }
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);
+ git_buf_clear(buf);
- if ((buff = git__malloc(len + 1)) == NULL) {
- p_close(fd);
+ if (git_buf_grow(buf, len + 1) < 0) {
+ close(fd);
return GIT_ENOMEM;
}
- if (p_read(fd, buff, len) < 0) {
- p_close(fd);
- git__free(buff);
- return git__throw(GIT_ERROR, "Failed to read file `%s`", path);
+ buf->ptr[len] = '\0';
+
+ while (len > 0) {
+ ssize_t read_size = p_read(fd, buf->ptr, len);
+
+ if (read_size < 0) {
+ close(fd);
+ return git__throw(GIT_EOSERR, "Failed to read from FD");
+ }
+
+ len -= read_size;
+ buf->size += read_size;
}
- 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(git_fbuffer *obj, const char *path)
-{
- return git_futils_readbuffer_updated(obj, path, NULL, NULL);
+ return 0;
}
-void git_futils_fbuffer_rtrim(git_fbuffer *obj)
+int git_futils_readbuffer(git_buf *buf, const char *path)
{
- unsigned char *buff = obj->data;
- while (obj->len > 0 && isspace(buff[obj->len - 1]))
- obj->len--;
- buff[obj->len] = '\0';
+ return git_futils_readbuffer_updated(buf, path, NULL, NULL);
}
-void git_futils_freebuffer(git_fbuffer *obj)
-{
- assert(obj);
- git__free(obj->data);
- obj->data = NULL;
-}
-
-
int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode)
{
if (git_futils_mkpath2file(to, dirmode) < GIT_SUCCESS)