/****************************************************************************
* bfs *
* Copyright (C) 2015-2021 Tavian Barnes <tavianator@tavianator.com> *
* *
* Permission to use, copy, modify, and/or distribute this software for any *
* purpose with or without fee is hereby granted. *
* *
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES *
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR *
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES *
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN *
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
****************************************************************************/
#include "color.h"
#include "bftw.h"
#include "dir.h"
#include "dstring.h"
#include "expr.h"
#include "fsade.h"
#include "stat.h"
#include "trie.h"
#include "util.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
/**
* The parsed form of LS_COLORS.
*/
struct colors {
char *reset;
char *leftcode;
char *rightcode;
char *endcode;
char *clear_to_eol;
char *bold;
char *gray;
char *red;
char *green;
char *yellow;
char *blue;
char *magenta;
char *cyan;
char *white;
char *warning;
char *error;
char *normal;
char *file;
char *multi_hard;
char *executable;
char *capable;
char *setgid;
char *setuid;
char *directory;
char *sticky;
char *other_writable;
char *sticky_other_writable;
char *link;
char *orphan;
char *missing;
bool link_as_target;
char *blockdev;
char *chardev;
char *door;
char *pipe;
char *socket;
/** A mapping from color names (fi, di, ln, etc.) to struct fields. */
struct trie names;
/** A mapping from file extensions to colors. */
struct trie ext_colors;
};
/** Initialize a color in the table. */
static int init_color(struct colors *colors, const char *name, const char *value, char **field) {
if (value) {
*field = dstrdup(value);
if (!*field) {
return -1;
}
} else {
*field = NULL;
}
struct trie_leaf *leaf = trie_insert_str(&colors->names, name);
if (leaf) {
leaf->value = field;
return 0;
} else {
return -1;
}
}
/** Get a color from the table. */
static char **get_color(const struct colors *colors, const char *name) {
const struct trie_leaf *leaf = trie_find_str(&colors->names, name);
if (leaf) {
return (char **)leaf->value;
} else {
return NULL;
}
}
/** Set the value of a color. */
static int set_color(struct colors *colors, const char *name, char *value) {
char **color = get_color(colors, name);
if (color) {
dstrfree(*color);
*color = value;
return 0;
} else {
return -1;
}
}
/**
* Transform a file extension for fast lookups, by reversing and lowercasing it.
*/
static void extxfrm(char *ext) {
size_t len = strlen(ext);
for (size_t i = 0; i < len - i; ++i) {
char a = ext[i];
char b = ext[len