commit - cb672fbdfe95d95d806a21fa0db320aa2636c927
commit + a1fd68d829c4e5eb0496107b9ac3d94968f81a8e
blob - 79deadb93b5f53f5dc7e8ed1b432d74c47ed11e5
blob + 8f4ae1a3a30d63c209f8f08cd86d333b4b0fd863
--- include/got_error.h
+++ include/got_error.h
*/
/* Error codes */
-#define GOT_ERR_UNKNOWN 0x0000
-#define GOT_ERR_NO_MEM 0x0001
-#define GOT_ERR_NOT_GIT_REPO 0x0002
-#define GOT_ERR_NOT_ABSPATH 0x0003
-#define GOT_ERR_BAD_PATH 0x0004
-#define GOT_ERR_NOT_REF 0x0005
-#define GOT_ERR_IO 0x0006
-#define GOT_ERR_EOF 0x0007
-#define GOT_ERR_DECOMPRESSION 0x0008
-#define GOT_ERR_NO_SPACE 0x0009
-#define GOT_ERR_BAD_OBJ_HDR 0x0010
-#define GOT_ERR_OBJ_TYPE 0x0011
-#define GOT_ERR_BAD_OBJ_DATA 0x0012
-#define GOT_ERR_FILE_OPEN 0x0013
-#define GOT_ERR_BAD_PACKIDX 0x0014
-#define GOT_ERR_PACKIDX_CSUM 0x0015
+#define GOT_ERR_UNKNOWN 0
+#define GOT_ERR_NO_MEM 1
+#define GOT_ERR_NOT_GIT_REPO 2
+#define GOT_ERR_NOT_ABSPATH 3
+#define GOT_ERR_BAD_PATH 4
+#define GOT_ERR_NOT_REF 5
+#define GOT_ERR_IO 6
+#define GOT_ERR_EOF 7
+#define GOT_ERR_DECOMPRESSION 8
+#define GOT_ERR_NO_SPACE 9
+#define GOT_ERR_BAD_OBJ_HDR 10
+#define GOT_ERR_OBJ_TYPE 11
+#define GOT_ERR_BAD_OBJ_DATA 12
+#define GOT_ERR_FILE_OPEN 13
+#define GOT_ERR_BAD_PACKIDX 14
+#define GOT_ERR_PACKIDX_CSUM 15
+#define GOT_ERR_BAD_PACKFILE 16
+#define GOT_ERR_NO_OBJ 17
static const struct got_error {
int code;
{ GOT_ERR_FILE_OPEN, "could not open file" },
{ GOT_ERR_BAD_PACKIDX, "bad pack index file" },
{ GOT_ERR_PACKIDX_CSUM, "pack index file checksum error" },
+ { GOT_ERR_BAD_PACKFILE, "bad pack file" },
+ { GOT_ERR_NO_OBJ, "object not found" },
};
const struct got_error * got_error(int code);
blob - 6854ce112fc51fe9f38a696a11921af6e3dea29f
blob + 9e3f32b04c48fb04b77e6f8312deb951ae55ea31
--- include/got_object.h
+++ include/got_object.h
/*
- * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
struct got_repository;
-char * got_object_id_str(struct got_object_id *, char *, size_t);
+char *got_object_id_str(struct got_object_id *, char *, size_t);
+int got_object_id_cmp(struct got_object_id *, struct got_object_id *);
+const char *got_object_get_type_tag(int);
const struct got_error *got_object_open(struct got_object **,
struct got_repository *, struct got_object_id *);
void got_object_close(struct got_object *);
blob - 65e7c610c725361e0c22696225499962bdad27aa
blob + 49c27b10f99d94b1ac7bced8c2a7d30c7c724446
--- include/got_repository.h
+++ include/got_repository.h
char *got_repo_get_path_git_dir(struct got_repository *);
char *got_repo_get_path_objects(struct got_repository *);
+char *got_repo_get_path_objects_pack(struct got_repository *);
char *got_repo_get_path_refs(struct got_repository *);
struct got_reference;
blob - 668013da54ca7a913d9378e2413398b9dd4a0185
blob + df56c0dec9b4f886d0894e14ad05aea9fde11040
--- include/got_sha1.h
+++ include/got_sha1.h
/*
- * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
*/
int got_parse_sha1_digest(uint8_t *, const char *);
+char *got_sha1_digest_to_str(const uint8_t *, char *, size_t);
blob - 0f5eb9be742c6f3c7540471e463276a101a096e0
blob + d99ed9f7c19a52512573c812b0f54ccfe0218861
--- lib/diff.c
+++ lib/diff.c
#include "got_diff.h"
#include "diff.h"
-
-static FILE *
-opentemp(void)
-{
- char name[PATH_MAX];
- int fd;
- FILE *f;
-
- if (strlcpy(name, "/tmp/got.XXXXXXXX", sizeof(name)) >= sizeof(name))
- return NULL;
-
- fd = mkstemp(name);
- if (fd < 0)
- return NULL;
-
- unlink(name);
- f = fdopen(fd, "w+");
- if (f == NULL) {
- close(fd);
- return NULL;
- }
+#include "path.h"
- return f;
-}
-
const struct got_error *
got_diff_blob(struct got_blob_object *blob1, struct got_blob_object *blob2,
const char *label1, const char *label2, FILE *outfile)
int res, flags = 0;
if (blob1) {
- f1 = opentemp();
+ f1 = got_opentemp();
if (f1 == NULL)
return got_error(GOT_ERR_FILE_OPEN);
} else
flags |= D_EMPTY1;
if (blob2) {
- f2 = opentemp();
+ f2 = got_opentemp();
if (f2 == NULL) {
fclose(f1);
return got_error(GOT_ERR_FILE_OPEN);
return NULL;
}
-static int
-same_id(struct got_object_id *id1, struct got_object_id *id2)
-{
- return (memcmp(id1->sha1, id2->sha1, SHA1_DIGEST_LENGTH) == 0);
-}
-
static const struct got_error *
diff_added_blob(struct got_object_id *id, struct got_repository *repo)
{
}
if (S_ISDIR(te1->mode) && S_ISDIR(te2->mode)) {
- if (!same_id(&te1->id, &te2->id))
+ if (got_object_id_cmp(&te1->id, &te2->id) != 0)
return diff_modified_tree(&te1->id, &te2->id, repo);
} else if (S_ISREG(te1->mode) && S_ISREG(te2->mode)) {
- if (!same_id(&te1->id, &te2->id))
+ if (got_object_id_cmp(&te1->id, &te2->id) != 0)
return diff_modified_blob(&te1->id, &te2->id, repo);
-
}
return diff_kind_mismatch(&te1->id, &te2->id);
blob - 87f6288f8d365111bb6ea7fd97603fe058c40bfa
blob + 2beacfb382bf9e479a9039320ec767d7564a03da
--- lib/object.c
+++ lib/object.c
/*
- * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include <sys/stat.h>
#include <sys/queue.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "got_object.h"
#include "got_repository.h"
#include "got_sha1.h"
+#include "pack.h"
#ifndef MIN
#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
char *
got_object_id_str(struct got_object_id *id, char *buf, size_t size)
{
- char *p = buf;
- char hex[3];
- int i;
+ return got_sha1_digest_to_str(id->sha1, buf, size);
+}
- if (size < SHA1_DIGEST_STRING_LENGTH)
- return NULL;
+int
+got_object_id_cmp(struct got_object_id *id1, struct got_object_id *id2)
+{
+ return memcmp(id1->sha1, id2->sha1, SHA1_DIGEST_LENGTH);
+}
- for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
- snprintf(hex, sizeof(hex), "%.2x", id->sha1[i]);
- p[0] = hex[0];
- p[1] = hex[1];
- p += 2;
+const char *
+got_object_get_type_tag(int type)
+{
+ switch (type) {
+ case GOT_OBJ_TYPE_COMMIT:
+ return GOT_OBJ_TAG_COMMIT;
+ case GOT_OBJ_TYPE_TREE:
+ return GOT_OBJ_TAG_TREE;
+ case GOT_OBJ_TYPE_BLOB:
+ return GOT_OBJ_TAG_BLOB;
}
- p[0] = '\0';
- return buf;
+ return NULL;
}
static void
static const struct got_error *
read_object_header(struct got_object **obj, struct got_repository *repo,
- const char *path)
+ FILE *f)
{
const struct got_error *err;
- FILE *f;
struct got_zstream_buf zb;
char *buf;
size_t len;
size_t outlen, totlen;
int i, ret;
- f = fopen(path, "rb");
- if (f == NULL)
- return got_error(GOT_ERR_BAD_PATH);
-
buf = calloc(zbsize, sizeof(char));
if (buf == NULL)
return got_error(GOT_ERR_NO_MEM);
err = inflate_init(&zb, zbsize);
- if (err) {
- fclose(f);
+ if (err)
return err;
- }
i = 0;
totlen = 0;
err = parse_object_header(obj, buf, totlen);
done:
inflate_end(&zb);
- fclose(f);
return err;
}
struct got_object_id *id)
{
const struct got_error *err = NULL;
- char *path = NULL;
+ char *path;
+ FILE *f = NULL;
err = object_path(&path, id, repo);
if (err)
return err;
- err = read_object_header(obj, repo, path);
+ f = fopen(path, "rb");
+ if (f == NULL) {
+ if (errno != ENOENT) {
+ err = got_error(GOT_ERR_BAD_PATH);
+ goto done;
+ }
+ err = got_packfile_extract_object(&f, id, repo);
+ if (err)
+ goto done;
+ if (f == NULL) {
+ err = got_error(GOT_ERR_NO_OBJ);
+ goto done;
+ }
+ }
+
+ err = read_object_header(obj, repo, f);
if (err == NULL)
memcpy((*obj)->id.sha1, id->sha1, SHA1_DIGEST_LENGTH);
done:
free(path);
+ if (f != NULL)
+ fclose(f);
return err;
}
{
return inflate_read(&blob->zb, blob->f, outlenp);
}
-
blob - 5f38af5b0c6763a70545931c03d88f214de45956
blob + 6f0e06cbee2c22585c03b3bb96b3396835605179
--- lib/pack.c
+++ lib/pack.c
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/queue.h>
+#include <dirent.h>
+#include <errno.h>
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sha1.h>
#include <endian.h>
+#include <zlib.h>
#include "got_error.h"
+#include "got_object.h"
+#include "got_repository.h"
+#include "got_sha1.h"
#include "pack.h"
+#include "path.h"
+#define GOT_PACK_PREFIX "pack-"
+#define GOT_PACKFILE_SUFFIX ".pack"
+#define GOT_PACKIDX_SUFFIX ".idx"
+#define GOT_PACKFILE_NAMELEN (strlen(GOT_PACK_PREFIX) + \
+ SHA1_DIGEST_STRING_LENGTH - 1 + \
+ strlen(GOT_PACKFILE_SUFFIX))
+#define GOT_PACKIDX_NAMELEN (strlen(GOT_PACK_PREFIX) + \
+ SHA1_DIGEST_STRING_LENGTH - 1 + \
+ strlen(GOT_PACKIDX_SUFFIX))
+
+#ifndef MIN
+#define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
static const struct got_error *
verify_fanout_table(uint32_t *fanout_table)
{
int i;
for (i = 0; i < 0xff - 1; i++) {
- if (fanout_table[i] > fanout_table[i + 1])
+ if (be32toh(fanout_table[i]) > be32toh(fanout_table[i + 1]))
return got_error(GOT_ERR_BAD_PACKIDX);
}
SHA1Update(&ctx, (uint8_t *)p->sorted_ids,
nobj * sizeof(*p->sorted_ids));
- p->offsets = calloc(nobj, sizeof(*p->offsets));
- if (p->offsets == NULL) {
+ p->crc32 = calloc(nobj, sizeof(*p->crc32));
+ if (p->crc32 == NULL) {
err = got_error(GOT_ERR_NO_MEM);
goto done;
}
- n = fread(p->offsets, sizeof(*p->offsets), nobj, f);
+ n = fread(p->crc32, sizeof(*p->crc32), nobj, f);
if (n != nobj) {
err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
goto done;
}
- SHA1Update(&ctx, (uint8_t *)p->offsets, nobj * sizeof(*p->offsets));
+ SHA1Update(&ctx, (uint8_t *)p->crc32, nobj * sizeof(*p->crc32));
- p->crc32 = calloc(nobj, sizeof(*p->crc32));
- if (p->crc32 == NULL) {
+ p->offsets = calloc(nobj, sizeof(*p->offsets));
+ if (p->offsets == NULL) {
err = got_error(GOT_ERR_NO_MEM);
goto done;
}
- n = fread(p->crc32, sizeof(*p->crc32), nobj, f);
+ n = fread(p->offsets, sizeof(*p->offsets), nobj, f);
if (n != nobj) {
err = got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKIDX);
goto done;
}
- SHA1Update(&ctx, (uint8_t *)p->crc32, nobj * sizeof(*p->crc32));
+ SHA1Update(&ctx, (uint8_t *)p->offsets, nobj * sizeof(*p->offsets));
/* Large file offsets are contained only in files > 2GB. */
if (packfile_size <= 0x80000000)
goto done;
}
- SHA1Update(&ctx, p->trailer.pack_file_sha1, SHA1_DIGEST_LENGTH);
+ SHA1Update(&ctx, p->trailer.packfile_sha1, SHA1_DIGEST_LENGTH);
SHA1Final(sha1, &ctx);
- if (memcmp(p->trailer.pack_idx_sha1, sha1, SHA1_DIGEST_LENGTH) != 0)
+ if (memcmp(p->trailer.packidx_sha1, sha1, SHA1_DIGEST_LENGTH) != 0)
err = got_error(GOT_ERR_PACKIDX_CSUM);
done:
fclose(f);
free(packidx->crc32);
free(packidx->large_offsets);
free(packidx);
+}
+
+static int
+is_packidx_filename(const char *name, size_t len)
+{
+ if (len != GOT_PACKIDX_NAMELEN)
+ return 0;
+
+ if (strncmp(name, GOT_PACK_PREFIX, strlen(GOT_PACK_PREFIX)) != 0)
+ return 0;
+
+ if (strcmp(name + strlen(GOT_PACK_PREFIX) +
+ SHA1_DIGEST_STRING_LENGTH - 1, GOT_PACKIDX_SUFFIX) != 0)
+ return 0;
+
+ return 1;
+}
+
+static off_t
+get_object_offset(struct got_packidx_v2_hdr *packidx, int idx)
+{
+ uint32_t totobj = betoh32(packidx->fanout_table[0xff]);
+ uint32_t offset = betoh32(packidx->offsets[idx]);
+ if (offset & GOT_PACKIDX_OFFSET_VAL_IS_LARGE_IDX) {
+ uint64_t loffset;
+ idx = offset & GOT_PACKIDX_OFFSET_VAL_MASK;
+ if (idx < 0 || idx > totobj || packidx->large_offsets == NULL)
+ return -1;
+ loffset = betoh64(packidx->large_offsets[idx]);
+ return (loffset > INT64_MAX ? -1 : (off_t)loffset);
+ }
+ return (off_t)(offset & GOT_PACKIDX_OFFSET_VAL_MASK);
+}
+
+static int
+get_object_idx(struct got_packidx_v2_hdr *packidx, struct got_object_id *id)
+{
+ u_int8_t id0 = id->sha1[0];
+ uint32_t totobj = betoh32(packidx->fanout_table[0xff]);
+ int i = 0;
+
+ if (id0 > 0)
+ i = betoh32(packidx->fanout_table[id0 - 1]);
+
+ while (i < totobj) {
+ struct got_object_id *oid = &packidx->sorted_ids[i++];
+ uint32_t offset;
+
+ if (got_object_id_cmp(id, oid) < 0)
+ continue;
+ if (got_object_id_cmp(id, oid) > 0)
+ break;
+
+ return i;
+ }
+
+ return -1;
+}
+
+const struct got_error *
+read_packfile_hdr(FILE *f, struct got_packidx_v2_hdr *packidx)
+{
+ const struct got_error *err = NULL;
+ uint32_t totobj = betoh32(packidx->fanout_table[0xff]);
+ struct got_packfile_hdr hdr;
+ size_t n;
+
+ n = fread(&hdr, sizeof(hdr), 1, f);
+ if (n != 1)
+ return got_error(ferror(f) ? GOT_ERR_IO : GOT_ERR_BAD_PACKFILE);
+
+ if (betoh32(hdr.signature) != GOT_PACKFILE_SIGNATURE ||
+ betoh32(hdr.version) != GOT_PACKFILE_VERSION ||
+ betoh32(hdr.nobjects) != totobj)
+ err = got_error(GOT_ERR_BAD_PACKFILE);
+
+ return err;
+}
+
+static const struct got_error *
+dump_packed_object(FILE **f, FILE *packfile, off_t offset)
+{
+ const struct got_error *err = NULL;
+ const char *template = "/tmp/got.XXXXXXXXXX";
+ uint64_t size = 0;
+ uint8_t type = 0;
+ uint8_t sizeN;
+ int i;
+ size_t n;
+ const char *type_tag;
+
+ *f = got_opentemp();
+ if (*f == NULL) {
+ err = got_error(GOT_ERR_FILE_OPEN);
+ goto done;
+ }
+
+ if (fseeko(packfile, offset, SEEK_SET) != 0) {
+ err = got_error(errno == EIO ? GOT_ERR_IO : GOT_ERR_BAD_PATH);
+ goto done;
+ }
+
+ i = 0;
+ do {
+ /* We do not support size values which don't fit in 64 bit. */
+ if (i > 9) {
+ err = got_error(GOT_ERR_NO_SPACE);
+ goto done;
+ }
+
+ n = fread(&sizeN, sizeof(sizeN), 1, packfile);
+ if (n != 1) {
+ err = got_error(ferror(packfile) ?
+ GOT_ERR_IO : GOT_ERR_BAD_PACKFILE);
+ goto done;
+ }
+ if (i == 0) {
+ type = (sizeN & GOT_PACK_OBJ_SIZE0_TYPE_MASK) >>
+ GOT_PACK_OBJ_SIZE0_TYPE_MASK_SHIFT;
+ size = (sizeN & GOT_PACK_OBJ_SIZE0_VAL_MASK);
+ } else {
+ size_t shift = 4 + 7 * (i - 1);
+ size |= ((sizeN & GOT_PACK_OBJ_SIZE_VAL_MASK) << shift);
+ }
+ i++;
+ } while (sizeN & GOT_PACK_OBJ_SIZE_MORE);
+
+ if (type == GOT_OBJ_TYPE_OFFSET_DELTA)
+ printf("object type OFFSET_DELTA not yet implemented\n");
+ else if (type == GOT_OBJ_TYPE_REF_DELTA)
+ printf("object type REF_DELTA not yet implemented\n");
+ else if (type == GOT_OBJ_TYPE_TAG)
+ printf("object type TAG not yet implemented\n");
+
+ type_tag = got_object_get_type_tag(type);
+ if (type_tag == NULL) {
+ err = got_error(GOT_ERR_BAD_OBJ_HDR);
+ goto done;
+ }
+
+ fprintf(*f, "%s %llu", type_tag, size);
+ fputc('\0', *f);
+
+ while (size > 0) {
+ uint8_t data[2048];
+ size_t len = MIN(size, sizeof(data));
+
+ n = fread(data, len, 1, packfile);
+ if (n != 1) {
+ err = got_error(ferror(packfile) ?
+ GOT_ERR_IO : GOT_ERR_BAD_PACKFILE);
+ goto done;
+ }
+
+ n = fwrite(data, len, 1, *f);
+ if (n != 1) {
+ err = got_error(ferror(*f) ?
+ GOT_ERR_IO : GOT_ERR_BAD_PACKFILE);
+ goto done;
+ }
+
+ size -= len;
+ }
+
+ printf("object type is %d\n", type);
+ rewind(*f);
+done:
+ if (err && *f)
+ fclose(*f);
+ return err;
}
+static const struct got_error *
+extract_object(FILE **f, const char *path_packdir,
+ struct got_packidx_v2_hdr *packidx, struct got_object_id *id)
+{
+ const struct got_error *err = NULL;
+ int idx = get_object_idx(packidx, id);
+ off_t offset;
+ char *path_packfile;
+ FILE *packfile;
+ char hex[SHA1_DIGEST_STRING_LENGTH];
+ char *sha1str;
+
+ *f = NULL;
+ if (idx == -1) /* object not found in pack index */
+ return NULL;
+
+ offset = get_object_offset(packidx, idx);
+ if (offset == (uint64_t)-1)
+ return got_error(GOT_ERR_BAD_PACKIDX);
+
+ sha1str = got_sha1_digest_to_str(packidx->trailer.packfile_sha1,
+ hex, sizeof(hex));
+ if (sha1str == NULL)
+ return got_error(GOT_ERR_PACKIDX_CSUM);
+
+ if (asprintf(&path_packfile, "%s/%s%s%s", path_packdir,
+ GOT_PACK_PREFIX, sha1str, GOT_PACKFILE_SUFFIX) == -1)
+ return got_error(GOT_ERR_NO_MEM);
+
+ packfile = fopen(path_packfile, "rb");
+ if (packfile == NULL) {
+ err = got_error(errno == EIO ? GOT_ERR_IO : GOT_ERR_BAD_PATH);
+ goto done;
+ }
+
+ err = read_packfile_hdr(packfile, packidx);
+ if (err)
+ goto done;
+
+ printf("Dumping object at offset %llu\n", offset);
+ err = dump_packed_object(f, packfile, offset);
+ if (err)
+ goto done;
+
+done:
+ free(path_packfile);
+ if (packfile && fclose(packfile) == -1 && errno == EIO && err == 0)
+ err = got_error(GOT_ERR_IO);
+ return err;
+}
+
+const struct got_error *
+got_packfile_extract_object(FILE **f, struct got_object_id *id,
+ struct got_repository *repo)
+{
+ const struct got_error *err = NULL;
+ DIR *packdir = NULL;
+ struct dirent *dent;
+ char *path_packdir = got_repo_get_path_objects_pack(repo);
+
+ if (path_packdir == NULL) {
+ err = got_error(GOT_ERR_NO_MEM);
+ goto done;
+ }
+
+ packdir = opendir(path_packdir);
+ if (packdir == NULL) {
+ err = got_error(errno == EIO ? GOT_ERR_IO : GOT_ERR_BAD_PATH);
+ goto done;
+ }
+
+ while ((dent = readdir(packdir)) != NULL) {
+ struct got_packidx_v2_hdr *packidx;
+ char *path_packidx, *path_object;
+
+ if (!is_packidx_filename(dent->d_name, dent->d_namlen))
+ continue;
+
+ if (asprintf(&path_packidx, "%s/%s", path_packdir,
+ dent->d_name) == -1) {
+ err = got_error(GOT_ERR_NO_MEM);
+ goto done;
+ }
+
+ err = got_packidx_open(&packidx, path_packidx);
+ free(path_packidx);
+ if (err)
+ goto done;
+
+ err = extract_object(f, path_packdir, packidx, id);
+ if (err)
+ goto done;
+ if (*f != NULL)
+ break;
+ }
+
+done:
+ free(path_packdir);
+ if (packdir && closedir(packdir) != 0 && errno == EIO && err == 0)
+ err = got_error(GOT_ERR_IO);
+ return err;
+}
blob - 4d508b318d7934d6ae1c48eeb2d580a8f6e8b80a
blob + 9e034eb2f7ab046e1448b158af3478bdf73aee1b
--- lib/pack.h
+++ lib/pack.h
/* See Documentation/technical/pack-format.txt in Git. */
-struct got_pack_obj_id {
- u_int8_t sha1[SHA1_DIGEST_LENGTH];
-} __attribute__((__packed__));
-
struct got_packidx_trailer {
- u_int8_t pack_file_sha1[SHA1_DIGEST_LENGTH];
- u_int8_t pack_idx_sha1[SHA1_DIGEST_LENGTH];
+ u_int8_t packfile_sha1[SHA1_DIGEST_LENGTH];
+ u_int8_t packidx_sha1[SHA1_DIGEST_LENGTH];
} __attribute__((__packed__));
/* Ignore pack index version 1 which is no longer written by Git. */
uint32_t fanout_table[0xff + 1]; /* values are big endian */
/* Sorted SHA1 checksums for each object in the pack file. */
- struct got_pack_obj_id *sorted_ids;
+ struct got_object_id *sorted_ids;
+ /* CRC32 of the packed representation of each object. */
+ uint32_t *crc32;
+
/* Offset into the pack file for each object. */
uint32_t *offsets; /* values are big endian */
#define GOT_PACKIDX_OFFSET_VAL_MASK 0x7fffffff
#define GOT_PACKIDX_OFFSET_VAL_IS_LARGE_IDX 0x80000000
- /* CRC32 of the packed representation of each object. */
- uint32_t *crc32;
-
/* Large offsets table is empty for pack files < 2 GB. */
uint64_t *large_offsets; /* values are big endian */
uint8_t *size; /* variable length */
#define GOT_PACK_OBJ_SIZE_MORE 0x80
#define GOT_PACK_OBJ_SIZE0_TYPE_MASK 0x70 /* See struct got_object->type */
+#define GOT_PACK_OBJ_SIZE0_TYPE_MASK_SHIFT 4
#define GOT_PACK_OBJ_SIZE0_VAL_MASK 0x0f
-#define GOT_PACK_OBJ_SIZEN_VAL_MASK 0x7f
+#define GOT_PACK_OBJ_SIZE_VAL_MASK 0x7f
};
/* If object is not a DELTA type. */
/* If object is of type GOT_OBJ_TYPE_REF_DELTA. */
struct got_packfile_object_data_ref_delta {
- struct got_pack_obj_id id;
+ struct got_object_id id;
uint8_t *delta_data; /* compressed */
};
const struct got_error *got_packidx_open(struct got_packidx_v2_hdr **,
const char *);
void got_packidx_close(struct got_packidx_v2_hdr *);
+
+const struct got_error *got_packfile_extract_object(FILE **,
+ struct got_object_id *, struct got_repository *);
blob - 3ca3b590a1c62b865c6be7a84c4826d3f5266e79
blob + 7ec32c1f45c6d2006e0355e0c06d728bfee555ee
--- lib/path.c
+++ lib/path.c
/*
- * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
return resolved;
}
+
+FILE *
+got_opentemp(void)
+{
+ char name[PATH_MAX];
+ int fd;
+ FILE *f;
+
+ if (strlcpy(name, "/tmp/got.XXXXXXXX", sizeof(name)) >= sizeof(name))
+ return NULL;
+
+ fd = mkstemp(name);
+ if (fd < 0)
+ return NULL;
+
+ /* unlink(name); */
+ f = fdopen(fd, "w+");
+ if (f == NULL) {
+ close(fd);
+ return NULL;
+ }
+
+ return f;
+}
blob - 80111d04b9214ae2860466b3cadba2b2ae2c7fa6
blob + 3bca95b3c18a88dff7ba4f0da9738a1e898be44b
--- lib/path.h
+++ lib/path.h
/*
- * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* The result is allocated with malloc(3).
*/
char *got_path_normalize(const char *);
+
+/* Open a new temporary file for writing.
+ * The file is not visible in the filesystem. */
+FILE *got_opentemp(void);
blob - 162c91475aa774b4a122e8cfec1eef07f938db6e
blob + 35425149aec6f9f82de230270de16cf37bb95705
--- lib/repository.c
+++ lib/repository.c
#define GOT_REFS_DIR "refs"
#define GOT_HEAD_FILE "HEAD"
+/* Other files and directories inside the git directory. */
#define GOT_FETCH_HEAD_FILE "FETCH_HEAD"
#define GOT_ORIG_HEAD_FILE "ORIG_HEAD"
+#define GOT_OBJECTS_PACK_DIR "objects/pack"
char *
got_repo_get_path_git_dir(struct got_repository *repo)
}
char *
+got_repo_get_path_objects_pack(struct got_repository *repo)
+{
+ return get_path_git_child(repo, GOT_OBJECTS_PACK_DIR);
+}
+
+char *
got_repo_get_path_refs(struct got_repository *repo)
{
return get_path_git_child(repo, GOT_REFS_DIR);
blob - e6058f894daa451ecd640fb5d2a0e836c8237a19
blob + a4ddd9d3a24fd55f76b3178e99a7ee145660c9a7
--- lib/sha1.c
+++ lib/sha1.c
/*
- * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>
+ * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include <sys/types.h>
#include <sha1.h>
#include <errno.h>
+#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
return 1;
}
+
+char *
+got_sha1_digest_to_str(const uint8_t *digest, char *buf, size_t size)
+{
+ char *p = buf;
+ char hex[3];
+ int i;
+
+ if (size < SHA1_DIGEST_STRING_LENGTH)
+ return NULL;
+
+ for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
+ snprintf(hex, sizeof(hex), "%.2x", digest[i]);
+ p[0] = hex[0];
+ p[1] = hex[1];
+ p += 2;
+ }
+ p[0] = '\0';
+
+ return buf;
+}
blob - 829b06d7cb1532e0343af4928d7ce406f568369b
blob + 21b28bc395ccfabde390d43e0eccb28fe26e1dee
--- regress/packfiles/Makefile
+++ regress/packfiles/Makefile
.PATH:${.CURDIR}/../../lib
PROG = packfile_test
-SRCS = error.c pack.c packfile_test.c
+SRCS = error.c pack.c repository.c object.c path.c sha1.c packfile_test.c
CPPFLAGS = -I${.CURDIR}/../../include -I${.CURDIR}/../../lib
-LDADD =
+LDADD = -lutil -lz
DEBUG = -O0 -g
NOMAN = yes
blob - fbe9c7437fe13d12c10a9584e75e2894a0943d46
blob + 4217a2737bf95376fc1e1b96daed4ea4ec97123e
--- regress/packfiles/packfile_test.c
+++ regress/packfiles/packfile_test.c
*/
#include <sys/stat.h>
+#include <sys/queue.h>
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
#include "got_error.h"
+#include "got_object.h"
#include "pack.h"
#define RUN_TEST(expr, name) \
- if (!(expr)) { printf("test %s failed", (name)); failure = 1; }
+ if (!(expr)) { printf("test %s failed\n", (name)); failure = 1; }
#define GOT_REPO_PATH "../../../"
blob - c1000921691f14bd6c3e1465b6e913321d140b5b
blob + 29207702c74a55aadd942a3cbc380e667852e237
--- regress/repository/Makefile
+++ regress/repository/Makefile
PROG = repository_test
SRCS = path.c repository.c error.c refs.c object.c sha1.c diff.c \
- diffreg.c xmalloc.c repository_test.c
+ diffreg.c xmalloc.c pack.c repository_test.c
CPPFLAGS = -I${.CURDIR}/../../include
LDADD = -lutil -lz
blob - 6abb0c9084000310bda6227a507778b6316756c2
blob + 8fd30992c9434f52ee5debdc68bdf0bbf2a550c3
--- regress/repository/repository_test.c
+++ regress/repository/repository_test.c
#include "got_diff.h"
#define RUN_TEST(expr, name) \
- if (!(expr)) { printf("test %s failed", (name)); failure = 1; }
+ if (!(expr)) { printf("test %s failed\n", (name)); failure = 1; }
#define GOT_REPO_PATH "../../../"