summaryrefslogtreecommitdiff
path: root/src/fileops.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fileops.c')
-rw-r--r--src/fileops.c417
1 files changed, 79 insertions, 338 deletions
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