예제 #1
0
파일: path.c 프로젝트: atrinik/atrinik
/**
 * Extracts the directory component of a path.
 *
 * Example:
 * @code
 * path_dirname("/usr/local/foobar"); --> "/usr/local"
 * @endcode
 * @param path
 * A path.
 * @return
 * A directory name. This string should be freed when no longer
 * needed.
 * @author Hongli Lai (public domain)
 */
char *path_dirname(const char *path)
{
    const char *end;
    char *result;

    TOOLKIT_PROTECT();

    if (!path) {
        return NULL;
    }

    end = strrchr(path, '/');

    if (!end) {
        return estrdup(".");
    }

    while (end > path && *end == '/') {
        end--;
    }

    result = estrndup(path, end - path + 1);

    if (result[0] == '\0') {
        efree(result);
        return estrdup("/");
    }

    return result;
}
예제 #2
0
파일: path.c 프로젝트: atrinik/atrinik
TOOLKIT_DEINIT_FUNC_FINISH

/**
 * Joins two path components, eg, '/usr' and 'bin' -> '/usr/bin'.
 * @param path
 * First path component.
 * @param path2
 * Second path component.
 * @return
 * The joined path; should be freed when no longer needed.
 */
char *path_join(const char *path, const char *path2)
{
    StringBuffer *sb;
    size_t len;
    char *cp;

    TOOLKIT_PROTECT();

    sb = stringbuffer_new();
    stringbuffer_append_string(sb, path);

    len = strlen(path);

    if (len && path[len - 1] != '/') {
        stringbuffer_append_string(sb, "/");
    }

    stringbuffer_append_string(sb, path2);
    cp = stringbuffer_finish(sb);

    return cp;
}
예제 #3
0
파일: path.c 프로젝트: atrinik/atrinik
/**
 * Copy the contents of file 'src' into 'dst'.
 * @param src
 * Path of the file to copy contents from.
 * @param dst
 * Where to put the contents of 'src'.
 * @param mode
 * Mode to open 'src' in.
 * @return
 * 1 on success, 0 on failure.
 */
int path_copy_file(const char *src, FILE *dst, const char *mode)
{
    FILE *fp;
    char buf[HUGE_BUF];

    TOOLKIT_PROTECT();

    if (!src || !dst || !mode) {
        return 0;
    }

    fp = fopen(src, mode);

    if (!fp) {
        return 0;
    }

    while (fgets(buf, sizeof(buf), fp)) {
        fputs(buf, dst);
    }

    fclose(fp);

    return 1;
}
예제 #4
0
파일: path.c 프로젝트: atrinik/atrinik
/**
 * Normalize a path, eg, foo//bar, foo/foo2/../bar, foo/./bar all become
 * foo/bar.
 *
 * If the path begins with either a forward slash or a dot *and* a forward
 * slash, they will be preserved.
 * @param path
 * Path to normalize.
 * @return
 * The normalized path; never NULL. Must be freed.
 */
char *path_normalize(const char *path)
{
    StringBuffer *sb;
    size_t pos, startsbpos;
    char component[MAX_BUF];
    ssize_t last_slash;

    TOOLKIT_PROTECT();

    if (string_isempty(path)) {
        return estrdup(".");
    }

    sb = stringbuffer_new();
    pos = 0;

    if (string_startswith(path, "/")) {
        stringbuffer_append_string(sb, "/");
    } else if (string_startswith(path, "./")) {
        stringbuffer_append_string(sb, "./");
    }

    startsbpos = stringbuffer_length(sb);

    while (string_get_word(path, &pos, '/', component, sizeof(component), 0)) {
        if (strcmp(component, ".") == 0) {
            continue;
        }

        if (strcmp(component, "..") == 0) {
            if (stringbuffer_length(sb) > startsbpos) {
                last_slash = stringbuffer_rindex(sb, '/');

                if (last_slash == -1) {
                    LOG(BUG, "Should have found a forward slash, but didn't: %s", path);
                    continue;
                }

                stringbuffer_seek(sb, last_slash);
            }
        } else {
            size_t len = stringbuffer_length(sb);
            if (len == 0 || stringbuffer_data(sb)[len - 1] != '/') {
                stringbuffer_append_string(sb, "/");
            }

            stringbuffer_append_string(sb, component);
        }
    }

    if (stringbuffer_length(sb) == 0) {
        stringbuffer_append_string(sb, ".");
    }

    return stringbuffer_finish(sb);
}
예제 #5
0
파일: logger.c 프로젝트: liwcezar/atrinik
/**
 * Default logger printing function, uses fputs to write to stdout.
 * @param str
 * String to print.
 */
