winebuild: generate deterministic temp filenames

Using the xorshift* pseudo random generator for the filenames.

Signed-off-by: Marko Semet <marko@marko10-000.de>
feature/deterministic
Marko Semet 2020-06-21 03:22:06 +02:00
parent 1b87584bf5
commit 6c5b40382b
3 changed files with 102 additions and 2 deletions

View File

@ -27,6 +27,7 @@
# error You must include config.h to use this header
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -352,6 +353,11 @@ extern void put_qword( unsigned int val );
extern void put_pword( unsigned int val );
extern void align_output( unsigned int align );
extern uint64_t pseudorandom(uint64_t add_to_state);
extern char pseudorandom_char(void);
extern int pseudorandom_tempfile(char* file);
extern void init_random_generator(int argc, char **argv);
/* global variables */
extern int current_line;

View File

@ -666,6 +666,7 @@ int main(int argc, char **argv)
signal( SIGTERM, exit_on_signal );
signal( SIGINT, exit_on_signal );
init_random_generator(argc, argv);
argv = parse_options( argc, argv, spec );
atexit( cleanup ); /* make sure we remove the output file on exit */

View File

@ -514,13 +514,13 @@ char *get_temp_file_name( const char *prefix, const char *suffix )
strcpy( name + (ext - prefix), ".XXXXXX" );
strcat( name, suffix );
if ((fd = mkstemps( name, strlen(suffix) )) == -1)
if ((fd = pseudorandom_tempfile(name)) == -1)
{
strcpy( name, "/tmp/" );
memcpy( name + 5, basename, ext - basename );
strcpy( name + 5 + (ext - basename), ".XXXXXX" );
strcat( name, suffix );
if ((fd = mkstemps( name, strlen(suffix) )) == -1)
if ((fd = pseudorandom_tempfile(name)) == -1)
fatal_error( "could not generate a temp file\n" );
}
@ -1275,3 +1275,96 @@ const char *get_asm_string_section(void)
default: return ".section .rodata";
}
}
/* xorshift* random generator. Source: https://en.wikipedia.org/wiki/Xorshift#xorshift* */
static uint64_t pseudorandom_state = 1;
extern char **environ;
uint64_t pseudorandom(uint64_t add_to_state)
{
uint64_t tmp = pseudorandom_state + add_to_state;
tmp ^= tmp >> 12;
tmp ^= tmp << 25;
tmp ^= tmp >> 27;
pseudorandom_state = tmp;
return tmp * UINT64_C(0x2545F4914F6CDD1D);
}
char pseudorandom_char(void)
{
char tmp = (char) (pseudorandom(0) % 62);
if (tmp < 10)
{
return '0' + tmp;
}
else if (tmp < 36)
{
return 'A' + (tmp - 10);
}
else
{
return 'a' + (tmp - 36);
}
}
int pseudorandom_tempfile(char* file)
{
/* replaces Xs */
for (char* tmp = file; (*tmp) != 0; tmp++)
{
if ((*tmp) == 'X')
{
(*tmp) = pseudorandom_char();
}
}
/* try to open file */
return open(file, O_CREAT | O_EXCL | O_RDWR, 0600);
}
void init_random_generator(int argc, char **argv)
{
/* process environment */
{
/* copy environment variables and sort them */
char **tmp_envs;
unsigned int counter = 0;
for (const char **env = environ; (*env) != 0; env++, counter++) {}
tmp_envs = (char**) malloc(sizeof(char*) * counter);
for (unsigned int i = 0; i < counter; i++)
{
size_t length = strlen(environ[i]) + 1;
char* tmp = malloc(length);
memcpy(tmp, environ[i], length);
tmp_envs[i] = tmp;
}
qsort(tmp_envs, counter, sizeof(char*), (int(*)(const void*, const void*)) &strcmp);
/* add sorted environment to random generator */
for (unsigned int i = 0; i < counter; i++)
{
size_t j_max = strlen(tmp_envs[i]);
for (size_t j = 0; j < j_max; j++)
{
pseudorandom(tmp_envs[i][j]);
}
}
/* free temp environment */
for (unsigned int i = 0; i < counter; i++)
{
free(tmp_envs[i]);
}
free(tmp_envs);
}
/* process argv */
for (int i = 0; i < argc; i++)
{
size_t j_max = strlen(argv[i]);
for (size_t j = 0; j < j_max; j++)
{
pseudorandom(argv[i][j]);
}
}
}