Beispiel #1
0
// Documented in header.
char *utf8DupFromZstring(zstring string) {
    zint size = utf8SizeFromZstring(string) + 1;  // `+1` for the final `\0`.
    char *result = utilAlloc(size);

    utf8FromZstring(size, result, string);
    return result;
}
Beispiel #2
0
// Documented in header.
char *utilReadLink(const char *path) {
    struct stat statBuf;

    if (lstat(path, &statBuf) != 0) {
        if ((errno == ENOENT) || (errno == ENOTDIR)) {
            // File not found or invalid component, neither of which are
            // really errors from the perspective of this function.
            errno = 0;
            return NULL;
        }
        die("Trouble with `lstat`: %s", strerror(errno));
    } else if (!S_ISLNK(statBuf.st_mode)) {
        // Not a symlink.
        errno = 0;
        return NULL;
    }

    // If `st_size` is non-zero, then it can safely be used as the size of
    // the link data. However, on Linux some valid links (particularly, those
    // in `/proc/`) will have `st_size` reported as `0`. In such cases, we
    // use an ample but fixed-size buffer, and hope for the best.

    bool assumeSize = (statBuf.st_size == 0);
    size_t linkSz = assumeSize ? 500 : statBuf.st_size;
    char *result = utilAlloc(linkSz + 1);
    ssize_t resultSz = readlink(path, result, linkSz);

    if (resultSz < 0) {
        die("Trouble with `readlink`: %s", strerror(errno));
    } else if (assumeSize ? (resultSz > linkSz) : (resultSz != linkSz)) {
        die("Strange `readlink` result: %d", (zint) resultSz);
    }

    result[resultSz] = '\0';
    return result;
}