Пример #1
0
static int buffer_want_with_caps(git_remote_head *head, git_transport_caps *caps, git_buf *buf)
{
	git_buf str = GIT_BUF_INIT;
	char oid[GIT_OID_HEXSZ +1] = {0};
	unsigned int len;

	if (caps->ofs_delta)
		git_buf_puts(&str, GIT_CAP_OFS_DELTA " ");

	if (caps->multi_ack)
		git_buf_puts(&str, GIT_CAP_MULTI_ACK " ");

	if (git_buf_oom(&str))
		return -1;

	len = (unsigned int)
		(strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ +
		 git_buf_len(&str) + 1 /* LF */);
	git_buf_grow(buf, git_buf_len(buf) + len);
	git_oid_fmt(oid, &head->oid);
	git_buf_printf(buf, "%04xwant %s %s\n", len, oid, git_buf_cstr(&str));
	git_buf_free(&str);

	return git_buf_oom(buf);
}
Пример #2
0
static int ident_insert_id(
	git_buf *to, const git_buf *from, const git_filter_source *src)
{
	char oid[GIT_OID_HEXSZ+1];
	const char *id_start, *id_end, *from_end = from->ptr + from->size;
	size_t need_size;

	/* replace $Id$ with blob id */

	if (!git_filter_source_id(src))
		return GIT_PASSTHROUGH;

	git_oid_tostr(oid, sizeof(oid), git_filter_source_id(src));

	if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
		return GIT_PASSTHROUGH;

	need_size = (size_t)(id_start - from->ptr) +
		5 /* "$Id: " */ + GIT_OID_HEXSZ + 1 /* "$" */ +
		(size_t)(from_end - id_end);

	if (git_buf_grow(to, need_size) < 0)
		return -1;

	git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
	git_buf_put(to, "$Id: ", 5);
	git_buf_put(to, oid, GIT_OID_HEXSZ);
	git_buf_putc(to, '$');
	git_buf_put(to, id_end, (size_t)(from_end - id_end));

	return git_buf_oom(to) ? -1 : 0;
}
Пример #3
0
static int bitflip_filter_apply(
	git_filter     *self,
	void          **payload,
	git_buf        *to,
	const git_buf  *from,
	const git_filter_source *source)
{
	const unsigned char *src = (const unsigned char *)from->ptr;
	unsigned char *dst;
	size_t i;

	GIT_UNUSED(self); GIT_UNUSED(payload);

	/* verify that attribute path match worked as expected */
	cl_assert_equal_i(
		0, git__strncmp("hero", git_filter_source_path(source), 4));

	if (!from->size)
		return 0;

	cl_git_pass(git_buf_grow(to, from->size));

	dst = (unsigned char *)to->ptr;

	for (i = 0; i < from->size; i++)
		dst[i] = VERY_SECURE_ENCRYPTION(src[i]);

	to->size = from->size;

	return 0;
}
Пример #4
0
int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len)
{
	git_zstream zs = GIT_ZSTREAM_INIT;
	int error = 0;

	if ((error = git_zstream_init(&zs)) < 0)
		return error;

	if ((error = git_zstream_set_input(&zs, in, in_len)) < 0)
		goto done;

	while (!git_zstream_done(&zs)) {
		size_t step = git_zstream_suggest_output_len(&zs), written;

		if ((error = git_buf_grow(out, out->size + step)) < 0)
			goto done;

		written = out->asize - out->size;

		if ((error = git_zstream_get_output(
				out->ptr + out->size, &written, &zs)) < 0)
			goto done;

		out->size += written;
	}

	/* NULL terminate for consistency if possible */
	if (out->size < out->asize)
		out->ptr[out->size] = '\0';

done:
	git_zstream_free(&zs);
	return error;
}
Пример #5
0
static int reverse_filter_apply(
	git_filter     *self,
	void          **payload,
	git_buf        *to,
	const git_buf  *from,
	const git_filter_source *source)
{
	const unsigned char *src = (const unsigned char *)from->ptr;
	const unsigned char *end = src + from->size;
	unsigned char *dst;

	GIT_UNUSED(self); GIT_UNUSED(payload); GIT_UNUSED(source);

	/* verify that attribute path match worked as expected */
	cl_assert_equal_i(
		0, git__strncmp("hero", git_filter_source_path(source), 4));

	if (!from->size)
		return 0;

	cl_git_pass(git_buf_grow(to, from->size));

	dst = (unsigned char *)to->ptr + from->size - 1;

	while (src < end)
		*dst-- = *src++;

	to->size = from->size;

	return 0;
}
Пример #6
0
/*
 * Create a git protocol request.
 *
 * For example: git-upload-pack '/libgit2/libgit2'
 */
