// +build linux package machineid /* #include #include #ifdef USE_MMAP #include #ifndef MAP_FAILED #define MAP_FAILED ((void *) -1) #endif #endif #include #include #include #include #include #include #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 }