Split a file into individually allocated lines
Bugs


If flock() fails, you don't close the file descriptor.  Instead of goto out it should be goto close.
If the file does not end in a newline, you allocate extra space for it but you don't actually fill it in.  This means that you leave your buffer with an uninitialized last character and no null terminator.  Later, in countlines(), your call to memchr() will return NULL if it doesn't find a newline on the last line, and your program will crash.


Simplification #1

This code:


tmp = getlines(buf, size);
if (tmp == NULL)
    goto free;

lns = tmp;



could be simplified to:

lns = getlines(buf, size);


Simplification #2

Instead of allocating *size bytes and then reallocating one extra byte if you need to add an extra newline, just allocate the one extra byte to start with.

Simplification #3

Instead of defining and undefining a macro like this:


#define LENGTH ((end) - (buf) + 1)

ln = malloc(LENGTH + 1);
if (ln == NULL)
    return NULL;
ln[LENGTH] = 0;
(void)memcpy(ln, buf, LENGTH);

#undef LENGTH



just use a variable:

size_t length = end - buf + 1;

ln = malloc(length + 1);
if (ln == NULL)
    return NULL;
ln[length] = 0;
memcpy(ln, buf, length);