You are not logged in.

#1 2012-11-30 03:40:37

demizer
Member
From: Santa Clara
Registered: 2010-03-03
Posts: 108
Website

Understanding {get,set}hostid() and /usr/bin/hostid

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

#2 2012-11-30 05:17:10

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 986

Re: Understanding {get,set}hostid() and /usr/bin/hostid

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

#3 2012-11-30 06:30:38

demizer
Member
From: Santa Clara
Registered: 2010-03-03
Posts: 108
Website

Re: Understanding {get,set}hostid() and /usr/bin/hostid

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

#4 2012-11-30 13:55:34

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 986

Re: Understanding {get,set}hostid() and /usr/bin/hostid

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

Board footer

Powered by FluxBB