build: avoid non-portable byte-swapping

Commit 0fc89098 used functions only available on glibc, completely
botched 32-bit environments, and risked SIGBUS due to unaligned
memory access on platforms that aren't as forgiving as x86_64.

* bootstrap.conf (gnulib_modules): Import ffsl.
* src/util/bitmap.c (includes): Use <strings.h> for ffsl.
(virBitmapNewData, virBitmapToData): Avoid 64-bit assumptions and
non-portable functions.
This commit is contained in:
Eric Blake 2012-09-18 13:53:15 -06:00
parent e6bd3ce056
commit 4bba6579cc
2 changed files with 28 additions and 11 deletions

View File

@ -44,6 +44,7 @@ fcntl
fcntl-h fcntl-h
fdatasync fdatasync
ffs ffs
ffsl
fnmatch fnmatch
fsync fsync
func func

View File

@ -1,7 +1,7 @@
/* /*
* bitmap.h: Simple bitmap operations * bitmap.h: Simple bitmap operations
* *
* Copyright (C) 2010-2011 Red Hat, Inc. * Copyright (C) 2010-2012 Red Hat, Inc.
* Copyright (C) 2010 Novell, Inc. * Copyright (C) 2010 Novell, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
@ -27,6 +27,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <strings.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
@ -418,15 +419,23 @@ virBitmapPtr virBitmapNewCopy(virBitmapPtr src)
virBitmapPtr virBitmapNewData(void *data, int len) virBitmapPtr virBitmapNewData(void *data, int len)
{ {
virBitmapPtr bitmap; virBitmapPtr bitmap;
int i; int i, j;
unsigned long *p;
unsigned char *bytes = data;
bitmap = virBitmapNew(len * CHAR_BIT); bitmap = virBitmapNew(len * CHAR_BIT);
if (!bitmap) if (!bitmap)
return NULL; return NULL;
memcpy(bitmap->map, data, len); /* le64toh is not provided by gnulib, so we do the conversion by hand */
for (i = 0; i < bitmap->map_len; i++) p = bitmap->map;
bitmap->map[i] = le64toh(bitmap->map[i]); for (i = j = 0; i < len; i++, j++) {
if (j == sizeof(*p)) {
j = 0;
p++;
}
*p |= bytes[i] << (j * CHAR_BIT);
}
return bitmap; return bitmap;
} }
@ -446,19 +455,26 @@ int virBitmapToData(virBitmapPtr bitmap, unsigned char **data, int *dataLen)
{ {
int len; int len;
unsigned long *l; unsigned long *l;
int i; int i, j;
unsigned char *bytes;
len = bitmap->map_len * (VIR_BITMAP_BITS_PER_UNIT / CHAR_BIT); len = (bitmap->max_bit + CHAR_BIT - 1) / CHAR_BIT;
if (VIR_ALLOC_N(*data, len) < 0) if (VIR_ALLOC_N(*data, len) < 0)
return -1; return -1;
memcpy(*data, bitmap->map, len); bytes = *data;
*dataLen = len; *dataLen = len;
l = (unsigned long *)*data; /* htole64 is not provided by gnulib, so we do the conversion by hand */
for (i = 0; i < bitmap->map_len; i++, l++) l = bitmap->map;
*l = htole64(*l); for (i = j = 0; i < len; i++, j++) {
if (j == sizeof(*l)) {
j = 0;
l++;
}
bytes[i] = *l >> (j * CHAR_BIT);
}
return 0; return 0;
} }