summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-07-04 11:43:34 +0200
committerVicent Marti <tanoku@gmail.com>2011-07-05 02:04:03 +0200
commitf79026b4912bcd2336667f4c1663c06e233f0b32 (patch)
tree645b776032e924b587fad986aa3f3dc08c98d4c5 /src
parent678e9e045becdc5d75f2ce2259ed01c3531ee181 (diff)
downloadlibgit2-f79026b4912bcd2336667f4c1663c06e233f0b32.tar.gz
fileops: Cleanup
Cleaned up the structure of the whole OS-abstraction layer. fileops.c now contains a set of utility methods for file management used by the library. These are abstractions on top of the original POSIX calls. There's a new file called `posix.c` that contains emulations/reimplementations of all the POSIX calls the library uses. These are prefixed with `p_`. There's a specific posix file for each platform (win32 and unix). All the path-related methods have been moved from `utils.c` to `path.c` and have their own prefix.
Diffstat (limited to 'src')
-rw-r--r--src/blob.c16
-rw-r--r--src/config.c4
-rw-r--r--src/config_file.c12
-rw-r--r--src/filebuf.c34
-rw-r--r--src/fileops.c417
-rw-r--r--src/fileops.h205
-rw-r--r--src/index.c18
-rw-r--r--src/map.h6
-rw-r--r--src/odb.c12
-rw-r--r--src/odb_loose.c30
-rw-r--r--src/odb_pack.c58
-rw-r--r--src/path.c204
-rw-r--r--src/path.h76
-rw-r--r--src/posix.c74
-rw-r--r--src/posix.h54
-rw-r--r--src/refs.c86
-rw-r--r--src/repository.c82
-rw-r--r--src/tag.c2
-rw-r--r--src/tree.c2
-rw-r--r--src/unix/map.c4
-rw-r--r--src/unix/posix.h14
-rw-r--r--src/util.c200
-rw-r--r--src/util.h54
-rw-r--r--src/win32/fileops.c41
-rw-r--r--src/win32/map.c4
-rw-r--r--src/win32/posix.c191
-rw-r--r--src/win32/posix.h25
27 files changed, 997 insertions, 928 deletions
diff --git a/src/blob.c b/src/blob.c
index 2e3c7b3b2..b8282e505 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -91,9 +91,9 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
if (repo->path_workdir == NULL)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. (No working directory found)");
- git__joinpath(full_path, repo->path_workdir, path);
+ git_path_join(full_path, repo->path_workdir, path);
- error = gitfo_lstat(full_path, &st);
+ error = p_lstat(full_path, &st);
if (error < 0) {
return git__throw(GIT_EOSERR, "Failed to stat blob. %s", strerror(errno));
}
@@ -102,12 +102,12 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
size = st.st_size;
if (!islnk)
- if ((fd = gitfo_open(full_path, O_RDONLY)) < 0)
+ if ((fd = p_open(full_path, O_RDONLY)) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. Could not open '%s'", full_path);
if ((error = git_odb_open_wstream(&stream, repo->db, (size_t)size, GIT_OBJ_BLOB)) < GIT_SUCCESS) {
if (!islnk)
- gitfo_close(fd);
+ p_close(fd);
return git__rethrow(error, "Failed to create blob");
}
@@ -115,13 +115,13 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
ssize_t read_len;
if (!islnk)
- read_len = gitfo_read(fd, buffer, sizeof(buffer));
+ read_len = p_read(fd, buffer, sizeof(buffer));
else
- read_len = gitfo_readlink(full_path, buffer, sizeof(buffer));
+ read_len = p_readlink(full_path, buffer, sizeof(buffer));
if (read_len < 0) {
if (!islnk)
- gitfo_close(fd);
+ p_close(fd);
stream->free(stream);
return git__throw(GIT_EOSERR, "Failed to create blob. Can't read full file");
}
@@ -133,7 +133,7 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
error = stream->finalize_write(oid, stream);
stream->free(stream);
if (!islnk)
- gitfo_close(fd);
+ p_close(fd);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create blob");
}
diff --git a/src/config.c b/src/config.c
index a2202d79b..12fa8f278 100644
--- a/src/config.c
+++ b/src/config.c
@@ -333,9 +333,9 @@ int git_config_find_global(char *global_config_path)
if (home == NULL)
return git__throw(GIT_EOSERR, "Failed to open global config file. Cannot locate the user's home directory");
- git__joinpath(global_config_path, home, GIT_CONFIG_FILENAME);
+ git_path_join(global_config_path, home, GIT_CONFIG_FILENAME);
- if (gitfo_exists(global_config_path) < GIT_SUCCESS)
+ if (git_futils_exists(global_config_path) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to open global config file. The file does not exist");
return GIT_SUCCESS;
diff --git a/src/config_file.c b/src/config_file.c
index b01778739..5f8cffa14 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -89,7 +89,7 @@ typedef struct {
cvar_t_list var_list;
struct {
- gitfo_buf buffer;
+ git_fbuffer buffer;
char *read_ptr;
int line_number;
int eof;
@@ -278,7 +278,7 @@ static int config_open(git_config_file *cfg)
int error;
diskfile_backend *b = (diskfile_backend *)cfg;
- error = gitfo_read_file(&b->reader.buffer, b->file_path);
+ error = git_futils_readbuffer(&b->reader.buffer, b->file_path);
if(error < GIT_SUCCESS)
goto cleanup;
@@ -286,13 +286,13 @@ static int config_open(git_config_file *cfg)
if (error < GIT_SUCCESS)
goto cleanup;
- gitfo_free_buf(&b->reader.buffer);
+ git_futils_freebuffer(&b->reader.buffer);
return error;
cleanup:
cvar_list_free(&b->var_list);
- gitfo_free_buf(&b->reader.buffer);
+ git_futils_freebuffer(&b->reader.buffer);
return git__rethrow(error, "Failed to open config");
}
@@ -921,7 +921,7 @@ static int config_write(diskfile_backend *cfg, cvar_t *var)
const char *pre_end = NULL, *post_start = NULL;
/* We need to read in our own config file */
- error = gitfo_read_file(&cfg->reader.buffer, cfg->file_path);
+ error = git_futils_readbuffer(&cfg->reader.buffer, cfg->file_path);
if (error < GIT_SUCCESS) {
return git__rethrow(error, "Failed to read existing config file %s", cfg->file_path);
}
@@ -1068,7 +1068,7 @@ static int config_write(diskfile_backend *cfg, cvar_t *var)
else
error = git_filebuf_commit(&file);
- gitfo_free_buf(&cfg->reader.buffer);
+ git_futils_freebuffer(&cfg->reader.buffer);
return error;
}
diff --git a/src/filebuf.c b/src/filebuf.c
index ea5599b6d..acfdcd141 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -32,39 +32,39 @@ static const size_t WRITE_BUFFER_SIZE = (4096 * 2);
static int lock_file(git_filebuf *file, int flags)
{
- if (gitfo_exists(file->path_lock) == 0) {
+ if (git_futils_exists(file->path_lock) == 0) {
if (flags & GIT_FILEBUF_FORCE)
- gitfo_unlink(file->path_lock);
+ p_unlink(file->path_lock);
else
return git__throw(GIT_EOSERR, "Failed to lock file");
}
/* create path to the file buffer is required */
if (flags & GIT_FILEBUF_FORCE) {
- file->fd = gitfo_creat_locked_force(file->path_lock, 0644);
+ file->fd = git_futils_creat_locked_withpath(file->path_lock, 0644);
} else {
- file->fd = gitfo_creat_locked(file->path_lock, 0644);
+ file->fd = git_futils_creat_locked(file->path_lock, 0644);
}
if (file->fd < 0)
return git__throw(GIT_EOSERR, "Failed to create lock");
- if ((flags & GIT_FILEBUF_APPEND) && gitfo_exists(file->path_original) == 0) {
+ if ((flags & GIT_FILEBUF_APPEND) && git_futils_exists(file->path_original) == 0) {
git_file source;
char buffer[2048];
size_t read_bytes;
- source = gitfo_open(file->path_original, O_RDONLY);
+ source = p_open(file->path_original, O_RDONLY);
if (source < 0)
return git__throw(GIT_EOSERR, "Failed to lock file. Could not open %s", file->path_original);
- while ((read_bytes = gitfo_read(source, buffer, 2048)) > 0) {
- gitfo_write(file->fd, buffer, read_bytes);
+ while ((read_bytes = p_read(source, buffer, 2048)) > 0) {
+ p_write(file->fd, buffer, read_bytes);
if (file->digest)
git_hash_update(file->digest, buffer, read_bytes);
}
- gitfo_close(source);
+ p_close(source);
}
return GIT_SUCCESS;
@@ -73,10 +73,10 @@ static int lock_file(git_filebuf *file, int flags)
void git_filebuf_cleanup(git_filebuf *file)
{
if (file->fd >= 0)
- gitfo_close(file->fd);
+ p_close(file->fd);
- if (file->fd >= 0 && file->path_lock && gitfo_exists(file->path_lock) == GIT_SUCCESS)
- gitfo_unlink(file->path_lock);
+ if (file->fd >= 0 && file->path_lock && git_futils_exists(file->path_lock) == GIT_SUCCESS)
+ p_unlink(file->path_lock);
if (file->digest)
git_hash_free_ctx(file->digest);
@@ -102,7 +102,7 @@ static int write_normal(git_filebuf *file, const void *source, size_t len)
int result = 0;
if (len > 0) {
- result = gitfo_write(file->fd, (void *)source, len);
+ result = p_write(file->fd, (void *)source, len);
if (file->digest)
git_hash_update(file->digest, source, len);
}
@@ -130,7 +130,7 @@ static int write_deflate(git_filebuf *file, const void *source, size_t len)
have = file->buf_size - zs->avail_out;
- if (gitfo_write(file->fd, file->z_buf, have) < GIT_SUCCESS)
+ if (p_write(file->fd, file->z_buf, have) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to write to file");
} while (zs->avail_out == 0);
@@ -200,7 +200,7 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags)
char tmp_path[GIT_PATH_MAX];
/* Open the file as temporary for locking */
- file->fd = gitfo_mktemp(tmp_path, path);
+ file->fd = git_futils_mktmp(tmp_path, path);
if (file->fd < 0) {
error = GIT_EOSERR;
goto cleanup;
@@ -283,10 +283,10 @@ int git_filebuf_commit(git_filebuf *file)
if ((error = flush_buffer(file)) < GIT_SUCCESS)
goto cleanup;
- gitfo_close(file->fd);
+ p_close(file->fd);
file->fd = -1;
- error = gitfo_mv(file->path_lock, file->path_original);
+ error = git_futils_mv_atomic(file->path_lock, file->path_original);
cleanup:
git_filebuf_cleanup(file);
diff --git a/src/fileops.c b/src/fileops.c
index 3f0198dc4..486ea3bbe 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -2,22 +2,45 @@
#include "fileops.h"
#include <ctype.h>
-int gitfo_mkdir_2file(const char *file_path)
+int git_futils_mv_atomic(const char *from, const char *to)
+{
+#ifdef GIT_WIN32
+ /*
+ * Win32 POSIX compilance my ass. If the destination
+ * file exists, the `rename` call fails. This is as
+ * close as it gets with the Win32 API.
+ */
+ return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
+#else
+ /* Don't even try this on Win32 */
+ if (!link(from, to)) {
+ p_unlink(from);
+ return GIT_SUCCESS;
+ }
+
+ if (!rename(from, to))
+ return GIT_SUCCESS;
+
+ return GIT_ERROR;
+#endif
+}
+
+int git_futils_mkpath2file(const char *file_path)
{
const int mode = 0755; /* or 0777 ? */
int error = GIT_SUCCESS;
char target_folder_path[GIT_PATH_MAX];
- error = git__dirname_r(target_folder_path, sizeof(target_folder_path), file_path);
+ error = git_path_dirname_r(target_folder_path, sizeof(target_folder_path), file_path);
if (error < GIT_SUCCESS)
return git__throw(GIT_EINVALIDPATH, "Failed to recursively build `%s` tree structure. Unable to parse parent folder name", file_path);
/* Does the containing folder exist? */
- if (gitfo_isdir(target_folder_path)) {
- git__joinpath(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */
+ if (git_futils_isdir(target_folder_path)) {
+ git_path_join(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */
/* Let's create the tree structure */
- error = gitfo_mkdir_recurs(target_folder_path, mode);
+ error = git_futils_mkdir_r(target_folder_path, mode);
if (error < GIT_SUCCESS)
return error; /* The callee already takes care of setting the correct error message. */
}
@@ -25,7 +48,7 @@ int gitfo_mkdir_2file(const char *file_path)
return GIT_SUCCESS;
}
-int gitfo_mktemp(char *path_out, const char *filename)
+int git_futils_mktmp(char *path_out, const char *filename)
{
int fd;
@@ -38,7 +61,7 @@ int gitfo_mktemp(char *path_out, const char *filename)
if (_mktemp_s(path_out, GIT_PATH_MAX) != 0)
return git__throw(GIT_EOSERR, "Failed to make temporary file %s", path_out);
- fd = gitfo_creat(path_out, 0744);
+ fd = p_creat(path_out, 0744);
#else
fd = mkstemp(path_out);
#endif
@@ -46,79 +69,29 @@ int gitfo_mktemp(char *path_out, const char *filename)
return fd >= 0 ? fd : git__throw(GIT_EOSERR, "Failed to create temporary file %s", path_out);
}
-int gitfo_open(const char *path, int flags)
+int git_futils_creat_withpath(const char *path, int mode)
{
- int fd = open(path, flags | O_BINARY);
- return fd >= 0 ? fd : git__throw(GIT_EOSERR, "Failed to open %s", path);
-}
-
-int gitfo_creat(const char *path, int mode)
-{
- int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
- return fd >= 0 ? fd : git__throw(GIT_EOSERR, "Failed to create file. Could not open %s", path);
-}
-
-int gitfo_creat_force(const char *path, int mode)
-{
- if (gitfo_mkdir_2file(path) < GIT_SUCCESS)
+ if (git_futils_mkpath2file(path) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to create file %s", path);
- return gitfo_creat(path, mode);
+ return p_creat(path, mode);
}
-int gitfo_creat_locked(const char *path, int mode)
+int git_futils_creat_locked(const char *path, int mode)
{
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_EXCL, mode);
return fd >= 0 ? fd : git__throw(GIT_EOSERR, "Failed to create locked file. Could not open %s", path);
}
-int gitfo_creat_locked_force(const char *path, int mode)
+int git_futils_creat_locked_withpath(const char *path, int mode)
{
- if (gitfo_mkdir_2file(path) < GIT_SUCCESS)
+ if (git_futils_mkpath2file(path) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to create locked file %s", path);
- return gitfo_creat_locked(path, mode);
-}
-
-int gitfo_read(git_file fd, void *buf, size_t cnt)
-{
- char *b = buf;
- while (cnt) {
- ssize_t r = read(fd, b, cnt);
- if (r < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return git__throw(GIT_EOSERR, "Failed to read from file");
- }
- if (!r)
- break;
- cnt -= r;
- b += r;
- }
- return (int)(b - (char *)buf);
-}
-
-int gitfo_write(git_file fd, void *buf, size_t cnt)
-{
- char *b = buf;
- while (cnt) {
- ssize_t r = write(fd, b, cnt);
- if (r < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return git__throw(GIT_EOSERR, "Failed to write to file");
- }
- if (!r) {
- errno = EPIPE;
- return git__throw(GIT_EOSERR, "Failed to write to file");
- }
- cnt -= r;
- b += r;
- }
- return GIT_SUCCESS;
+ return git_futils_creat_locked(path, mode);
}
-int gitfo_isdir(const char *path)
+int git_futils_isdir(const char *path)
{
struct stat st;
int len, stat_error;
@@ -132,10 +105,10 @@ int gitfo_isdir(const char *path)
char *path_fixed = NULL;
path_fixed = git__strdup(path);
path_fixed[len - 1] = 0;
- stat_error = gitfo_stat(path_fixed, &st);
+ stat_error = p_stat(path_fixed, &st);
free(path_fixed);
} else {
- stat_error = gitfo_stat(path, &st);
+ stat_error = p_stat(path, &st);
}
if (stat_error < GIT_SUCCESS)
@@ -147,15 +120,15 @@ int gitfo_isdir(const char *path)
return GIT_SUCCESS;
}
-int gitfo_isfile(const char *path)
+int git_futils_isfile(const char *path)
{
struct stat st;
int stat_error;
if (!path)
- return git__throw(GIT_ENOTFOUND, "No path given to gitfo_isfile");
+ return git__throw(GIT_ENOTFOUND, "No path given to git_futils_isfile");
- stat_error = gitfo_stat(path, &st);
+ stat_error = p_stat(path, &st);
if (stat_error < GIT_SUCCESS)
return git__throw(GIT_ENOTFOUND, "%s does not exist", path);
@@ -166,21 +139,21 @@ int gitfo_isfile(const char *path)
return GIT_SUCCESS;
}
-int gitfo_exists(const char *path)
+int git_futils_exists(const char *path)
{
assert(path);
return access(path, F_OK);
}
-git_off_t gitfo_size(git_file fd)
+git_off_t git_futils_filesize(git_file fd)
{
struct stat sb;
- if (gitfo_fstat(fd, &sb))
+ if (p_fstat(fd, &sb))
return git__throw(GIT_EOSERR, "Failed to get size of file. File missing or corrupted");
return sb.st_size;
}
-int gitfo_read_file(gitfo_buf *obj, const char *path)
+int git_futils_readbuffer(git_fbuffer *obj, const char *path)
{
git_file fd;
size_t len;
@@ -189,28 +162,28 @@ int gitfo_read_file(gitfo_buf *obj, const char *path)
assert(obj && path && *path);
- if ((fd = gitfo_open(path, O_RDONLY)) < 0)
+ if ((fd = p_open(path, O_RDONLY)) < 0)
return git__throw(GIT_ERROR, "Failed to open %s for reading", path);
- if (((size = gitfo_size(fd)) < 0) || !git__is_sizet(size+1)) {
- gitfo_close(fd);
+ if (((size = git_futils_filesize(fd)) < 0) || !git__is_sizet(size+1)) {
+ p_close(fd);
return git__throw(GIT_ERROR, "Failed to read file `%s`. An error occured while calculating its size", path);
}
len = (size_t) size;
if ((buff = git__malloc(len + 1)) == NULL) {
- gitfo_close(fd);
+ p_close(fd);
return GIT_ENOMEM;
}
- if (gitfo_read(fd, buff, len) < 0) {
- gitfo_close(fd);
+ 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';
- gitfo_close(fd);
+ p_close(fd);
obj->data = buff;
obj->len = len;
@@ -218,64 +191,33 @@ int gitfo_read_file(gitfo_buf *obj, const char *path)
return GIT_SUCCESS;
}
-void gitfo_free_buf(gitfo_buf *obj)
+void git_futils_freebuffer(git_fbuffer *obj)
{
assert(obj);
free(obj->data);
obj->data = NULL;
}
-int gitfo_mv(const char *from, const char *to)
-{
- int error;
-
-#ifdef GIT_WIN32
- /*
- * Win32 POSIX compilance my ass. If the destination
- * file exists, the `rename` call fails. This is as
- * close as it gets with the Win32 API.
- */
- error = MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
-#else
- /* Don't even try this on Win32 */
- if (!link(from, to)) {
- gitfo_unlink(from);
- return GIT_SUCCESS;
- }
- if (!rename(from, to))
- return GIT_SUCCESS;
-
- error = GIT_EOSERR;
-#endif
-
- if (error < GIT_SUCCESS)
- return git__throw(error, "Failed to move file from `%s` to `%s`", from, to);
-
- return GIT_SUCCESS;
-}
-
-int gitfo_mv_force(const char *from, const char *to)
+int git_futils_mv_withpath(const char *from, const char *to)
{
- if (gitfo_mkdir_2file(to) < GIT_SUCCESS)
+ if (git_futils_mkpath2file(to) < GIT_SUCCESS)
return GIT_EOSERR; /* The callee already takes care of setting the correct error message. */
- return gitfo_mv(from, to); /* The callee already takes care of setting the correct error message. */
+ return git_futils_mv_atomic(from, to); /* The callee already takes care of setting the correct error message. */
}
-int gitfo_map_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
+int git_futils_mmap_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
{
- if (git__mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin) < GIT_SUCCESS)
- return GIT_EOSERR;
- return GIT_SUCCESS;
+ return p_mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin);
}
-void gitfo_free_map(git_map *out)
+void git_futils_mmap_free(git_map *out)
{
- git__munmap(out);
+ p_munmap(out);
}
-int gitfo_dirent(
+int git_futils_direach(
char *path,
size_t path_sz,
int (*fn)(void *, char *),
@@ -331,33 +273,14 @@ int gitfo_dirent(
return GIT_SUCCESS;
}
-#if GIT_PLATFORM_PATH_SEP == '/'
-void gitfo_posixify_path(char *GIT_UNUSED(path))
-{
- /* nothing to do*/
-}
-#else
-void gitfo_posixify_path(char *path)
-{
- while (*path) {
- if (*path == GIT_PLATFORM_PATH_SEP)
- *path = '/';
-
- path++;
- }
-}
-#endif
-
-int gitfo_retrieve_path_root_offset(const char *path)
+int git_futils_root_offset(const char *path)
{
int offset = 0;
#ifdef GIT_WIN32
-
/* Does the root of the path look like a windows drive ? */
if (isalpha(path[0]) && (path[1] == ':'))
offset += 2;
-
#endif
if (*(path + offset) == '/')
@@ -366,7 +289,7 @@ int gitfo_retrieve_path_root_offset(const char *path)
return -1; /* Not a real error. Rather a signal than the path is not rooted */
}
-int gitfo_mkdir_recurs(const char *path, int mode)
+int git_futils_mkdir_r(const char *path, int mode)
{
int error, root_path_offset;
char *pp, *sp;
@@ -378,14 +301,14 @@ int gitfo_mkdir_recurs(const char *path, int mode)
error = GIT_SUCCESS;
pp = path_copy;
- root_path_offset = gitfo_retrieve_path_root_offset(pp);
+ root_path_offset = git_futils_root_offset(pp);
if (root_path_offset > 0)
pp += root_path_offset; /* On Windows, will skip the drive name (eg. C: or D:) */
while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != NULL) {
- if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) {
+ if (sp != pp && git_futils_isdir(path_copy) < GIT_SUCCESS) {
*sp = 0;
- error = gitfo_mkdir(path_copy, mode);
+ error = p_mkdir(path_copy, mode);
/* Do not choke while trying to recreate an existing directory */
if (errno == EEXIST)
@@ -398,7 +321,7 @@ int gitfo_mkdir_recurs(const char *path, int mode)
}
if (*pp != '\0' && error == GIT_SUCCESS) {
- error = gitfo_mkdir(path, mode);
+ error = p_mkdir(path, mode);
if (errno == EEXIST)
error = GIT_SUCCESS;
}
@@ -415,7 +338,7 @@ static int retrieve_previous_path_component_start(const char *path)
{
int offset, len, root_offset, start = 0;
- root_offset = gitfo_retrieve_path_root_offset(path);
+ root_offset = git_futils_root_offset(path);
if (root_offset > -1)
start += root_offset;
@@ -440,7 +363,7 @@ static int retrieve_previous_path_component_start(const char *path)
return offset;
}
-int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, const char *base_path)
+int git_futils_prettify_dir(char *buffer_out, size_t size, const char *path, const char *base_path)
{
int len = 0, segment_len, only_dots, root_path_offset, error = GIT_SUCCESS;
char *current;
@@ -450,10 +373,10 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, con
buffer_end = path + strlen(path);
buffer_out_start = buffer_out;
- root_path_offset = gitfo_retrieve_path_root_offset(path);
+ root_path_offset = git_futils_root_offset(path);
if (root_path_offset < 0) {
if (base_path == NULL) {
- error = gitfo_getcwd(buffer_out, size);
+ error = p_getcwd(buffer_out, size);
if (error < GIT_SUCCESS)
return error; /* The callee already takes care of setting the correct error message. */
} else {
@@ -461,8 +384,8 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, con
return git__throw(GIT_EOVERFLOW, "Failed to prettify dir path: the base path is too long for the buffer.");
strcpy(buffer_out, base_path);
- gitfo_posixify_path(buffer_out);
- git__joinpath(buffer_out, buffer_out, "");
+ git_path_mkposix(buffer_out);
+ git_path_join(buffer_out, buffer_out, "");
}
len = strlen(buffer_out);
@@ -527,7 +450,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, con
return GIT_SUCCESS;
}
-int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path, const char *base_path)
+int git_futils_prettyify_file(char *buffer_out, size_t size, const char *path, const char *base_path)
{
int error, path_len, i, root_offset;
const char* pattern = "/..";
@@ -544,12 +467,12 @@ int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path, co
return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path);
}
- error = gitfo_prettify_dir_path(buffer_out, size, path, base_path);
+ error = git_futils_prettify_dir(buffer_out, size, path, base_path);
if (error < GIT_SUCCESS)
return error; /* The callee already takes care of setting the correct error message. */
path_len = strlen(buffer_out);
- root_offset = gitfo_retrieve_path_root_offset(buffer_out) + 1;
+ root_offset = git_futils_root_offset(buffer_out) + 1;
if (path_len == root_offset)
return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path);
@@ -559,7 +482,7 @@ int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path, co
return GIT_SUCCESS;
}
-int gitfo_cmp_path(const char *name1, int len1, int isdir1,
+int git_futils_cmp_path(const char *name1, int len1, int isdir1,
const char *name2, int len2, int isdir2)
{
int len = len1 < len2 ? len1 : len2;
@@ -577,185 +500,3 @@ int gitfo_cmp_path(const char *name1, int len1, int isdir1,
return 0;
}
-int gitfo_getcwd(char *buffer_out, size_t size)
-{
- char *cwd_buffer;
-
- assert(buffer_out && size > 0);
-
-#ifdef GIT_WIN32
- cwd_buffer = _getcwd(buffer_out, size);
-#else
- cwd_buffer = getcwd(buffer_out, size);
-#endif
-
- if (cwd_buffer == NULL)
- return git__throw(GIT_EOSERR, "Failed to retrieve current working directory");
-
- gitfo_posixify_path(buffer_out);
-
- git__joinpath(buffer_out, buffer_out, ""); //Ensure the path ends with a trailing slash
-
- return GIT_SUCCESS;
-}
-
-#ifdef GIT_WIN32
-GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
-{
- long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
- winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
- winTime /= 10000000; /* Nano to seconds resolution */
- return (time_t)winTime;
-}
-
-static int do_lstat(const char *file_name, struct stat *buf)
-{
- WIN32_FILE_ATTRIBUTE_DATA fdata;
-
- if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
- int fMode = S_IREAD;
-
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- fMode |= S_IFDIR;
- else
- fMode |= S_IFREG;
-
- if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
- fMode |= S_IWRITE;
-
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
- fMode |= S_IFLNK;
-
- buf->st_ino = 0;
- buf->st_gid = 0;
- buf->st_uid = 0;
- buf->st_nlink = 1;
- buf->st_mode = (mode_t)fMode;
- buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
- buf->st_dev = buf->st_rdev = (_getdrive() - 1);
- buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
- buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
- buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
- return GIT_SUCCESS;
- }
-
- switch (GetLastError()) {
- case ERROR_ACCESS_DENIED:
- case ERROR_SHARING_VIOLATION:
- case ERROR_LOCK_VIOLATION:
- case ERROR_SHARING_BUFFER_EXCEEDED:
- return GIT_EOSERR;
-
- case ERROR_BUFFER_OVERFLOW:
- case ERROR_NOT_ENOUGH_MEMORY:
- return GIT_ENOMEM;
-
- default:
- return GIT_EINVALIDPATH;
- }
-}
-
-int gitfo_lstat__w32(const char *file_name, struct stat *buf)
-{
- int namelen, error;
- char alt_name[GIT_PATH_MAX];
-
- if ((error = do_lstat(file_name, buf)) == GIT_SUCCESS)
- return GIT_SUCCESS;
-
- /* if file_name ended in a '/', Windows returned ENOENT;
- * try again without trailing slashes
- */
- if (error != GIT_EINVALIDPATH)
- return git__throw(GIT_EOSERR, "Failed to lstat file");
-
- namelen = strlen(file_name);
- if (namelen && file_name[namelen-1] != '/')
- return git__throw(GIT_EOSERR, "Failed to lstat file");
-
- while (namelen && file_name[namelen-1] == '/')
- --namelen;
-
- if (!namelen || namelen >= GIT_PATH_MAX)
- return git__throw(GIT_ENOMEM, "Failed to lstat file");
-
- memcpy(alt_name, file_name, namelen);
- alt_name[namelen] = 0;
- return do_lstat(alt_name, buf);
-}
-
-int gitfo_readlink__w32(const char *link, char *target, size_t target_len)
-{
- typedef DWORD (WINAPI *fpath_func)(HANDLE, LPTSTR, DWORD, DWORD);
- static fpath_func pGetFinalPath = NULL;
- HANDLE hFile;
- DWORD dwRet;
-
- /*
- * Try to load the pointer to pGetFinalPath dynamically, because
- * it is not available in platforms older than Vista
- */
- if (pGetFinalPath == NULL) {
- HINSTANCE library = LoadLibrary("kernel32");
-
- if (library != NULL)
- pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleA");
-
- if (pGetFinalPath == NULL)
- return git__throw(GIT_EOSERR,
- "'GetFinalPathNameByHandleA' is not available in this platform");
- }
-
- hFile = CreateFile(link, // file to open
- GENERIC_READ, // open for reading
- FILE_SHARE_READ, // share for reading
- NULL, // default security
- OPEN_EXISTING, // existing file only
- FILE_FLAG_BACKUP_SEMANTICS, // normal file
- NULL); // no attr. template
-
- if (hFile == INVALID_HANDLE_VALUE)
- return GIT_EOSERR;
-
- dwRet = pGetFinalPath(hFile, target, target_len, 0x0);
- if (dwRet >= target_len)
- return GIT_ENOMEM;
-
- CloseHandle(hFile);
-
- if (dwRet > 4) {
- /* Skip first 4 characters if they are "\\?\" */
- if (target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') {
- char tmp[GIT_PATH_MAX];
- unsigned int offset = 4;
- dwRet -= 4;
-
- /* \??\UNC\ */
- if (dwRet > 7 && target[4] == 'U' && target[5] == 'N' && target[6] == 'C') {
- offset += 2;
- dwRet -= 2;
- target[offset] = '\\';
- }
-
- memcpy(tmp, target + offset, dwRet);
- memcpy(target, tmp, dwRet);
- }
- }
-
- target[dwRet] = '\0';
- return dwRet;
-}
-
-int gitfo_hide_directory__w32(const char *path)
-{
- int error;
-
- error = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN) != 0 ?
- GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
-
- if (error < GIT_SUCCESS)
- error = git__throw(GIT_EOSERR, "Failed to hide directory '%s'", path);
-
- return error;
-}
-#endif
diff --git a/src/fileops.h b/src/fileops.h
index d9fa96008..52eb2295c 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -9,110 +9,98 @@
#include "common.h"
#include "map.h"
#include "dir.h"
-#include <fcntl.h>
-#include <time.h>
-
-#ifdef GIT_WIN32
-#define GIT_PLATFORM_PATH_SEP '\\'
-#else
-#define GIT_PLATFORM_PATH_SEP '/'
-#endif
-
-#define S_IFGITLINK 0160000
-#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
-
-#ifdef GIT_WIN32
-GIT_INLINE(int) link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
-{
- GIT_UNUSED_ARG(old)
- GIT_UNUSED_ARG(new)
- errno = ENOSYS;
- return -1;
-}
-
-GIT_INLINE(int) git__mkdir(const char *path, int GIT_UNUSED(mode))
-{
- GIT_UNUSED_ARG(mode)
- return mkdir(path);
-}
-
-extern int git__unlink(const char *path);
-extern int git__mkstemp(char *template);
-extern int git__fsync(int fd);
-
-# ifndef GIT__WIN32_NO_HIDE_FILEOPS
-# define unlink(p) git__unlink(p)
-# define mkstemp(t) git__mkstemp(t)
-# define mkdir(p,m) git__mkdir(p, m)
-# define fsync(fd) git__fsync(fd)
-# endif
-#endif /* GIT_WIN32 */
-
-
-#if !defined(O_BINARY)
-#define O_BINARY 0
-#endif
-
-#define GITFO_BUF_INIT {NULL, 0}
-
-typedef int git_file;
+#include "posix.h"
+#include "path.h"
+
+/**
+ * Filebuffer methods
+ *
+ * Read whole files into an in-memory buffer for processing
+ */
+#define GIT_FBUFFER_INIT {NULL, 0}
typedef struct { /* file io buffer */
void *data; /* data bytes */
size_t len; /* data length */
-} gitfo_buf;
-
-extern int gitfo_exists(const char *path);
-extern int gitfo_open(const char *path, int flags);
-extern int gitfo_creat(const char *path, int mode);
-extern int gitfo_creat_force(const char *path, int mode);
-extern int gitfo_creat_locked(const char *path, int mode);
-extern int gitfo_creat_locked_force(const char *path, int mode);
-extern int gitfo_mktemp(char *path_out, const char *filename);
-extern int gitfo_isdir(const char *path);
-extern int gitfo_isfile(const char *path);
-extern int gitfo_mkdir_recurs(const char *path, int mode);
-extern int gitfo_mkdir_2file(const char *path);
-#define gitfo_close(fd) close(fd)
-
-extern int gitfo_read(git_file fd, void *buf, size_t cnt);
-extern int gitfo_write(git_file fd, void *buf, size_t cnt);
-#define gitfo_lseek(f,n,w) lseek(f, n, w)
-extern git_off_t gitfo_size(git_file fd);
-
-extern int gitfo_read_file(gitfo_buf *obj, const char *path);
-extern void gitfo_free_buf(gitfo_buf *obj);
-
-/* Move (rename) a file; this operation is atomic */
-extern int gitfo_mv(const char *from, const char *to);
-
-/* Move a file (forced); this will create the destination
- * path if it doesn't exist */
-extern int gitfo_mv_force(const char *from, const char *to);
-
-#define gitfo_stat(p,b) stat(p, b)
-#define gitfo_fstat(f,b) fstat(f, b)
-
-#ifdef GIT_WIN32
-# define gitfo_lstat(p,b) gitfo_lstat__w32(p,b)
-# define gitfo_readlink(a, b, c) gitfo_readlink__w32(a, b, c)
-
- extern int gitfo_lstat__w32(const char *file_name, struct stat *buf);
- extern int gitfo_readlink__w32(const char *link, char *target, size_t target_len);
- extern int gitfo_hide_directory__w32(const char *path);
-#else
-# define gitfo_lstat(p,b) lstat(p,b)
-# define gitfo_readlink(a, b, c) readlink(a, b, c)
-#endif
-
-#define gitfo_unlink(p) unlink(p)
-#define gitfo_rmdir(p) rmdir(p)
-#define gitfo_chdir(p) chdir(p)
-#define gitfo_mkdir(p,m) mkdir(p, m)
-
-#define gitfo_mkstemp(t) mkstemp(t)
-#define gitfo_fsync(fd) fsync(fd)
-#define gitfo_chmod(p,m) chmod(p, m)
+} git_fbuffer;
+
+extern int git_futils_readbuffer(git_fbuffer *obj, const char *path);
+extern void git_futils_freebuffer(git_fbuffer *obj);
+
+/**
+ * File utils
+ *
+ * These are custom filesystem-related helper methods. They are
+ * rather high level, and wrap the underlying POSIX methods
+ *
+ * All these methods return GIT_SUCCESS on success,
+ * or an error code on failure and an error message is set.
+ */
+
+/**
+ * Check if a file exists and can be accessed.
+ */
+extern int git_futils_exists(const char *path);
+
+/**
+ * Create and open a file, while also
+ * creating all the folders in its path
+ */
+extern int git_futils_creat_withpath(const char *path, int mode);
+
+/**
+ * Create an open a process-locked file
+ */
+extern int git_futils_creat_locked(const char *path, int mode);
+
+/**
+ * Create an open a process-locked file, while
+ * also creating all the folders in its path
+ */
+extern int git_futils_creat_locked_withpath(const char *path, int mode);
+
+/**
+ * Check if the given path points to a directory
+ */
+extern int git_futils_isdir(const char *path);
+
+/**
+ * Check if the given path points to a regular file
+ */
+extern int git_futils_isfile(const char *path);
+
+/**
+ * Create a path recursively
+ */
+extern int git_futils_mkdir_r(const char *path, int mode);
+
+/**
+ * Create all the folders required to contain
+ * the full path of a file
+ */
+extern int git_futils_mkpath2file(const char *path);
+
+/**
+ * Create and open a temporary file with a `_git2_` suffix
+ */
+extern int git_futils_mktmp(char *path_out, const char *filename);
+
+/**
+ * Atomically rename a file on the filesystem
+ */
+extern int git_futils_mv_atomic(const char *from, const char *to);
+
+/**
+ * Move a file on the filesystem, create the
+ * destination path if it doesn't exist
+ */
+extern int git_futils_mv_withpath(const char *from, const char *to);
+
+
+/**
+ * Get the filesize in bytes of a file
+ */
+extern git_off_t git_futils_filesize(git_file fd);
/**
* Read-only map all or part of a file into memory.
@@ -129,7 +117,7 @@ extern int gitfo_mv_force(const char *from, const char *to);
* - GIT_SUCCESS on success;
* - GIT_EOSERR on an unspecified OS related error.
*/
-extern int gitfo_map_ro(
+extern int git_futils_mmap_ro(
git_map *out,
git_file fd,
git_off_t begin,
@@ -139,7 +127,7 @@ extern int gitfo_map_ro(
* Release the memory associated with a previous memory mapping.
* @param map the mapping description previously configured.
*/
-extern void gitfo_free_map(git_map *map);
+extern void git_futils_mmap_free(git_map *map);
/**
* Walk each directory entry, except '.' and '..', calling fn(state).
@@ -152,16 +140,15 @@ extern void gitfo_free_map(git_map *map);
* may modify the pathbuf, but only by appending new text.
* @param state to pass to fn as the first arg.
*/
-extern int gitfo_dirent(
+extern int git_futils_direach(
char *pathbuf,
size_t pathmax,
int (*fn)(void *, char *),
void *state);
-extern int gitfo_cmp_path(const char *name1, int len1, int isdir1,
+extern int git_futils_cmp_path(const char *name1, int len1, int isdir1,
const char *name2, int len2, int isdir2);
-extern int gitfo_getcwd(char *buffer_out, size_t size);
/**
* Clean up a provided absolute or relative directory path.
@@ -186,7 +173,7 @@ extern int gitfo_getcwd(char *buffer_out, size_t size);
* - GIT_SUCCESS on success;
* - GIT_ERROR when the input path is invalid or escapes the current directory.
*/
-int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, const char *base_path);
+int git_futils_prettify_dir(char *buffer_out, size_t size, const char *path, const char *base_path);
/**
* Clean up a provided absolute or relative file path.
@@ -209,10 +196,8 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path, con
* - GIT_SUCCESS on success;
* - GIT_ERROR when the input path is invalid or escapes the current directory.
*/
-int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path, const char *base_path);
-
-void gitfo_posixify_path(char *path);
+int git_futils_prettyify_file(char *buffer_out, size_t size, const char *path, const char *base_path);
-int gitfo_retrieve_path_root_offset(const char *path);
+int git_futils_root_offset(const char *path);
#endif /* INCLUDE_fileops_h__ */
diff --git a/src/index.c b/src/index.c
index ed91e050c..06fa95c7b 100644
--- a/src/index.c
+++ b/src/index.c
@@ -170,7 +170,7 @@ static int index_initialize(git_index **index_out, git_repository *owner, const
git_vector_init(&index->entries, 32, index_cmp);
/* Check if index file is stored on disk already */
- if (gitfo_exists(index->index_file_path) == 0)
+ if (git_futils_exists(index->index_file_path) == 0)
index->on_disk = 1;
*index_out = index;
@@ -259,13 +259,13 @@ int git_index_read(git_index *index)
assert(index->index_file_path);
- if (!index->on_disk || gitfo_exists(index->index_file_path) < 0) {
+ if (!index->on_disk || git_futils_exists(index->index_file_path) < 0) {
git_index_clear(index);
index->on_disk = 0;
return GIT_SUCCESS;
}
- if (gitfo_stat(index->index_file_path, &indexst) < 0)
+ if (p_stat(index->index_file_path, &indexst) < 0)
return git__throw(GIT_EOSERR, "Failed to read index. %s does not exist or is corrupted", index->index_file_path);
if (!S_ISREG(indexst.st_mode))
@@ -273,9 +273,9 @@ int git_index_read(git_index *index)
if (indexst.st_mtime != index->last_modified) {
- gitfo_buf buffer;
+ git_fbuffer buffer;
- if ((error = gitfo_read_file(&buffer, index->index_file_path)) < GIT_SUCCESS)
+ if ((error = git_futils_readbuffer(&buffer, index->index_file_path)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to read index");
git_index_clear(index);
@@ -284,7 +284,7 @@ int git_index_read(git_index *index)
if (error == GIT_SUCCESS)
index->last_modified = indexst.st_mtime;
- gitfo_free_buf(&buffer);
+ git_futils_freebuffer(&buffer);
}
if (error < GIT_SUCCESS)
@@ -311,7 +311,7 @@ int git_index_write(git_index *index)
if ((error = git_filebuf_commit(&file)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write index");
- if (gitfo_stat(index->index_file_path, &indexst) == 0) {
+ if (p_stat(index->index_file_path, &indexst) == 0) {
index->last_modified = indexst.st_mtime;
index->on_disk = 1;
}
@@ -409,9 +409,9 @@ static int index_init_entry(git_index_entry *entry, git_index *index, const char
if (index->repository == NULL)
return git__throw(GIT_EBAREINDEX, "Failed to initialize entry. Repository is bare");
- git__joinpath(full_path, index->repository->path_workdir, rel_path);
+ git_path_join(full_path, index->repository->path_workdir, rel_path);
- if (gitfo_lstat(full_path, &st) < 0)
+ if (p_lstat(full_path, &st) < 0)
return git__throw(GIT_EOSERR, "Failed to initialize entry. '%s' cannot be opened", full_path);
if (stage < 0 || stage > 3)
diff --git a/src/map.h b/src/map.h
index be569abc8..1dfbeeb4b 100644
--- a/src/map.h
+++ b/src/map.h
@@ -4,7 +4,7 @@
#include "common.h"
-/* git__mmap() prot values */
+/* p_mmap() prot values */
#define GIT_PROT_NONE 0x0
#define GIT_PROT_READ 0x1
#define GIT_PROT_WRITE 0x2
@@ -25,7 +25,7 @@ typedef struct { /* memory mapped buffer */
#endif
} git_map;
-extern int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset);
-extern int git__munmap(git_map *map);
+extern int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset);
+extern int p_munmap(git_map *map);
#endif /* INCLUDE_map_h__ */
diff --git a/src/odb.c b/src/odb.c
index 0ee790e14..b09931660 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -323,15 +323,15 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
char alternates_path[GIT_PATH_MAX];
char *buffer, *alternate;
- gitfo_buf alternates_buf = GITFO_BUF_INIT;
+ git_fbuffer alternates_buf = GIT_FBUFFER_INIT;
int error;
- git__joinpath(alternates_path, objects_dir, GIT_ALTERNATES_FILE);
+ git_path_join(alternates_path, objects_dir, GIT_ALTERNATES_FILE);
- if (gitfo_exists(alternates_path) < GIT_SUCCESS)
+ if (git_futils_exists(alternates_path) < GIT_SUCCESS)
return GIT_SUCCESS;
- if (gitfo_read_file(&alternates_buf, alternates_path) < GIT_SUCCESS)
+ if (git_futils_readbuffer(&alternates_buf, alternates_path) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to add backend. Can't read alternates");
buffer = (char *)alternates_buf.data;
@@ -346,7 +346,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
/* relative path: build based on the current `objects` folder */
if (*alternate == '.') {
- git__joinpath(full_path, objects_dir, alternate);
+ git_path_join(full_path, objects_dir, alternate);
alternate = full_path;
}
@@ -354,7 +354,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
break;
}
- gitfo_free_buf(&alternates_buf);
+ git_futils_freebuffer(&alternates_buf);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to load alternates");
return error;
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 510712bd8..2a2c464c7 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -97,7 +97,7 @@ static size_t object_file_name(char *name, size_t n, char *dir, const git_oid *i
}
-static size_t get_binary_object_header(obj_hdr *hdr, gitfo_buf *obj)
+static size_t get_binary_object_header(obj_hdr *hdr, git_fbuffer *obj)
{
unsigned char c;
unsigned char *data = obj->data;
@@ -199,7 +199,7 @@ static void set_stream_output(z_stream *s, void *out, size_t len)
}
-static int start_inflate(z_stream *s, gitfo_buf *obj, void *out, size_t len)
+static int start_inflate(z_stream *s, git_fbuffer *obj, void *out, size_t len)
{
int status;
@@ -309,7 +309,7 @@ static void *inflate_tail(z_stream *s, void *hb, size_t used, obj_hdr *hdr)
* of loose object data into packs. This format is no longer used, but
* we must still read it.
*/
-static int inflate_packlike_loose_disk_obj(git_rawobj *out, gitfo_buf *obj)
+static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_fbuffer *obj)
{
unsigned char *in, *buf;
obj_hdr hdr;
@@ -347,7 +347,7 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, gitfo_buf *obj)
return GIT_SUCCESS;
}
-static int inflate_disk_obj(git_rawobj *out, gitfo_buf *obj)
+static int inflate_disk_obj(git_rawobj *out, git_fbuffer *obj)
{
unsigned char head[64], *buf;
z_stream zs;
@@ -405,7 +405,7 @@ static int inflate_disk_obj(git_rawobj *out, gitfo_buf *obj)
static int read_loose(git_rawobj *out, const char *loc)
{
int error;
- gitfo_buf obj = GITFO_BUF_INIT;
+ git_fbuffer obj = GIT_FBUFFER_INIT;
assert(out && loc);
@@ -413,11 +413,11 @@ static int read_loose(git_rawobj *out, const char *loc)
out->len = 0;
out->type = GIT_OBJ_BAD;
- if (gitfo_read_file(&obj, loc) < 0)
+ if (git_futils_readbuffer(&obj, loc) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to read loose object. File not found");
error = inflate_disk_obj(out, &obj);
- gitfo_free_buf(&obj);
+ git_futils_freebuffer(&obj);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to read loose object");
}
@@ -434,7 +434,7 @@ static int read_header_loose(git_rawobj *out, const char *loc)
out->data = NULL;
- if ((fd = gitfo_open(loc, O_RDONLY)) < 0)
+ if ((fd = p_open(loc, O_RDONLY)) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to read loose object header. File not found");
init_stream(&zs, inflated_buffer, sizeof(inflated_buffer));
@@ -466,7 +466,7 @@ static int read_header_loose(git_rawobj *out, const char *loc)
cleanup:
finish_inflate(&zs);
- gitfo_close(fd);
+ p_close(fd);
if (error < GIT_SUCCESS)
return git__throw(error, "Failed to read loose object header. Header is corrupted");
@@ -477,7 +477,7 @@ cleanup:
static int locate_object(char *object_location, loose_backend *backend, const git_oid *oid)
{
object_file_name(object_location, GIT_PATH_MAX, backend->objects_dir, oid);
- return gitfo_exists(object_location);
+ return git_futils_exists(object_location);
}
/* Explore an entry of a directory and see if it matches a short oid */
@@ -490,7 +490,7 @@ int fn_locate_object_short_oid(void *state, char *pathbuf) {
return GIT_SUCCESS;
}
- if (!gitfo_exists(pathbuf) && gitfo_isdir(pathbuf)) {
+ if (!git_futils_exists(pathbuf) && git_futils_isdir(pathbuf)) {
/* We are already in the directory matching the 2 first hex characters,
* compare the first ncmp characters of the oids */
if (!memcmp(sstate->short_oid + 2,
@@ -534,14 +534,14 @@ static int locate_object_short_oid(char *object_location, git_oid *res_oid, loos
sprintf(object_location+dir_len, "%.2s/", state.short_oid);
/* Check that directory exists */
- if (gitfo_exists(object_location) || gitfo_isdir(object_location))
+ if (git_futils_exists(object_location) || git_futils_isdir(object_location))
return git__throw(GIT_ENOTFOUND, "Failed to locate object from short oid. Object not found");
state.dir_len = dir_len+3;
state.short_oid_len = len;
state.found = 0;
/* Explore directory to find a unique object matching short_oid */
- error = gitfo_dirent(object_location, GIT_PATH_MAX, fn_locate_object_short_oid, &state);
+ error = git_futils_direach(object_location, GIT_PATH_MAX, fn_locate_object_short_oid, &state);
if (error) {
return git__rethrow(error, "Failed to locate object from short oid");
}
@@ -684,7 +684,7 @@ int loose_backend__stream_fwrite(git_oid *oid, git_odb_stream *_stream)
if (object_file_name(final_path, sizeof(final_path), backend->objects_dir, oid))
return GIT_ENOMEM;
- if ((error = gitfo_mkdir_2file(final_path)) < GIT_SUCCESS)
+ if ((error = git_futils_mkpath2file(final_path)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write loose backend");
stream->finished = 1;
@@ -749,7 +749,7 @@ int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend
stream->stream.free = &loose_backend__stream_free;
stream->stream.mode = GIT_STREAM_WRONLY;
- git__joinpath(tmp_path, backend->objects_dir, "tmp_object");
+ git_path_join(tmp_path, backend->objects_dir, "tmp_object");
error = git_filebuf_open(&stream->fbuf, tmp_path,
GIT_FILEBUF_HASH_CONTENTS |
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 2f95faee5..59661a662 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -359,7 +359,7 @@ void pack_window_free_all(struct pack_backend *backend, struct pack_file *p)
backend->mapped -= w->window_map.len;
backend->open_windows--;
- gitfo_free_map(&w->window_map);
+ git_futils_mmap_free(&w->window_map);
p->windows = w->next;
free(w);
@@ -416,14 +416,14 @@ static int pack_window_close_lru(
if (lru_p) {
backend->mapped -= lru_w->window_map.len;
- gitfo_free_map(&lru_w->window_map);
+ git_futils_mmap_free(&lru_w->window_map);
if (lru_l)
lru_l->next = lru_w->next;
else {
lru_p->windows = lru_w->next;
if (!lru_p->windows && lru_p->pack_fd != keep_fd) {
- gitfo_close(lru_p->pack_fd);
+ p_close(lru_p->pack_fd);
lru_p->pack_fd = -1;
}
}
@@ -491,7 +491,7 @@ static unsigned char *pack_window_open(
while (backend->mapped_limit < backend->mapped &&
pack_window_close_lru(backend, p, p->pack_fd) == GIT_SUCCESS) {}
- if (gitfo_map_ro(&win->window_map, p->pack_fd,
+ if (git_futils_mmap_ro(&win->window_map, p->pack_fd,
win->offset, len) < GIT_SUCCESS)
return NULL;
@@ -539,7 +539,7 @@ static unsigned char *pack_window_open(
static void pack_index_free(struct pack_file *p)
{
if (p->index_map.data) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
p->index_map.data = NULL;
}
}
@@ -555,15 +555,15 @@ static int pack_index_check(const char *path, struct pack_file *p)
struct stat st;
/* TODO: properly open the file without access time */
- git_file fd = gitfo_open(path, O_RDONLY /*| O_NOATIME */);
+ git_file fd = p_open(path, O_RDONLY /*| O_NOATIME */);
int error;
if (fd < 0)
return git__throw(GIT_EOSERR, "Failed to check index. File missing or corrupted");
- if (gitfo_fstat(fd, &st) < GIT_SUCCESS) {
- gitfo_close(fd);
+ if (p_fstat(fd, &st) < GIT_SUCCESS) {
+ p_close(fd);
return git__throw(GIT_EOSERR, "Failed to check index. File appears to be corrupted");
}
@@ -573,12 +573,12 @@ static int pack_index_check(const char *path, struct pack_file *p)
idx_size = (size_t)st.st_size;
if (idx_size < 4 * 256 + 20 + 20) {
- gitfo_close(fd);
+ p_close(fd);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Object is corrupted");
}
- error = gitfo_map_ro(&p->index_map, fd, 0, idx_size);
- gitfo_close(fd);
+ error = git_futils_mmap_ro(&p->index_map, fd, 0, idx_size);
+ p_close(fd);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to check index");
@@ -589,7 +589,7 @@ static int pack_index_check(const char *path, struct pack_file *p)
version = ntohl(hdr->idx_version);
if (version < 2 || version > 2) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Unsupported index version");
}
@@ -605,7 +605,7 @@ static int pack_index_check(const char *path, struct pack_file *p)
for (i = 0; i < 256; i++) {
uint32_t n = ntohl(index[i]);
if (n < nr) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Index is non-monotonic");
}
nr = n;
@@ -620,7 +620,7 @@ static int pack_index_check(const char *path, struct pack_file *p)
* - 20-byte SHA1 file checksum
*/
if (idx_size != 4*256 + nr * 24 + 20 + 20) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Object is corrupted");
}
} else if (version == 2) {
@@ -644,14 +644,14 @@ static int pack_index_check(const char *path, struct pack_file *p)
max_size += (nr - 1)*8;
if (idx_size < min_size || idx_size > max_size) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOBJCORRUPTED, "Failed to check index. Wrong index size");
}
/* Make sure that off_t is big enough to access the whole pack...
* Is this an issue in libgit2? It shouldn't. */
if (idx_size != min_size && (sizeof(off_t) <= 4)) {
- gitfo_free_map(&p->index_map);
+ git_futils_mmap_free(&p->index_map);
return git__throw(GIT_EOSERR, "Failed to check index. off_t not big enough to access the whole pack");
}
}
@@ -738,7 +738,7 @@ static void packfile_free(struct pack_backend *backend, struct pack_file *p)
pack_window_free_all(backend, p);
if (p->pack_fd != -1)
- gitfo_close(p->pack_fd);
+ p_close(p->pack_fd);
pack_index_free(p);
@@ -757,8 +757,8 @@ static int packfile_open(struct pack_file *p)
return git__throw(GIT_ENOTFOUND, "Failed to open packfile. File not found");
/* TODO: open with noatime */
- p->pack_fd = gitfo_open(p->pack_name, O_RDONLY);
- if (p->pack_fd < 0 || gitfo_fstat(p->pack_fd, &st) < GIT_SUCCESS)
+ p->pack_fd = p_open(p->pack_name, O_RDONLY);
+ if (p->pack_fd < 0 || p_fstat(p->pack_fd, &st) < GIT_SUCCESS)
return git__throw(GIT_EOSERR, "Failed to open packfile. File appears to be corrupted");
/* If we created the struct before we had the pack we lack size. */
@@ -783,7 +783,7 @@ static int packfile_open(struct pack_file *p)
#endif
/* Verify we recognize this pack file format. */
- if (gitfo_read(p->pack_fd, &hdr, sizeof(hdr)) < GIT_SUCCESS)
+ if (p_read(p->pack_fd, &hdr, sizeof(hdr)) < GIT_SUCCESS)
goto cleanup;
if (hdr.hdr_signature != htonl(PACK_SIGNATURE))
@@ -796,10 +796,10 @@ static int packfile_open(struct pack_file *p)
if (p->num_objects != ntohl(hdr.hdr_entries))
goto cleanup;
- if (gitfo_lseek(p->pack_fd, p->pack_size - GIT_OID_RAWSZ, SEEK_SET) == -1)
+ if (p_lseek(p->pack_fd, p->pack_size - GIT_OID_RAWSZ, SEEK_SET) == -1)
goto cleanup;
- if (gitfo_read(p->pack_fd, sha1.id, GIT_OID_RAWSZ) < GIT_SUCCESS)
+ if (p_read(p->pack_fd, sha1.id, GIT_OID_RAWSZ) < GIT_SUCCESS)
goto cleanup;
idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
@@ -810,7 +810,7 @@ static int packfile_open(struct pack_file *p)
return GIT_SUCCESS;
cleanup:
- gitfo_close(p->pack_fd);
+ p_close(p->pack_fd);
p->pack_fd = -1;
return git__throw(GIT_EPACKCORRUPTED, "Failed to packfile. Pack is corrupted");
}
@@ -838,11 +838,11 @@ static int packfile_check(struct pack_file **pack_out, const char *path)
memcpy(p->pack_name, path, path_len);
strcpy(p->pack_name + path_len, ".keep");
- if (gitfo_exists(p->pack_name) == GIT_SUCCESS)
+ if (git_futils_exists(p->pack_name) == GIT_SUCCESS)
p->pack_keep = 1;
strcpy(p->pack_name + path_len, ".pack");
- if (gitfo_stat(p->pack_name, &st) < GIT_SUCCESS || !S_ISREG(st.st_mode)) {
+ if (p_stat(p->pack_name, &st) < GIT_SUCCESS || !S_ISREG(st.st_mode)) {
free(p);
return git__throw(GIT_ENOTFOUND, "Failed to check packfile. File not found");
}
@@ -899,7 +899,7 @@ static int packfile_refresh_all(struct pack_backend *backend)
if (backend->pack_folder == NULL)
return GIT_SUCCESS;
- if (gitfo_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
+ if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
return git__throw(GIT_ENOTFOUND, "Failed to refresh packfiles. Backend not found");
if (st.st_mtime != backend->pack_folder_mtime) {
@@ -907,7 +907,7 @@ static int packfile_refresh_all(struct pack_backend *backend)
strcpy(path, backend->pack_folder);
/* reload all packs */
- error = gitfo_dirent(path, GIT_PATH_MAX, packfile_load__cb, (void *)backend);
+ error = git_futils_direach(path, GIT_PATH_MAX, packfile_load__cb, (void *)backend);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to refresh packfiles");
@@ -1549,8 +1549,8 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
backend->window_size = DEFAULT_WINDOW_SIZE;
backend->mapped_limit = DEFAULT_MAPPED_LIMIT;
- git__joinpath(path, objects_dir, "pack");
- if (gitfo_isdir(path) == GIT_SUCCESS) {
+ git_path_join(path, objects_dir, "pack");
+ if (git_futils_isdir(path) == GIT_SUCCESS) {
backend->pack_folder = git__strdup(path);
backend->pack_folder_mtime = 0;
diff --git a/src/path.c b/src/path.c
new file mode 100644
index 000000000..766f67427
--- /dev/null
+++ b/src/path.c
@@ -0,0 +1,204 @@
+#include "common.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * Check http://android.git.kernel.org/
+ */
+int git_path_basename_r(char *buffer, size_t bufflen, const char *path)
+{
+ const char *endp, *startp;
+ int len, result;
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+ startp = ".";
+ len = 1;
+ goto Exit;
+ }
+
+ /* Strip trailing slashes */
+ endp = path + strlen(path) - 1;
+ while (endp > path && *endp == '/')
+ endp--;
+
+ /* All slashes becomes "/" */
+ if (endp == path && *endp == '/') {
+ startp = "/";
+ len = 1;
+ goto Exit;
+ }
+
+ /* Find the start of the base */
+ startp = endp;
+ while (startp > path && *(startp - 1) != '/')
+ startp--;
+
+ len = endp - startp +1;
+
+Exit:
+ result = len;
+ if (buffer == NULL) {
+ return result;
+ }
+ if (len > (int)bufflen-1) {
+ len = (int)bufflen-1;
+ result = GIT_ENOMEM;
+ }
+
+ if (len >= 0) {
+ memmove(buffer, startp, len);
+ buffer[len] = 0;
+ }
+ return result;
+}
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * Check http://android.git.kernel.org/
+ */
+int git_path_dirname_r(char *buffer, size_t bufflen, const char *path)
+{
+ const char *endp;
+ int result, len;
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+ path = ".";
+ len = 1;
+ goto Exit;
+ }
+
+ /* Strip trailing slashes */
+ endp = path + strlen(path) - 1;
+ while (endp > path && *endp == '/')
+ endp--;
+
+ /* Find the start of the dir */
+ while (endp > path && *endp != '/')
+ endp--;
+
+ /* Either the dir is "/" or there are no slashes */
+ if (endp == path) {
+ path = (*endp == '/') ? "/" : ".";
+ len = 1;
+ goto Exit;
+ }
+
+ do {
+ endp--;
+ } while (endp > path && *endp == '/');
+
+ len = endp - path +1;
+
+Exit:
+ result = len;
+ if (len+1 > GIT_PATH_MAX) {
+ return GIT_ENOMEM;
+ }
+ if (buffer == NULL)
+ return result;
+
+ if (len > (int)bufflen-1) {
+ len = (int)bufflen-1;
+ result = GIT_ENOMEM;
+ }
+
+ if (len >= 0) {
+ memmove(buffer, path, len);
+ buffer[len] = 0;
+ }
+ return result;
+}
+
+
+char *git_path_dirname(const char *path)
+{
+ char *dname = NULL;
+ int len;
+
+ len = (path ? strlen(path) : 0) + 2;
+ dname = (char *)git__malloc(len);
+ if (dname == NULL)
+ return NULL;
+
+ if (git_path_dirname_r(dname, len, path) < GIT_SUCCESS) {
+ free(dname);
+ return NULL;
+ }
+
+ return dname;
+}
+
+char *git_path_basename(const char *path)
+{
+ char *bname = NULL;
+ int len;
+
+ len = (path ? strlen(path) : 0) + 2;
+ bname = (char *)git__malloc(len);
+ if (bname == NULL)
+ return NULL;
+
+ if (git_path_basename_r(bname, len, path) < GIT_SUCCESS) {
+ free(bname);
+ return NULL;
+ }
+
+ return bname;
+}
+
+
+const char *git_path_topdir(const char *path)
+{
+ size_t len;
+ int i;
+
+ assert(path);
+ len = strlen(path);
+
+ if (!len || path[len - 1] != '/')
+ return NULL;
+
+ for (i = len - 2; i >= 0; --i)
+ if (path[i] == '/')
+ break;
+
+ return &path[i + 1];
+}
+
+void git_path_join_n(char *buffer_out, int count, ...)
+{
+ va_list ap;
+ int i;
+ char *buffer_start = buffer_out;
+
+ va_start(ap, count);
+ for (i = 0; i < count; ++i) {
+ const char *path;
+ int len;
+
+ path = va_arg(ap, const char *);
+
+ assert((i == 0) || path != buffer_start);
+
+ if (i > 0 && *path == '/' && buffer_out > buffer_start && buffer_out[-1] == '/')
+ path++;
+
+ if (!*path)
+ continue;
+
+ len = strlen(path);
+ memmove(buffer_out, path, len);
+ buffer_out = buffer_out + len;
+
+ if (i < count - 1 && buffer_out[-1] != '/')
+ *buffer_out++ = '/';
+ }
+ va_end(ap);
+
+ *buffer_out = '\0';
+}
+
diff --git a/src/path.h b/src/path.h
new file mode 100644
index 000000000..1bae9dfbe
--- /dev/null
+++ b/src/path.h
@@ -0,0 +1,76 @@
+/*
+ * posix.h - Path management methods
+ */
+#ifndef INCLUDE_path_h__
+#define INCLUDE_path_h__
+
+#include "common.h"
+
+/*
+ * The dirname() function shall take a pointer to a character string
+ * that contains a pathname, and return a pointer to a string that is a
+ * pathname of the parent directory of that file. Trailing '/' characters
+ * in the path are not counted as part of the path.
+ *
+ * If path does not contain a '/', then dirname() shall return a pointer to
+ * the string ".". If path is a null pointer or points to an empty string,
+ * dirname() shall return a pointer to the string "." .
+ *
+ * The `git_path_dirname` implementation is thread safe. The returned
+ * string must be manually free'd.
+ *
+ * The `git_path_dirname_r` implementation expects a string allocated
+ * by the user with big enough size.
+ */
+extern char *git_path_dirname(const char *path);
+extern int git_path_dirname_r(char *buffer, size_t bufflen, const char *path);
+
+/*
+ * This function returns the basename of the file, which is the last
+ * part of its full name given by fname, with the drive letter and
+ * leading directories stripped off. For example, the basename of
+ * c:/foo/bar/file.ext is file.ext, and the basename of a:foo is foo.
+ *
+ * Trailing slashes and backslashes are significant: the basename of
+ * c:/foo/bar/ is an empty string after the rightmost slash.
+ *
+ * The `git_path_basename` implementation is thread safe. The returned
+ * string must be manually free'd.
+ *
+ * The `git_path_basename_r` implementation expects a string allocated
+ * by the user with big enough size.
+ */
+extern char *git_path_basename(const char *path);
+extern int git_path_basename_r(char *buffer, size_t bufflen, const char *path);
+
+extern const char *git_path_topdir(const char *path);
+
+/**
+ * Join two paths together. Takes care of properly fixing the
+ * middle slashes and everything
+ *
+ * The paths are joined together into buffer_out; this is expected
+ * to be an user allocated buffer of `GIT_PATH_MAX` size
+ */
+extern void git_path_join_n(char *buffer_out, int npath, ...);
+
+GIT_INLINE(void) git_path_join(char *buffer_out, const char *path_a, const char *path_b)
+{
+ git_path_join_n(buffer_out, 2, path_a, path_b);
+}
+
+#ifdef GIT_WIN32
+GIT_INLINE(void) git_path_mkposix(char *path)
+{
+ while (*path) {
+ if (*path == '\\')
+ *path = '/';
+
+ path++;
+ }
+}
+#else
+# define git_path_mkposix(p) /* blank */
+#endif
+
+#endif
diff --git a/src/posix.c b/src/posix.c
new file mode 100644
index 000000000..9dbebbd57
--- /dev/null
+++ b/src/posix.c
@@ -0,0 +1,74 @@
+#include "common.h"
+#include "posix.h"
+#include "path.h"
+#include <stdio.h>
+#include <ctype.h>
+
+int p_open(const char *path, int flags)
+{
+ return open(path, flags | O_BINARY);
+}
+
+int p_creat(const char *path, int mode)
+{
+ return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
+}
+
+int p_read(git_file fd, void *buf, size_t cnt)
+{
+ char *b = buf;
+ while (cnt) {
+ ssize_t r = read(fd, b, cnt);
+ if (r < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return GIT_EOSERR;
+ }
+ if (!r)
+ break;
+ cnt -= r;
+ b += r;
+ }
+ return (int)(b - (char *)buf);
+}
+
+int p_write(git_file fd, void *buf, size_t cnt)
+{
+ char *b = buf;
+ while (cnt) {
+ ssize_t r = write(fd, b, cnt);
+ if (r < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return GIT_EOSERR;
+ }
+ if (!r) {
+ errno = EPIPE;
+ return GIT_EOSERR;
+ }
+ cnt -= r;
+ b += r;
+ }
+ return GIT_SUCCESS;
+}
+
+int p_getcwd(char *buffer_out, size_t size)
+{
+ char *cwd_buffer;
+
+ assert(buffer_out && size > 0);
+
+#ifdef GIT_WIN32
+ cwd_buffer = _getcwd(buffer_out, size);
+#else
+ cwd_buffer = getcwd(buffer_out, size);
+#endif
+
+ if (cwd_buffer == NULL)
+ return git__throw(GIT_EOSERR, "Failed to retrieve current working directory");
+
+ git_path_mkposix(buffer_out);
+
+ git_path_join(buffer_out, buffer_out, ""); //Ensure the path ends with a trailing slash
+ return GIT_SUCCESS;
+}
diff --git a/src/posix.h b/src/posix.h
new file mode 100644
index 000000000..eaa89383d
--- /dev/null
+++ b/src/posix.h
@@ -0,0 +1,54 @@
+/*
+ * posix.h - OS agnostic POSIX calls
+ */
+#ifndef INCLUDE_posix_h__
+#define INCLUDE_posix_h__
+
+#include "common.h"
+#include <fcntl.h>
+#include <time.h>
+
+#ifdef GIT_WIN32
+# include "win32/posix.h"
+#else
+# include "unix/posix.h"
+#endif
+
+#define S_IFGITLINK 0160000
+#define S_ISGITLINK(m) (((m) & S_IFMT) == S_IFGITLINK)
+
+#if !defined(O_BINARY)
+#define O_BINARY 0
+#endif
+
+typedef int git_file;
+
+
+/**
+ * Standard POSIX Methods
+ *
+ * All the methods starting with the `p_` prefix are
+ * direct ports of the standard POSIX methods.
+ *
+ * Some of the methods are slightly wrapped to provide
+ * saner defaults. Some of these methods are emulated
+ * in Windows platforns.
+ *
+ * Use your manpages to check the docs on these.
+ * Straightforward
+ */
+extern int p_open(const char *path, int flags);
+extern int p_creat(const char *path, int mode);
+extern int p_read(git_file fd, void *buf, size_t cnt);
+extern int p_write(git_file fd, void *buf, size_t cnt);
+extern int p_getcwd(char *buffer_out, size_t size);
+
+#define p_lseek(f,n,w) lseek(f, n, w)
+#define p_stat(p,b) stat(p, b)
+#define p_fstat(f,b) fstat(f, b)
+#define p_chdir(p) chdir(p)
+#define p_rmdir(p) rmdir(p)
+#define p_chmod(p,m) chmod(p, m)
+#define p_close(fd) close(fd)
+
+#endif
diff --git a/src/refs.c b/src/refs.c
index ad81bb3c1..eea96adba 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -59,11 +59,11 @@ static uint32_t reftable_hash(const void *key, int hash_id)
static void reference_free(git_reference *reference);
static int reference_create(git_reference **ref_out, git_repository *repo, const char *name, git_rtype type);
-static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *repo_path, const char *ref_name);
+static int reference_read(git_fbuffer *file_content, time_t *mtime, const char *repo_path, const char *ref_name);
/* loose refs */
-static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content);
-static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content);
+static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content);
+static int loose_parse_oid(git_reference *ref, git_fbuffer *file_content);
static int loose_lookup(git_reference **ref_out, git_repository *repo, const char *name, int skip_symbolic);
static int loose_write(git_reference *ref);
static int loose_update(git_reference *ref);
@@ -150,15 +150,15 @@ cleanup:
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to create reference");
}
-static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *repo_path, const char *ref_name)
+static int reference_read(git_fbuffer *file_content, time_t *mtime, const char *repo_path, const char *ref_name)
{
struct stat st;
char path[GIT_PATH_MAX];
/* Determine the full path of the file */
- git__joinpath(path, repo_path, ref_name);
+ git_path_join(path, repo_path, ref_name);
- if (gitfo_stat(path, &st) < 0 || S_ISDIR(st.st_mode))
+ if (p_stat(path, &st) < 0 || S_ISDIR(st.st_mode))
return git__throw(GIT_ENOTFOUND,
"Cannot read reference file '%s'", ref_name);
@@ -166,7 +166,7 @@ static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *re
*mtime = st.st_mtime;
if (file_content)
- return gitfo_read_file(file_content, path);
+ return git_futils_readbuffer(file_content, path);
return GIT_SUCCESS;
}
@@ -181,7 +181,7 @@ static int loose_update(git_reference *ref)
{
int error;
time_t ref_time;
- gitfo_buf ref_file = GITFO_BUF_INIT;
+ git_fbuffer ref_file = GIT_FBUFFER_INIT;
if (ref->type & GIT_REF_PACKED)
return packed_load(ref->owner);
@@ -205,7 +205,7 @@ static int loose_update(git_reference *ref)
error = git__throw(GIT_EOBJCORRUPTED,
"Invalid reference type (%d) for loose reference", ref->type);
- gitfo_free_buf(&ref_file);
+ git_futils_freebuffer(&ref_file);
cleanup:
if (error != GIT_SUCCESS) {
@@ -216,7 +216,7 @@ cleanup:
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to update loose reference");
}
-static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
+static int loose_parse_symbolic(git_reference *ref, git_fbuffer *file_content)
{
const unsigned int header_len = strlen(GIT_SYMREF);
const char *refname_start;
@@ -255,7 +255,7 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
return GIT_SUCCESS;
}
-static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
+static int loose_parse_oid(git_reference *ref, git_fbuffer *file_content)
{
int error;
reference_oid *ref_oid;
@@ -286,19 +286,19 @@ static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
static git_rtype loose_guess_rtype(const char *full_path)
{
- gitfo_buf ref_file = GITFO_BUF_INIT;
+ git_fbuffer ref_file = GIT_FBUFFER_INIT;
git_rtype type;
type = GIT_REF_INVALID;
- if (gitfo_read_file(&ref_file, full_path) == GIT_SUCCESS) {
+ if (git_futils_readbuffer(&ref_file, full_path) == GIT_SUCCESS) {
if (git__prefixcmp((const char *)(ref_file.data), GIT_SYMREF) == 0)
type = GIT_REF_SYMBOLIC;
else
type = GIT_REF_OID;
}
- gitfo_free_buf(&ref_file);
+ git_futils_freebuffer(&ref_file);
return type;
}
@@ -309,7 +309,7 @@ static int loose_lookup(
int skip_symbolic)
{
int error = GIT_SUCCESS;
- gitfo_buf ref_file = GITFO_BUF_INIT;
+ git_fbuffer ref_file = GIT_FBUFFER_INIT;
git_reference *ref = NULL;
time_t ref_time;
@@ -341,11 +341,11 @@ static int loose_lookup(
ref->mtime = ref_time;
*ref_out = ref;
- gitfo_free_buf(&ref_file);
+ git_futils_freebuffer(&ref_file);
return GIT_SUCCESS;
cleanup:
- gitfo_free_buf(&ref_file);
+ git_futils_freebuffer(&ref_file);
reference_free(ref);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to lookup loose reference");
}
@@ -357,7 +357,7 @@ static int loose_write(git_reference *ref)
int error;
struct stat st;
- git__joinpath(ref_path, ref->owner->path_repository, ref->name);
+ git_path_join(ref_path, ref->owner->path_repository, ref->name);
if ((error = git_filebuf_open(&file, ref_path, GIT_FILEBUF_FORCE)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write loose reference");
@@ -384,7 +384,7 @@ static int loose_write(git_reference *ref)
error = git_filebuf_commit(&file);
- if (gitfo_stat(ref_path, &st) == GIT_SUCCESS)
+ if (p_stat(ref_path, &st) == GIT_SUCCESS)
ref->mtime = st.st_mtime;
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write loose reference");
@@ -501,7 +501,7 @@ cleanup:
static int packed_load(git_repository *repo)
{
int error = GIT_SUCCESS;
- gitfo_buf packfile = GITFO_BUF_INIT;
+ git_fbuffer packfile = GIT_FBUFFER_INIT;
const char *buffer_start, *buffer_end;
git_refcache *ref_cache = &repo->references;
@@ -580,13 +580,13 @@ static int packed_load(git_repository *repo)
}
}
- gitfo_free_buf(&packfile);
+ git_futils_freebuffer(&packfile);
return GIT_SUCCESS;
cleanup:
git_hashtable_free(ref_cache->packfile);
ref_cache->packfile = NULL;
- gitfo_free_buf(&packfile);
+ git_futils_freebuffer(&packfile);
return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to load packed references");
}
@@ -607,8 +607,8 @@ static int _dirent_loose_listall(void *_data, char *full_path)
struct dirent_list_data *data = (struct dirent_list_data *)_data;
char *file_path = full_path + data->repo_path_len;
- if (gitfo_isdir(full_path) == GIT_SUCCESS)
- return gitfo_dirent(full_path, GIT_PATH_MAX, _dirent_loose_listall, _data);
+ if (git_futils_isdir(full_path) == GIT_SUCCESS)
+ return git_futils_direach(full_path, GIT_PATH_MAX, _dirent_loose_listall, _data);
/* do not add twice a reference that exists already in the packfile */
if ((data->list_flags & GIT_REF_PACKED) != 0 &&
@@ -630,8 +630,8 @@ static int _dirent_loose_load(void *data, char *full_path)
char *file_path;
int error;
- if (gitfo_isdir(full_path) == GIT_SUCCESS)
- return gitfo_dirent(full_path, GIT_PATH_MAX, _dirent_loose_load, repository);
+ if (git_futils_isdir(full_path) == GIT_SUCCESS)
+ return git_futils_direach(full_path, GIT_PATH_MAX, _dirent_loose_load, repository);
file_path = full_path + strlen(repository->path_repository);
error = loose_lookup(&reference, repository, file_path, 1);
@@ -663,7 +663,7 @@ static int packed_loadloose(git_repository *repository)
/* the packfile must have been previously loaded! */
assert(repository->references.packfile);
- git__joinpath(refs_path, repository->path_repository, GIT_REFS_DIR);
+ git_path_join(refs_path, repository->path_repository, GIT_REFS_DIR);
/* Remove any loose references from the cache */
{
@@ -682,7 +682,7 @@ static int packed_loadloose(git_repository *repository)
* This will overwrite any old packed entries with their
* updated loose versions
*/
- return gitfo_dirent(refs_path, GIT_PATH_MAX, _dirent_loose_load, repository);
+ return git_futils_direach(refs_path, GIT_PATH_MAX, _dirent_loose_load, repository);
}
/*
@@ -803,10 +803,10 @@ static int packed_remove_loose(git_repository *repo, git_vector *packing_list)
if (reference != NULL)
continue;
- git__joinpath(full_path, repo->path_repository, ref->name);
+ git_path_join(full_path, repo->path_repository, ref->name);
- if (gitfo_exists(full_path) == GIT_SUCCESS &&
- gitfo_unlink(full_path) < GIT_SUCCESS)
+ if (git_futils_exists(full_path) == GIT_SUCCESS &&
+ p_unlink(full_path) < GIT_SUCCESS)
error = GIT_EOSERR;
/*
@@ -864,7 +864,7 @@ static int packed_write(git_repository *repo)
git_vector_sort(&packing_list);
/* Now we can open the file! */
- git__joinpath(pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE);
+ git_path_join(pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE);
if ((error = git_filebuf_open(&pack_file, pack_file_path, 0)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write packed reference");
@@ -904,7 +904,7 @@ cleanup:
error = packed_remove_loose(repo, &packing_list);
- if (gitfo_stat(pack_file_path, &st) == GIT_SUCCESS)
+ if (p_stat(pack_file_path, &st) == GIT_SUCCESS)
repo->references.packfile_time = st.st_mtime;
}
}
@@ -1367,10 +1367,10 @@ int git_reference_rename(git_reference *ref, const char *new_name, int force)
goto rename_loose_to_old_name;
} else {
- git__joinpath(old_path, ref->owner->path_repository, old_name);
- git__joinpath(new_path, ref->owner->path_repository, ref->name);
+ git_path_join(old_path, ref->owner->path_repository, old_name);
+ git_path_join(new_path, ref->owner->path_repository, ref->name);
- error = gitfo_mv_force(old_path, new_path);
+ error = git_futils_mv_withpath(old_path, new_path);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -1405,11 +1405,11 @@ rename_loose_to_old_name:
* for good. :-/
*/
- git__joinpath(old_path, ref->owner->path_repository, ref->name);
- git__joinpath(new_path, ref->owner->path_repository, old_name);
+ git_path_join(old_path, ref->owner->path_repository, ref->name);
+ git_path_join(new_path, ref->owner->path_repository, old_name);
/* No error checking. We'll return the initial error */
- gitfo_mv_force(old_path, new_path);
+ git_futils_mv_withpath(old_path, new_path);
/* restore the old name */
free(ref->name);
@@ -1452,9 +1452,9 @@ int git_reference_delete(git_reference *ref)
error = packed_write(ref->owner);
} else {
char full_path[GIT_PATH_MAX];
- git__joinpath(full_path, ref->owner->path_repository, ref->name);
+ git_path_join(full_path, ref->owner->path_repository, ref->name);
git_hashtable_remove(ref->owner->references.loose_cache, ref->name);
- error = gitfo_unlink(full_path);
+ error = p_unlink(full_path);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -1547,8 +1547,8 @@ int git_reference_foreach(git_repository *repo, unsigned int list_flags, int (*c
data.callback_payload = payload;
- git__joinpath(refs_path, repo->path_repository, GIT_REFS_DIR);
- return gitfo_dirent(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
+ git_path_join(refs_path, repo->path_repository, GIT_REFS_DIR);
+ return git_futils_direach(refs_path, GIT_PATH_MAX, _dirent_loose_listall, &data);
}
int cb__reflist_add(const char *ref, void *data)
diff --git a/src/repository.c b/src/repository.c
index 8ebfd6745..a8ead3a32 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -68,7 +68,7 @@ static int assign_repository_dirs(
if (git_dir == NULL)
return git__throw(GIT_ENOTFOUND, "Failed to open repository. Git dir not found");
- error = gitfo_prettify_dir_path(path_aux, sizeof(path_aux), git_dir, NULL);
+ error = git_futils_prettify_dir(path_aux, sizeof(path_aux), git_dir, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open repository");
@@ -79,9 +79,9 @@ static int assign_repository_dirs(
/* path to GIT_OBJECT_DIRECTORY */
if (git_object_directory == NULL)
- git__joinpath(path_aux, repo->path_repository, GIT_OBJECTS_DIR);
+ git_path_join(path_aux, repo->path_repository, GIT_OBJECTS_DIR);
else {
- error = gitfo_prettify_dir_path(path_aux, sizeof(path_aux), git_object_directory, NULL);
+ error = git_futils_prettify_dir(path_aux, sizeof(path_aux), git_object_directory, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open repository");
}
@@ -95,7 +95,7 @@ static int assign_repository_dirs(
if (git_work_tree == NULL)
repo->is_bare = 1;
else {
- error = gitfo_prettify_dir_path(path_aux, sizeof(path_aux), git_work_tree, NULL);
+ error = git_futils_prettify_dir(path_aux, sizeof(path_aux), git_work_tree, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open repository");
@@ -106,9 +106,9 @@ static int assign_repository_dirs(
/* Path to GIT_INDEX_FILE */
if (git_index_file == NULL)
- git__joinpath(path_aux, repo->path_repository, GIT_INDEX_FILE);
+ git_path_join(path_aux, repo->path_repository, GIT_INDEX_FILE);
else {
- error = gitfo_prettify_file_path(path_aux, sizeof(path_aux), git_index_file, NULL);
+ error = git_futils_prettyify_file(path_aux, sizeof(path_aux), git_index_file, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to open repository");
}
@@ -126,16 +126,16 @@ static int check_repository_dirs(git_repository *repo)
{
char path_aux[GIT_PATH_MAX];
- if (gitfo_isdir(repo->path_repository) < GIT_SUCCESS)
+ if (git_futils_isdir(repo->path_repository) < GIT_SUCCESS)
return git__throw(GIT_ENOTAREPO, "`%s` is not a folder", repo->path_repository);
/* Ensure GIT_OBJECT_DIRECTORY exists */
- if (gitfo_isdir(repo->path_odb) < GIT_SUCCESS)
+ if (git_futils_isdir(repo->path_odb) < GIT_SUCCESS)
return git__throw(GIT_ENOTAREPO, "`%s` does not exist", repo->path_odb);
/* Ensure HEAD file exists */
- git__joinpath(path_aux, repo->path_repository, GIT_HEAD_FILE);
- if (gitfo_exists(path_aux) < 0)
+ git_path_join(path_aux, repo->path_repository, GIT_HEAD_FILE);
+ if (git_futils_exists(path_aux) < 0)
return git__throw(GIT_ENOTAREPO, "HEAD file is missing");
return GIT_SUCCESS;
@@ -147,12 +147,12 @@ static int guess_repository_dirs(git_repository *repo, const char *repository_pa
const char *path_work_tree = NULL;
/* Git directory name */
- if (git__basename_r(buffer, sizeof(buffer), repository_path) < 0)
+ if (git_path_basename_r(buffer, sizeof(buffer), repository_path) < 0)
return git__throw(GIT_EINVALIDPATH, "Unable to parse folder name from `%s`", repository_path);
if (strcmp(buffer, DOT_GIT) == 0) {
/* Path to working dir */
- if (git__dirname_r(buffer, sizeof(buffer), repository_path) < 0)
+ if (git_path_dirname_r(buffer, sizeof(buffer), repository_path) < 0)
return git__throw(GIT_EINVALIDPATH, "Unable to parse parent folder name from `%s`", repository_path);
path_work_tree = buffer;
}
@@ -286,7 +286,7 @@ int git_repository_config(
if (error < GIT_SUCCESS)
return error;
- git__joinpath(config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
+ git_path_join(config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO);
error = git_config_add_file_ondisk(*out, config_path, 3);
if (error < GIT_SUCCESS)
goto cleanup;
@@ -364,7 +364,7 @@ static int abspath(char *buffer_out, size_t size, const char *path)
return git__throw(GIT_EOSERR, "Failed to retrieve real path: %s causing errors", buffer_out);
#endif
- gitfo_posixify_path(buffer_out);
+ git_path_mkposix(buffer_out);
return GIT_SUCCESS;
}
@@ -375,7 +375,7 @@ static int retrieve_device(dev_t *device_out, const char *path)
assert(device_out);
- if (gitfo_stat(path, &path_info))
+ if (p_stat(path, &path_info))
return git__throw(GIT_EOSERR, "Failed to get file informations: %s", path);
*device_out = path_info.st_dev;
@@ -393,7 +393,7 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
assert(path);
- min_len = gitfo_retrieve_path_root_offset(path) + 1;
+ min_len = git_futils_root_offset(path) + 1;
if (ceiling_directories == NULL || min_len == 0)
return min_len;
@@ -402,7 +402,7 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
for (sep = ceil; *sep && *sep != GIT_PATH_LIST_SEPARATOR; sep++);
len = sep - ceil;
- if (len == 0 || len > GIT_PATH_MAX || gitfo_retrieve_path_root_offset(ceil) == -1)
+ if (len == 0 || len > GIT_PATH_MAX || git_futils_root_offset(ceil) == -1)
continue;
strncpy(buf, ceil, len);
@@ -428,13 +428,13 @@ static int retrieve_ceiling_directories_offset(const char *path, const char *cei
static int read_gitfile(char *path_out, size_t size, const char *file_path, const char *base_path)
{
- gitfo_buf file;
+ git_fbuffer file;
int error, end_offset;
char *data;
assert(file_path && path_out && size > 0);
- error = gitfo_read_file(&file, file_path);
+ error = git_futils_readbuffer(&file, file_path);
if (error < GIT_SUCCESS)
return error;
@@ -442,7 +442,7 @@ static int read_gitfile(char *path_out, size_t size, const char *file_path, cons
data = (char*)(file.data);
if (git__prefixcmp(data, GIT_FILE_CONTENT_PREFIX)) {
- gitfo_free_buf(&file);
+ git_futils_freebuffer(&file);
return git__throw(GIT_ENOTFOUND, "Invalid gitfile format `%s`", file_path);
}
@@ -452,11 +452,11 @@ static int read_gitfile(char *path_out, size_t size, const char *file_path, cons
data[end_offset + 1] = '\0';
if (GIT_FILE_CONTENT_PREFIX_LENGTH == end_offset + 1) {
- gitfo_free_buf(&file);
+ git_futils_freebuffer(&file);
return git__throw(GIT_ENOTFOUND, "No path in git file `%s`", file_path);
}
- error = gitfo_prettify_dir_path(path_out, size, data + GIT_FILE_CONTENT_PREFIX_LENGTH, base_path);
+ error = git_futils_prettify_dir(path_out, size, data + GIT_FILE_CONTENT_PREFIX_LENGTH, base_path);
if (error == GIT_SUCCESS) {
end_offset = strlen(path_out);
@@ -464,7 +464,7 @@ static int read_gitfile(char *path_out, size_t size, const char *file_path, cons
path_out[end_offset - 1 ] = '\0';
}
- gitfo_free_buf(&file);
+ git_futils_freebuffer(&file);
return error;
}
@@ -521,11 +521,11 @@ int git_repository_discover(char *repository_path, size_t size, const char *star
}
ceiling_offset = retrieve_ceiling_directories_offset(bare_path, ceiling_dirs);
- git__joinpath(normal_path, bare_path, DOT_GIT);
+ git_path_join(normal_path, bare_path, DOT_GIT);
while(1){
//look for .git file
- if (gitfo_isfile(normal_path) == GIT_SUCCESS) {
+ if (git_futils_isfile(normal_path) == GIT_SUCCESS) {
error = read_gitfile(repository_path, size, normal_path, bare_path);
if (error < GIT_SUCCESS) {
@@ -566,7 +566,7 @@ int git_repository_discover(char *repository_path, size_t size, const char *star
git_repository__free_dirs(&repo);
- if (git__dirname_r(normal_path, sizeof(normal_path), bare_path) < GIT_SUCCESS)
+ if (git_path_dirname_r(normal_path, sizeof(normal_path), bare_path) < GIT_SUCCESS)
goto cleanup;
if (!across_fs) {
@@ -585,7 +585,7 @@ int git_repository_discover(char *repository_path, size_t size, const char *star
}
strcpy(bare_path, normal_path);
- git__joinpath(normal_path, bare_path, DOT_GIT);
+ git_path_join(normal_path, bare_path, DOT_GIT);
//nothing has been found, lets try the parent directory
if (bare_path[ceiling_offset] == '\0') {
@@ -633,8 +633,8 @@ static int repo_init_check_head_existence(char * repository_path)
{
char temp_path[GIT_PATH_MAX];
- git__joinpath(temp_path, repository_path, GIT_HEAD_FILE);
- return gitfo_exists(temp_path);
+ git_path_join(temp_path, repository_path, GIT_HEAD_FILE);
+ return git_futils_exists(temp_path);
}
static int repo_init_structure(repo_init *results)
@@ -645,39 +645,39 @@ static int repo_init_structure(repo_init *results)
char temp_path[GIT_PATH_MAX];
char *git_dir = results->path_repository;
- if (gitfo_mkdir_recurs(git_dir, mode))
+ if (git_futils_mkdir_r(git_dir, mode))
return git__throw(GIT_ERROR, "Failed to initialize repository structure. Could not mkdir");
#ifdef GIT_WIN32
/* Hides the ".git" directory */
if (!results->is_bare) {
- error = gitfo_hide_directory__w32(git_dir);
+ error = p_hide_directory__w32(git_dir);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to initialize repository structure");
}
#endif
/* Creates the '/objects/info/' directory */
- git__joinpath(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
- error = gitfo_mkdir_recurs(temp_path, mode);
+ git_path_join(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
+ error = git_futils_mkdir_r(temp_path, mode);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to initialize repository structure");
/* Creates the '/objects/pack/' directory */
- git__joinpath(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
- error = gitfo_mkdir(temp_path, mode);
+ git_path_join(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
+ error = p_mkdir(temp_path, mode);
if (error < GIT_SUCCESS)
return git__throw(error, "Unable to create `%s` folder", temp_path);
/* Creates the '/refs/heads/' directory */
- git__joinpath(temp_path, git_dir, GIT_REFS_HEADS_DIR);
- error = gitfo_mkdir_recurs(temp_path, mode);
+ git_path_join(temp_path, git_dir, GIT_REFS_HEADS_DIR);
+ error = git_futils_mkdir_r(temp_path, mode);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to initialize repository structure");
/* Creates the '/refs/tags/' directory */
- git__joinpath(temp_path, git_dir, GIT_REFS_TAGS_DIR);
- error = gitfo_mkdir(temp_path, mode);
+ git_path_join(temp_path, git_dir, GIT_REFS_TAGS_DIR);
+ error = p_mkdir(temp_path, mode);
if (error < GIT_SUCCESS)
return git__throw(error, "Unable to create `%s` folder", temp_path);
@@ -691,12 +691,12 @@ static int repo_init_find_dir(repo_init *results, const char* path)
char temp_path[GIT_PATH_MAX];
int error = GIT_SUCCESS;
- error = gitfo_prettify_dir_path(temp_path, sizeof(temp_path), path, NULL);
+ error = git_futils_prettify_dir(temp_path, sizeof(temp_path), path, NULL);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to find directory to initialize repository");
if (!results->is_bare) {
- git__joinpath(temp_path, temp_path, GIT_DIR);
+ git_path_join(temp_path, temp_path, GIT_DIR);
}
results->path_repository = git__strdup(temp_path);
diff --git a/src/tag.c b/src/tag.c
index 53e28f526..de70c50ae 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -170,7 +170,7 @@ static int retreive_tag_reference(git_reference **tag_reference_out, char *ref_n
git_reference *tag_ref;
int error;
- git__joinpath(ref_name_out, GIT_REFS_TAGS_DIR, tag_name);
+ git_path_join(ref_name_out, GIT_REFS_TAGS_DIR, tag_name);
error = git_reference_lookup(&tag_ref, repo, ref_name_out);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to retrieve tag reference");
diff --git a/src/tree.c b/src/tree.c
index 6a21709f5..51b19f535 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -56,7 +56,7 @@ int entry_sort_cmp(const void *a, const void *b)
const git_tree_entry *entry_a = *(const git_tree_entry **)(a);
const git_tree_entry *entry_b = *(const git_tree_entry **)(b);
- return gitfo_cmp_path(entry_a->filename, strlen(entry_a->filename),
+ return git_futils_cmp_path(entry_a->filename, strlen(entry_a->filename),
entry_a->attr & 040000,
entry_b->filename, strlen(entry_b->filename),
entry_b->attr & 040000);
diff --git a/src/unix/map.c b/src/unix/map.c
index 1f50bcf2e..5192c8e4c 100644
--- a/src/unix/map.c
+++ b/src/unix/map.c
@@ -6,7 +6,7 @@
#include <sys/mman.h>
#include <errno.h>
-int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
+int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
int mprot = 0;
int mflag = 0;
@@ -48,7 +48,7 @@ int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t o
return GIT_SUCCESS;
}
-int git__munmap(git_map *map)
+int p_munmap(git_map *map)
{
assert(map != NULL);
diff --git a/src/unix/posix.h b/src/unix/posix.h
new file mode 100644
index 000000000..ab98c451d
--- /dev/null
+++ b/src/unix/posix.h
@@ -0,0 +1,14 @@
+#ifndef INCLUDE_posix__w32_h__
+#define INCLUDE_posix__w32_h__
+
+#include "common.h"
+
+#define p_lstat(p,b) lstat(p,b)
+#define p_readlink(a, b, c) readlink(a, b, c)
+#define p_link(o,n) link(o, n)
+#define p_unlink(p) unlink(p)
+#define p_mkdir(p,m) mkdir(p, m)
+#define p_fsync(fd) fsync(fd)
+#define p_realpath(p, r) realpath(p, r)
+
+#endif
diff --git a/src/util.c b/src/util.c
index b654e08d1..7dc8d3b4f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,4 +1,3 @@
-#define GIT__NO_HIDE_MALLOC
#include <git2.h>
#include "common.h"
#include <stdarg.h>
@@ -146,205 +145,6 @@ int git__suffixcmp(const char *str, const char *suffix)
return strcmp(str + (a - b), suffix);
}
-/*
- * Based on the Android implementation, BSD licensed.
- * Check http://android.git.kernel.org/
- */
-int git__basename_r(char *buffer, size_t bufflen, const char *path)
-{
- const char *endp, *startp;
- int len, result;
-
- /* Empty or NULL string gets treated as "." */
- if (path == NULL || *path == '\0') {
- startp = ".";
- len = 1;
- goto Exit;
- }
-
- /* Strip trailing slashes */
- endp = path + strlen(path) - 1;
- while (endp > path && *endp == '/')
- endp--;
-
- /* All slashes becomes "/" */
- if (endp == path && *endp == '/') {
- startp = "/";
- len = 1;
- goto Exit;
- }
-
- /* Find the start of the base */
- startp = endp;
- while (startp > path && *(startp - 1) != '/')
- startp--;
-
- len = endp - startp +1;
-
-Exit:
- result = len;
- if (buffer == NULL) {
- return result;
- }
- if (len > (int)bufflen-1) {
- len = (int)bufflen-1;
- result = GIT_ENOMEM;
- }
-
- if (len >= 0) {
- memmove(buffer, startp, len);
- buffer[len] = 0;
- }
- return result;
-}
-
-/*
- * Based on the Android implementation, BSD licensed.
- * Check http://android.git.kernel.org/
- */
-int git__dirname_r(char *buffer, size_t bufflen, const char *path)
-{
- const char *endp;
- int result, len;
-
- /* Empty or NULL string gets treated as "." */
- if (path == NULL || *path == '\0') {
- path = ".";
- len = 1;
- goto Exit;
- }
-
- /* Strip trailing slashes */
- endp = path + strlen(path) - 1;
- while (endp > path && *endp == '/')
- endp--;
-
- /* Find the start of the dir */
- while (endp > path && *endp != '/')
- endp--;
-
- /* Either the dir is "/" or there are no slashes */
- if (endp == path) {
- path = (*endp == '/') ? "/" : ".";
- len = 1;
- goto Exit;
- }
-
- do {
- endp--;
- } while (endp > path && *endp == '/');
-
- len = endp - path +1;
-
-Exit:
- result = len;
- if (len+1 > GIT_PATH_MAX) {
- return GIT_ENOMEM;
- }
- if (buffer == NULL)
- return result;
-
- if (len > (int)bufflen-1) {
- len = (int)bufflen-1;
- result = GIT_ENOMEM;
- }
-
- if (len >= 0) {
- memmove(buffer, path, len);
- buffer[len] = 0;
- }
- return result;
-}
-
-
-char *git__dirname(const char *path)
-{
- char *dname = NULL;
- int len;
-
- len = (path ? strlen(path) : 0) + 2;
- dname = (char *)git__malloc(len);
- if (dname == NULL)
- return NULL;
-
- if (git__dirname_r(dname, len, path) < GIT_SUCCESS) {
- free(dname);
- return NULL;
- }
-
- return dname;
-}
-
-char *git__basename(const char *path)
-{
- char *bname = NULL;
- int len;
-
- len = (path ? strlen(path) : 0) + 2;
- bname = (char *)git__malloc(len);
- if (bname == NULL)
- return NULL;
-
- if (git__basename_r(bname, len, path) < GIT_SUCCESS) {
- free(bname);
- return NULL;
- }
-
- return bname;
-}
-
-
-const char *git__topdir(const char *path)
-{
- size_t len;
- int i;
-
- assert(path);
- len = strlen(path);
-
- if (!len || path[len - 1] != '/')
- return NULL;
-
- for (i = len - 2; i >= 0; --i)
- if (path[i] == '/')
- break;
-
- return &path[i + 1];
-}
-
-void git__joinpath_n(char *buffer_out, int count, ...)
-{
- va_list ap;
- int i;
- char *buffer_start = buffer_out;
-
- va_start(ap, count);
- for (i = 0; i < count; ++i) {
- const char *path;
- int len;
-
- path = va_arg(ap, const char *);
-
- assert((i == 0) || path != buffer_start);
-
- if (i > 0 && *path == '/' && buffer_out > buffer_start && buffer_out[-1] == '/')
- path++;
-
- if (!*path)
- continue;
-
- len = strlen(path);
- memmove(buffer_out, path, len);
- buffer_out = buffer_out + len;
-
- if (i < count - 1 && buffer_out[-1] != '/')
- *buffer_out++ = '/';
- }
- va_end(ap);
-
- *buffer_out = '\0';
-}
-
char *git__strtok(char **end, const char *sep)
{
char *ptr = *end;
diff --git a/src/util.h b/src/util.h
index 999c3b8aa..eac615141 100644
--- a/src/util.h
+++ b/src/util.h
@@ -68,63 +68,9 @@ extern int git__suffixcmp(const char *str, const char *suffix);
extern int git__strtol32(long *n, const char *buff, const char **end_buf, int base);
-/*
- * The dirname() function shall take a pointer to a character string
- * that contains a pathname, and return a pointer to a string that is a
- * pathname of the parent directory of that file. Trailing '/' characters
- * in the path are not counted as part of the path.
- *
- * If path does not contain a '/', then dirname() shall return a pointer to
- * the string ".". If path is a null pointer or points to an empty string,
- * dirname() shall return a pointer to the string "." .
- *
- * The `git__dirname` implementation is thread safe. The returned
- * string must be manually free'd.
- *
- * The `git__dirname_r` implementation expects a string allocated
- * by the user with big enough size.
- */
-extern char *git__dirname(const char *path);
-extern int git__dirname_r(char *buffer, size_t bufflen, const char *path);
-
-/*
- * This function returns the basename of the file, which is the last
- * part of its full name given by fname, with the drive letter and
- * leading directories stripped off. For example, the basename of
- * c:/foo/bar/file.ext is file.ext, and the basename of a:foo is foo.
- *
- * Trailing slashes and backslashes are significant: the basename of
- * c:/foo/bar/ is an empty string after the rightmost slash.
- *
- * The `git__basename` implementation is thread safe. The returned
- * string must be manually free'd.
- *
- * The `git__basename_r` implementation expects a string allocated
- * by the user with big enough size.
- */
-extern char *git__basename(const char *path);
-extern int git__basename_r(char *buffer, size_t bufflen, const char *path);
-
-extern const char *git__topdir(const char *path);
-
-/**
- * Join two paths together. Takes care of properly fixing the
- * middle slashes and everything
- *
- * The paths are joined together into buffer_out; this is expected
- * to be an user allocated buffer of `GIT_PATH_MAX` size
- */
-extern void git__joinpath_n(char *buffer_out, int npath, ...);
-
-GIT_INLINE(void) git__joinpath(char *buffer_out, const char *path_a, const char *path_b)
-{
- git__joinpath_n(buffer_out, 2, path_a, path_b);
-}
-
extern void git__hexdump(const char *buffer, size_t n);
extern uint32_t git__hash(const void *key, int len, uint32_t seed);
-
/** @return true if p fits into the range of a size_t */
GIT_INLINE(int) git__is_sizet(git_off_t p)
{
diff --git a/src/win32/fileops.c b/src/win32/fileops.c
deleted file mode 100644
index d435e706e..000000000
--- a/src/win32/fileops.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#define GIT__WIN32_NO_HIDE_FILEOPS
-#include "fileops.h"
-#include <errno.h>
-
-int git__unlink(const char *path)
-{
- chmod(path, 0666);
- return unlink(path);
-}
-
-int git__mkstemp(char *template)
-{
- char *file = mktemp(template);
- if (file == NULL)
- return -1;
- return open(file, O_RDWR | O_CREAT | O_BINARY, 0600);
-}
-
-int git__fsync(int fd)
-{
- HANDLE fh = (HANDLE)_get_osfhandle(fd);
-
- if (fh == INVALID_HANDLE_VALUE) {
- errno = EBADF;
- return -1;
- }
-
- if (!FlushFileBuffers(fh)) {
- DWORD code = GetLastError();
-
- if (code == ERROR_INVALID_HANDLE)
- errno = EINVAL;
- else
- errno = EIO;
-
- return -1;
- }
-
- return 0;
-}
-
diff --git a/src/win32/map.c b/src/win32/map.c
index c7a39fcf6..76b926490 100644
--- a/src/win32/map.c
+++ b/src/win32/map.c
@@ -16,7 +16,7 @@ static DWORD get_page_size(void)
return page_size;
}
-int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
+int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
HANDLE fh = (HANDLE)_get_osfhandle(fd);
DWORD page_size = get_page_size();
@@ -92,7 +92,7 @@ int git__mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t o
return GIT_SUCCESS;
}
-int git__munmap(git_map *map)
+int p_munmap(git_map *map)
{
assert(map != NULL);
diff --git a/src/win32/posix.c b/src/win32/posix.c
new file mode 100644
index 000000000..003ce1fd6
--- /dev/null
+++ b/src/win32/posix.c
@@ -0,0 +1,191 @@
+#include "posix.h"
+#include <errno.h>
+
+int p_unlink(const char *path)
+{
+ chmod(path, 0666);
+ return unlink(path);
+}
+
+int p_fsync(int fd)
+{
+ HANDLE fh = (HANDLE)_get_osfhandle(fd);
+
+ if (fh == INVALID_HANDLE_VALUE) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (!FlushFileBuffers(fh)) {
+ DWORD code = GetLastError();
+
+ if (code == ERROR_INVALID_HANDLE)
+ errno = EINVAL;
+ else
+ errno = EIO;
+
+ return -1;
+ }
+
+ return 0;
+}
+
+GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
+{
+ long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
+ winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
+ winTime /= 10000000; /* Nano to seconds resolution */
+ return (time_t)winTime;
+}
+
+static int do_lstat(const char *file_name, struct stat *buf)
+{
+ WIN32_FILE_ATTRIBUTE_DATA fdata;
+
+ if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
+ int fMode = S_IREAD;
+
+ if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ fMode |= S_IFDIR;
+ else
+ fMode |= S_IFREG;
+
+ if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+ fMode |= S_IWRITE;
+
+ if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ fMode |= S_IFLNK;
+
+ buf->st_ino = 0;
+ buf->st_gid = 0;
+ buf->st_uid = 0;
+ buf->st_nlink = 1;
+ buf->st_mode = (mode_t)fMode;
+ buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
+ buf->st_dev = buf->st_rdev = (_getdrive() - 1);
+ buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
+ buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
+ buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
+ return GIT_SUCCESS;
+ }
+
+ switch (GetLastError()) {
+ case ERROR_ACCESS_DENIED:
+ case ERROR_SHARING_VIOLATION:
+ case ERROR_LOCK_VIOLATION:
+ case ERROR_SHARING_BUFFER_EXCEEDED:
+ return GIT_EOSERR;
+
+ case ERROR_BUFFER_OVERFLOW:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ return GIT_ENOMEM;
+
+ default:
+ return GIT_EINVALIDPATH;
+ }
+}
+
+int p_lstat(const char *file_name, struct stat *buf)
+{
+ int namelen, error;
+ char alt_name[GIT_PATH_MAX];
+
+ if ((error = do_lstat(file_name, buf)) == GIT_SUCCESS)
+ return GIT_SUCCESS;
+
+ /* if file_name ended in a '/', Windows returned ENOENT;
+ * try again without trailing slashes
+ */
+ if (error != GIT_EINVALIDPATH)
+ return git__throw(GIT_EOSERR, "Failed to lstat file");
+
+ namelen = strlen(file_name);
+ if (namelen && file_name[namelen-1] != '/')
+ return git__throw(GIT_EOSERR, "Failed to lstat file");
+
+ while (namelen && file_name[namelen-1] == '/')
+ --namelen;
+
+ if (!namelen || namelen >= GIT_PATH_MAX)
+ return git__throw(GIT_ENOMEM, "Failed to lstat file");
+
+ memcpy(alt_name, file_name, namelen);
+ alt_name[namelen] = 0;
+ return do_lstat(alt_name, buf);
+}
+
+int p_readlink(const char *link, char *target, size_t target_len)
+{
+ typedef DWORD (WINAPI *fpath_func)(HANDLE, LPTSTR, DWORD, DWORD);
+ static fpath_func pGetFinalPath = NULL;
+ HANDLE hFile;
+ DWORD dwRet;
+
+ /*
+ * Try to load the pointer to pGetFinalPath dynamically, because
+ * it is not available in platforms older than Vista
+ */
+ if (pGetFinalPath == NULL) {
+ HINSTANCE library = LoadLibrary("kernel32");
+
+ if (library != NULL)
+ pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleA");
+
+ if (pGetFinalPath == NULL)
+ return git__throw(GIT_EOSERR,
+ "'GetFinalPathNameByHandleA' is not available in this platform");
+ }
+
+ hFile = CreateFile(link, // file to open
+ GENERIC_READ, // open for reading
+ FILE_SHARE_READ, // share for reading
+ NULL, // default security
+ OPEN_EXISTING, // existing file only
+ FILE_FLAG_BACKUP_SEMANTICS, // normal file
+ NULL); // no attr. template
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return GIT_EOSERR;
+
+ dwRet = pGetFinalPath(hFile, target, target_len, 0x0);
+ if (dwRet >= target_len)
+ return GIT_ENOMEM;
+
+ CloseHandle(hFile);
+
+ if (dwRet > 4) {
+ /* Skip first 4 characters if they are "\\?\" */
+ if (target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') {
+ char tmp[GIT_PATH_MAX];
+ unsigned int offset = 4;
+ dwRet -= 4;
+
+ /* \??\UNC\ */
+ if (dwRet > 7 && target[4] == 'U' && target[5] == 'N' && target[6] == 'C') {
+ offset += 2;
+ dwRet -= 2;
+ target[offset] = '\\';
+ }
+
+ memcpy(tmp, target + offset, dwRet);
+ memcpy(target, tmp, dwRet);
+ }
+ }
+
+ target[dwRet] = '\0';
+ return dwRet;
+}
+
+int p_hide_directory__w32(const char *path)
+{
+ int error;
+
+ error = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN) != 0 ?
+ GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
+
+ if (error < GIT_SUCCESS)
+ error = git__throw(GIT_EOSERR, "Failed to hide directory '%s'", path);
+
+ return error;
+}
+
diff --git a/src/win32/posix.h b/src/win32/posix.h
new file mode 100644
index 000000000..31ee7201c
--- /dev/null
+++ b/src/win32/posix.h
@@ -0,0 +1,25 @@
+#ifndef INCLUDE_posix__w32_h__
+#define INCLUDE_posix__w32_h__
+
+#include "common.h"
+
+GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
+{
+ GIT_UNUSED_ARG(old)
+ GIT_UNUSED_ARG(new)
+ errno = ENOSYS;
+ return -1;
+}
+
+GIT_INLINE(int) p_mkdir(const char *path, int GIT_UNUSED(mode))
+{
+ GIT_UNUSED_ARG(mode)
+ return mkdir(path);
+}
+
+extern int p_unlink(const char *path);
+extern int p_lstat(const char *file_name, struct stat *buf);
+extern int p_readlink(const char *link, char *target, size_t target_len);
+extern int p_hide_directory__w32(const char *path);
+
+#endif