mirror of
https://github.com/AltraMayor/f3.git
synced 2025-09-09 07:09:35 -04:00
Adopt h2testw's file format
Now F3 and h2testw share the same file format. Guenter Knauf has suggested this feature and got the random-number generator used in h2testw from Harald Bogeholz, the author of h2testw. This change also addresses the issue that the original random-number generator only fills the first 32 bits of the 64 bits of the random numbers on 64-bit machines. Besides the lower entropy on 64-bit machines, this issue was making files generated on 32-bit and 64-bit machines incompatible. Anselm Distelrath was the first to report this issue.
This commit is contained in:
parent
1c50c85a4d
commit
be1f587142
2
f3read.1
2
f3read.1
@ -18,7 +18,7 @@ card and then checks if can read it. It will assure you haven't been
|
||||
sold a card with a smaller capacity than stated.
|
||||
.PP
|
||||
When writing to flash drive, \fBf3write\fP fills the filesystem with 1GB
|
||||
files named N.fff, where N is a number (i.e. /[0-9]+/).
|
||||
files named N.h2w, where N is a number (i.e. /[0-9]+/).
|
||||
.PP
|
||||
WARNING: all data on the tested disk might be lost!
|
||||
.SH OPTIONS
|
||||
|
12
f3read.c
12
f3read.c
@ -44,8 +44,6 @@ static void validate_file(const char *path, int number,
|
||||
int offset_match, error_count;
|
||||
size_t sectors_read;
|
||||
uint64_t offset, expected_offset;
|
||||
struct drand48_data state;
|
||||
long int rand_int;
|
||||
int final_errno;
|
||||
struct timeval t1, t2;
|
||||
/* Progress time. */
|
||||
@ -79,17 +77,19 @@ static void validate_file(const char *path, int number,
|
||||
final_errno = errno;
|
||||
expected_offset = (uint64_t)number * GIGABYTES;
|
||||
while (sectors_read > 0) {
|
||||
uint64_t rn;
|
||||
|
||||
assert(sectors_read == 1);
|
||||
offset = *((uint64_t *) sector);
|
||||
offset_match = offset == expected_offset;
|
||||
|
||||
srand48_r(offset, &state);
|
||||
rn = offset;
|
||||
p = sector + sizeof(offset);
|
||||
error_count = 0;
|
||||
for (; error_count <= TOLERANCE && p < ptr_end;
|
||||
p += sizeof(long int)) {
|
||||
lrand48_r(&state, &rand_int);
|
||||
if (rand_int != *((long int *) p))
|
||||
p += sizeof(rn)) {
|
||||
rn = random_number(rn);
|
||||
if (rn != *((typeof(rn) *) p))
|
||||
error_count++;
|
||||
}
|
||||
|
||||
|
12
f3write.c
12
f3write.c
@ -18,20 +18,24 @@
|
||||
static uint64_t fill_buffer(void *buf, size_t size, uint64_t offset)
|
||||
{
|
||||
uint8_t *p, *ptr_next_sector, *ptr_end;
|
||||
struct drand48_data state;
|
||||
uint64_t rn;
|
||||
|
||||
assert(size > 0);
|
||||
assert(size % SECTOR_SIZE == 0);
|
||||
assert(SECTOR_SIZE >= sizeof(offset) + sizeof(rn));
|
||||
assert((SECTOR_SIZE - sizeof(offset)) % sizeof(rn) == 0);
|
||||
|
||||
p = buf;
|
||||
ptr_end = p + size;
|
||||
while (p < ptr_end) {
|
||||
rn = offset;
|
||||
memmove(p, &offset, sizeof(offset));
|
||||
srand48_r(offset, &state);
|
||||
ptr_next_sector = p + SECTOR_SIZE;
|
||||
p += sizeof(offset);
|
||||
for (; p < ptr_next_sector; p += sizeof(long int))
|
||||
lrand48_r(&state, (long int *)p);
|
||||
for (; p < ptr_next_sector; p += sizeof(rn)) {
|
||||
rn = random_number(rn);
|
||||
memmove(p, &rn, sizeof(rn));
|
||||
}
|
||||
assert(p == ptr_next_sector);
|
||||
offset += SECTOR_SIZE;
|
||||
}
|
||||
|
83
utils.c
83
utils.c
@ -33,14 +33,14 @@ int is_my_file(const char *filename)
|
||||
p++;
|
||||
} while (isdigit(*p));
|
||||
|
||||
return (p[0] == '.') && (p[1] == 'f') && (p[2] == 'f') &&
|
||||
(p[3] == 'f') && (p[4] == '\0');
|
||||
return (p[0] == '.') && (p[1] == 'h') && (p[2] == '2') &&
|
||||
(p[3] == 'w') && (p[4] == '\0');
|
||||
}
|
||||
|
||||
void full_fn_from_number(char *full_fn, const char **filename,
|
||||
const char *path, int num)
|
||||
{
|
||||
assert(snprintf(full_fn, PATH_MAX, "%s/%i.fff", path, num + 1) <
|
||||
assert(snprintf(full_fn, PATH_MAX, "%s/%i.h2w", path, num + 1) <
|
||||
PATH_MAX);
|
||||
*filename = full_fn + strlen(path) + 1;
|
||||
}
|
||||
@ -140,80 +140,3 @@ void print_header(FILE *f, char *name)
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"\n", name);
|
||||
}
|
||||
|
||||
#if defined(APPLE_MAC) || defined (CYGWIN)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int srand48_r(long int seedval, struct drand48_data *buffer)
|
||||
{
|
||||
/* The standards say we only have 32 bits. */
|
||||
if (sizeof(long int) > 4)
|
||||
seedval &= 0xffffffffl;
|
||||
|
||||
buffer->__x[2] = seedval >> 16;
|
||||
buffer->__x[1] = seedval & 0xffffl;
|
||||
buffer->__x[0] = 0x330e;
|
||||
|
||||
buffer->__a = 0x5deece66dull;
|
||||
buffer->__c = 0xb;
|
||||
buffer->__init = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __drand48_iterate(unsigned short int xsubi[3],
|
||||
struct drand48_data *buffer)
|
||||
{
|
||||
uint64_t X;
|
||||
uint64_t result;
|
||||
|
||||
/* Initialize buffer, if not yet done. */
|
||||
if (__builtin_expect(!buffer->__init, 0)) {
|
||||
buffer->__a = 0x5deece66dull;
|
||||
buffer->__c = 0xb;
|
||||
buffer->__init = 1;
|
||||
}
|
||||
|
||||
/* Do the real work. We choose a data type which contains at least
|
||||
48 bits. Because we compute the modulus it does not care how
|
||||
many bits really are computed. */
|
||||
|
||||
X = (uint64_t) xsubi[2] << 32 | (uint32_t) xsubi[1] << 16 | xsubi[0];
|
||||
|
||||
result = X * buffer->__a + buffer->__c;
|
||||
|
||||
xsubi[0] = result & 0xffff;
|
||||
xsubi[1] = (result >> 16) & 0xffff;
|
||||
xsubi[2] = (result >> 32) & 0xffff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __nrand48_r(unsigned short int xsubi[3],
|
||||
struct drand48_data *buffer, long int *result)
|
||||
{
|
||||
/* Compute next state. */
|
||||
if (__drand48_iterate(xsubi, buffer) < 0)
|
||||
return -1;
|
||||
|
||||
/* Store the result. */
|
||||
if (sizeof(unsigned short int) == 2)
|
||||
*result = xsubi[2] << 15 | xsubi[1] >> 1;
|
||||
else
|
||||
*result = xsubi[2] >> 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lrand48_r(struct drand48_data *buffer, long int *result)
|
||||
{
|
||||
/* Be generous for the arguments, detect some errors. */
|
||||
if (buffer == NULL)
|
||||
return -1;
|
||||
|
||||
return __nrand48_r(buffer->__x, buffer, result);
|
||||
}
|
||||
|
||||
#endif /* APPLE_MAC or CYGWIN */
|
||||
|
37
utils.h
37
utils.h
@ -6,13 +6,14 @@
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define SECTOR_SIZE (512)
|
||||
#define GIGABYTES (1024 * 1024 * 1024)
|
||||
|
||||
const char *adjust_unit(double *ptr_bytes);
|
||||
|
||||
/* Return true if @filename matches the regex /^[0-9]+\.fff$/ */
|
||||
/* Return true if @filename matches the regex /^[0-9]+\.h2w$/ */
|
||||
int is_my_file(const char *filename);
|
||||
|
||||
/* @filename should be PATH_MAX long. */
|
||||
@ -35,6 +36,11 @@ const int *ls_my_files(const char *path, int start_at);
|
||||
|
||||
void print_header(FILE *f, char *name);
|
||||
|
||||
static inline uint64_t random_number(uint64_t prv_number)
|
||||
{
|
||||
return prv_number * 4294967311ULL + 17;
|
||||
}
|
||||
|
||||
#ifdef APPLE_MAC
|
||||
|
||||
/* For function fcntl. */
|
||||
@ -66,33 +72,4 @@ static inline int posix_fadvise(int fd, off_t offset, off_t len, int advice)
|
||||
|
||||
#endif /* APPLE_MAC */
|
||||
|
||||
#if defined(APPLE_MAC) || defined(CYGWIN)
|
||||
|
||||
/*
|
||||
* The following functions were copied from GNU Library C to make F3
|
||||
* more portable.
|
||||
*/
|
||||
|
||||
/* Data structure for communication with thread safe versions. This
|
||||
* type is to be regarded as opaque. It's only exported because users
|
||||
* have to allocate objects of this type.
|
||||
*/
|
||||
struct drand48_data {
|
||||
unsigned short int __x[3]; /* Current state. */
|
||||
unsigned short int __old_x[3]; /* Old state. */
|
||||
unsigned short int __c; /* Additive const. in congruential formula. */
|
||||
unsigned short int __init; /* Flag for initializing. */
|
||||
unsigned long long int __a; /* Factor in congruential formula. */
|
||||
};
|
||||
|
||||
/* Seed random number generator. */
|
||||
extern int srand48_r(long int __seedval, struct drand48_data *__buffer)
|
||||
__attribute__ ((nonnull(2)));
|
||||
|
||||
/* Return non-negative, long integer in [0,2^31). */
|
||||
extern int lrand48_r(struct drand48_data *__restrict __buffer,
|
||||
long int *__restrict __result) __attribute__ ((nonnull(1, 2)));
|
||||
|
||||
#endif /* APPLE_MAC or CYGWIN */
|
||||
|
||||
#endif /* HEADER_UTILS_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user