Jim's Depository

this code is not written

Sometimes you will find data structures to read that are encoded little-endian. You may find these functions useful. They aren’t as nightmarish to read as macros and presumably your compiler will do right by them.

#include <stdio.h>
#include <arpa/inet.h>/*
** Little endian to host, short
static unsigned short ltohs( unsigned short v)
    if ( htons(1) == 1) {
    return ((v>>8)&0xff) | ((v<<8)&0xff00);
    } else return v;
** Little endian to host, Long
static unsigned long ltohl( unsigned long v)
    if ( htons(1) == 1) {
    return ((v>>24)&0xff) | ((v>>8)&0xff00) | 
               ((v<<8)&0xff0000) | ((v << 24)&0xff000000);
    } else return v;
** Little endian to host, "double" i.e. long long
static unsigned long long ltohd( unsigned long long v)
    if ( htons(1) == 1) {
    return (unsigned long long)ltohl( v&0x00000000ffffffff) << 32 | 
        (unsigned long long)ltohl( (v>>32)&0x00000000ffffffff);
    } else return v;
}int main( int argc, char **argv)
    unsigned char t1[] = { 0x01, 0x02, 0x03, 0x04, 
                           0x05, 0x06, 0x07, 0x08 };
    unsigned char t2[] = { 0xff, 0xfe, 0xfd, 0xfc, 
                           0xfb, 0xfa, 0xf9, 0xf8 };    printf("ltohs(01,02) = %04x\n", ltohs(*(unsigned short *)t1));
    printf("ltohs(ff,fe) = %04x\n", ltohs(*(unsigned short *)t2));
    printf("ltohl(01,02,03,04) = %08x\n", ltohl(*(unsigned long *)t1));
    printf("ltohl(ff,fe,fd,fc) = %08x\n", ltohl(*(unsigned long *)t2));
    printf("ltohd(01,02,03,04,05,06,07,08) = %016llx\n", 
           ltohd(*(unsigned long long *)t1));
    printf("ltohd(ff,fe,fd,fc,fb,fa,f9,f8) = %016llx\n", 
           ltohd(*(unsigned long long *)t2));

Temperature is the enemy of hard disks. Hot disks fail sooner.

If you have a well designed server with lightly loaded disks in a cool room your drives are probably running around 25°C(77°F). If you have a 4U box that you chucked full of drives you may find some of your drives running much hotter. For instance, I just found two running at 41°C(105°F) in a box with otherwise cool drives.

Drives are typically specified to operate up to 55°C(131°F), but their lives are shortened. Estimating from Google data it looks like your failure rate within three years is about triple for 45°C versus 25°C. In the third year, about 1 in 6 of the hot drives will fail.

So protect your servers:

  1. Know the problem: In debian land, install hddtemp and run it to see which drives are hot. Windows users might use DTemp.

    `` vev# for v in a b c d ;do hddtemp /dev/sd\$v ;done /dev/sda: ST3750640AS: 34°C /dev/sdb: ST3750640AS: 27°C /dev/sdc: ST3750640AS: 41°C /dev/sdd: ST3750640AS: 40°C vev# # I have two hot drives.

  2. Mitigate: If you have hot drives, move them around or adjust airflow, perhaps by making little cardstock air dams inside the server to cool the drives. Add a fan blowing on them if you have a large case.

  3. Monitor: Record their temperatures and check in on them once in a while to make sure things aren’t going badly.

Debian users might also want to install smartmontools which will track your S.M.A.R.T. data and notify you of problems.

Note: for SATA drives you will need a “-d ata” or it will misaddress them as SCSI drives and you need a “-m foo@example.com” if you want to be email notified.

Somewhere along the line the GNU C library and the BSD folks added variants of sprintf() that malloc() the resulting string. Very handy for avoiding an overflow situation and also makes for cleaner reading code.

`` int asprintf( char **ret, const char *format, …); int vasprintf( char **ret, const char *format, va_list ap);


`` char buf[32]; sprintf(buf, “s:%d m:%s”, code, msg); // stack overflow when msg is too long

… or …


char buf[1024];
snprintf( buf, sizeof(buf)-1, “s:%d m:%s”, code, msg); // fail oddly if we guessed wrong on the maximum buf size



char *buf;
asprintf( &buf, “s:%d m:%s”, code, msg);
… free(buf);

Danger danger DANGER: This will not work on the tiny libc in OpenWRT and similar embedded systems. But at least you will get a link error during the build.

Now if only we had a scanf() that would do a realloc() on its pointers.

Oh look, there is a similar function for scanf().  You can do something like...

char *adj = 0;
sscanf(somestuff,"Some %as stuff", &adj);

... but only if you are using GNU libc. I got burned when I used this in a daemon and then moved it to OpenWRT where they uses a different libc.

Femtoblogger has just been rolled out to a corporate community of 150 users. Let the bug reports and feature requests roll.