From: Karthik Nayak <karthik.188@gmail.com>
To: git@vger.kernel.org
Cc: Karthik Nayak <karthik.188@gmail.com>
Subject: [PATCH v4 2/2] sha1_file: refactor sha1_file.c to support 'cat-file --literally'
Date: Tue, 17 Mar 2015 10:46:59 +0530 [thread overview]
Message-ID: <1426569419-8266-1-git-send-email-karthik.188@gmail.com> (raw)
In-Reply-To: <5507B7EE.1070403@gmail.com>
Modify sha1_loose_object_info() to support 'cat-file --literally'
by accepting flags and also make changes to copy the type to
object_info::typename.
Add parse_sha1_header_extended() which acts as a wrapper around
parse_sha1_header() allowing for more information to be obtained
based on the given flags.
Add unpack_sha1_header_literally() to unpack sha1 headers of
unknown/corrupt objects which have a unknown sha1 header size.
This was written by Junio C Hamano but tested by me.
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Karthik Nayak <karthik.188@gmail.com>
---
sha1_file.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 97 insertions(+), 24 deletions(-)
diff --git a/sha1_file.c b/sha1_file.c
index 69a60ec..e31e9e2 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1564,6 +1564,36 @@ int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long ma
return git_inflate(stream, 0);
}
+static int unpack_sha1_header_literally(git_zstream *stream, unsigned char *map,
+ unsigned long mapsize,
+ struct strbuf *header)
+{
+ unsigned char buffer[32], *cp;
+ unsigned long bufsiz = sizeof(buffer);
+ int status;
+
+ /* Get the data stream */
+ memset(stream, 0, sizeof(*stream));
+ stream->next_in = map;
+ stream->avail_in = mapsize;
+ stream->next_out = buffer;
+ stream->avail_out = bufsiz;
+
+ git_inflate_init(stream);
+
+ do {
+ status = git_inflate(stream, 0);
+ strbuf_add(header, buffer, stream->next_out - buffer);
+ for (cp = buffer; cp < stream->next_out; cp++)
+ if (!*cp)
+ /* Found the NUL at the end of the header */
+ return 0;
+ stream->next_out = buffer;
+ stream->avail_out = bufsiz;
+ } while (status == Z_OK);
+ return -1;
+}
+
static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long size, const unsigned char *sha1)
{
int bytes = strlen(buffer) + 1;
@@ -1609,32 +1639,24 @@ static void *unpack_sha1_rest(git_zstream *stream, void *buffer, unsigned long s
return NULL;
}
-/*
- * We used to just use "sscanf()", but that's actually way
- * too permissive for what we want to check. So do an anal
- * object header parse by hand.
- */
-int parse_sha1_header(const char *hdr, unsigned long *sizep)
+int parse_sha1_header_extended(const char *hdr, struct object_info *oi,
+ int flags)
{
- char type[10];
- int i;
+ struct strbuf typename = STRBUF_INIT;
unsigned long size;
+ int type;
/*
* The type can be at most ten bytes (including the
* terminating '\0' that we add), and is followed by
* a space.
*/
- i = 0;
for (;;) {
char c = *hdr++;
if (c == ' ')
break;
- type[i++] = c;
- if (i >= sizeof(type))
- return -1;
+ strbuf_addch(&typename, c);
}
- type[i] = 0;
/*
* The length must follow immediately, and be in canonical
@@ -1652,12 +1674,45 @@ int parse_sha1_header(const char *hdr, unsigned long *sizep)
size = size * 10 + c;
}
}
- *sizep = size;
+
+ type = type_from_string_gently(typename.buf, -1, 1);
+ if (oi->sizep)
+ *oi->sizep = size;
+ if (oi->typename)
+ strbuf_addstr(oi->typename, typename.buf);
+ if (oi->typep)
+ *oi->typep = type;
+ strbuf_release(&typename);
+
+ /*
+ * Set type to 0 if its an unknown object and
+ * we're obtaining the type using '--literally'
+ * option.
+ */
+ if ((flags & LOOKUP_LITERALLY) && (type == -1))
+ type = 0;
+ else if (type == -1)
+ die("invalid object type");
/*
* The length must be followed by a zero byte
*/
- return *hdr ? -1 : type_from_string(type);
+ return *hdr ? -1 : type;
+}
+
+/*
+ * We used to just use "sscanf()", but that's actually way
+ * too permissive for what we want to check. So do an anal
+ * object header parse by hand. Calls the extended function.
+ */
+int parse_sha1_header(const char *hdr, unsigned long *sizep)
+{
+ struct object_info oi;
+
+ oi.sizep = sizep;
+ oi.typename = NULL;
+ oi.typep = NULL;
+ return parse_sha1_header_extended(hdr, &oi, LOOKUP_REPLACE_OBJECT);
}
static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1)
@@ -2524,13 +2579,15 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,
}
static int sha1_loose_object_info(const unsigned char *sha1,
- struct object_info *oi)
+ struct object_info *oi,
+ int flags)
{
- int status;
+ int status = 0;
unsigned long mapsize, size;
void *map;
git_zstream stream;
char hdr[32];
+ struct strbuf hdrbuf = STRBUF_INIT;
if (oi->delta_base_sha1)
hashclr(oi->delta_base_sha1);
@@ -2557,17 +2614,29 @@ static int sha1_loose_object_info(const unsigned char *sha1,
return -1;
if (oi->disk_sizep)
*oi->disk_sizep = mapsize;
- if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
- status = error("unable to unpack %s header",
- sha1_to_hex(sha1));
- else if ((status = parse_sha1_header(hdr, &size)) < 0)
- status = error("unable to parse %s header", sha1_to_hex(sha1));
- else if (oi->sizep)
+ if ((flags & LOOKUP_LITERALLY)) {
+ if (unpack_sha1_header_literally(&stream, map, mapsize, &hdrbuf) < 0)
+ status = error("unable to unpack %s header with --literally",
+ sha1_to_hex(sha1));
+ else if ((status = parse_sha1_header_extended(hdrbuf.buf, oi, flags)) < 0)
+ status = error("unable to parse %s header", sha1_to_hex(sha1));
+ } else {
+ if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
+ status = error("unable to unpack %s header",
+ sha1_to_hex(sha1));
+ else if ((status = parse_sha1_header(hdr, &size)) < 0)
+ status = error("unable to parse %s header", sha1_to_hex(sha1));
+ }
+ if (oi->sizep)
*oi->sizep = size;
git_inflate_end(&stream);
munmap(map, mapsize);
if (oi->typep)
*oi->typep = status;
+ if (oi->typename && !(oi->typename->len))
+ strbuf_addstr(oi->typename, typename(status));
+ if (hdrbuf.buf)
+ strbuf_release(&hdrbuf);
return 0;
}
@@ -2588,13 +2657,15 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
*(oi->disk_sizep) = 0;
if (oi->delta_base_sha1)
hashclr(oi->delta_base_sha1);
+ if (oi->typename)
+ strbuf_addstr(oi->typename, typename(co->type));
oi->whence = OI_CACHED;
return 0;
}
if (!find_pack_entry(real, &e)) {
/* Most likely it's a loose object. */
- if (!sha1_loose_object_info(real, oi)) {
+ if (!sha1_loose_object_info(real, oi, flags)) {
oi->whence = OI_LOOSE;
return 0;
}
@@ -2618,6 +2689,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
rtype == OBJ_OFS_DELTA);
}
+ if (oi->typename)
+ strbuf_addstr(oi->typename, typename(rtype));
return 0;
}
--
2.3.1.307.gf3db8a5
next prev parent reply other threads:[~2015-03-17 5:17 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-17 5:13 [PATCH v4 0/2] cat-file: add a '--literally' option karthik nayak
2015-03-17 5:16 ` [PATCH v4 1/2] cat-file: teach cat-file " Karthik Nayak
2015-03-17 6:51 ` Eric Sunshine
2015-03-17 13:59 ` Karthik Nayak
2015-03-17 5:16 ` Karthik Nayak [this message]
2015-03-17 20:10 ` [PATCH v4 2/2] sha1_file: refactor sha1_file.c to support 'cat-file --literally' Junio C Hamano
2015-03-18 19:35 ` karthik nayak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1426569419-8266-1-git-send-email-karthik.188@gmail.com \
--to=karthik.188@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).