123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- // +build linux
- package machineid
- /*
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifdef USE_MMAP
- #include <sys/mman.h>
- #ifndef MAP_FAILED
- #define MAP_FAILED ((void *) -1)
- #endif
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <fcntl.h>
- #include <errno.h>
- #ifndef TYPES_H
- #define TYPES_H
- typedef unsigned char u8;
- typedef unsigned short u16;
- typedef signed short i16;
- typedef unsigned int u32;
- #ifdef BIGENDIAN
- typedef struct {
- u32 h;
- u32 l;
- } u64;
- #else
- typedef struct {
- u32 l;
- u32 h;
- } u64;
- #endif
- #ifdef ALIGNMENT_WORKAROUND
- static inline u64 U64(u32 low, u32 high)
- {
- u64 self;
- self.l = low;
- self.h = high;
- return self;
- }
- #endif
- #ifdef ALIGNMENT_WORKAROUND
- # ifdef BIGENDIAN
- # define WORD(x) (u16)((x)[1] + ((x)[0] << 8))
- # define DWORD(x) (u32)((x)[3] + ((x)[2] << 8) + ((x)[1] << 16) + ((x)[0] << 24))
- # define QWORD(x) (U64(DWORD(x + 4), DWORD(x)))
- # else
- # define WORD(x) (u16)((x)[0] + ((x)[1] << 8))
- # define DWORD(x) (u32)((x)[0] + ((x)[1] << 8) + ((x)[2] << 16) + ((x)[3] << 24))
- # define QWORD(x) (U64(DWORD(x), DWORD(x + 4)))
- # endif
- #else
- #define WORD(x) (u16)(*(const u16 *)(x))
- #define DWORD(x) (u32)(*(const u32 *)(x))
- #define QWORD(x) (*(const u64 *)(x))
- #endif
- #endif
- struct dmi_header
- {
- u8 type;
- u8 length;
- u16 handle;
- u8 *data;
- };
- static int myread(int fd, u8 *buf, size_t count, const char *prefix)
- {
- ssize_t r = 1;
- size_t r2 = 0;
- while (r2 != count && r != 0)
- {
- r = read(fd, buf + r2, count - r2);
- if (r == -1)
- {
- if (errno != EINTR)
- {
- close(fd);
- perror(prefix);
- return -1;
- }
- }
- else
- r2 += r;
- }
- if (r2 != count)
- {
- close(fd);
- fprintf(stderr, "%s: Unexpected end of file\n", prefix);
- return -1;
- }
- return 0;
- }
- int checksum(const u8 *buf, size_t len)
- {
- u8 sum = 0;
- size_t a;
- for (a = 0; a < len; a++)
- sum += buf[a];
- return (sum == 0);
- }
- void *mem_chunk(size_t base, size_t len, const char *devmem)
- {
- void *p;
- int fd;
- #ifdef USE_MMAP
- size_t mmoffset;
- void *mmp;
- #endif
- if ((fd = open(devmem, O_RDONLY)) == -1)
- {
- perror(devmem);
- return NULL;
- }
- if ((p = malloc(len)) == NULL)
- {
- perror("malloc");
- return NULL;
- }
- #ifdef USE_MMAP
- #ifdef _SC_PAGESIZE
- mmoffset = base % sysconf(_SC_PAGESIZE);
- #else
- mmoffset = base % getpagesize();
- #endif
- mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset);
- if (mmp == MAP_FAILED)
- goto try_read;
- memcpy(p, (u8 *)mmp + mmoffset, len);
- if (munmap(mmp, mmoffset + len) == -1)
- {
- fprintf(stderr, "%s: ", devmem);
- perror("munmap");
- }
- goto out;
- #endif
- try_read:
- if (lseek(fd, base, SEEK_SET) == -1)
- {
- fprintf(stderr, "%s: ", devmem);
- perror("lseek");
- free(p);
- return NULL;
- }
- if (myread(fd, p, len, devmem) == -1)
- {
- free(p);
- return NULL;
- }
- out:
- if (close(fd) == -1)
- perror(devmem);
- return p;
- }
- void to_dmi_header(struct dmi_header *h, u8 *data)
- {
- h->type = data[0];
- h->length = data[1];
- h->handle = WORD(data + 2);
- h->data = data;
- }
- int get_cpuid(char *cpuid)
- {
- char devmem[10] = "/dev/mem";
- u16 len;
- u16 num;
- size_t fp;
- u8 *buf=NULL, *nbuf=NULL, *data, *p;
- int i = 0;
- if ((buf = mem_chunk(0xF0000, 0x10000, devmem)) == NULL)
- {
- free(buf);
- return 0;
- }
- for (fp = 0; fp <= 0xFFF0; fp += 16)
- {
- if(memcmp(buf + fp, "_SM_", 4) == 0 && fp <= 0xFFE0)
- {
- len = WORD(buf + fp + 0x16);
- num = WORD(buf + fp + 0x1C);
- if (!checksum(buf + fp, (buf + fp)[0x05]) || memcmp(buf + fp + 0x10, "_DMI_", 5) != 0 || !checksum(buf + fp + 0x10, 0x0F))
- {
- free(buf);
- return 0;
- }
- if ((nbuf = mem_chunk(DWORD(buf + fp + 0x18), len, devmem)) == NULL)
- {
- fprintf(stderr, "Table is unreachable, sorry.\n");
- free(buf);
- free(nbuf);
- return 0;
- }
- data = nbuf;
- while (i < num && data+4 <= nbuf + len)
- {
- u8 *next;
- struct dmi_header h;
- to_dmi_header(&h, data);
- if (h.length < 4)
- {
- printf("Invalid entry length (%u). DMI table is "
- "broken! Stop.\n\n", (unsigned int)h.length);
- free(buf);
- free(nbuf);
- return 0;
- }
- next = data + h.length;
- while (next - nbuf + 1 < len && (next[0] != 0 || next[1] != 0))
- next++;
- next += 2;
- if (h.type ==4)
- {
- p = h.data + 0x08;
- //printf("CPUID:%02X%02X%02X%02X%02X%02X%02X%02X\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
- sprintf(cpuid, "%02X%02X%02X%02X%02X%02X%02X%02X", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
- free(buf);
- free(nbuf);
- return 1;
- }
- data = next;
- i++;
- }
- fp += 16;
- }
- }
- free(buf);
- free(nbuf);
- return 0;
- }
- */
- import "C"
- import (
- "encoding/hex"
- "io/ioutil"
- )
- func getMachineID() (s string, err error) {
- paths := []string{
- "/var/lib/dbus/machine-id",
- "/etc/machine-id",
- "/sys/class/dmi/id/product_uuid",
- }
- var (
- buf []byte
- )
- for _, p := range paths {
- if buf, err = ioutil.ReadFile(p); err == nil {
- s = string(buf)
- break
- }
- }
- if s == "" {
- buf = make([]byte, 16)
- C.get_cpuid((*C.char)(unsafe.Pointer(&buf[0])))
- s = hex.EncodeToString(buf)
- }
- return
- }
|