0

I'm trying to improve Facter on FreeBSD. Previously this was Ruby code, so it was fairly easy to grok as a Ruby programmer. Since Facter's 3.X release it's mainly shifted to C/C++ for performance.

During this shift, it's lost some facts, such as on FreebSD. I'm trying to add them back. However, I'm not a C++/C programmer, so I've basically just been reading other people's C code for FreeBSD and adapting it.

So I think I'm in the right direction with this:

facter/lib/inc/internal/facts/freebsd/dmi_resolver.hpp

/**
 * @file
 * Declares the FreeBSD Desktop Management Interface (DMI) fact resolver.
 */
#pragma once

#include "../resolvers/dmi_resolver.hpp"

namespace facter { namespace facts { namespace freebsd {

    /**
     * Responsible for resolving DMI facts.
     */
    struct dmi_resolver : resolvers::dmi_resolver
    {
     protected:
        /**
         * Collects the resolver data.
         * @param facts The fact collection that is resolving facts.
         * @return Returns the resolver data.
         */
        virtual data collect_data(collection& facts) override;

     private:
        std::string sysctl_lookup(int mib);
    };

}}}  // namespace facter::facts::openbsd

facter/lib/src/facts/freebsd/dmi_resolver.cc

#include <internal/facts/freebsd/dmi_resolver.hpp>
#include <leatherman/logging/logging.hpp>

#include <kenv.h>

using namespace std;

namespace facter { namespace facts { namespace freebsd {

    dmi_resolver::data dmi_resolver::collect_data(collection& facts)
    {
        data result;
        result.bios_vendor = kenv_lookup("smbios.bios.vendor");
        result.uuid = kenv_lookup("smbios.system.uuid");
        result.serial_number = kenv_lookup("smbios.planar.serial");
        result.product_name = kenv_lookup("smbios.system.product");
        result.bios_version = kenv_lookup("smbios.bios.vendor");

        return result;
    }

    string dmi_resolver::kenv_lookup(char file)
    {
        char buffer[100] = {};

        LOG_DEBUG("localchassis", "DMI request for %s", file);
        if (kenv(KENV_GET, file, buffer, sizeof(buffer) - 1) == -1) {
            LOG_DEBUG("localchassis", "cannot get %s", file);
            return "";
        }
        return buffer;
    }

} } }  // namespace facter::facts::freebsd

But when I run this I get the following errors:

/root/facter/lib/src/facts/freebsd/dmi_resolver.cc:13:42: error: conversion from string literal to 'char *' is deprecated
      [-Werror,-Wc++11-compat-deprecated-writable-strings]
        result.bios_vendor = kenv_lookup("smbios.bios.vendor");
                                         ^
/root/facter/lib/src/facts/freebsd/dmi_resolver.cc:14:35: error: conversion from string literal to 'char *' is deprecated
      [-Werror,-Wc++11-compat-deprecated-writable-strings]
        result.uuid = kenv_lookup("smbios.system.uuid");
                                  ^
/root/facter/lib/src/facts/freebsd/dmi_resolver.cc:15:44: error: conversion from string literal to 'char *' is deprecated
      [-Werror,-Wc++11-compat-deprecated-writable-strings]
        result.serial_number = kenv_lookup("smbios.planar.serial");
                                           ^
/root/facter/lib/src/facts/freebsd/dmi_resolver.cc:16:43: error: conversion from string literal to 'char *' is deprecated
      [-Werror,-Wc++11-compat-deprecated-writable-strings]
        result.product_name = kenv_lookup("smbios.system.product");
                                          ^
/root/facter/lib/src/facts/freebsd/dmi_resolver.cc:17:43: error: conversion from string literal to 'char *' is deprecated
      [-Werror,-Wc++11-compat-deprecated-writable-strings]
        result.bios_version = kenv_lookup("smbios.bios.vendor");
                                          ^
/root/facter/lib/src/facts/freebsd/dmi_resolver.cc:22:26: error: out-of-line definition of 'kenv_lookup' does not match any
      declaration in 'facter::facts::freebsd::dmi_resolver'
    string dmi_resolver::kenv_lookup(char file)
                         ^~~~~~~~~~~
/root/facter/lib/inc/internal/facts/freebsd/dmi_resolver.hpp:25:33: note: type of 1st parameter of member declaration does not
      match definition ('char *' vs 'char')
        std::string kenv_lookup(char *file);
                                ^
/root/facter/lib/src/facts/freebsd/dmi_resolver.cc:27:13: error: no matching function for call to 'kenv'
        if (kenv(KENV_GET, file, buffer, sizeof(buffer) - 1) == -1) {
            ^~~~
/usr/include/kenv.h:36:5: note: candidate function not viable: no known conversion from 'char' to 'const char *' for 2nd argument;
      take the address of the argument with &
int kenv(int, const char *, char *, int);
    ^

How do I fix this?

Peter Souter
  • 5,110
  • 1
  • 33
  • 62
  • 3
    You have `kenv_lookup(char file)`, should that be a `char*` or `const char*`? – Richard Smith Jun 04 '16 at 17:58
  • Wow, that was a super simple fix heh, changed it to `const char* file` in both and it worked! Do you want to add that as an answer and I can mark it as accepted? :) – Peter Souter Jun 04 '16 at 18:13

1 Answers1

0

Richard Smith was correct. The working code was the following

/Users/petersouter/projects/facter/lib/src/facts/freebsd/dmi_resolver.cc

#include <internal/facts/freebsd/dmi_resolver.hpp>
#include <leatherman/logging/logging.hpp>

#include <kenv.h>

using namespace std;

namespace facter { namespace facts { namespace freebsd {

    dmi_resolver::data dmi_resolver::collect_data(collection& facts)
    {
        data result;
        result.bios_vendor = kenv_lookup("smbios.bios.vendor");
        result.bios_version = kenv_lookup("smbios.bios.version");
        result.bios_release_date = kenv_lookup("smbios.bios.reldate");
        result.uuid = kenv_lookup("smbios.system.uuid");
        result.serial_number = kenv_lookup("smbios.planar.serial");
        result.product_name = kenv_lookup("smbios.system.product");
        result.manufacturer = kenv_lookup("smbios.system.maker");

        return result;
    }

    string dmi_resolver::kenv_lookup(const char* file)
    {
        char buffer[100] = {};

        LOG_DEBUG("kenv lookup for %s", file);
        if (kenv(KENV_GET, file, buffer, sizeof(buffer) - 1) == -1) {
            LOG_WARNING("kenv lookup for %1% failed: %2% (%3%)", file, strerror(errno), errno);
            return "";
        }
        return buffer;
    }

} } }  // namespace facter::facts::freebsd

facter/lib/inc/internal/facts/freebsd/dmi_resolver.hpp

/**
 * @file
 * Declares the FreeBSD Desktop Management Interface (DMI) fact resolver.
 */
#pragma once

#include "../resolvers/dmi_resolver.hpp"

namespace facter { namespace facts { namespace freebsd {

    /**
     * Responsible for resolving DMI facts.
     */
    struct dmi_resolver : resolvers::dmi_resolver
    {
     protected:
        /**
         * Collects the resolver data.
         * @param facts The fact collection that is resolving facts.
         * @return Returns the resolver data.
         */
        virtual data collect_data(collection& facts) override;

     private:
        static std::string kenv_lookup(const char* file);
    };

}}}  // namespace facter::facts::freebsd
Peter Souter
  • 5,110
  • 1
  • 33
  • 62