static int gen_proto(git_buf *request, const char *cmd, const char *url)
{
	char *repo;
	int len;

	if (!git__prefixcmp(url, prefix_ssh)) {
		url = url + strlen(prefix_ssh);
		repo = strchr(url, '/');
	} else {
		repo = strchr(url, ':');
		if (repo) repo++;
	}

	if (!repo) {
		giterr_set(GITERR_NET, "Malformed git protocol URL");
		return -1;
	}

	len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1;

	git_buf_grow(request, len);
	git_buf_printf(request, "%s '%s'", cmd, repo);
	git_buf_putc(request, '\0');

	if (git_buf_oom(request))
		return -1;

	return 0;
}
Пример #7
0
int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
{
	ssize_t read_size = 0;
	size_t alloc_len;

	git_buf_clear(buf);

	if (!git__is_ssizet(len)) {
		giterr_set(GITERR_INVALID, "read too large");
		return -1;
	}

	GITERR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
	if (git_buf_grow(buf, alloc_len) < 0)
		return -1;

	/* p_read loops internally to read len bytes */
	read_size = p_read(fd, buf->ptr, len);

	if (read_size != (ssize_t)len) {
		giterr_set(GITERR_OS, "failed to read descriptor");
		git_buf_free(buf);
		return -1;
	}

	buf->ptr[read_size] = '\0';
	buf->size = read_size;

	return 0;
}
Пример #8
0
/*
 * Create a git protocol request.
 *
 * For example: 0035git-upload-pack /libgit2/libgit2\0host=github.com\0
 */