void logger_do_print(const char *str)
{
    TOOLKIT_PROTECT();

    fputs(str, stdout);

#ifdef WIN32
    fflush(stdout);
#endif
}
예제 #6
0
파일: path.c 프로젝트: atrinik/atrinik
/**
 * Get size of the specified file, in bytes.
 * @param path
 * Path to the file.
 * @return
 * Size of the file.
 */
size_t path_size(const char *path)
{
    struct stat statbuf;

    TOOLKIT_PROTECT();

    if (stat(path, &statbuf) != 0) {
        return 0;
    }

    return statbuf.st_size;
}
예제 #7
0
파일: logger.c 프로젝트: liwcezar/atrinik
/**
 * Print a message to the console/stdout/log file/etc.
 * @param level
 * Log level to use.
 * @param function
 * Name of the function that is calling this.
 * @param line
 * Line in the code that is calling this.
 * @param format
 * Format string.
 * @param ...
 * Format arguments.
 */
void logger_print(logger_level level, const char *function, uint64_t line,
        const char *format, ...)
{
    char formatted[HUGE_BUF], timebuf[HUGE_BUF], buf[sizeof(formatted) * 2];
    va_list ap;
    struct timeval tv;
    struct tm *tm;

    TOOLKIT_PROTECT();

    /* Safety... */
    if (level >= LOG_MAX) {
        return;
    }

    /* If the log level is unwanted, bail out. */
    if (!((1U << level) & logger_filter_stdout) &&
            !((1U << level) & logger_filter_logfile)) {
        return;
    }

    va_start(ap, format);
    vsnprintf(formatted, sizeof(formatted), format, ap);
    va_end(ap);

    gettimeofday(&tv, NULL);
    tm = localtime(&tv.tv_sec);

    if (tm != NULL) {
        char timebuf2[MAX_BUF];

        strftime(VS(timebuf2), "%H:%M:%S", tm);
        snprintf(VS(timebuf), "[%s.%06"PRIu64 "] ", timebuf2,
                (uint64_t) tv.tv_usec);
    } else {
        timebuf[0] = '\0';
    }

    if ((1U << level) & logger_filter_stdout) {
        snprintf(VS(buf), "%s%s%s""%s%-6s%s ""%s[%s:%" PRIu64 "]%s ""%s%s%s\n",
                LOGGER_ESC_SEQ(BOLD), timebuf, LOGGER_ESC_SEQ(END),
                LOGGER_ESC_SEQ(RED), logger_names[level], LOGGER_ESC_SEQ(END),
                LOGGER_ESC_SEQ(CYAN), function, line, LOGGER_ESC_SEQ(END),
                LOGGER_ESC_SEQ(YELLOW), formatted, LOGGER_ESC_SEQ(END));
        print_func(buf);
    }

    if (log_fp != NULL && (1U << level) & logger_filter_logfile) {
        fprintf(log_fp, "%s%-6s [%s:%"PRIu64 "] %s\n", timebuf,
                logger_names[level], function, line, formatted);
        fflush(log_fp);
    }
}
예제 #8
0
파일: path.c 프로젝트: atrinik/atrinik
/**
 * Check if the specified path exists.
 * @param path
 * Path to check.
 * @return
 * 1 if 'path' exists, 0 otherwise.
 */
int path_exists(const char *path)
{
    struct stat statbuf;

    TOOLKIT_PROTECT();

    if (stat(path, &statbuf) != 0) {
        return 0;
    }

    return 1;
}
예제 #9
0
파일: logger.c 프로젝트: liwcezar/atrinik
TOOLKIT_DEINIT_FUNC_FINISH

/**
 * Open the specified path as a log file.
 * @param path
 * File to open.
 */
void logger_open_log(const char *path)
{
    TOOLKIT_PROTECT();

    if (log_fp != NULL) {
        fclose(log_fp);
    }

    log_fp = fopen(path, "w");
}
예제 #10
0
파일: path.c 프로젝트: atrinik/atrinik
/**
 * Extracts the basename from path.
 *
 * Example:
 * @code
 * path_basename("/usr/bin/kate"); --> "kate"
 * @endcode
 * @param path
 * A path.
 * @return
 * The basename of the path. Should be freed when no longer
 * needed.
 */
char *path_basename(const char *path)
{
    const char *slash;

    TOOLKIT_PROTECT();

    if (!path) {
        return NULL;
    }

    while ((slash = strrchr(path, '/'))) {
        if (*(slash + 1) != '\0') {
            return estrdup(slash + 1);
        }
    }

    return estrdup(path);
}
예제 #11
0
파일: datetime.c 프로젝트: liwcezar/atrinik
TOOLKIT_DEINIT_FUNC_FINISH

/**
 * Get the current UTC time as UNIX timestamp.
 * @return
 * UTC time as UNIX timestamp.
 */
