You are not logged in.
Hello,
I need help understanding how gethostid() and sethostid() from glibc work. These functions can be viewed here: gethostid.c. This file contains the functions for getting and setting the hostid in /etc/hostid used by /usr/bin/hostid. /etc/hostid is a 4 byte binary file.
So, when you run /usr/bin/hostid and /etc/hostid does not exist, it will print to stdout a generated hostid in hex. So on my machine I get
007f0100
. This number needs to be included into /etc/hostid, so next I use
printf $(echo -n 007F0100 | sed 's/\([0-9A-F]\{2\}\)/\\\\x\1/gI') >/etc/hostid
and to check the file I use
$ od -A n -t x1
> 00 7f 01 00
Which seems correct.
However, when I again use /usr/bin/hostid, it produces
00017f00
which is backwards. My machine is little endian, so the printf above should be correct. I could simply reverse the string above with another bash command, but I must figure out what is going on. So next I use a compiled c program to use sethostid()
#include <stdio.h>
#include <unistd.h>
int main() {
long id,res;
id = gethostid();
printf("current hostid is: %x\n",id);
// set new hostid if is superuser
res = sethostid(0x01020304);
if (res == 0) printf("if result is zero - success! (%d) \n",res);
id = gethostid();
printf("current hostid is: %x\n",id);
}
$ cc sethostid.c
# ./a.out
> current hostid is: 17f00
> if result is zero - success! (0)
> current hostid is: 11223344
od -A n -t x1
> 44 33 22 11
So my question is, why is sethostid() saving the hex backwards and gethostid() outputting it back reversed? My machine is little endian, so shouldn't this value be from left to right? I'm missing something, please help.
Thanks!
Offline
The command you're using to set it is incorrect.
sed is a stream editor. It takes "00", translates it into a byte with the hex value 0, and spits it out, followed by 7f, etc. sed knows nothing of endianness; it just manipulates bytes. So you write the following four bytes to the file: 00 7f 01 00. od tells you what you already know: the order of bytes in the file.
But the file's format isn't "four bytes"; it's an integer. A little-endian, 32-bit integer. The first byte is the least significant. The last byte is the most significant. gethostid (presumably, at some point) loads this 4-byte value into a register, and it's no longer four distinct bytes: it's one value, 0x00017f00. Which is then converted by printf into standard written form (which is big-endian; printf() operates on values, not representations).
tl;dr -- you're packing the number into the file, big end first. Oops.
Offline
After Trent's comment and reading this: http://phoxis.org/2010/01/28/little-big … onversion/ I realized I had my endianess backwards in my head. The hostid file is LSB first, but I was putting the MSB first (which I thought was really the LSB). Stupid me.
Here is the revised printf:
printf $(echo -n 007F0100 | sed 's/\(..\)\(..\)\(..\)\(..\)/\\x\4\\x\3\\x\2\\x\1/') >/etc/hostid
It uses sed to reverse the hostid and add format specifiers for printf to write the data.
\x00\x01\x7F\x00
Thanks!
Offline
Glad you figured it out; endianness is one of those things that's hard to describe verbally without pretty pictures and occasional hand gestures, so I wasn't sure I was conveying the right impression
Offline