static int gen_proto(git_buf *request, const char *cmd, const char *url)
{
	char *delim, *repo;
	char host[] = "host=";
	size_t len;

	delim = strchr(url, '/');
	if (delim == NULL) {
		giterr_set(GITERR_NET, "Malformed URL");
		return -1;
	}

	repo = delim;

	delim = strchr(url, ':');
	if (delim == NULL)
		delim = strchr(url, '/');

	len = 4 + strlen(cmd) + 1 + strlen(repo) + 1 + strlen(host) + (delim - url) + 1;

	git_buf_grow(request, len);
	git_buf_printf(request, "%04x%s %s%c%s",
		(unsigned int)(len & 0x0FFFF), cmd, repo, 0, host);
	git_buf_put(request, url, delim - url);
	git_buf_putc(request, '\0');

	if (git_buf_oom(request))
		return -1;

	return 0;
}
Пример #9
0
int git_buf_put_w(git_buf *buf, const wchar_t *string_w, size_t len_w)
{
	int utf8_len, utf8_write_len;
	size_t new_size;

	if (!len_w)
		return 0;

	assert(string_w);

	/* Measure the string necessary for conversion */
	if ((utf8_len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, string_w, len_w, NULL, 0, NULL, NULL)) == 0)
		return 0;

	assert(utf8_len > 0);

	GITERR_CHECK_ALLOC_ADD(&new_size, buf->size, (size_t)utf8_len);
	GITERR_CHECK_ALLOC_ADD(&new_size, new_size, 1);

	if (git_buf_grow(buf, new_size) < 0)
		return -1;

	if ((utf8_write_len = WideCharToMultiByte(
			CP_UTF8, WC_ERR_INVALID_CHARS, string_w, len_w, &buf->ptr[buf->size], utf8_len, NULL, NULL)) == 0)
		return handle_wc_error();

	assert(utf8_write_len == utf8_len);

	buf->size += utf8_write_len;
	buf->ptr[buf->size] = '\0';
	return 0;
}
Пример #10
0
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");
}
Пример #11
0
static int buffer_want_with_caps(const git_remote_head *head, transport_smart_caps *caps, git_buf *buf)
{
	git_buf str = GIT_BUF_INIT;
	char oid[GIT_OID_HEXSZ +1] = {0};
	unsigned int len;

	/* Prefer side-band-64k if the server supports both */
	if (caps->side_band) {
		if (caps->side_band_64k)
			git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND_64K);
		else
			git_buf_printf(&str, "%s ", GIT_CAP_SIDE_BAND);
	}
	if (caps->ofs_delta)
		git_buf_puts(&str, GIT_CAP_OFS_DELTA " ");

	if (caps->multi_ack)
		git_buf_puts(&str, GIT_CAP_MULTI_ACK " ");

	if (caps->include_tag)
		git_buf_puts(&str, GIT_CAP_INCLUDE_TAG " ");

	if (git_buf_oom(&str))
		return -1;

	len = (unsigned int)
		(strlen("XXXXwant ") + GIT_OID_HEXSZ + 1 /* NUL */ +
		 git_buf_len(&str) + 1 /* LF */);
	git_buf_grow(buf, git_buf_len(buf) + len);
	git_oid_fmt(oid, &head->oid);
	git_buf_printf(buf, "%04xwant %s %s\n", len, oid, git_buf_cstr(&str));
	git_buf_free(&str);

	return git_buf_oom(buf);
}
Пример #12
0
/**
 * If we make a ridiculously large request the first time we
 * actually allocate some space in the git_buf, the realloc()
 * will fail.  And because the git_buf_grow() wrapper always
 * sets mark_oom, the code in git_buf_try_grow() will free
 * the internal buffer and set it to git_buf__oom.
 *
 * We initialized the internal buffer to (the static variable)
 * git_buf__initbuf.  The purpose of this test is to make sure
 * that we don't try to free the static buffer.
 */
