diff options
author | Vicent Marti <tanoku@gmail.com> | 2011-07-04 11:43:34 +0200 |
---|---|---|
committer | Vicent Marti <tanoku@gmail.com> | 2011-07-05 02:04:03 +0200 |
commit | f79026b4912bcd2336667f4c1663c06e233f0b32 (patch) | |
tree | 645b776032e924b587fad986aa3f3dc08c98d4c5 /src | |
parent | 678e9e045becdc5d75f2ce2259ed01c3531ee181 (diff) | |
download | libgit2-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.c | 16 | ||||
-rw-r--r-- | src/config.c | 4 | ||||
-rw-r--r-- | src/config_file.c | 12 | ||||
-rw-r--r-- | src/filebuf.c | 34 | ||||
-rw-r--r-- | src/fileops.c | 417 | ||||
-rw-r--r-- | src/fileops.h | 205 | ||||
-rw-r--r-- | src/index.c | 18 | ||||
-rw-r--r-- | src/map.h | 6 | ||||
-rw-r--r-- | src/odb.c | 12 | ||||
-rw-r--r-- | src/odb_loose.c | 30 | ||||
-rw-r--r-- | src/odb_pack.c | 58 | ||||
-rw-r--r-- | src/path.c | 204 | ||||
-rw-r--r-- | src/path.h | 76 | ||||
-rw-r--r-- | src/posix.c | 74 | ||||
-rw-r--r-- | src/posix.h | 54 | ||||
-rw-r--r-- | src/refs.c | 86 | ||||
-rw-r--r-- | src/repository.c | 82 | ||||
-rw-r--r-- | src/tag.c | 2 | ||||
-rw-r--r-- | src/tree.c | 2 | ||||
-rw-r--r-- | src/unix/map.c | 4 | ||||
-rw-r--r-- | src/unix/posix.h | 14 | ||||
-rw-r--r-- | src/util.c | 200 | ||||
-rw-r--r-- | src/util.h | 54 | ||||
-rw-r--r-- | src/win32/fileops.c | 41 | ||||
-rw-r--r-- | src/win32/map.c | 4 | ||||
-rw-r--r-- | src/win32/posix.c | 191 | ||||
-rw-r--r-- | src/win32/posix.h | 25 |
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) @@ -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__ */ @@ -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); @@ -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 |