Cross-platform C89 library to get a platform identifier, libmachineid will
attempt to gather a system identifier. If one cannot be determined a random
identifier is generated. The system identifier is hashed, and then optionally
truncated and converted to a UUIDv4 representation.
An example on Ubuntu:
sudo apt-get -y update
sudo apt-get install -y build-essential cmake git
git clone https://github.com/harporoeder/libmachineid.git
cd libmachineid
mkdir build
cmake ..
make
./test
> machine id: 4f6d8e5d-3837-473a-a707-8ec1f310e717
> error: MACHINEID_ERROR_NONEDuring utilization of machineid_generate an error may be returned of the
type enum machineid_error. Error conditions should be checked to ensure
that the result buffer will actually contain a valid result.
MACHINEID_ERROR_NONEAn identifier was successfully found.MACHINEID_ERROR_RNGAn identifier was not found and the random number generator also failed. No result is provided in this case.MACHINEID_ERROR_NULL_OUTPUT_BUFFERThe library was utilized incorrectly, and nowhere to store the result was indicated. No result is provided in this case.MACHINEID_ERROR_FALLBACKAn identifier was not found, but a fallback was successfully generatedMACHINEID_HASH_FAILUREThe library utilized for hashing returned an error. No result is provided in this case.
Error cases can be converted to a constant string with
machineid_error_to_string. This is likely useful for logging failures. The
library will never log of it's own volition.
Bit flags of the type enum machineid_flags are provided to control the
desired behavior of machineid_generate.
MACHINEID_FLAG_DEFAULTThe default behavior of placing a raw digest in the result buffer. This flag is only required when no other flags are used. When using this mode the result buffer must be at leastMACHINEID_HASH_SIZEin size.MACHINEID_FLAG_AS_UUIDInstead of returning a raw digest in the result buffer, truncate the digest and encode it as a UUIDv4. In this mode the result buffer must be at leastMACHINEID_UUID_SIZEin size.MACHINEID_FLAG_NULL_TERMINATEThe character'\0'will be inserted at the end of the result. When using this flag the result buffer must be eitherMACHINEID_HASH_SIZE + 1, orMACHINEID_UUID_SIZE + 1as a minimum size depending on the other flags used.
#include <stdio.h>
#include "machineid.h"
int main() {
enum machineid_error err;
unsigned char buffer[MACHINEID_UUID_SIZE + 1];
err = machineid_generate(buffer, MACHINEID_FLAG_AS_UUID
| MACHINEID_FLAG_NULL_TERMINATE);
printf("error: %s\n", machineid_error_to_string(err));
if (err != MACHINEID_ERROR_NONE && err != MACHINEID_ERROR_FALLBACK) {
return 1;
}
printf("machine id: %s\n", buffer);
return 0;
}For convenience libmachineid provides a vendored implementation of SHA256,
and platform specific random number generation capabilities. I recommend if
possible utilizing an external cryptography library. Support is available for
sodium, or openssl.
- To build with
sodiumusecmake -D MACHINEID_USE_SODIUM=ON .. - To build with
opensslusecmake -D MACHINEID_USE_OPENSSL=ON ..
When compiled with either of those options the vendored SHA256 will not be
built, and random number generation will switch to using them.
The projected has been tested on Windows, MacOS, Linux, FreeBSD, and OpenBSD. If a platform does not have first class support it will gracefully degrade with reduced functionality.
If you need support for a specific platform that is not already handled open an issue and it can likely be added contingent on my ability to test against it.
The projected has been tested with Clang, MSVC, GCC, and TCC.
If you need support for additional compilers, and libmachineid does not
already build feel free to open an issue.
This project follows semantic versioning. Additionally
the main branch is maintained in a usable state with development happening
on branches.
There exist 4 declarations inside machineid.h that can be used to
programmatically determine the version. There is a version string of the name
MACHINEID_VERSION, and 3 declarations for each specific component
MACHINEID_VERSION_MAJOR, MACHINEID_VERSION_MINOR,
and MACHINEID_VERSION_PATCH.
While CMake is used in this repository it can be easily avoided based on preference for an alternative build system.
The only notable complication is that you are required to define
MACHINEID_USE_SODIUM, or MACHINEID_USE_OPENSSL if you utilize either of
of those libraries with libmachineid.
On Linux the file /etc/machine-id is used with /var/lib/dbus/machine-id
as an alternative.
On OpenBSD HW_UUID is queried. The file /etc/machine-id is used as an
alternative. DBUS is not installed by default and /etc/machine-id may not
be present.
On FreeBSD the file /etc/hostid is used.
On MacOS the registry key kIOPlatformUUIDKey is queried.
On Windows the registry key MachineGuid is queried.
When built with either sodium or openssl the random number generators
provided by those libraries are always used, otherwise a platform specific
generator is used.
On Windows rand_s is used. For OpenBSD or FreeBSD arc4random_buf is used.
On other platforms rand is used. When using rand you must ensure that you
seed with srand else fallback identifiers will be the same across
instances of your application.
It is common for Docker containers to have neither /var/lib/dbus/machine-id,
or /etc/machine-id. In this instance a fallback is generated. These files
can be made accessible to a container from the host system utilizing volumes:
docker run --rm -it \
-v /etc/machine-id:/etc/machine-id:ro \
ubuntu /bin/bashThis is not a universal property of Docker containers. Some may internally
run DBus, or otherwise provide a machine-id.