void test_buf_oom__grow(void)
{
    git_buf buf = GIT_BUF_INIT;

    git_buf_clear(&buf);

    cl_assert(git_buf_grow(&buf, TOOBIG) == -1);
    cl_assert(git_buf_oom(&buf));

    git_buf_free(&buf);
}
Пример #13
0
void test_core_buffer__dont_grow_borrowed(void)
{
	const char *somestring = "blah blah";
	git_buf buf = GIT_BUF_INIT;

	git_buf_attach_notowned(&buf, somestring, strlen(somestring) + 1);
	cl_assert_equal_p(somestring, buf.ptr);
	cl_assert_equal_i(0, buf.asize);
	cl_assert_equal_i(strlen(somestring) + 1, buf.size);

	cl_git_fail_with(GIT_EINVALID, git_buf_grow(&buf, 1024));
}
Пример #14
0
int git_path_iconv(git_path_iconv_t *ic, const char **in, size_t *inlen)
{
	char *nfd = *in, *nfc;
	size_t nfdlen = *inlen, nfclen, wantlen = nfdlen, alloclen, rv;
	int retry = 1;

	if (!ic || ic->map == (iconv_t)-1 ||
		!git_path_has_non_ascii(*in, *inlen))
		return 0;

	git_buf_clear(&ic->buf);

	while (1) {
		GITERR_CHECK_ALLOC_ADD(&alloclen, wantlen, 1);
		if (git_buf_grow(&ic->buf, alloclen) < 0)
			return -1;

		nfc    = ic->buf.ptr   + ic->buf.size;
		nfclen = ic->buf.asize - ic->buf.size;

		rv = iconv(ic->map, &nfd, &nfdlen, &nfc, &nfclen);

		ic->buf.size = (nfc - ic->buf.ptr);

		if (rv != (size_t)-1)
			break;

		/* if we cannot convert the data (probably because iconv thinks
		 * it is not valid UTF-8 source data), then use original data
		 */
		if (errno != E2BIG)
			return 0;

		/* make space for 2x the remaining data to be converted
		 * (with per retry overhead to avoid infinite loops)
		 */
		wantlen = ic->buf.size + max(nfclen, nfdlen) * 2 + (size_t)(retry * 4);

		if (retry++ > 4)
			goto fail;
	}

	ic->buf.ptr[ic->buf.size] = '\0';

	*in    = ic->buf.ptr;
	*inlen = ic->buf.size;

	return 0;

fail:
	giterr_set(GITERR_OS, "Unable to convert unicode path data");
	return -1;
}
Пример #15
0
int git_buf_text_puts_escaped(
	git_buf *buf,
	const char *string,
	const char *esc_chars,
	const char *esc_with)
{
	const char *scan;
	size_t total = 0, esc_len = strlen(esc_with), count;

	if (!string)
		return 0;

	for (scan = string; *scan; ) {
		/* count run of non-escaped characters */
		count = strcspn(scan, esc_chars);
		total += count;
		scan += count;
		/* count run of escaped characters */
		count = strspn(scan, esc_chars);
		total += count * (esc_len + 1);
		scan += count;
	}

	if (git_buf_grow(buf, buf->size + total + 1) < 0)
		return -1;

	for (scan = string; *scan; ) {
		count = strcspn(scan, esc_chars);

		memmove(buf->ptr + buf->size, scan, count);
		scan += count;
		buf->size += count;

		for (count = strspn(scan, esc_chars); count > 0; --count) {
			/* copy escape sequence */
			memmove(buf->ptr + buf->size, esc_with, esc_len);
			buf->size += esc_len;
			/* copy character to be escaped */
			buf->ptr[buf->size] = *scan;
			buf->size++;
			scan++;
		}
	}

	buf->ptr[buf->size] = '\0';

	return 0;
}
Пример #16
0
int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src)
{
    const char *scan = src->ptr;
    const char *scan_end = src->ptr + src->size;
    const char *next = memchr(scan, '\r', src->size);
    size_t new_size;
    char *out;

    assert(tgt != src);

    if (!next)
        return git_buf_set(tgt, src->ptr, src->size);

    /* reduce reallocs while in the loop */
    GITERR_CHECK_ALLOC_ADD(&new_size, src->size, 1);
    if (git_buf_grow(tgt, new_size) < 0)
        return -1;

    out = tgt->ptr;
    tgt->size = 0;

    /* Find the next \r and copy whole chunk up to there to tgt */
    for (; next; scan = next + 1, next = memchr(scan, '\r', scan_end - scan)) {
        if (next > scan) {
            size_t copylen = (size_t)(next - scan);
            memcpy(out, scan, copylen);
            out += copylen;
        }

        /* Do not drop \r unless it is followed by \n */
        if (next + 1 == scan_end || next[1] != '\n')
            *out++ = '\r';
    }

    /* Copy remaining input into dest */
    if (scan < scan_end) {
        size_t remaining = (size_t)(scan_end - scan);
        memcpy(out, scan, remaining);
        out += remaining;
    }

    tgt->size = (size_t)(out - tgt->ptr);
    tgt->ptr[tgt->size] = '\0';

    return 0;
}
Пример #17
0
int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
{
    const char *start = src->ptr;
    const char *end = start + src->size;
    const char *scan = start;
    const char *next = memchr(scan, '\n', src->size);
    size_t alloclen;

    assert(tgt != src);

    if (!next)
        return git_buf_set(tgt, src->ptr, src->size);

    /* attempt to reduce reallocs while in the loop */
    GITERR_CHECK_ALLOC_ADD(&alloclen, src->size, src->size >> 4);
    GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
    if (git_buf_grow(tgt, alloclen) < 0)
        return -1;
    tgt->size = 0;

    for (; next; scan = next + 1, next = memchr(scan, '\n', end - scan)) {
        size_t copylen = next - scan;

        /* if we find mixed line endings, bail */
        if (next > start && next[-1] == '\r') {
            git_buf_free(tgt);
            return GIT_PASSTHROUGH;
        }

        GITERR_CHECK_ALLOC_ADD(&alloclen, copylen, 3);
        if (git_buf_grow_by(tgt, alloclen) < 0)
            return -1;

        if (next > scan) {
            memcpy(tgt->ptr + tgt->size, scan, copylen);
            tgt->size += copylen;
        }

        tgt->ptr[tgt->size++] = '\r';
        tgt->ptr[tgt->size++] = '\n';
    }

    tgt->ptr[tgt->size] = '\0';
    return git_buf_put(tgt, scan, end - scan);
}
Пример #18
0
int git_object_short_id(git_buf *out, const git_object *obj)
{
	git_repository *repo;
	int len = GIT_ABBREV_DEFAULT, error;
	git_oid id = {{0}};
	git_odb *odb;

	assert(out && obj);

	git_buf_sanitize(out);
	repo = git_object_owner(obj);

	if ((error = git_repository__cvar(&len, repo, GIT_CVAR_ABBREV)) < 0)
		return error;

	if ((error = git_repository_odb(&odb, repo)) < 0)
		return error;

	while (len < GIT_OID_HEXSZ) {
		/* set up short oid */
		memcpy(&id.id, &obj->cached.oid.id, (len + 1) / 2);
		if (len & 1)
			id.id[len / 2] &= 0xf0;

		error = git_odb_exists_prefix(NULL, odb, &id, len);
		if (error != GIT_EAMBIGUOUS)
			break;

		giterr_clear();
		len++;
	}

	if (!error && !(error = git_buf_grow(out, len + 1))) {
		git_oid_tostr(out->ptr, len + 1, &id);
		out->size = len;
	}

	git_odb_free(odb);

	return error;
}
Пример #19
0
static int index_path(git_buf *path, git_indexer *idx, const char *suffix)
{
	const char prefix[] = "pack-";
	size_t slash = (size_t)path->size;

	/* search backwards for '/' */
	while (slash > 0 && path->ptr[slash - 1] != '/')
		slash--;

	if (git_buf_grow(path, slash + 1 + strlen(prefix) +
					 GIT_OID_HEXSZ + strlen(suffix) + 1) < 0)
		return -1;

	git_buf_truncate(path, slash);
	git_buf_puts(path, prefix);
	git_oid_fmt(path->ptr + git_buf_len(path), &idx->hash);
	path->size += GIT_OID_HEXSZ;
	git_buf_puts(path, suffix);

	return git_buf_oom(path) ? -1 : 0;
}
Пример #20
0
static int ident_remove_id(
	git_buf *to, const git_buf *from)
{
	const char *id_start, *id_end, *from_end = from->ptr + from->size;
	size_t need_size;

	if (ident_find_id(&id_start, &id_end, from->ptr, from->size) < 0)
		return GIT_PASSTHROUGH;

	need_size = (size_t)(id_start - from->ptr) +
		4 /* "$Id$" */ + (size_t)(from_end - id_end);

	if (git_buf_grow(to, need_size) < 0)
		return -1;

	git_buf_set(to, from->ptr, (size_t)(id_start - from->ptr));
	git_buf_put(to, "$Id$", 4);
	git_buf_put(to, id_end, (size_t)(from_end - id_end));

	return git_buf_oom(to) ? -1 : 0;
}
Пример #21
0
static int object_file_name(
	git_buf *name, const loose_backend *be, const git_oid *id)
{
	size_t alloclen;

	/* expand length for object root + 40 hex sha1 chars + 2 * '/' + '\0' */
	GITERR_CHECK_ALLOC_ADD(&alloclen, be->objects_dirlen, GIT_OID_HEXSZ);
	GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 3);
	if (git_buf_grow(name, alloclen) < 0)
		return -1;

	git_buf_set(name, be->objects_dir, be->objects_dirlen);
	git_path_to_dir(name);

	/* loose object filename: aa/aaa... (41 bytes) */
	git_oid_pathfmt(name->ptr + name->size, id);
	name->size += GIT_OID_HEXSZ + 1;
	name->ptr[name->size] = '\0';

	return 0;
}
Пример #22
0
/*
 * Create a git protocol request.
 *
 * For example: git-upload-pack '/libgit2/libgit2'
 */
