/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include <errno.h>
#include <fnmatch.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>

#include "sd-hwdb.h"

#include "alloc-util.h"
#include "device-util.h"
#include "hwdb-util.h"
#include "parse-util.h"
#include "string-util.h"
#include "udev-builtin.h"

static sd_hwdb *hwdb;

int udev_builtin_hwdb_lookup(sd_device *dev,
                             const char *prefix, const char *modalias,
                             const char *filter, bool test) {
        _cleanup_free_ char *lookup = NULL;
        const char *key, *value;
        int n = 0, r;

        if (!hwdb)
                return -ENOENT;

        if (prefix) {
                lookup = strjoin(prefix, modalias);
                if (!lookup)
                        return -ENOMEM;
                modalias = lookup;
        }

        SD_HWDB_FOREACH_PROPERTY(hwdb, modalias, key, value) {
                if (filter && fnmatch(filter, key, FNM_NOESCAPE) != 0)
                        continue;

                r = udev_builtin_add_property(dev, test, key, value);
                if (r < 0)
                        return r;
                n++;
        }
        return n;
}

static const char *modalias_usb(sd_device *dev, char *s, size_t size) {
        const char *v, *p, *n = NULL;
        uint16_t vn, pn;

        if (sd_device_get_sysattr_value(dev, "idVendor", &v) < 0)
                return NULL;
        if (sd_device_get_sysattr_value(dev, "idProduct", &p) < 0)
                return NULL;
        if (safe_atoux16(v, &vn) < 0)
                return NULL;
        if (safe_atoux16(p, &pn) < 0)
                return NULL;
        (void) sd_device_get_sysattr_value(dev, "product", &n);

        (void) snprintf(s, size, "usb:v%04Xp%04X:%s", vn, pn, strempty(n));
        return s;
}

static int udev_builtin_hwdb_search(sd_device *dev, sd_device *srcdev,
                                    const char *subsystem, const char *prefix,
                                    const char *filter, bool test) {
        char s[LINE_MAX];
        bool last = false;
        int r = 0;

        assert(dev);

        if (!srcdev)
                srcdev = dev;

        for (sd_device *d = srcdev; d; ) {
                const char *dsubsys, *devtype, *modalias = NULL;

                if (sd_device_get_subsystem(d, &dsubsys) < 0)
                        goto next;

                /* look only at devices of a specific subsystem */
                if (subsystem && !streq(dsubsys, subsystem))
                        goto next;

                (void) sd_device_get_property_value(d, "MODALIAS", &modalias);

                if (streq(dsubsys, "usb") &&
                    sd_device_get_devtype(d, &devtype) >= 0 &&
                    streq(devtype, "usb_device")) {
                        /* if the usb_device does not have a modalias, compose one */
                        if (!modalias)
                                modalias = modalias_usb(d, s, sizeof(s));

                        /* avoid looking at any parent device, they are usually just a USB hub */
                        last = true;
                }

                if (!modalias)
                        goto next;

                log_device_debug(dev, "hwdb modalias key: \"%s\"", modalias);

                r = udev_builtin_hwdb_lookup(dev, prefix, modalias, filter, test);
                if (r > 0)
                        break;

                if (last)
                        break;
next:
                if (sd_device_get_parent(d, &d) < 0)
                        break;
        }

        return r;
}

static int builtin_hwdb(sd_device *dev, sd_netlink **rtnl, int argc, char *argv[], bool test) {
        static const struct option options[] = {
                { "filter", required_argument, NULL, 'f' },
                { "device", required_argument, NULL, 'd' },
                { "subsystem", required_argument, NULL, 's' },
                { "lookup-prefix", required_argument, NULL, 'p' },
                {}
        };
        const char *filter = NULL;
        const char *device = NULL;
        const char *subsystem = NULL;
        const char *prefix = NULL;
        _cleanup_(sd_device_unrefp) sd_device *srcdev = NULL;
        int r;

        if (!hwdb)
                return -EINVAL;

        for (;;) {
                int option;

                option = getopt_long(argc, argv, "f:d:s:p:", options, NULL);
                if (option == -1)
                        break;

                switch (option) {
                case 'f':
                        filter = optarg;
                        break;

                case 'd':
                        device = optarg;
                        break;

                case 's':
                        subsystem = optarg;
                        break;

                case 'p':
                        prefix = optarg;
                        break;
                }
        }

        /* query a specific key given as argument */
        if (argv[optind]) {
                r = udev_builtin_hwdb_lookup(dev, prefix, argv[optind], filter, test);
                if (r < 0)
                        return log_device_debug_errno(dev, r, "Failed to look up hwdb: %m");
                if (r == 0)
                        return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENODATA), "No entry found from hwdb.");
                return r;
        }

        /* read data from another device than the device we will store the data */
        if (device) {
                r = sd_device_new_from_device_id(&srcdev, device);
                if (r < 0)
                        return log_device_debug_errno(dev, r, "Failed to create sd_device object '%s': %m", device);
        }

        r = udev_builtin_hwdb_search(dev, srcdev, subsystem, prefix, filter, test);
        if (r < 0)
                return log_device_debug_errno(dev, r, "Failed to look up hwdb: %m");
        if (r == 0)
                return log_device_debug_errno(dev, SYNTHETIC_ERRNO(ENODATA), "No entry found from hwdb.");
        return r;
}

/* called at udev startup and reload */
static int builtin_hwdb_init(void) {
        int r;

        if (hwdb)
                return 0;

        r = sd_hwdb_new(&hwdb);
        if (r < 0)
                return r;

        return 0;
}

/* called on udev shutdown and reload request */
static void builtin_hwdb_exit(void) {
        hwdb = sd_hwdb_unref(hwdb);
}

/* called every couple of seconds during event activity; 'true' if config has changed */
static bool builtin_hwdb_should_reload(void) {
        if (hwdb_should_reload(hwdb)) {
                log_debug("hwdb needs reloading.");
                return true;
        }

        return false;
}

const UdevBuiltin udev_builtin_hwdb = {
        .name = "hwdb",
        .cmd = builtin_hwdb,
        .init = builtin_hwdb_init,
        .exit = builtin_hwdb_exit,
        .should_reload = builtin_hwdb_should_reload,
        .help = "Hardware database",
};