time_t datetime_getutc(void)
{
    time_t t;
    struct tm *tm;

    TOOLKIT_PROTECT();

    time(&t);
    tm = gmtime(&t);

    return mktime(tm);
}
예제 #12
0
파일: path.c 프로젝트: atrinik/atrinik
/**
 * Create a new blank file.
 * @param path
 * Path to the file.
 * @return
 * 1 on success, 0 on failure.
 */
int path_touch(const char *path)
{
    FILE *fp;

    TOOLKIT_PROTECT();

    path_ensure_directories(path);
    fp = fopen(path, "w");

    if (!fp) {
        return 0;
    }

    if (fclose(fp) == EOF) {
        return 0;
    }

    return 1;
}
예제 #13
0
파일: mempool.c 프로젝트: atrinik/atrinik
mempool_struct *
mempool_create (const char           *description,
                size_t                expand,
                size_t                size,
                uint32_t              flags,
                chunk_initialisator   initialisator,
                chunk_deinitialisator deinitialisator,
                chunk_constructor     constructor,
                chunk_destructor      destructor)
{
    size_t i;
    mempool_struct *pool;

    TOOLKIT_PROTECT();

    pool = ecalloc(1, sizeof(*pool));

    pool->chunk_description = description;
    pool->expand_size = expand;
    pool->chunksize = size;
    pool->flags = flags;
    pool->initialisator = initialisator;
    pool->deinitialisator = deinitialisator;
    pool->constructor = constructor;
    pool->destructor = destructor;

    for (i = 0; i < MEMPOOL_NROF_FREELISTS; i++) {
        pool->freelist[i] = &end_marker;
        pool->nrof_free[i] = 0;
        pool->nrof_allocated[i] = 0;
    }

    pools = erealloc(pools, sizeof(*pools) * (pools_num + 1));
    pools[pools_num] = pool;
    pools_num++;

    return pool;
}
예제 #14
0
파일: path.c 프로젝트: atrinik/atrinik
/**
 * Checks whether any directories in the given path don't exist, and
 * creates them if necessary.
 * @param path
 * The path to check.
 */
void path_ensure_directories(const char *path)
{
    char buf[MAXPATHLEN], *cp;
    struct stat statbuf;

    TOOLKIT_PROTECT();

    if (path == NULL || *path == '\0') {
        return;
    }

    snprintf(VS(buf), "%s", path);
    cp = buf;

    while ((cp = strchr(cp + 1, '/')) != NULL) {
        *cp = '\0';

        if (mkdir(buf, 0777) != 0 && errno != EEXIST) {
            LOG(BUG, "Cannot mkdir %s (path: %s): %s", buf, path,
                    strerror(errno));
            return;
        }

        if (stat(buf, &statbuf) != 0) {
            LOG(BUG, "Cannot stat %s (path: %s): %s", buf, path,
                    strerror(errno));
            return;
        }

        if (!S_ISDIR(statbuf.st_mode)) {
            LOG(BUG, "Not a directory: %s (path: %s)", buf, path);
            return;
        }

        *cp = '/';
    }
}
예제 #15
0
파일: path.c 프로젝트: atrinik/atrinik
/**
 * Load the entire contents of file 'path' into a StringBuffer instance,
 * then return the created string.
 * @param path
 * File to load contents of.
 * @return
 * The loaded contents. Must be freed.
 */
char *path_file_contents(const char *path)
{
    FILE *fp;
    StringBuffer *sb;
    char buf[MAX_BUF];

    TOOLKIT_PROTECT();

    fp = fopen(path, "rb");

    if (!fp) {
        return NULL;
    }

    sb = stringbuffer_new();

    while (fgets(buf, sizeof(buf), fp)) {
        stringbuffer_append_string(sb, buf);
    }

    fclose(fp);

    return stringbuffer_finish(sb);
}
예제 #16
0
파일: datetime.c 프로젝트: liwcezar/atrinik
/**
 * Converts UTC time to local time.
 * @param t
 * UTC time.
 * @return
 * Converted local time.
 */
time_t datetime_utctolocal(time_t t)
{
    TOOLKIT_PROTECT();
    return t - (datetime_getutc() - time(NULL));
}
예제 #17
0
파일: logger.c 프로젝트: liwcezar/atrinik
/**
 * Set the logger's printing function.
 * @param func
 * Function to use.
 */
void logger_set_print_func(logger_print_func func)
{
    TOOLKIT_PROTECT();
    print_func = func;
}
예제 #18
0
파일: logger.c 프로젝트: liwcezar/atrinik
/**
 * Acquire the log file pointer.
 * @return
 * Log file pointer. In the case that no log file is currently open,
 * stdout is returned.
 */
FILE *logger_get_logfile(void)
{
    TOOLKIT_PROTECT();
    return log_fp != NULL ? log_fp : stdout;
}