static int gen_proto(git_buf *request, const char *cmd, const char *url)
{
	const char *repo;
	int len;
	size_t i;

	for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
		const char *p = ssh_prefixes[i];

		if (!git__prefixcmp(url, p)) {
			url = url + strlen(p);
			repo = strchr(url, '/');
			if (repo && repo[1] == '~')
				++repo;

			goto done;
		}
	}
	repo = strchr(url, ':');
	if (repo) repo++;

done:
	if (!repo) {
		giterr_set(GITERR_NET, "malformed git protocol URL");
		return -1;
	}

	len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1;

	git_buf_grow(request, len);
	git_buf_puts(request, cmd);
	git_buf_puts(request, " '");
	git_buf_decode_percent(request, repo, strlen(repo));
	git_buf_puts(request, "'");

	if (git_buf_oom(request))
		return -1;

	return 0;
}
Пример #23
0
int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len)
{
	ssize_t read_size = 0;

	git_buf_clear(buf);

	if (git_buf_grow(buf, len + 1) < 0)
		return -1;

	/* p_read loops internally to read len bytes */
	read_size = p_read(fd, buf->ptr, len);

	if (read_size != (ssize_t)len) {
		giterr_set(GITERR_OS, "Failed to read descriptor");
		return -1;
	}

	buf->ptr[read_size] = '\0';
	buf->size = read_size;

	return 0;
}
Пример #24
0
int git_futils_readbuffer_updated(git_buf *buf, const char *path, time_t *mtime, int *updated)
{
	git_file fd;
	size_t len;
	struct stat st;

	assert(buf && path && *path);

	if (updated != NULL)
		*updated = 0;

	if ((fd = git_futils_open_ro(path)) < 0)
		return fd;

	if (p_fstat(fd, &st) < 0 || S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) {
		p_close(fd);
		giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path);
		return -1;
	}

	/*
	 * 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) {
		p_close(fd);
		return 0;
	}

	if (mtime != NULL)
		*mtime = st.st_mtime;

	len = (size_t) st.st_size;

	git_buf_clear(buf);

	if (git_buf_grow(buf, len + 1) < 0) {
		p_close(fd);
		return -1;
	}

	buf->ptr[len] = '\0';

	while (len > 0) {
		ssize_t read_size = p_read(fd, buf->ptr, len);

		if (read_size < 0) {
			p_close(fd);
			giterr_set(GITERR_OS, "Failed to read descriptor for '%s'", path);
			return -1;
		}

		len -= read_size;
		buf->size += read_size;
	}

	p_close(fd);

	if (updated != NULL)
		*updated = 1;

	return 0;
}
Пример #25
0
static int parse_section_header_ext(git_config_parser *reader, const char *line, const char *base_name, char **section_name)
{
	int c, rpos;
	char *first_quote, *last_quote;
	git_buf buf = GIT_BUF_INIT;
	size_t quoted_len, alloc_len, base_name_len = strlen(base_name);

	/*
	 * base_name is what came before the space. We should be at the
	 * first quotation mark, except for now, line isn't being kept in
	 * sync so we only really use it to calculate the length.
	 */

	first_quote = strchr(line, '"');
	if (first_quote == NULL) {
		set_parse_error(reader, 0, "Missing quotation marks in section header");
		goto end_error;
	}

	last_quote = strrchr(line, '"');
	quoted_len = last_quote - first_quote;

	if (quoted_len == 0) {
		set_parse_error(reader, 0, "Missing closing quotation mark in section header");
		goto end_error;
	}

	GITERR_CHECK_ALLOC_ADD(&alloc_len, base_name_len, quoted_len);
	GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);

	if (git_buf_grow(&buf, alloc_len) < 0 ||
	    git_buf_printf(&buf, "%s.", base_name) < 0)
		goto end_error;

	rpos = 0;

	line = first_quote;
	c = line[++rpos];

	/*
	 * At the end of each iteration, whatever is stored in c will be
	 * added to the string. In case of error, jump to out
	 */
	do {

		switch (c) {
		case 0:
			set_parse_error(reader, 0, "Unexpected end-of-line in section header");
			goto end_error;

		case '"':
			goto end_parse;

		case '\\':
			c = line[++rpos];

			if (c == 0) {
				set_parse_error(reader, rpos, "Unexpected end-of-line in section header");
				goto end_error;
			}

		default:
			break;
		}

		git_buf_putc(&buf, (char)c);
		c = line[++rpos];
	} while (line + rpos < last_quote);

