Working with paths in C

Today I needed to work with some paths in C99 and I couldn't find good solutions to it if any, so I made my own, here's a small set of functions you can use to work with paths and path-like strings :)

Also I haven't really optimised it so like, if you want to please do optimise it and post it to CaO :)

(BTW this can probably be made to work with C89, but as I am using C99 in this example I don't mind it lol, you can convert it quite easily :))

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

/*
 * Chop a string from index `begin` to index `end`
 * returns a `malloc` pointer casted to `char *`,
 * meaning don't forget to `free()` it
 */
const char *
chop_str(const char *str, const unsigned long begin, const unsigned long end) {
    if (begin >= end)
        return NULL;

    char *buf = (char *)malloc((sizeof str[0]) * (end - begin) + 1);

    unsigned long idx;
    for (idx = begin; idx <= end; ++idx)
        buf[idx - begin] = str[idx];

    buf[idx] = '\0';

    return buf;
}

/*
 * Remove trailing char(s) `chr` (if any) from a a string `str` of length
 * `len`, this function returns a `malloc()` pointer, don't forget to `free()`
 * it
 */
const char *
remove_ntrailing(const char *str, const unsigned long len, const char chr) {
    char *cpy = (char *)malloc(((sizeof str[0]) * len) + 1);
    strncpy(cpy, str, len); // NOLINT

    for (unsigned long idx = len - 1; idx > 0; --idx)
        if (cpy[idx] == chr)
            cpy[idx] = '\0';
        else
            break;

    return cpy;
}
#define remove_trailing(str, chr) remove_ntrailing(str, strlen(str), chr)

/*
 * Get base path of path `path` which is the length of `len`,
 * this is a wrapper around `chop_str()`, which returns a `malloc`
 * pointer, don't forget to free it
 */
const char *get_nbase(const char *path, const unsigned long len) {
    unsigned long last_slash = 0;

    for (unsigned long idx = 0; idx < len; ++idx) {
        if (path[idx] == '/')
            last_slash = idx;
    }

    return chop_str(path, last_slash + 1, strlen(path));
}
#define get_base(path) get_nbase(path, strlen(path))
#define get_bbase(path) get_base(remove_trailing(path, '/'))

The macros are optional, just some nice wrappers, anyway, enjoy :)