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.
|
sold a card with a smaller capacity than stated.
|
||||||
.PP
|
.PP
|
||||||
When writing to flash drive, \fBf3write\fP fills the filesystem with 1GB
|
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
|
.PP
|
||||||
WARNING: all data on the tested disk might be lost!
|
WARNING: all data on the tested disk might be lost!
|
||||||
.SH OPTIONS
|
.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;
|
int offset_match, error_count;
|
||||||
size_t sectors_read;
|
size_t sectors_read;
|
||||||
uint64_t offset, expected_offset;
|
uint64_t offset, expected_offset;
|
||||||
struct drand48_data state;
|
|
||||||
long int rand_int;
|
|
||||||
int final_errno;
|
int final_errno;
|
||||||
struct timeval t1, t2;
|
struct timeval t1, t2;
|
||||||
/* Progress time. */
|
/* Progress time. */
|
||||||
@ -79,17 +77,19 @@ static void validate_file(const char *path, int number,
|
|||||||
final_errno = errno;
|
final_errno = errno;
|
||||||
expected_offset = (uint64_t)number * GIGABYTES;
|
expected_offset = (uint64_t)number * GIGABYTES;
|
||||||
while (sectors_read > 0) {
|
while (sectors_read > 0) {
|
||||||
|
uint64_t rn;
|
||||||
|
|
||||||
assert(sectors_read == 1);
|
assert(sectors_read == 1);
|
||||||
offset = *((uint64_t *) sector);
|
offset = *((uint64_t *) sector);
|
||||||
offset_match = offset == expected_offset;
|
offset_match = offset == expected_offset;
|
||||||
|
|
||||||
srand48_r(offset, &state);
|
rn = offset;
|
||||||
p = sector + sizeof(offset);
|
p = sector + sizeof(offset);
|
||||||
error_count = 0;
|
error_count = 0;
|
||||||
for (; error_count <= TOLERANCE && p < ptr_end;
|
for (; error_count <= TOLERANCE && p < ptr_end;
|
||||||
p += sizeof(long int)) {
|
p += sizeof(rn)) {
|
||||||
lrand48_r(&state, &rand_int);
|
rn = random_number(rn);
|
||||||
if (rand_int != *((long int *) p))
|
if (rn != *((typeof(rn) *) p))
|
||||||
error_count++;
|
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)
|
static uint64_t fill_buffer(void *buf, size_t size, uint64_t offset)
|
||||||
{
|
{
|
||||||
uint8_t *p, *ptr_next_sector, *ptr_end;
|
uint8_t *p, *ptr_next_sector, *ptr_end;
|
||||||
struct drand48_data state;
|
uint64_t rn;
|
||||||
|
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
assert(size % SECTOR_SIZE == 0);
|
assert(size % SECTOR_SIZE == 0);
|
||||||
|
assert(SECTOR_SIZE >= sizeof(offset) + sizeof(rn));
|
||||||
|
assert((SECTOR_SIZE - sizeof(offset)) % sizeof(rn) == 0);
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
ptr_end = p + size;
|
ptr_end = p + size;
|
||||||
while (p < ptr_end) {
|
while (p < ptr_end) {
|
||||||
|
rn = offset;
|
||||||
memmove(p, &offset, sizeof(offset));
|
memmove(p, &offset, sizeof(offset));
|
||||||
srand48_r(offset, &state);
|
|
||||||
ptr_next_sector = p + SECTOR_SIZE;
|
ptr_next_sector = p + SECTOR_SIZE;
|
||||||
p += sizeof(offset);
|
p += sizeof(offset);
|
||||||
for (; p < ptr_next_sector; p += sizeof(long int))
|
for (; p < ptr_next_sector; p += sizeof(rn)) {
|
||||||
lrand48_r(&state, (long int *)p);
|
rn = random_number(rn);
|
||||||
|
memmove(p, &rn, sizeof(rn));
|
||||||
|
}
|
||||||
assert(p == ptr_next_sector);
|
assert(p == ptr_next_sector);
|
||||||
offset += SECTOR_SIZE;
|
offset += SECTOR_SIZE;
|
||||||
}
|
}
|
||||||
|
83
utils.c
83
utils.c
@ -33,14 +33,14 @@ int is_my_file(const char *filename)
|
|||||||
p++;
|
p++;
|
||||||
} while (isdigit(*p));
|
} while (isdigit(*p));
|
||||||
|
|
||||||
return (p[0] == '.') && (p[1] == 'f') && (p[2] == 'f') &&
|
return (p[0] == '.') && (p[1] == 'h') && (p[2] == '2') &&
|
||||||
(p[3] == 'f') && (p[4] == '\0');
|
(p[3] == 'w') && (p[4] == '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
void full_fn_from_number(char *full_fn, const char **filename,
|
void full_fn_from_number(char *full_fn, const char **filename,
|
||||||
const char *path, int num)
|
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);
|
PATH_MAX);
|
||||||
*filename = full_fn + strlen(path) + 1;
|
*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"
|
"This is free software; see the source for copying conditions.\n"
|
||||||
"\n", name);
|
"\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 <assert.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define SECTOR_SIZE (512)
|
#define SECTOR_SIZE (512)
|
||||||
#define GIGABYTES (1024 * 1024 * 1024)
|
#define GIGABYTES (1024 * 1024 * 1024)
|
||||||
|
|
||||||
const char *adjust_unit(double *ptr_bytes);
|
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);
|
int is_my_file(const char *filename);
|
||||||
|
|
||||||
/* @filename should be PATH_MAX long. */
|
/* @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);
|
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
|
#ifdef APPLE_MAC
|
||||||
|
|
||||||
/* For function fcntl. */
|
/* 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 */
|
#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 */
|
#endif /* HEADER_UTILS_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user