end_parse:
	if (git_buf_oom(&buf))
		goto end_error;

	if (line[rpos] != '"' || line[rpos + 1] != ']') {
		set_parse_error(reader, rpos, "Unexpected text after closing quotes");
		git_buf_free(&buf);
		return -1;
	}

	*section_name = git_buf_detach(&buf);
	return 0;

end_error:
	git_buf_free(&buf);

	return -1;
}
Пример #26
0
/* Locate an object matching a given short oid */
static int locate_object_short_oid(
	git_buf *object_location,
	git_oid *res_oid,
	loose_backend *backend,
	const git_oid *short_oid,
	size_t len)
{
	char *objects_dir = backend->objects_dir;
	size_t dir_len = strlen(objects_dir), alloc_len;
	loose_locate_object_state state;
	int error;

	/* prealloc memory for OBJ_DIR/xx/xx..38x..xx */
	GITERR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
	GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 3);
	if (git_buf_grow(object_location, alloc_len) < 0)
		return -1;

	git_buf_set(object_location, objects_dir, dir_len);
	git_path_to_dir(object_location);

	/* save adjusted position at end of dir so it can be restored later */
	dir_len = git_buf_len(object_location);

	/* Convert raw oid to hex formatted oid */
	git_oid_fmt((char *)state.short_oid, short_oid);

	/* Explore OBJ_DIR/xx/ where xx is the beginning of hex formatted short oid */
	if (git_buf_put(object_location, (char *)state.short_oid, 3) < 0)
		return -1;
	object_location->ptr[object_location->size - 1] = '/';

	/* Check that directory exists */
	if (git_path_isdir(object_location->ptr) == false)
		return git_odb__error_notfound("no matching loose object for prefix",
			short_oid, len);

	state.dir_len = git_buf_len(object_location);
	state.short_oid_len = len;
	state.found = 0;

	/* Explore directory to find a unique object matching short_oid */
	error = git_path_direach(
		object_location, 0, fn_locate_object_short_oid, &state);
	if (error < 0 && error != GIT_EAMBIGUOUS)
		return error;

	if (!state.found)
		return git_odb__error_notfound("no matching loose object for prefix",
			short_oid, len);

	if (state.found > 1)
		return git_odb__error_ambiguous("multiple matches in loose objects");

	/* Convert obtained hex formatted oid to raw */
	error = git_oid_fromstr(res_oid, (char *)state.res_oid);
	if (error)
		return error;

	/* Update the location according to the oid obtained */
	GITERR_CHECK_ALLOC_ADD(&alloc_len, dir_len, GIT_OID_HEXSZ);
	GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);

	git_buf_truncate(object_location, dir_len);
	if (git_buf_grow(object_location, alloc_len) < 0)
		return -1;

	git_oid_pathfmt(object_location->ptr + dir_len, res_oid);

	object_location->size += GIT_OID_HEXSZ + 1;
	object_location->ptr[object_location->size] = '\0';

	return 0;
}