Commit deafee7b by Russell Belfer

Continue error conversion

This converts blob.c, fileops.c, and all of the win32 files.
Also, various minor cleanups throughout the code.  Plus, in
testing the win32 build, I cleaned up a bunch (although not
all) of the warnings with the 64-bit build.
parent ab43ad2f
......@@ -42,7 +42,7 @@ int git_blob__parse(git_blob *blob, git_odb_object *odb_obj)
assert(blob);
git_cached_obj_incref((git_cached_obj *)odb_obj);
blob->odb_object = odb_obj;
return GIT_SUCCESS;
return 0;
}
int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len)
......@@ -51,58 +51,50 @@ int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *b
git_odb *odb;
git_odb_stream *stream;
error = git_repository_odb__weakptr(&odb, repo);
if (error < GIT_SUCCESS)
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
(error = git_odb_open_wstream(&stream, odb, len, GIT_OBJ_BLOB)) < 0)
return error;
if ((error = git_odb_open_wstream(&stream, odb, len, GIT_OBJ_BLOB)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to create blob");
if ((error = stream->write(stream, buffer, len)) == 0)
error = stream->finalize_write(oid, stream);
if ((error = stream->write(stream, buffer, len)) < GIT_SUCCESS) {
stream->free(stream);
return error;
}
error = stream->finalize_write(oid, stream);
stream->free(stream);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to create blob");
return GIT_SUCCESS;
}
static int write_file_stream(git_oid *oid, git_odb *odb, const char *path, git_off_t file_size)
static int write_file_stream(
git_oid *oid, git_odb *odb, const char *path, git_off_t file_size)
{
int fd, error;
char buffer[4096];
git_odb_stream *stream = NULL;
if ((error = git_odb_open_wstream(&stream, odb, (size_t)file_size, GIT_OBJ_BLOB)) < GIT_SUCCESS)
if ((error = git_odb_open_wstream(
&stream, odb, (size_t)file_size, GIT_OBJ_BLOB)) < 0)
return error;
if ((fd = p_open(path, O_RDONLY)) < 0) {
error = git__throw(GIT_ENOTFOUND, "Failed to create blob. Could not open '%s'", path);
goto cleanup;
if ((fd = git_futils_open_ro(path)) < 0) {
stream->free(stream);
return -1;
}
while (file_size > 0) {
while (!error && file_size > 0) {
ssize_t read_len = p_read(fd, buffer, sizeof(buffer));
if (read_len < 0) {
error = git__throw(GIT_EOSERR, "Failed to create blob. Can't read full file");
p_close(fd);
goto cleanup;
giterr_set(
GITERR_OS, "Failed to create blob. Can't read whole file");
error = -1;
}
stream->write(stream, buffer, read_len);
else if (!(error = stream->write(stream, buffer, read_len)))
file_size -= read_len;
}
p_close(fd);
if (!error)
error = stream->finalize_write(oid, stream);
cleanup:
stream->free(stream);
return error;
}
......@@ -117,8 +109,7 @@ static int write_file_filtered(
git_buf source = GIT_BUF_INIT;
git_buf dest = GIT_BUF_INIT;
error = git_futils_readbuffer(&source, full_path);
if (error < GIT_SUCCESS)
if ((error = git_futils_readbuffer(&source, full_path)) < 0)
return error;
error = git_filters_apply(&dest, &source, filters);
......@@ -127,30 +118,29 @@ static int write_file_filtered(
* and we don't want to ODB write to choke */
git_buf_free(&source);
if (error == GIT_SUCCESS) {
/* Write the file to disk if it was properly filtered */
if (!error)
error = git_odb_write(oid, odb, dest.ptr, dest.size, GIT_OBJ_BLOB);
}
git_buf_free(&dest);
return GIT_SUCCESS;
return error;
}
static int write_symlink(git_oid *oid, git_odb *odb, const char *path, size_t link_size)
static int write_symlink(
git_oid *oid, git_odb *odb, const char *path, size_t link_size)
{
char *link_data;
ssize_t read_len;
int error;
link_data = git__malloc(link_size);
if (!link_data)
return GIT_ENOMEM;
GITERR_CHECK_ALLOC(link_data);
read_len = p_readlink(path, link_data, link_size);
if (read_len != (ssize_t)link_size) {
giterr_set(GITERR_OS, "Failed to create blob. Can't read symlink '%s'", path);
free(link_data);
return git__throw(GIT_EOSERR, "Failed to create blob. Can't read symlink");
return -1;
}
error = git_odb_write(oid, odb, (void *)link_data, link_size, GIT_OBJ_BLOB);
......@@ -168,25 +158,18 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
git_odb *odb = NULL;
workdir = git_repository_workdir(repo);
if (workdir == NULL)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. (No working directory found)");
assert(workdir); /* error to call this on bare repo */
error = git_buf_joinpath(&full_path, workdir, path);
if (error < GIT_SUCCESS)
if ((error = git_buf_joinpath(&full_path, workdir, path)) < 0 ||
(error = git_path_lstat(full_path.ptr, &st)) < 0 ||
(error = git_repository_odb__weakptr(&odb, repo)) < 0)
{
git_buf_free(&full_path);
return error;
error = p_lstat(full_path.ptr, &st);
if (error < 0) {
error = git__throw(GIT_EOSERR, "Failed to stat blob. %s", strerror(errno));
goto cleanup;
}
size = st.st_size;
error = git_repository_odb__weakptr(&odb, repo);
if (error < GIT_SUCCESS)
goto cleanup;
if (S_ISLNK(st.st_mode)) {
error = write_symlink(oid, odb, full_path.ptr, (size_t)size);
} else {
......@@ -194,12 +177,12 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
int filter_count;
/* Load the filters for writing this file to the ODB */
filter_count = git_filters_load(&write_filters, repo, path, GIT_FILTER_TO_ODB);
filter_count = git_filters_load(
&write_filters, repo, path, GIT_FILTER_TO_ODB);
if (filter_count < 0) {
/* Negative value means there was a critical error */
error = filter_count;
goto cleanup;
} else if (filter_count == 0) {
/* No filters need to be applied to the document: we can stream
* directly from disk */
......@@ -212,19 +195,20 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
git_filters_free(&write_filters);
/*
* TODO: eventually support streaming filtered files, for files which are bigger
* than a given threshold. This is not a priority because applying a filter in
* streaming mode changes the final size of the blob, and without knowing its
* final size, the blob cannot be written in stream mode to the ODB.
* TODO: eventually support streaming filtered files, for files
* which are bigger than a given threshold. This is not a priority
* because applying a filter in streaming mode changes the final
* size of the blob, and without knowing its final size, the blob
* cannot be written in stream mode to the ODB.
*
* The plan is to do streaming writes to a tempfile on disk and then opening
* streaming that file to the ODB, using `write_file_stream`.
* The plan is to do streaming writes to a tempfile on disk and then
* opening streaming that file to the ODB, using
* `write_file_stream`.
*
* CAREFULLY DESIGNED APIS YO
*/
}
cleanup:
git_buf_free(&full_path);
return error;
}
......
......@@ -215,8 +215,8 @@ void git_buf_truncate(git_buf *buf, size_t len)
void git_buf_rtruncate_at_char(git_buf *buf, char separator)
{
int idx = git_buf_rfind_next(buf, separator);
git_buf_truncate(buf, idx < 0 ? 0 : idx);
ssize_t idx = git_buf_rfind_next(buf, separator);
git_buf_truncate(buf, idx < 0 ? 0 : (size_t)idx);
}
void git_buf_swap(git_buf *buf_a, git_buf *buf_b)
......
......@@ -102,9 +102,9 @@ void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf);
#define git_buf_PUTS(buf, str) git_buf_put(buf, str, sizeof(str) - 1)
GIT_INLINE(int) git_buf_rfind_next(git_buf *buf, char ch)
GIT_INLINE(ssize_t) git_buf_rfind_next(git_buf *buf, char ch)
{
int idx = buf->size - 1;
ssize_t idx = (ssize_t)buf->size - 1;
while (idx >= 0 && buf->ptr[idx] == ch) idx--;
while (idx >= 0 && buf->ptr[idx] != ch) idx--;
return idx;
......
......@@ -79,11 +79,25 @@ int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, con
return git_futils_creat_locked(path, mode);
}
int git_futils_open_ro(const char *path)
{
int fd = p_open(path, O_RDONLY);
if (fd < 0) {
if (errno == ENOENT)
fd = GIT_ENOTFOUND;
giterr_set(GITERR_OS, "Failed to open '%s'", path);
}
return fd;
}
git_off_t git_futils_filesize(git_file fd)
{
struct stat sb;
if (p_fstat(fd, &sb))
return GIT_ERROR;
if (p_fstat(fd, &sb)) {
giterr_set(GITERR_OS, "Failed to stat file descriptor");
return -1;
}
return sb.st_size;
}
......@@ -176,10 +190,15 @@ int git_futils_readbuffer(git_buf *buf, const char *path)
int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode)
{
if (git_futils_mkpath2file(to, dirmode) < GIT_SUCCESS)
return GIT_EOSERR; /* The callee already takes care of setting the correct error message. */
if (git_futils_mkpath2file(to, dirmode) < 0)
return -1;
if (p_rename(from, to) < 0) {
giterr_set(GITERR_OS, "Failed to rename '%s' to '%s'", from, to);
return -1;
}
return p_rename(from, to); /* The callee already takes care of setting the correct error message. */
return 0;
}
int git_futils_mmap_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
......@@ -192,8 +211,10 @@ int git_futils_mmap_ro_file(git_map *out, const char *path)
git_file fd = p_open(path, O_RDONLY /* | O_NOATIME */);
git_off_t len = git_futils_filesize(fd);
int result;
if (!git__is_sizet(len))
return git__throw(GIT_ERROR, "File `%s` too large to mmap", path);
if (!git__is_sizet(len)) {
giterr_set(GITERR_OS, "File `%s` too large to mmap", path);
return -1;
}
result = git_futils_mmap_ro(out, fd, 0, (size_t)len);
p_close(fd);
return result;
......@@ -260,20 +281,31 @@ int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)
static int _rmdir_recurs_foreach(void *opaque, git_buf *path)
{
int error = GIT_SUCCESS;
int force = *(int *)opaque;
if (git_path_isdir(path->ptr) == true) {
error = git_path_direach(path, _rmdir_recurs_foreach, opaque);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to remove directory `%s`", path->ptr);
return p_rmdir(path->ptr);
if (git_path_direach(path, _rmdir_recurs_foreach, opaque) < 0)
return -1;
if (p_rmdir(path->ptr) < 0) {
giterr_set(GITERR_OS, "Could not remove directory '%s'", path->ptr);
return -1;
}
} else if (force) {
return p_unlink(path->ptr);
return 0;
}
if (force) {
if (p_unlink(path->ptr) < 0) {
giterr_set(GITERR_OS, "Could not remove directory. File '%s' cannot be removed", path->ptr);
return -1;
}
return git__rethrow(error, "Failed to remove directory. `%s` is not empty", path->ptr);
return 0;
}
giterr_set(GITERR_OS, "Could not remove directory. File '%s' still present", path->ptr);
return -1;
}
int git_futils_rmdir_r(const char *path, int force)
......@@ -282,7 +314,7 @@ int git_futils_rmdir_r(const char *path, int force)
git_buf p = GIT_BUF_INIT;
error = git_buf_sets(&p, path);
if (error == GIT_SUCCESS)
if (!error)
error = _rmdir_recurs_foreach(&force, &p);
git_buf_free(&p);
return error;
......@@ -328,9 +360,8 @@ static const win32_path *win32_system_root(void)
const wchar_t *root_tmpl = L"%PROGRAMFILES%\\Git\\etc\\";
s_root.len = ExpandEnvironmentStringsW(root_tmpl, NULL, 0);
if (s_root.len <= 0) {
git__throw(GIT_EOSERR, "Failed to expand environment strings");
giterr_set(GITERR_OS, "Failed to expand environment strings");
return NULL;
}
......@@ -339,7 +370,7 @@ static const win32_path *win32_system_root(void)
return NULL;
if (ExpandEnvironmentStringsW(root_tmpl, s_root.path, s_root.len) != s_root.len) {
git__throw(GIT_EOSERR, "Failed to expand environment strings");
giterr_set(GITERR_OS, "Failed to expand environment strings");
git__free(s_root.path);
s_root.path = NULL;
return NULL;
......@@ -351,7 +382,7 @@ static const win32_path *win32_system_root(void)
static int win32_find_system_file(git_buf *path, const char *filename)
{
int error = GIT_SUCCESS;
int error = 0;
const win32_path *root = win32_system_root();
size_t len;
wchar_t *file_utf16 = NULL, *scan;
......@@ -362,8 +393,7 @@ static int win32_find_system_file(git_buf *path, const char *filename)
/* allocate space for wchar_t path to file */
file_utf16 = git__calloc(root->len + len + 2, sizeof(wchar_t));
if (!file_utf16)
return GIT_ENOMEM;
GITERR_CHECK_ALLOC(file_utf16);
/* append root + '\\' + filename as wchar_t */
memcpy(file_utf16, root->path, root->len * sizeof(wchar_t));
......@@ -373,7 +403,7 @@ static int win32_find_system_file(git_buf *path, const char *filename)
if (gitwin_append_utf16(file_utf16 + root->len - 1, filename, len + 1) !=
(int)len + 1) {
error = git__throw(GIT_EOSERR, "Failed to build file path");
error = -1;
goto cleanup;
}
......@@ -389,9 +419,8 @@ static int win32_find_system_file(git_buf *path, const char *filename)
/* convert to utf8 */
if ((file_utf8 = gitwin_from_utf16(file_utf16)) == NULL)
error = GIT_ENOMEM;
if (file_utf8) {
error = -1;
else {
git_path_mkposix(file_utf8);
git_buf_attach(path, file_utf8, 0);
}
......@@ -409,7 +438,7 @@ int git_futils_find_system_file(git_buf *path, const char *filename)
return -1;
if (git_path_exists(path->ptr) == true)
return GIT_SUCCESS;
return 0;
git_buf_clear(path);
......
......@@ -77,18 +77,9 @@ extern int git_futils_mktmp(git_buf *path_out, const char *filename);
extern int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode);
/**
* Open a file readonly and set error if needed
*/
GIT_INLINE(int) git_futils_open_ro(const char *path)
{
int fd = p_open(path, O_RDONLY);
if (fd < 0) {
if (errno == ENOENT)
fd = GIT_ENOTFOUND;
giterr_set(GITERR_OS, "Failed to open '%s'", path);
}
return fd;
}
* Open a file readonly and set error if needed.
*/
extern int git_futils_open_ro(const char *path);
/**
* Get the filesize in bytes of a file
......
......@@ -258,5 +258,10 @@ uint32_t git_hash__strhash_cb(const void *key, int hash_id)
0x7daaab3c
};
return git__hash(key, strlen((const char *)key), hash_seeds[hash_id]);
size_t key_len = strlen((const char *)key);
/* won't take hash of strings longer than 2^31 right now */
assert(key_len == (size_t)((int)key_len));
return git__hash(key, (int)key_len, hash_seeds[hash_id]);
}
......@@ -66,7 +66,7 @@ GIT_INLINE(int) git_hashtable_insert(git_hashtable *h, const void *key, void *va
#define git_hashtable_node_at(nodes, pos) ((git_hashtable_node *)(&nodes[pos]))
#define GIT_HASHTABLE__FOREACH(self,block) { \
unsigned int _c; \
size_t _c; \
git_hashtable_node *_n = (self)->nodes; \
for (_c = (self)->size; _c > 0; _c--, _n++) { \
if (!_n->key) continue; block } }
......
......@@ -319,8 +319,7 @@ static int index_entry_init(git_index_entry **entry_out, git_index *index, const
if (error < GIT_SUCCESS)
return error;
if (p_lstat(full_path.ptr, &st) < 0) {
error = git__throw(GIT_ENOTFOUND, "Failed to initialize entry. '%s' cannot be opened. %s", full_path.ptr, strerror(errno));
if ((error = git_path_lstat(full_path.ptr, &st)) < 0) {
git_buf_free(&full_path);
return error;
}
......
......@@ -133,12 +133,15 @@ int git_indexer_new(git_indexer **out, const char *packname)
idx->nr_objects = ntohl(idx->hdr.hdr_entries);
error = git_vector_init(&idx->pack->cache, idx->nr_objects, cache_cmp);
/* for now, limit to 2^32 objects */
assert(idx->nr_objects == (size_t)((unsigned int)idx->nr_objects));
error = git_vector_init(&idx->pack->cache, (unsigned int)idx->nr_objects, cache_cmp);
if (error < GIT_SUCCESS)
goto cleanup;
idx->pack->has_cache = 1;
error = git_vector_init(&idx->objects, idx->nr_objects, objects_cmp);
error = git_vector_init(&idx->objects, (unsigned int)idx->nr_objects, objects_cmp);
if (error < GIT_SUCCESS)
goto cleanup;
......@@ -319,7 +322,7 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to register mwindow file");
stats->total = idx->nr_objects;
stats->total = (unsigned int)idx->nr_objects;
stats->processed = processed = 0;
while (processed < idx->nr_objects) {
......@@ -375,7 +378,7 @@ int git_indexer_run(git_indexer *idx, git_indexer_stats *stats)
error = git__rethrow(error, "Failed to open window to read packed data");
goto cleanup;
}
entry->crc = htonl(crc32(entry->crc, packed, entry_size));
entry->crc = htonl(crc32(entry->crc, packed, (uInt)entry_size));
git_mwindow_close(&w);
/* Add the object to the list */
......
......@@ -309,7 +309,7 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi)
/* only push new ignores if this is not top level directory */
if (wi->stack->next != NULL) {
int slash_pos = git_buf_rfind_next(&wi->path, '/');
ssize_t slash_pos = git_buf_rfind_next(&wi->path, '/');
(void)git_ignore__push_dir(&wi->ignores, &wi->path.ptr[slash_pos + 1]);
}
......
......@@ -203,7 +203,7 @@ unsigned char *git_mwindow_open(
git_mwindow_file *mwf,
git_mwindow **cursor,
git_off_t offset,
int extra,
size_t extra,
unsigned int *left)
{
git_mwindow_ctl *ctl = &GIT_GLOBAL->mem_ctl;
......
......@@ -15,8 +15,8 @@ typedef struct git_mwindow {
struct git_mwindow *next;
git_map window_map;
git_off_t offset;
unsigned int last_used;
unsigned int inuse_cnt;
size_t last_used;
size_t inuse_cnt;
} git_mwindow;
typedef struct git_mwindow_file {
......@@ -37,7 +37,7 @@ typedef struct git_mwindow_ctl {
int git_mwindow_contains(git_mwindow *win, git_off_t offset);
void git_mwindow_free_all(git_mwindow_file *mwf);
unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, git_off_t offset, int extra, unsigned int *left);
unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, git_off_t offset, size_t extra, unsigned int *left);
void git_mwindow_scan_lru(git_mwindow_file *mwf, git_mwindow **lru_w, git_mwindow **lru_l);
int git_mwindow_file_register(git_mwindow_file *mwf);
void git_mwindow_close(git_mwindow **w_cursor);
......
......@@ -145,10 +145,8 @@ int git_odb__hashlink(git_oid *out, const char *path)
git_off_t size;
int result;
if (p_lstat(path, &st) < 0) {
giterr_set(GITERR_OS, "Failed to stat object '%s'", path);
if (git_path_lstat(path, &st) < 0)
return -1;
}
size = st.st_size;
......
......@@ -49,7 +49,8 @@ int git_path_basename_r(git_buf *buffer, const char *path)
while (startp > path && *(startp - 1) != '/')
startp--;
len = endp - startp +1;
/* Cast is safe because max path < max int */
len = (int)(endp - startp + 1);
Exit:
result = len;
......@@ -96,7 +97,8 @@ int git_path_dirname_r(git_buf *buffer, const char *path)
endp--;
} while (endp > path && *endp == '/');
len = endp - path +1;
/* Cast is safe because max path < max int */
len = (int)(endp - path + 1);
#ifdef GIT_WIN32
/* Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return
......@@ -146,7 +148,7 @@ char *git_path_basename(const char *path)
const char *git_path_topdir(const char *path)
{
size_t len;
int i;
ssize_t i;
assert(path);
len = strlen(path);
......@@ -154,7 +156,7 @@ const char *git_path_topdir(const char *path)
if (!len || path[len - 1] != '/')
return NULL;
for (i = len - 2; i >= 0; --i)
for (i = (ssize_t)len - 2; i >= 0; --i)
if (path[i] == '/')
break;
......@@ -235,7 +237,7 @@ int git__percent_decode(git_buf *decoded_out, const char *input)
int len, hi, lo, i;
assert(decoded_out && input);
len = strlen(input);
len = (int)strlen(input);
git_buf_clear(decoded_out);
for(i = 0; i < len; i++)
......@@ -281,7 +283,7 @@ int git_path_fromurl(git_buf *local_path_out, const char *file_url)
return error_invalid_local_file_uri(file_url);
offset += 7;
len = strlen(file_url);
len = (int)strlen(file_url);
if (offset < len && file_url[offset] == '/')
offset++;
......@@ -381,6 +383,18 @@ bool git_path_isfile(const char *path)
return S_ISREG(st.st_mode) != 0;
}
int git_path_lstat(const char *path, struct stat *st)
{
int err = 0;
if (p_lstat(path, st) < 0) {
err = (errno == ENOENT) ? GIT_ENOTFOUND : -1;
giterr_set(GITERR_OS, "Failed to stat file '%s'", path);
}
return err;
}
static bool _check_dir_contents(
git_buf *dir,
const char *sub,
......@@ -600,16 +614,9 @@ int git_path_dirload_with_stat(
memmove(ps->path, ps, path_len + 1);
ps->path_len = path_len;
if (git_buf_joinpath(&full, full.ptr, ps->path) < 0) {
error = -1;
if ((error = git_buf_joinpath(&full, full.ptr, ps->path)) < 0 ||
(error = git_path_lstat(full.ptr, &ps->st)) < 0)
break;
}
if (p_lstat(full.ptr, &ps->st) < 0) {
giterr_set(GITERR_OS, "Failed to stat file '%s'", full.ptr);
error = -1;
break;
}
git_buf_truncate(&full, prefix_len);
......
......@@ -130,6 +130,11 @@ extern bool git_path_isdir(const char *path);
extern bool git_path_isfile(const char *path);
/**
* Stat a file and/or link and set error if needed.
*/
extern int git_path_lstat(const char *path, struct stat *st);
/**
* Check if the parent directory contains the item.
*
* @param dir Directory to check.
......
......@@ -34,9 +34,9 @@ int p_getcwd(char *buffer_out, size_t size)
return -1;
git_path_mkposix(buffer_out);
git_path_string_to_dir(buffer_out, size); //Ensure the path ends with a trailing slash
git_path_string_to_dir(buffer_out, size); /* append trailing slash */
return GIT_SUCCESS;
return 0;
}
int p_rename(const char *from, const char *to)
......
......@@ -377,17 +377,15 @@ void git_repository_set_index(git_repository *repo, git_index *index)
static int retrieve_device(dev_t *device_out, const char *path)
{
int error;
struct stat path_info;
assert(device_out);
if (p_lstat(path, &path_info)) {
giterr_set(GITERR_OS, "Failed to retrieve file information: %s", strerror(errno));
return -1;
}
if ((error = git_path_lstat(path, &path_info)) == 0)
*device_out = path_info.st_dev;
return 0;
return error;
}
/*
......
......@@ -27,8 +27,8 @@ static int init_filter(char *filter, size_t n, const char *dir)
git__DIR *git__opendir(const char *dir)
{
char filter[4096];
wchar_t* filter_w;
git__DIR *new;
wchar_t* filter_w = NULL;
git__DIR *new = NULL;
if (!dir || !init_filter(filter, sizeof(filter), dir))
return NULL;
......@@ -37,25 +37,29 @@ git__DIR *git__opendir(const char *dir)
if (!new)
return NULL;
new->dir = git__malloc(strlen(dir)+1);
if (!new->dir) {
git__free(new);
return NULL;
}
strcpy(new->dir, dir);
new->dir = git__strdup(dir);
if (!new->dir)
goto fail;
filter_w = gitwin_to_utf16(filter);
if (!filter_w)
goto fail;
new->h = FindFirstFileW(filter_w, &new->f);
git__free(filter_w);
if (new->h == INVALID_HANDLE_VALUE) {
git__free(new->dir);
git__free(new);
return NULL;
giterr_set(GITERR_OS, "Could not open directory '%s'", dir);
goto fail;
}
new->first = 1;
new->first = 1;
return new;
fail:
git__free(new->dir);
git__free(new);
return NULL;
}
int git__readdir_ext(
......@@ -67,22 +71,32 @@ int git__readdir_ext(
if (!d || !entry || !result || d->h == INVALID_HANDLE_VALUE)
return -1;
*result = NULL;
if (d->first)
d->first = 0;
else if (!FindNextFileW(d->h, &d->f)) {
*result = NULL;
if (GetLastError() == ERROR_NO_MORE_FILES)
return 0;
giterr_set(GITERR_OS, "Could not read from directory '%s'", d->dir);
return -1;
}
if (wcslen(d->f.cFileName) >= sizeof(entry->d_name))
return -1;
entry->d_ino = 0;
WideCharToMultiByte(
if (WideCharToMultiByte(
gitwin_get_codepage(), 0, d->f.cFileName, -1,
entry->d_name, GIT_PATH_MAX, NULL, NULL);
entry->d_name, GIT_PATH_MAX, NULL, NULL) == 0)
{
giterr_set(GITERR_OS, "Could not convert filename to UTF-8");
return -1;
}
*result = entry;
if (is_dir != NULL)
*is_dir = ((d->f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
......@@ -102,32 +116,40 @@ void git__rewinddir(git__DIR *d)
char filter[4096];
wchar_t* filter_w;
if (d) {
if (d->h != INVALID_HANDLE_VALUE)
if (!d)
return;
if (d->h != INVALID_HANDLE_VALUE) {
FindClose(d->h);
d->h = INVALID_HANDLE_VALUE;
d->first = 0;
}
if (!init_filter(filter, sizeof(filter), d->dir) ||
(filter_w = gitwin_to_utf16(filter)) == NULL)
return;
if (init_filter(filter, sizeof(filter), d->dir)) {
filter_w = gitwin_to_utf16(filter);
d->h = FindFirstFileW(filter_w, &d->f);
git__free(filter_w);
if (d->h != INVALID_HANDLE_VALUE)
if (d->h == INVALID_HANDLE_VALUE)
giterr_set(GITERR_OS, "Could not open directory '%s'", d->dir);
else
d->first = 1;
}
}
}
int git__closedir(git__DIR *d)
{
if (d) {
if (d->h != INVALID_HANDLE_VALUE)
if (!d)
return 0;
if (d->h != INVALID_HANDLE_VALUE) {
FindClose(d->h);
if (d->dir)
d->h = INVALID_HANDLE_VALUE;
}
git__free(d->dir);
d->dir = NULL;
git__free(d);
}
return 0;
}
......@@ -17,10 +17,11 @@ int p_unlink(const char *path)
int ret = 0;
wchar_t* buf;
buf = gitwin_to_utf16(path);
if ((buf = gitwin_to_utf16(path)) != NULL) {
_wchmod(buf, 0666);
ret = _wunlink(buf);
git__free(buf);
}
return ret;
}
......@@ -60,6 +61,8 @@ static int do_lstat(const char *file_name, struct stat *buf)
{
WIN32_FILE_ATTRIBUTE_DATA fdata;
wchar_t* fbuf = gitwin_to_utf16(file_name);
if (!fbuf)
return -1;
if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) {
int fMode = S_IREAD;
......@@ -87,54 +90,43 @@ static int do_lstat(const char *file_name, struct stat *buf)
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
git__free(fbuf);
return GIT_SUCCESS;
return 0;
}
git__free(fbuf);
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;
}
return -1;
}
int p_lstat(const char *file_name, struct stat *buf)
{
int namelen, error;
char alt_name[GIT_PATH_MAX];
int error;
size_t namelen;
char *alt_name;
if ((error = do_lstat(file_name, buf)) == GIT_SUCCESS)
return GIT_SUCCESS;
if (do_lstat(file_name, buf) == 0)
return 0;
/* 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");
return -1;
while (namelen && file_name[namelen-1] == '/')
--namelen;
if (!namelen || namelen >= GIT_PATH_MAX)
return git__throw(GIT_ENOMEM, "Failed to lstat file");
if (!namelen)
return -1;
alt_name = git__strndup(file_name, namelen);
if (!alt_name)
return -1;
error = do_lstat(alt_name, buf);
memcpy(alt_name, file_name, namelen);
alt_name[namelen] = 0;
return do_lstat(alt_name, buf);
git__free(alt_name);
return error;
}
int p_readlink(const char *link, char *target, size_t target_len)
......@@ -145,6 +137,9 @@ int p_readlink(const char *link, char *target, size_t target_len)
DWORD dwRet;
wchar_t* link_w;
wchar_t* target_w;
int error = 0;
assert(link && target && target_len > 0);
/*
* Try to load the pointer to pGetFinalPath dynamically, because
......@@ -156,12 +151,15 @@ int p_readlink(const char *link, char *target, size_t target_len)
if (library != NULL)
pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleW");
if (pGetFinalPath == NULL)
return git__throw(GIT_EOSERR,
if (pGetFinalPath == NULL) {
giterr_set(GITERR_OS,
"'GetFinalPathNameByHandleW' is not available in this platform");
return -1;
}
}
link_w = gitwin_to_utf16(link);
GITERR_CHECK_ALLOC(link_w);
hFile = CreateFileW(link_w, // file to open
GENERIC_READ, // open for reading
......@@ -173,50 +171,49 @@ int p_readlink(const char *link, char *target, size_t target_len)
git__free(link_w);
if (hFile == INVALID_HANDLE_VALUE)
return GIT_EOSERR;
if (target_len <= 0) {
return GIT_EINVALIDARGS;
if (hFile == INVALID_HANDLE_VALUE) {
giterr_set(GITERR_OS, "Cannot open '%s' for reading", link);
return -1;
}
target_w = (wchar_t*)git__malloc(target_len * sizeof(wchar_t));
GITERR_CHECK_ALLOC(target_w);
dwRet = pGetFinalPath(hFile, target_w, target_len, 0x0);
if (dwRet >= target_len) {
git__free(target_w);
CloseHandle(hFile);
return GIT_ENOMEM;
}
if (!WideCharToMultiByte(CP_UTF8, 0, target_w, -1, target, target_len * sizeof(char), NULL, NULL)) {
git__free(target_w);
return GIT_EOSERR;
}
if (dwRet == 0 ||
dwRet >= target_len ||
!WideCharToMultiByte(CP_UTF8, 0, target_w, -1, target,
target_len * sizeof(char), NULL, NULL))
error = -1;
git__free(target_w);
CloseHandle(hFile);
if (dwRet > 4) {
if (error)
return error;
/* Skip first 4 characters if they are "\\?\" */
if (target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') {
char tmp[GIT_PATH_MAX];
if (dwRet > 4 &&
target[0] == '\\' && target[1] == '\\' &&
target[2] == '?' && target[3] == '\\')
{
unsigned int offset = 4;
dwRet -= 4;
/* \??\UNC\ */
if (dwRet > 7 && target[4] == 'U' && target[5] == 'N' && target[6] == 'C') {
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);
}
memmove(target, target + offset, dwRet);
}
target[dwRet] = '\0';
return dwRet;
}
......@@ -224,8 +221,9 @@ int p_open(const char *path, int flags)
{
int fd;
wchar_t* buf = gitwin_to_utf16(path);
if (!buf)
return -1;
fd = _wopen(buf, flags | _O_BINARY);
git__free(buf);
return fd;
}
......@@ -234,8 +232,9 @@ int p_creat(const char *path, mode_t mode)
{
int fd;
wchar_t* buf = gitwin_to_utf16(path);
if (!buf)
return -1;
fd = _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode);
git__free(buf);
return fd;
}
......@@ -243,15 +242,15 @@ int p_creat(const char *path, mode_t mode)
int p_getcwd(char *buffer_out, size_t size)
{
wchar_t* buf = (wchar_t*)git__malloc(sizeof(wchar_t) * (int)size);
int ret;
_wgetcwd(buf, (int)size);
if (!WideCharToMultiByte(CP_UTF8, 0, buf, -1, buffer_out, size, NULL, NULL)) {
git__free(buf);
return GIT_EOSERR;
}
ret = WideCharToMultiByte(
CP_UTF8, 0, buf, -1, buffer_out, size, NULL, NULL);
git__free(buf);
return GIT_SUCCESS;
return !ret ? -1 : 0;
}
int p_stat(const char* path, struct stat* buf)
......@@ -262,8 +261,10 @@ int p_stat(const char* path, struct stat* buf)
int p_chdir(const char* path)
{
wchar_t* buf = gitwin_to_utf16(path);
int ret = _wchdir(buf);
int ret;
if (!buf)
return -1;
ret = _wchdir(buf);
git__free(buf);
return ret;
}
......@@ -271,8 +272,10 @@ int p_chdir(const char* path)
int p_chmod(const char* path, mode_t mode)
{
wchar_t* buf = gitwin_to_utf16(path);
int ret = _wchmod(buf, mode);
int ret;
if (!buf)
return -1;
ret = _wchmod(buf, mode);
git__free(buf);
return ret;
}
......@@ -280,8 +283,10 @@ int p_chmod(const char* path, mode_t mode)
int p_rmdir(const char* path)
{
wchar_t* buf = gitwin_to_utf16(path);
int ret = _wrmdir(buf);
int ret;
if (!buf)
return -1;
ret = _wrmdir(buf);
git__free(buf);
return ret;
}
......@@ -290,11 +295,13 @@ int p_hide_directory__w32(const char *path)
{
int res;
wchar_t* buf = gitwin_to_utf16(path);
if (!buf)
return -1;
res = SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN);
git__free(buf);
return (res != 0) ? GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
return (res != 0) ? 0 : -1; /* MSDN states a "non zero" value indicates a success */
}
char *p_realpath(const char *orig_path, char *buffer)
......@@ -303,6 +310,9 @@ char *p_realpath(const char *orig_path, char *buffer)
wchar_t* orig_path_w = gitwin_to_utf16(orig_path);
wchar_t* buffer_w = (wchar_t*)git__malloc(GIT_PATH_MAX * sizeof(wchar_t));
if (!orig_path_w || !buffer_w)
return NULL;
ret = GetFullPathNameW(orig_path_w, GIT_PATH_MAX, buffer_w, NULL);
git__free(orig_path_w);
......@@ -365,10 +375,10 @@ int p_mkstemp(char *tmp_path)
{
#if defined(_MSC_VER)
if (_mktemp_s(tmp_path, strlen(tmp_path) + 1) != 0)
return GIT_EOSERR;
return -1;
#else
if (_mktemp(tmp_path) == NULL)
return GIT_EOSERR;
return -1;
#endif
return p_creat(tmp_path, 0744);
......@@ -377,15 +387,17 @@ int p_mkstemp(char *tmp_path)
int p_setenv(const char* name, const char* value, int overwrite)
{
if (overwrite != 1)
return EINVAL;
return -1;
return (SetEnvironmentVariableA(name, value) == 0 ? GIT_EOSERR : GIT_SUCCESS);
return (SetEnvironmentVariableA(name, value) == 0 ? -1 : 0);
}
int p_access(const char* path, mode_t mode)
{
wchar_t *buf = gitwin_to_utf16(path);
int ret;
if (!buf)
return -1;
ret = _waccess(buf, mode);
git__free(buf);
......@@ -393,13 +405,16 @@ int p_access(const char* path, mode_t mode)
return ret;
}
extern int p_rename(const char *from, const char *to)
int p_rename(const char *from, const char *to)
{
wchar_t *wfrom = gitwin_to_utf16(from);
wchar_t *wto = gitwin_to_utf16(to);
int ret;
ret = MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
if (!wfrom || !wto)
return -1;
ret = MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1;
git__free(wfrom);
git__free(wto);
......
......@@ -7,13 +7,16 @@
#include "pthread.h"
int pthread_create(pthread_t *GIT_RESTRICT thread,
int pthread_create(
pthread_t *GIT_RESTRICT thread,
const pthread_attr_t *GIT_RESTRICT attr,
void *(*start_routine)(void*), void *GIT_RESTRICT arg)
void *(*start_routine)(void*),
void *GIT_RESTRICT arg)
{
GIT_UNUSED(attr);
*thread = (pthread_t) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, NULL);
return *thread ? GIT_SUCCESS : git__throw(GIT_EOSERR, "Failed to create pthread");
*thread = (pthread_t) CreateThread(
NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, NULL);
return *thread ? 0 : -1;
}
int pthread_join(pthread_t thread, void **value_ptr)
......
......@@ -33,13 +33,13 @@ wchar_t* gitwin_to_utf16(const char* str)
wchar_t* ret;
int cb;
if (!str) {
if (!str)
return NULL;
}
cb = strlen(str) * sizeof(wchar_t);
if (cb == 0) {
ret = (wchar_t*)git__malloc(sizeof(wchar_t));
if (ret)
ret[0] = 0;
return ret;
}
......@@ -48,8 +48,11 @@ wchar_t* gitwin_to_utf16(const char* str)
cb += sizeof(wchar_t);
ret = (wchar_t*)git__malloc(cb);
if (!ret)
return NULL;
if (MultiByteToWideChar(_active_codepage, 0, str, -1, ret, cb) == 0) {
giterr_set(GITERR_OS, "Could not convert string to UTF-16");
git__free(ret);
ret = NULL;
}
......@@ -59,7 +62,10 @@ wchar_t* gitwin_to_utf16(const char* str)
int gitwin_append_utf16(wchar_t *buffer, const char *str, size_t len)
{
return MultiByteToWideChar(_active_codepage, 0, str, -1, buffer, len);
int result = MultiByteToWideChar(_active_codepage, 0, str, -1, buffer, len);
if (result == 0)
giterr_set(GITERR_OS, "Could not convert string to UTF-16");
return result;
}
char* gitwin_from_utf16(const wchar_t* str)
......@@ -74,6 +80,7 @@ char* gitwin_from_utf16(const wchar_t* str)
cb = wcslen(str) * sizeof(char);
if (cb == 0) {
ret = (char*)git__malloc(sizeof(char));
if (ret)
ret[0] = 0;
return ret;
}
......@@ -82,8 +89,11 @@ char* gitwin_from_utf16(const wchar_t* str)
cb += sizeof(char);
ret = (char*)git__malloc(cb);
if (!ret)
return NULL;
if (WideCharToMultiByte(_active_codepage, 0, str, -1, ret, cb, NULL, NULL) == 0) {
giterr_set(GITERR_OS, "Could not convert string to UTF-8");
git__free(ret);
ret = NULL;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment