commit - 6c00b54532f90be3b76dd1aed025376a35dc35de
commit + 3ee5fc2109eca572a496f0da1a80fecfc8b56aea
blob - ebe18b51f48a920944e61349e59e0a689b6ef282
blob + b85bd54d8416997549d793f8e47ea9dc6dc802ed
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_BAD_PACKFILE 16
#define GOT_ERR_NO_OBJ 17
#define GOT_ERR_NOT_IMPL 18
+#define GOT_ERR_OBJ_NOT_PACKED 19
static const struct got_error {
int code;
{ GOT_ERR_BAD_PACKFILE, "bad pack file" },
{ GOT_ERR_NO_OBJ, "object not found" },
{ GOT_ERR_NOT_IMPL, "feature not implemented" },
+ { GOT_ERR_OBJ_NOT_PACKED,"object is not packed" },
};
const struct got_error * got_error(int code);
blob - f3581b6726ebe6258178022ac2703b58f32165bb
blob + 96d336a171264be9c2e02e38fbaa135a7859c3aa
--- lib/object.c
+++ lib/object.c
const struct got_error *err = NULL;
char *path;
- if (obj->flags & GOT_OBJ_FLAG_PACKED) {
- return got_error(GOT_ERR_NOT_IMPL);
- }
+ if (obj->flags & GOT_OBJ_FLAG_PACKED)
+ return got_packfile_extract_object(f, obj, repo);
err = object_path(&path, &obj->id, repo);
if (err)
blob - 7e7325a8f390d9822562634b04bd0eb7fc9da742
blob + 32b5af0d196466272bd3893c0d65454a8f1e4509
--- lib/pack.c
+++ lib/pack.c
}
static const struct got_error *
-decode_type_and_size(uint8_t *type, uint64_t *size, FILE *packfile)
+decode_type_and_size(uint8_t *type, uint64_t *size, size_t *len, FILE *packfile)
{
uint8_t t = 0;
uint64_t s = 0;
*type = t;
*size = s;
+ *len = i * sizeof(sizeN);
return NULL;
}
FILE *packfile;
uint8_t type;
uint64_t size;
+ size_t tslen;
*obj = NULL;
if (idx == -1) /* object not found in pack index */
goto done;
}
- err = decode_type_and_size(&type, &size, packfile);
+ err = decode_type_and_size(&type, &size, &tslen, packfile);
if (err)
goto done;
(*obj)->hdrlen = 0;
(*obj)->size = size;
memcpy(&(*obj)->id, id, sizeof((*obj)->id));
- (*obj)->pack_offset = offset;
+ (*obj)->pack_offset = offset + tslen;
break;
case GOT_OBJ_TYPE_REF_DELTA:
case GOT_OBJ_TYPE_TAG:
done:
free(path_packdir);
if (packdir && closedir(packdir) != 0 && err == 0)
+ err = got_error_from_errno();
+ return err;
+}
+
+static const struct got_error *
+dump_plain_object(FILE *infile, uint8_t type, size_t size, FILE *outfile)
+{
+ size_t n;
+
+ while (size > 0) {
+ uint8_t data[2048];
+ size_t len = MIN(size, sizeof(data));
+
+ n = fread(data, len, 1, infile);
+ if (n != 1)
+ return got_ferror(infile, GOT_ERR_BAD_PACKIDX);
+
+ n = fwrite(data, len, 1, outfile);
+ if (n != 1)
+ return got_ferror(outfile, GOT_ERR_BAD_PACKIDX);
+
+ size -= len;
+ }
+
+ rewind(outfile);
+ return NULL;
+}
+
+const struct got_error *
+got_packfile_extract_object(FILE **f, struct got_object *obj,
+ struct got_repository *repo)
+{
+ const struct got_error *err = NULL;
+ FILE *packfile = NULL;
+
+ if ((obj->flags & GOT_OBJ_FLAG_PACKED) == 0)
+ return got_error(GOT_ERR_OBJ_NOT_PACKED);
+
+ *f = got_opentemp();
+ if (*f == NULL) {
+ err = got_error(GOT_ERR_FILE_OPEN);
+ goto done;
+ }
+
+ packfile = fopen(obj->path_packfile, "rb");
+ if (packfile == NULL) {
err = got_error_from_errno();
+ goto done;
+ }
+
+ if (fseeko(packfile, obj->pack_offset, SEEK_SET) != 0) {
+ err = got_error_from_errno();
+ goto done;
+ }
+
+ switch (obj->type) {
+ case GOT_OBJ_TYPE_COMMIT:
+ case GOT_OBJ_TYPE_TREE:
+ case GOT_OBJ_TYPE_BLOB:
+ err = dump_plain_object(packfile, obj->type, obj->size, *f);
+ break;
+ case GOT_OBJ_TYPE_REF_DELTA:
+ case GOT_OBJ_TYPE_TAG:
+ case GOT_OBJ_TYPE_OFFSET_DELTA:
+ default:
+ err = got_error(GOT_ERR_NOT_IMPL);
+ goto done;
+ }
+done:
+ if (packfile)
+ fclose(packfile);
+ if (err && *f)
+ fclose(*f);
return err;
}
blob - e26be48fe9e5fa02953cf19e02932e77d46a40d5
blob + 18a6071e88706cf03a4eb280c3b30f5cd73fc425
--- lib/pack.h
+++ lib/pack.h
const struct got_error *got_packfile_open_object(struct got_object **,
struct got_object_id *, struct got_repository *);
+const struct got_error *got_packfile_extract_object(FILE **,
+ struct got_object *, struct got_repository *);