diff options
author | Russell Belfer <arrbee@arrbee.com> | 2012-03-15 04:36:15 +0400 |
---|---|---|
committer | Russell Belfer <arrbee@arrbee.com> | 2012-03-15 04:36:15 +0400 |
commit | deafee7bd7a9e2efcdff90627b6094d8c1519319 (patch) | |
tree | 4b11910d7d315a6db667cc4af4c6749630612ed3 | |
parent | ab43ad2fd822504446e7876d6352c968a74beb53 (diff) |
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.
-rw-r--r-- | src/blob.c | 110 | ||||
-rw-r--r-- | src/buffer.c | 4 | ||||
-rw-r--r-- | src/buffer.h | 4 | ||||
-rw-r--r-- | src/fileops.c | 83 | ||||
-rw-r--r-- | src/fileops.h | 15 | ||||
-rw-r--r-- | src/hashtable.c | 7 | ||||
-rw-r--r-- | src/hashtable.h | 2 | ||||
-rw-r--r-- | src/index.c | 3 | ||||
-rw-r--r-- | src/indexer.c | 11 | ||||
-rw-r--r-- | src/iterator.c | 2 | ||||
-rw-r--r-- | src/mwindow.c | 2 | ||||
-rw-r--r-- | src/mwindow.h | 6 | ||||
-rw-r--r-- | src/odb.c | 4 | ||||
-rw-r--r-- | src/path.c | 37 | ||||
-rw-r--r-- | src/path.h | 5 | ||||
-rw-r--r-- | src/posix.c | 4 | ||||
-rw-r--r-- | src/repository.c | 10 | ||||
-rw-r--r-- | src/win32/dir.c | 88 | ||||
-rw-r--r-- | src/win32/posix_w32.c | 189 | ||||
-rw-r--r-- | src/win32/pthread.c | 13 | ||||
-rw-r--r-- | src/win32/utf-conv.c | 20 |
21 files changed, 344 insertions, 275 deletions
diff --git a/src/blob.c b/src/blob.c index 60a6b55d6..20dcece74 100644 --- a/src/blob.c +++ b/src/blob.c @@ -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; + return error; } -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); - file_size -= read_len; + else if (!(error = stream->write(stream, buffer, read_len))) + file_size -= read_len; } p_close(fd); - error = stream->finalize_write(oid, stream); -cleanup: + if (!error) + error = stream->finalize_write(oid, stream); + 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 */ + /* 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; } diff --git a/src/buffer.c b/src/buffer.c index dd245e243..b0e329908 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -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) diff --git a/src/buffer.h b/src/buffer.h index 6f59dce62..d90db4d4a 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -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; diff --git a/src/fileops.c b/src/fileops.c index 0ce48828b..aa52b09d7 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -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; - return p_rename(from, to); /* The callee already takes care of setting the correct error message. */ + if (p_rename(from, to) < 0) { + giterr_set(GITERR_OS, "Failed to rename '%s' to '%s'", from, to); + return -1; + } + + 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; } - return git__rethrow(error, "Failed to remove directory. `%s` is not empty", path->ptr); + 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 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); diff --git a/src/fileops.h b/src/fileops.h index c2ba8ffc8..6df565321 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -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 diff --git a/src/hashtable.c b/src/hashtable.c index 0364bb52b..8e057d4b1 100644 --- a/src/hashtable.c +++ b/src/hashtable.c @@ -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]); } diff --git a/src/hashtable.h b/src/hashtable.h index e09965965..0bab84543 100644 --- a/src/hashtable.h +++ b/src/hashtable.h @@ -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 } } diff --git a/src/index.c b/src/index.c index d5410a3a7..7f5909ae0 100644 --- a/src/index.c +++ b/src/index.c @@ -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; } diff --git a/src/indexer.c b/src/indexer.c index da6495f90..6f8bd329f 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -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 */ diff --git a/src/iterator.c b/src/iterator.c index 0ce89df9e..c10b9ffc2 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -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]); } diff --git a/src/mwindow.c b/src/mwindow.c index e3de0709c..cde24d1b1 100644 --- a/src/mwindow.c +++ b/src/mwindow.c @@ -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; diff --git a/src/mwindow.h b/src/mwindow.h index 94bfb5d61..058027251 100644 --- a/src/mwindow.h +++ b/src/mwindow.h @@ -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; diff --git a/src/path.c b/src/path.c index d1f094a1a..0f45d7130 100644 --- a/src/path.c +++ b/src/path.c @@ -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); diff --git a/src/path.h b/src/path.h index e885d875e..3cf73940e 100644 --- a/src/path.h +++ b/src/path.h @@ -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. diff --git a/src/posix.c b/src/posix.c index 9d96d3013..977880999 100644 --- a/src/posix.c +++ b/src/posix.c @@ -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) diff --git a/src/repository.c b/src/repository.c index 7d7b3c4e0..99eee52ea 100644 --- a/src/repository.c +++ b/src/repository.c @@ -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; - *device_out = path_info.st_dev; - return 0; + return error; } /* diff --git a/src/win32/dir.c b/src/win32/dir.c index 035e2b685..bc3d40fa5 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -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; - return 0; + 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) - FindClose(d->h); + 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); - d->h = FindFirstFileW(filter_w, &d->f); - git__free(filter_w); + if (!init_filter(filter, sizeof(filter), d->dir) || + (filter_w = gitwin_to_utf16(filter)) == NULL) + return; - if (d->h != INVALID_HANDLE_VALUE) - d->first = 1; - } - } + d->h = FindFirstFileW(filter_w, &d->f); + git__free(filter_w); + + 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) - FindClose(d->h); - if (d->dir) - git__free(d->dir); - git__free(d); + if (!d) + return 0; + + if (d->h != INVALID_HANDLE_VALUE) { + FindClose(d->h); + d->h = INVALID_HANDLE_VALUE; } + git__free(d->dir); + d->dir = NULL; + git__free(d); return 0; } diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index a9158980b..c6b36a847 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -17,10 +17,11 @@ int p_unlink(const char *path) int ret = 0; wchar_t* buf; - buf = gitwin_to_utf16(path); - _wchmod(buf, 0666); - ret = _wunlink(buf); - git__free(buf); + 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) { - /* 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); + if (error) + return error; + + /* Skip first 4 characters if they are "\\?\" */ + 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') + { + offset += 2; + dwRet -= 2; + target[offset] = '\\'; } + + 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); diff --git a/src/win32/pthread.c b/src/win32/pthread.c index 3db536848..3a186c8d9 100644 --- a/src/win32/pthread.c +++ b/src/win32/pthread.c @@ -7,13 +7,16 @@ #include "pthread.h" -int pthread_create(pthread_t *GIT_RESTRICT thread, - const pthread_attr_t *GIT_RESTRICT attr, - void *(*start_routine)(void*), void *GIT_RESTRICT arg) +int pthread_create( + pthread_t *GIT_RESTRICT thread, + const pthread_attr_t *GIT_RESTRICT attr, + 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) diff --git a/src/win32/utf-conv.c b/src/win32/utf-conv.c index 3c8be81d1..f00f5be92 100644 --- a/src/win32/utf-conv.c +++ b/src/win32/utf-conv.c @@ -33,14 +33,14 @@ 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)); - ret[0] = 0; + 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,7 +80,8 @@ char* gitwin_from_utf16(const wchar_t* str) cb = wcslen(str) * sizeof(char); if (cb == 0) { ret = (char*)git__malloc(sizeof(char)); - ret[0] = 0; + 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; } |