--- numactl/libnuma.c	2006-06-09 15:23:48.000000000 +0200
+++ numactl/libnuma.c	2006-06-09 11:24:37.000000000 +0200
@@ -398,6 +398,22 @@
 
 static unsigned long *node_cpu_mask[NUMA_NUM_NODES];  
 
+static void bad_cpumap(int ncpus, unsigned *mask)
+{
+	int n;
+	for (n = 0; n < ncpus; n++)
+		set_bit(n, (unsigned long *)mask);
+}
+
+static int strcount(char *s, int c)
+{
+	int n = 0;
+	for (; *s; s++) 
+		if (*s == c)
+			n++;
+	return n;
+}
+
 /* This would be better with some locking, but I don't want to make libnuma
    dependent on pthreads right now. The races are relatively harmless. */
 int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) 
@@ -406,83 +422,76 @@
 	FILE *f; 
 	char *line = NULL; 
 	size_t len = 0; 
-	char *s;
-	int n;
+	char *p;
 	int buflen_needed;
-	unsigned long *mask, prev;
+	unsigned *mask;
 	int ncpus = number_of_configured_cpus();
 	int i;
-	int mask_words;
-	int bits_in_mask_0;
 
 	buflen_needed = CPU_BYTES(ncpus);
 	if ((unsigned)node > maxnode || bufferlen < buflen_needed) { 
 		errno = ERANGE;
 		return -1;
 	}
-
+	if (bufferlen > buflen_needed)
+		memset(buffer, 0, bufferlen); 
 	if (node_cpu_mask[node]) { 
-		if (bufferlen > buflen_needed)
-			memset(buffer, 0, bufferlen); 
 		memcpy(buffer, node_cpu_mask[node], buflen_needed);
 		return 0;
 	}
 
 	mask = malloc(buflen_needed);
 	if (!mask) 
-		mask = (unsigned long *)buffer; 
+		mask = (unsigned *)buffer; 
 	memset(mask, 0, buflen_needed); 
-			
+
 	sprintf(fn, "/sys/devices/system/node/node%d/cpumap", node); 
 	f = fopen(fn, "r"); 
 	if (!f || getdelim(&line, &len, '\n', f) < 1) { 
 		numa_warn(W_nosysfs2,
 		   "/sys not mounted or invalid. Assuming one node: %s",
 			  strerror(errno)); 
-		for (n = 0; n < ncpus; n++)
-			set_bit(n, (unsigned long *)mask);
+		bad_cpumap(ncpus, mask);
 		goto out;
 	} 
-        mask_words = 0;
-	bits_in_mask_0 = 0;
-	n = 0;
-	s = line;
-	prev = 0; 
-        for (i = 0; s[i]; i++) {
-                static const char hexdigits[] = "0123456789abcdef";
-                char *w = strchr(hexdigits, tolower(s[i]));
-                if (!w) {
-                        if (isspace(s[i]) || s[i] == ',')
-                                continue;
-                        numa_warn(W_cpumap,
-                                  "Unexpected character `%c' in sysfs cpumap", 
-					s[i]);
-                        set_bit(node, mask);
-                        goto out;
-		}
-
-		/* if mask[0] is full shift left before adding another */
-		if (bits_in_mask_0 >= sizeof(mask[0])*8) {
-			/* shift over any previously loaded masks */
-			mask_words++;
-			for (n = mask_words; n > 0; n--)
-				memmove(mask+n, mask+n-1, sizeof(mask[0]));
-			bits_in_mask_0 = 0;
-			mask[0] = 0;
-		}
- 
-		mask[0] = (mask[0]*16) + (w - hexdigits);
-	      	bits_in_mask_0 += 4; /* 4 bits per hex char */
+	fclose(f);
+	p = strchr(line, '\n'); 
+	if (!p) {
+		numa_warn(W_cpumap, "Cannot parse cpumap. Assuming one node");
+		bad_cpumap(ncpus, mask);
+		goto out;
 	}
+	for (i = 0; p > line;i++) {
+		char *oldp, *endp; 
+		oldp = p;
+		if (*p == ',') 
+			--p;
+		while (p > line && *p != ',')
+			--p;
+		p++;
+		if (i >= CPU_LONGS(ncpus) * (sizeof(long)/sizeof(unsigned))) {
+			numa_warn(W_cpumap, 
+   "cpumap too long, has %d longs. ncpus %d, Assuming one node", 
+			  strcount(line, ',')+1, ncpus);
+			bad_cpumap(ncpus, mask);
+			goto out;
+		}
+		mask[i] = strtoul(p, &endp, 16);
+		if (endp != oldp) {
+			numa_warn(W_cpumap, "Cannot parse cpumap. Assuming one node");
+			bad_cpumap(ncpus, mask); 
+			goto out;
+		}
+		p--;
+	}
+
  out:
- 	free(line);
-	if (f) 
-		fclose(f);
+	free(line);
 	memcpy(buffer, mask, buflen_needed);
 
 	/* slightly racy, see above */ 
 	if (node_cpu_mask[node]) {
-		if (mask != (unsigned long *)buffer)
+		if (mask != (unsigned *)buffer)
 			free(mask); 	       
 	} else {
 		node_cpu_mask[node] = (unsigned long *)mask; 
