How to treat libgit2 blobs as file handles

I figured I’d document the solution to my hyper-specific problem in case anyone in the future has the same issue.

So here’s the setup: I am using libgit2 to operate on the contents of some files stored in a repository and I would like to pass the contents of a blob (i.e. a piece of data in the Git store) to foo, but libgit2 only lets me access the content of the blob through git_blob_rawcontent which returns a char * and foo only operates on FILE *s.

The POSIX standard comes to the rescue! It defines the special function fmemopen which allows one to construct a file handle from a piece of memory. Here’s an example from the docs:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static char buffer[] = "foobar";

int main (void)
{
    int ch;
    FILE *stream;

    stream = fmemopen(buffer, strlen (buffer), "r");
    if (stream == NULL) {
        perror("failed to fmemopen buffer");
        exit(EXIT_FAILURE);
    }

    while ((ch = fgetc(stream)) != EOF) {
        printf("Got %c\n", ch);
    }

    fclose(stream);
    return EXIT_SUCCESS;
}

It produces the following output.

Got f
Got o
Got o
Got b
Got a
Got r

Just what I was looking for! With this I can wrap the result of git_blob_rawcontent in a FILE * and pass it to foo.

#include <git2.h>
#include <stdio.h>
git_blob *blob = /* ... */;
FILE *fp = fmemopen(git_blob_rawcontent(blob), git_blob_rawsize(blob), "rb");
foo(fp);

Hopefully this is the solution to your hyper-specific problem as well :^)