diff --git a/tools/winegcc/utils.c b/tools/winegcc/utils.c index 0135f94da37..15fd04571bd 100644 --- a/tools/winegcc/utils.c +++ b/tools/winegcc/utils.c @@ -387,21 +387,28 @@ int spawn(const strarray* prefix, const strarray* args, int ignore_errors) /* xorshift* random generator. Source: https://en.wikipedia.org/wiki/Xorshift#xorshift* */ static uint64_t pseudorandom_state = 1; -extern char **environ; +static const char* pseudorandom_source = NULL; +static size_t pseudorandom_source_size = 0; -uint64_t pseudorandom(uint64_t add_to_state) +static uint64_t pseudorandom_algo(uint64_t* generator_state, uint64_t add_to_state) { - uint64_t tmp = pseudorandom_state + add_to_state; + uint64_t tmp = (*generator_state) + add_to_state; tmp ^= tmp >> 12; tmp ^= tmp << 25; tmp ^= tmp >> 27; - pseudorandom_state = tmp; + (*generator_state) = tmp; return tmp * UINT64_C(0x2545F4914F6CDD1D); } +uint64_t pseudorandom(uint64_t add_to_state) +{ + return pseudorandom_algo(&pseudorandom_state, add_to_state); +} + char pseudorandom_char(void) { - char tmp = (char) (pseudorandom(0) % 62); + char tmp; + tmp = (char) (pseudorandom(0) % 62); if (tmp < 10) { return '0' + tmp; @@ -418,18 +425,26 @@ char pseudorandom_char(void) int pseudorandom_tempfile(char* file) { + /* variables */ + int result; + + int counter; + char *filename_pos; + + char *debug_filename; + FILE *debug_file; + /* replaces Xs */ - for (char* tmp = file; (*tmp) != 0; tmp++) + for (filename_pos = file; (*filename_pos) != 0; filename_pos++) { - if ((*tmp) == 'X') + if ((*filename_pos) == 'X') { - (*tmp) = pseudorandom_char(); + (*filename_pos) = pseudorandom_char(); } } /* try to open file */ - int result; - int counter = 0; + counter = 0; do { result = open(file, O_CREAT | O_EXCL | O_RDWR, 0600); @@ -440,52 +455,116 @@ int pseudorandom_tempfile(char* file) sleep(5); counter++; } while (counter <= 12); + + /* add deebug info */ + if ((result != -1) && (getenv("SOURCE_RANDOM_DEBUG") != NULL)) + { + debug_filename = strmake("%s.random_debug", file); + debug_file = fopen(debug_filename, "wb"); + fwrite(pseudorandom_source, 1, pseudorandom_source_size, debug_file); + fclose(debug_file); + free(debug_filename); + } return result; } void init_random_generator(int argc, char **argv) { + /* variables */ + uint64_t generator_state; + + void *argv_data; + size_t argv_size; + + unsigned int counter; + void *env_data; + size_t env_size; + char **tmp_envs; + + char *buffer_pos; + char **env; + size_t length; + + unsigned int i; + size_t j; + /* process environment */ + generator_state = 1; + env_size = 0; { - /* 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++) + /* sort environment variables */ + counter = 0; + for (env = environ; (*env) != NULL; env++) { - size_t length = strlen(environ[i]) + 1; - char* tmp = malloc(length); - memcpy(tmp, environ[i], length); - tmp_envs[i] = tmp; + counter++; + env_size += strlen(*env) + 1; + } + tmp_envs = (char**) malloc(sizeof(char*) * counter); + for (i = 0; i < counter; i++) + { + tmp_envs[i] = (char*) (environ[i]); } 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++) + /* and copy them */ + env_data = malloc(env_size * sizeof(char)); + buffer_pos = env_data; + for (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]); - } + length = strlen(tmp_envs[i]) + 1; + memcpy(buffer_pos, tmp_envs[i], length); + buffer_pos += length; + } + + /* add sorted environment to random generator */ + for (j = 0; j < env_size; j++) + { + pseudorandom_algo(&generator_state, ((unsigned char*) env_data)[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++) + /* copy argv */ + argv_size = 0; + for (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]); - } + argv_size += strlen(argv[i]) + 1; } + argv_data = malloc(sizeof(char) * argv_size); + buffer_pos = argv_data; + for (i = 0; i < argc; i++) + { + length = strlen(argv[i]) + 1; + memcpy(buffer_pos, argv[i], length); + buffer_pos += length; + } + + /* add arguments to gnerator */ + for (j = 0; j < argv_size; j++) + { + pseudorandom_algo(&generator_state, ((unsigned char*) argv_data)[j]); + } + + /* add debug if required */ + if (getenv("SOURCE_RANDOM_DEBUG") != NULL) + { + /* gen field */ + pseudorandom_source_size = env_size + argv_size + sizeof(generator_state); + buffer_pos = malloc(sizeof(char) * pseudorandom_source_size); + pseudorandom_source = buffer_pos; + + /* copy data into it */ + memcpy(buffer_pos, env_data, env_size); + buffer_pos += env_size; + memcpy(buffer_pos, argv_data, argv_size); + buffer_pos += argv_size; + memcpy(buffer_pos, &generator_state, sizeof(generator_state)); + } + + /* set state and free rest */ + free(env_data); + free(argv_data); + pseudorandom_state = generator_state; }