int git_refspec_transform(char *out, size_t outlen, const git_refspec *spec, const char *name) { size_t baselen, namelen; baselen = strlen(spec->dst); if (outlen <= baselen) return git__throw(GIT_EINVALIDREFNAME, "Reference name too long"); /* * No '*' at the end means that it's mapped to one specific local * branch, so no actual transformation is needed. */ if (spec->dst[baselen - 1] != '*') { memcpy(out, spec->dst, baselen + 1); /* include '\0' */ return GIT_SUCCESS; } /* There's a '*' at the end, so remove its length */ baselen--; /* skip the prefix, -1 is for the '*' */ name += strlen(spec->src) - 1; namelen = strlen(name); if (outlen <= baselen + namelen) return git__throw(GIT_EINVALIDREFNAME, "Reference name too long"); memcpy(out, spec->dst, baselen); memcpy(out + baselen, name, namelen + 1); return GIT_SUCCESS; }
int p_munmap(git_map *map) { assert(map != NULL); if (!map) return git__throw(GIT_ERROR, "Failed to munmap. Map does not exist"); if (map->data) { if (!UnmapViewOfFile(map->data)) { /* errno = ? */ CloseHandle(map->fmh); map->data = NULL; map->fmh = NULL; return git__throw(GIT_ERROR, "Failed to munmap. Could not unmap view of file"); } map->data = NULL; } if (map->fmh) { if (!CloseHandle(map->fmh)) { /* errno = ? */ map->fmh = NULL; return git__throw(GIT_ERROR, "Failed to munmap. Could not close handle"); } map->fmh = NULL; } return GIT_SUCCESS; }
int p_lstat(const char *file_name, struct stat *buf) { int namelen, error; char alt_name[GIT_PATH_MAX]; if ((error = do_lstat(file_name, buf)) == GIT_SUCCESS) return GIT_SUCCESS; /* if file_name ended in a '/', Windows returned ENOENT; * try again without trailing slashes */ if (error != GIT_EINVALIDPATH) return git__throw(GIT_EOSERR, "Failed to lstat file"); namelen = strlen(file_name); if (namelen && file_name[namelen-1] != '/') return git__throw(GIT_EOSERR, "Failed to lstat file"); while (namelen && file_name[namelen-1] == '/') --namelen; if (!namelen || namelen >= GIT_PATH_MAX) return git__throw(GIT_ENOMEM, "Failed to lstat file"); memcpy(alt_name, file_name, namelen); alt_name[namelen] = 0; return do_lstat(alt_name, buf); }
static int win32_find_system(char *system_config_path) { const wchar_t *query = L"%PROGRAMFILES%\\Git\\etc\\gitconfig"; wchar_t *apphome_utf16; char *apphome_utf8; DWORD size, ret; size = ExpandEnvironmentStringsW(query, NULL, 0); /* The function gave us the full size of the buffer in chars, including NUL */ apphome_utf16 = git__malloc(size * sizeof(wchar_t)); if (apphome_utf16 == NULL) return GIT_ENOMEM; ret = ExpandEnvironmentStringsW(query, apphome_utf16, size); if (ret != size) return git__throw(GIT_ERROR, "Failed to expand environment strings"); if (_waccess(apphome_utf16, F_OK) < 0) { free(apphome_utf16); return GIT_ENOTFOUND; } apphome_utf8 = conv_utf16_to_utf8(apphome_utf16); free(apphome_utf16); if (strlen(apphome_utf8) >= GIT_PATH_MAX) { free(apphome_utf8); return git__throw(GIT_ESHORTBUFFER, "Path is too long"); } strcpy(system_config_path, apphome_utf8); free(apphome_utf8); return GIT_SUCCESS; }
int git_futils_readbuffer_updated(git_fbuffer *obj, const char *path, time_t *mtime, int *updated) { git_file fd; size_t len; struct stat st; unsigned char *buff; assert(obj && path && *path); if (updated != NULL) *updated = 0; if (p_stat(path, &st) < 0) return git__throw(GIT_ENOTFOUND, "Failed to stat file %s", path); if (S_ISDIR(st.st_mode)) return git__throw(GIT_ERROR, "Can't read a dir into a buffer"); /* * If we were given a time, we only want to read the file if it * has been modified. */ if (mtime != NULL && *mtime >= st.st_mtime) return GIT_SUCCESS; if (mtime != NULL) *mtime = st.st_mtime; if (!git__is_sizet(st.st_size+1)) return git__throw(GIT_ERROR, "Failed to read file `%s`. An error occured while calculating its size", path); len = (size_t) st.st_size; if ((fd = p_open(path, O_RDONLY)) < 0) return git__throw(GIT_EOSERR, "Failed to open %s for reading", path); if ((buff = git__malloc(len + 1)) == NULL) { p_close(fd); return GIT_ENOMEM; } 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'; p_close(fd); if (mtime != NULL) *mtime = st.st_mtime; if (updated != NULL) *updated = 1; obj->data = buff; obj->len = len; return GIT_SUCCESS; }
static int read_unmerged(git_index *index, const char *buffer, size_t size) { const char *endptr; size_t len; int i; git_vector_init(&index->unmerged, 16, unmerged_cmp); while (size) { git_index_entry_unmerged *lost; len = strlen(buffer) + 1; if (size <= len) return git__throw(GIT_ERROR, "Failed to read unmerged entries"); if ((lost = git__malloc(sizeof(git_index_entry_unmerged))) == NULL) return GIT_ENOMEM; if (git_vector_insert(&index->unmerged, lost) < GIT_SUCCESS) return git__throw(GIT_ERROR, "Failed to read unmerged entries"); lost->path = git__strdup(buffer); if (!lost->path) return GIT_ENOMEM; size -= len; buffer += len; for (i = 0; i < 3; i++) { long tmp; if (git__strtol32(&tmp, buffer, &endptr, 8) < GIT_SUCCESS || !endptr || endptr == buffer || *endptr || tmp > UINT_MAX) return GIT_ERROR; lost->mode[i] = tmp; len = (endptr + 1) - buffer; if (size <= len) return git__throw(GIT_ERROR, "Failed to read unmerged entries"); size -= len; buffer += len; } for (i = 0; i < 3; i++) { if (!lost->mode[i]) continue; if (size < 20) return git__throw(GIT_ERROR, "Failed to read unmerged entries"); git_oid_fromraw(&lost->oid[i], (unsigned char *) buffer); size -= 20; buffer += 20; } } return GIT_SUCCESS; }
/* * Parse an other-ref line. */ int ref_pkt(git_pkt **out, const char *line, size_t len) { git_pkt_ref *pkt; int error, has_caps = 0; pkt = git__malloc(sizeof(git_pkt_ref)); if (pkt == NULL) return GIT_ENOMEM; memset(pkt, 0x0, sizeof(git_pkt_ref)); pkt->type = GIT_PKT_REF; error = git_oid_fromstr(&pkt->head.oid, line); if (error < GIT_SUCCESS) { error = git__throw(error, "Failed to parse reference ID"); goto out; } /* Check for a bit of consistency */ if (line[GIT_OID_HEXSZ] != ' ') { error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse ref. No SP"); goto out; } /* Jump from the name */ line += GIT_OID_HEXSZ + 1; len -= (GIT_OID_HEXSZ + 1); if (strlen(line) < len) has_caps = 1; if (line[len - 1] == '\n') --len; pkt->head.name = git__malloc(len + 1); if (pkt->head.name == NULL) { error = GIT_ENOMEM; goto out; } memcpy(pkt->head.name, line, len); pkt->head.name[len] = '\0'; if (has_caps) { pkt->capabilities = strchr(pkt->head.name, '\0') + 1; } out: if (error < GIT_SUCCESS) free(pkt); else *out = (git_pkt *)pkt; return error; }
int git_futils_direach( char *path, size_t path_sz, int (*fn)(void *, char *), void *arg) { size_t wd_len = strlen(path); DIR *dir; struct dirent *de; if (!wd_len || path_sz < wd_len + 2) return git__throw(GIT_EINVALIDARGS, "Failed to process `%s` tree structure. Path is either empty or buffer size is too short", path); while (path[wd_len - 1] == '/') wd_len--; path[wd_len++] = '/'; path[wd_len] = '\0'; dir = opendir(path); if (!dir) return git__throw(GIT_EOSERR, "Failed to process `%s` tree structure. An error occured while opening the directory", path); while ((de = readdir(dir)) != NULL) { size_t de_len; int result; if (is_dot_or_dotdot(de->d_name)) continue; de_len = strlen(de->d_name); if (path_sz < wd_len + de_len + 1) { closedir(dir); return git__throw(GIT_ERROR, "Failed to process `%s` tree structure. Buffer size is too short", path); } strcpy(path + wd_len, de->d_name); result = fn(arg, path); if (result < GIT_SUCCESS) { closedir(dir); return result; /* The callee is reponsible for setting the correct error message */ } if (result > 0) { closedir(dir); return result; } } closedir(dir); return GIT_SUCCESS; }
static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buffer_end) { int error = GIT_SUCCESS; if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < GIT_SUCCESS) return GIT_ENOMEM; while (buffer < buffer_end) { git_tree_entry *entry; int tmp; entry = git__calloc(1, sizeof(git_tree_entry)); if (entry == NULL) { error = GIT_ENOMEM; break; } if (git_vector_insert(&tree->entries, entry) < GIT_SUCCESS) return GIT_ENOMEM; if (git__strtol32(&tmp, buffer, &buffer, 8) < GIT_SUCCESS || !buffer || !valid_attributes(tmp)) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Can't parse attributes"); entry->attr = tmp; if (*buffer++ != ' ') { error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Object it corrupted"); break; } if (memchr(buffer, 0, buffer_end - buffer) == NULL) { error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Object it corrupted"); break; } entry->filename = git__strdup(buffer); entry->filename_len = strlen(buffer); while (buffer < buffer_end && *buffer != 0) buffer++; buffer++; git_oid_fromraw(&entry->oid, (const unsigned char *)buffer); buffer += GIT_OID_RAWSZ; } return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to parse buffer"); }
static int write_deflate(git_filebuf *file, const void *source, size_t len) { int result = Z_OK; z_stream *zs = &file->zs; if (len > 0 || file->flush_mode == Z_FINISH) { zs->next_in = (void *)source; zs->avail_in = len; do { int have; zs->next_out = file->z_buf; zs->avail_out = file->buf_size; result = deflate(zs, file->flush_mode); assert(result != Z_STREAM_ERROR); have = file->buf_size - zs->avail_out; if (gitfo_write(file->fd, file->z_buf, have) < GIT_SUCCESS) return git__throw(GIT_EOSERR, "Failed to write to file"); } while (zs->avail_out == 0); assert(zs->avail_in == 0); if (file->digest) git_hash_update(file->digest, source, len); } return GIT_SUCCESS; }
/* * Close the least recently used window. You should check to see if * the file descriptors need closing from time to time. */ static int git_mwindow_close_lru(git_mwindow_file *mwf) { unsigned int i; git_mwindow *lru_w = NULL, *lru_l = NULL; /* FIMXE: Does this give us any advantage? */ if(mwf->windows) git_mwindow_scan_lru(mwf, &lru_w, &lru_l); for (i = 0; i < ctl.windowfiles.length; ++i) { git_mwindow_scan_lru(git_vector_get(&ctl.windowfiles, i), &lru_w, &lru_l); } if (lru_w) { git_mwindow_close(&lru_w); ctl.mapped -= lru_w->window_map.len; git_futils_mmap_free(&lru_w->window_map); if (lru_l) lru_l->next = lru_w->next; else mwf->windows = lru_w->next; free(lru_w); ctl.open_windows--; return GIT_SUCCESS; } return git__throw(GIT_ERROR, "Failed to close memory window. Couln't find LRU"); }
static int process_trimming(const char *input, char **storage, const char *input_end, int fail_when_empty) { const char *left, *right; int trimmed_input_length; left = skip_leading_spaces(input, input_end); right = skip_trailing_spaces(input, input_end - 1); if (right < left) { if (fail_when_empty) return git__throw(GIT_EINVALIDARGS, "Failed to trim. Input is either empty or only contains spaces"); else right = left - 1; } trimmed_input_length = right - left + 1; *storage = git__malloc(trimmed_input_length + 1); if (*storage == NULL) return GIT_ENOMEM; memcpy(*storage, left, trimmed_input_length); (*storage)[trimmed_input_length] = 0; return GIT_SUCCESS; }
/* * Moved from `repository.c` */ int git_repository_index(git_index **index_out, git_repository *repo) { if (repo->is_bare) return git__throw(GIT_EBAREINDEX, "Failed to open index. Repository is bare"); return index_initialize(index_out, repo, repo->path_index); }
static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backend, const git_oid *oid) { int error; size_t i; if ((error = packfile_refresh_all(backend)) < GIT_SUCCESS) return git__rethrow(error, "Failed to find pack entry"); if (backend->last_found && git_pack_entry_find(e, backend->last_found, oid, GIT_OID_HEXSZ) == GIT_SUCCESS) return GIT_SUCCESS; for (i = 0; i < backend->packs.length; ++i) { struct git_pack_file *p; p = git_vector_get(&backend->packs, i); if (p == backend->last_found) continue; if (git_pack_entry_find(e, p, oid, GIT_OID_HEXSZ) == GIT_SUCCESS) { backend->last_found = p; return GIT_SUCCESS; } } return git__throw(GIT_ENOTFOUND, "Failed to find pack entry"); }
int gitno_extract_host_and_port(char **host, char **port, const char *url, const char *default_port) { char *colon, *slash, *delim; int error = GIT_SUCCESS; colon = strchr(url, ':'); slash = strchr(url, '/'); if (slash == NULL) return git__throw(GIT_EOBJCORRUPTED, "Malformed URL: missing /"); if (colon == NULL) { *port = git__strdup(default_port); } else { *port = git__strndup(colon + 1, slash - colon - 1); } if (*port == NULL) return GIT_ENOMEM;; delim = colon == NULL ? slash : colon; *host = git__strndup(url, delim - url); if (*host == NULL) { git__free(*port); error = GIT_ENOMEM; } return error; }
int git_refspec_parse(git_refspec *refspec, const char *str) { char *delim; memset(refspec, 0x0, sizeof(git_refspec)); if (*str == '+') { refspec->force = 1; str++; } delim = strchr(str, ':'); if (delim == NULL) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse refspec. No ':'"); refspec->src = git__strndup(str, delim - str); if (refspec->src == NULL) return GIT_ENOMEM; refspec->dst = git__strdup(delim + 1); if (refspec->dst == NULL) { free(refspec->src); refspec->src = NULL; return GIT_ENOMEM; } return GIT_SUCCESS; }
static int packfile_refresh_all(struct pack_backend *backend) { int error; struct stat st; if (backend->pack_folder == NULL) return GIT_SUCCESS; if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode)) return git__throw(GIT_ENOTFOUND, "Failed to refresh packfiles. Backend not found"); if (st.st_mtime != backend->pack_folder_mtime) { char path[GIT_PATH_MAX]; strcpy(path, backend->pack_folder); /* reload all packs */ error = git_futils_direach(path, GIT_PATH_MAX, packfile_load__cb, (void *)backend); if (error < GIT_SUCCESS) return git__rethrow(error, "Failed to refresh packfiles"); git_vector_sort(&backend->packs); backend->pack_folder_mtime = st.st_mtime; } return GIT_SUCCESS; }
int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld) { unsigned int i; int error; git_buf tree = GIT_BUF_INIT; assert(bld); sort_entries(bld); /* Grow the buffer beforehand to an estimated size */ git_buf_grow(&tree, bld->entries.length * 72); for (i = 0; i < bld->entries.length; ++i) { git_tree_entry *entry = bld->entries.contents[i]; if (entry->removed) continue; git_buf_printf(&tree, "%o ", entry->attr); git_buf_put(&tree, entry->filename, entry->filename_len + 1); git_buf_put(&tree, (char *)entry->oid.id, GIT_OID_RAWSZ); } if (git_buf_oom(&tree)) { git_buf_free(&tree); return git__throw(GIT_ENOMEM, "Not enough memory to build the tree data"); } error = git_odb_write(oid, git_repository_database(repo), tree.ptr, tree.size, GIT_OBJ_TREE); git_buf_free(&tree); return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to write tree"); }
int git_futils_creat_locked_withpath(const char *path, int mode) { if (git_futils_mkpath2file(path) < GIT_SUCCESS) return git__throw(GIT_EOSERR, "Failed to create locked file %s", path); return git_futils_creat_locked(path, mode); }
int git_config_get_int64(git_config *cfg, const char *name, int64_t *out) { const char *value, *num_end; int ret; int64_t num; ret = git_config_get_string(cfg, name, &value); if (ret < GIT_SUCCESS) return git__rethrow(ret, "Failed to retrieve value for '%s'", name); ret = git__strtol64(&num, value, &num_end, 0); if (ret < GIT_SUCCESS) return git__rethrow(ret, "Failed to convert value for '%s'", name); switch (*num_end) { case 'g': case 'G': num *= 1024; /* fallthrough */ case 'm': case 'M': num *= 1024; /* fallthrough */ case 'k': case 'K': num *= 1024; /* check that that there are no more characters after the * given modifier suffix */ if (num_end[1] != '\0') return git__throw(GIT_EINVALIDTYPE, "Failed to get value for '%s'. Invalid type suffix", name); /* fallthrough */ case '\0': *out = num; return GIT_SUCCESS; default: return git__throw(GIT_EINVALIDTYPE, "Failed to get value for '%s'. Value is of invalid type", name); } }
static int filter_wants(git_remote *remote) { git_vector list; git_headarray refs; git_transport *t = remote->transport; git_repository *repo = remote->repo; const git_refspec *spec; int error; unsigned int i; error = git_vector_init(&list, 16, NULL); if (error < GIT_SUCCESS) return error; error = t->ls(t, &refs); if (error < GIT_SUCCESS) { error = git__rethrow(error, "Failed to get remote ref list"); goto cleanup; } spec = git_remote_fetchspec(remote); if (spec == NULL) { error = git__throw(GIT_ERROR, "The remote has no fetchspec"); goto cleanup; } for (i = 0; i < refs.len; ++i) { git_remote_head *head = refs.heads[i]; /* If it doesn't match the refpec, we don't want it */ error = git_refspec_src_match(spec, head->name); if (error == GIT_ENOMATCH) continue; if (error < GIT_SUCCESS) { error = git__rethrow(error, "Error matching remote ref name"); goto cleanup; } /* If we have the object, mark it so we don't ask for it */ if (git_odb_exists(repo->db, &head->oid)) head->local = 1; else remote->need_pack = 1; error = git_vector_insert(&list, head); if (error < GIT_SUCCESS) goto cleanup; } remote->refs.len = list.length; remote->refs.heads = (git_remote_head **) list.contents; return GIT_SUCCESS; cleanup: git_vector_free(&list); return error; }
int git_vector_bsearch2(git_vector *v, git_vector_cmp key_lookup, const void *key) { void **find; assert(v && key && key_lookup); /* need comparison function to sort the vector */ if (v->_cmp == NULL) return git__throw(GIT_ENOTFOUND, "Can't sort vector. No comparison function set"); git_vector_sort(v); find = git__bsearch(key, v->contents, v->length, key_lookup); if (find != NULL) return (int)(find - v->contents); return git__throw(GIT_ENOTFOUND, "Can't find element"); }
int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, const char *filename, const git_oid *id, unsigned int attributes) { git_tree_entry *entry; int pos; struct tree_key_search ksearch; assert(bld && id && filename); if (!valid_attributes(attributes)) return git__throw(GIT_ERROR, "Failed to insert entry. Invalid attributes"); if (build_ksearch(&ksearch, filename) < GIT_SUCCESS) return git__throw(GIT_ERROR, "Failed to insert entry. Invalid filename '%s'", filename); if ((pos = git_vector_bsearch2(&bld->entries, entry_search_cmp, &ksearch)) != GIT_ENOTFOUND) { entry = git_vector_get(&bld->entries, pos); if (entry->removed) { entry->removed = 0; bld->entry_count++; } } else { if ((entry = git__malloc(sizeof(git_tree_entry))) == NULL) return GIT_ENOMEM; memset(entry, 0x0, sizeof(git_tree_entry)); entry->filename = git__strdup(filename); entry->filename_len = strlen(entry->filename); bld->entry_count++; } git_oid_cpy(&entry->oid, id); entry->attr = attributes; if (pos == GIT_ENOTFOUND) { if (git_vector_insert(&bld->entries, entry) < 0) return GIT_ENOMEM; } if (entry_out != NULL) *entry_out = entry; return GIT_SUCCESS; }
int git_config_get_string(git_config *cfg, const char *name, const char **out) { file_internal *internal; git_config_file *file; int error = GIT_ENOTFOUND; unsigned int i; if (cfg->files.length == 0) return git__throw(GIT_EINVALIDARGS, "Cannot get variable value; no files open in the `git_config` instance"); for (i = 0; i < cfg->files.length; ++i) { internal = git_vector_get(&cfg->files, i); file = internal->file; if ((error = file->get(file, name, out)) == GIT_SUCCESS) return GIT_SUCCESS; } return git__throw(error, "Config value '%s' not found", name); }
int git_treebuilder_remove(git_treebuilder *bld, const char *filename) { git_tree_entry *remove_ptr = treebuilder_get(bld, filename); if (remove_ptr == NULL || remove_ptr->removed) return git__throw(GIT_ENOTFOUND, "Failed to remove entry. File isn't in the tree"); remove_ptr->removed = 1; bld->entry_count--; return GIT_SUCCESS; }
int p_munmap(git_map *map) { assert(map != NULL); if (!map) return git__throw(GIT_ERROR, "Failed to munmap. Map does not exist"); munmap(map->data, map->len); return GIT_SUCCESS; }
int git_commit_parent(git_commit **parent, git_commit *commit, unsigned int n) { git_oid *parent_oid; assert(commit); parent_oid = git_vector_get(&commit->parent_oids, n); if (parent_oid == NULL) return git__throw(GIT_ENOTFOUND, "Parent %u does not exist", n); return git_commit_lookup(parent, commit->object.repo, parent_oid); }
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset) { int mprot = 0; int mflag = 0; assert((out != NULL) && (len > 0)); if ((out == NULL) || (len == 0)) { errno = EINVAL; return git__throw(GIT_ERROR, "Failed to mmap. No map or zero length"); } out->data = NULL; out->len = 0; if (prot & GIT_PROT_WRITE) mprot = PROT_WRITE; else if (prot & GIT_PROT_READ) mprot = PROT_READ; else { errno = EINVAL; return git__throw(GIT_ERROR, "Failed to mmap. Invalid protection parameters"); } if ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED) mflag = MAP_SHARED; else if ((flags & GIT_MAP_TYPE) == GIT_MAP_PRIVATE) mflag = MAP_PRIVATE; if (flags & GIT_MAP_FIXED) { errno = EINVAL; return git__throw(GIT_ERROR, "Failed to mmap. FIXED not set"); } out->data = mmap(NULL, len, mprot, mflag, fd, offset); if (!out->data || out->data == MAP_FAILED) return git__throw(GIT_EOSERR, "Failed to mmap. Could not write data"); out->len = len; return GIT_SUCCESS; }
int git_futils_mktmp(char *path_out, const char *filename) { int fd; strcpy(path_out, filename); strcat(path_out, "_git2_XXXXXX"); if ((fd = p_mkstemp(path_out)) < 0) return git__throw(GIT_EOSERR, "Failed to create temporary file %s", path_out); return fd; }
int git_config_find_global(char *global_config_path) { const char *home; home = getenv("HOME"); #ifdef GIT_WIN32 if (home == NULL) home = getenv("USERPROFILE"); #endif if (home == NULL) return git__throw(GIT_EOSERR, "Failed to open global config file. Cannot locate the user's home directory"); git_path_join(global_config_path, home, GIT_CONFIG_FILENAME); if (git_futils_exists(global_config_path) < GIT_SUCCESS) return git__throw(GIT_EOSERR, "Failed to open global config file. The file does not exist"); return GIT_SUCCESS; }