main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
const char *v4; // rax
__int64 v5; // rdi
__int64 v6; // rdx
int v7; // eax
const char *v9; // rax
unsigned int v10; // eax
const char *v11; // rax
const char *v12; // rax

stats_main_start = get_current_time_millis(argc, argv, envp);
pthread_key_create(&thread_name, 0LL);
pthread_setspecific(thread_name, "[MAIN] ");
pthread_key_create(&duplicate_path_buffer, 0LL);
v3 = process_args((unsigned int)argc, (__int64)argv);
if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v4 = (const char *)get_thread_name();
printf("%s", v4);
argv = (const char **)log_level_name[log_level];
printf("Log level: %s\n", (const char *)argv);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
if ( v3 )
{
--v3;
}
else if ( start_path_state == 2 )
{
v3 = 1;
}
else
{
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v9 = (const char *)get_thread_name();
printf("%s", v9);
v10 = cpu_cores();
printf("Claimed CPU cores: %d\n", v10);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
max_open_files = get_file_limit() - 10;
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v11 = (const char *)get_thread_name();
printf("%s", v11);
printf("Max open files: %d\n", (unsigned int)max_open_files);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
signal(10, handle_signal);
signal(12, handle_signal);
if ( trace_file && (trace_file_fd = open64(trace_file, 1601, 416LL), trace_file_fd < 0) )
{
argv = (const char **)trace_file;
printf("error: unable to create trace-file [%s]\n", trace_file);
}
else
{
argv = (const char **)(unsigned int)operation;
switch ( operation )
{
case -1:
show_help();
v3 = 1;
break;
case 1:
scan();
break;
case 2:
operation_refresh();
break;
case 3:
operation_report();
break;
case 4:
operation_file();
break;
case 5:
operation_uniques();
break;
case 6:
operation_dups();
break;
case 7:
operation_ls();
break;
case 8:
operation_hash_file();
break;
case 9:
operation_cache();
break;
case 10:
operation_shell_script();
break;
case 11:
v3 = operation_validate();
break;
case 12:
show_help();
break;
case 13:
case 14:
show_usage();
break;
case 15:
show_license();
break;
case 16:
puts("2.0-dev");
break;
case 17:
testing();
break;
case 18:
operation_info();
break;
default:
printf("error: unknown operation [%d]\n", (unsigned int)operation);
v3 = 1;
break;
}
}
}
if ( free_file_path )
free(file_path);
if ( free_db_path )
free(db_path);
if ( free_cache_db_path )
free(cache_db_path);
if ( path_sep_string )
free(path_sep_string);
free_size_tree();
free_size_list();
free_path_block();
free_filecompare();
free_scanlist();
free_start_paths();
free_read_list();
free_dirtree();
free_path_buffer();
v5 = thread_name;
pthread_key_delete(thread_name);
stats_time_total = get_current_time_millis(v5, argv, v6) - stats_main_start;
if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v12 = (const char *)get_thread_name();
printf("%s", v12);
printf("Total time: %ld ms\n", stats_time_total);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
if ( trace_file_fd != -1 )
{
close(trace_file_fd);
trace_file_fd = -1;
}
if ( stats_file )
save_stats();
if ( log_level >= 0 && ((unsigned int)(operation - 1) <= 1 || (unsigned int)(operation - 11) <= 5) )
{
v7 = fileno(stdout);
if ( isatty(v7) )
{
fwrite(
"\nNote: This is a development version of dupd (2.0-dev) (41a45edbb0762fda94dcc840e91e7986d7e48f51)\n",
1uLL,
0x62uLL,
stdout);
fwrite("May contain known bugs or unstable work in progress!\n", 1uLL, 0x35uLL, stdout);
fwrite("If stability is desired, use a release version of dupd.\n", 1uLL, 0x38uLL, stdout);
}
}
return v3;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
const char *v4; // rax
__int64 v5; // rdi
__int64 v6; // rdx
int v7; // eax
const char *v9; // rax
unsigned int v10; // eax
const char *v11; // rax
const char *v12; // rax

stats_main_start = get_current_time_millis(argc, argv, envp);
pthread_key_create(&thread_name, 0LL);
pthread_setspecific(thread_name, "[MAIN] ");
pthread_key_create(&duplicate_path_buffer, 0LL);
v3 = func6((unsigned int)argc, (__int64)argv);
if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v4 = (const char *)get_thread_name();
printf("%s", v4);
argv = (const char **)log_level_name[log_level];
printf("Log level: %s\n", (const char *)argv);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
if ( v3 )
{
--v3;
}
else if ( start_path_state == 2 )
{
v3 = 1;
}
else
{
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v9 = (const char *)get_thread_name();
printf("%s", v9);
v10 = cpu_cores();
printf("Claimed CPU cores: %d\n", v10);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
max_open_files = get_file_limit() - 10;
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v11 = (const char *)get_thread_name();
printf("%s", v11);
printf("Max open files: %d\n", (unsigned int)max_open_files);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
signal(10, handle_signal);
signal(12, handle_signal);
if ( trace_file && (trace_file_fd = open64(trace_file, 1601, 416LL), trace_file_fd < 0) )
{
argv = (const char **)trace_file;
printf("error: unable to create trace-file [%s]\n", trace_file);
}
else
{
argv = (const char **)(unsigned int)operation;
switch ( operation )
{
case -1:
func5();
v3 = 1;
break;
case 1:
scan();
break;
case 2:
operation_refresh();
break;
case 3:
operation_report();
break;
case 4:
operation_file();
break;
case 5:
operation_uniques();
break;
case 6:
operation_dups();
break;
case 7:
operation_ls();
break;
case 8:
operation_hash_file();
break;
case 9:
func4();
break;
case 10:
operation_shell_script();
break;
case 11:
v3 = operation_validate();
break;
case 12:
func5();
break;
case 13:
case 14:
func3();
break;
case 15:
show_license();
break;
case 16:
puts("2.0-dev");
break;
case 17:
testing();
break;
case 18:
operation_info();
break;
default:
printf("error: unknown operation [%d]\n", (unsigned int)operation);
v3 = 1;
break;
}
}
}
if ( free_file_path )
free(file_path);
if ( free_db_path )
free(db_path);
if ( free_cache_db_path )
free(cache_db_path);
if ( path_sep_string )
free(path_sep_string);
free_size_tree();
free_size_list();
free_path_block();
free_filecompare();
free_scanlist();
func1();
free_read_list();
free_dirtree();
free_path_buffer();
v5 = thread_name;
pthread_key_delete(thread_name);
stats_time_total = get_current_time_millis(v5, argv, v6) - stats_main_start;
if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v12 = (const char *)get_thread_name();
printf("%s", v12);
printf("Total time: %ld ms\n", stats_time_total);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
if ( trace_file_fd != -1 )
{
close(trace_file_fd);
trace_file_fd = -1;
}
if ( stats_file )
save_stats();
if ( log_level >= 0 && ((unsigned int)(operation - 1) <= 1 || (unsigned int)(operation - 11) <= 5) )
{
v7 = fileno(stdout);
if ( isatty(v7) )
{
fwrite(
"\nNote: This is a development version of dupd (2.0-dev) (41a45edbb0762fda94dcc840e91e7986d7e48f51)\n",
1uLL,
0x62uLL,
stdout);
fwrite("May contain known bugs or unstable work in progress!\n", 1uLL, 0x35uLL, stdout);
fwrite("If stability is desired, use a release version of dupd.\n", 1uLL, 0x38uLL, stdout);
}
}
return v3;
}

original_code:
int main(int argc, char * argv[])
{
  stats_main_start = get_current_time_millis();
  int rv = 0;
  pthread_key_create(&thread_name, ((void *)0));
  pthread_setspecific(thread_name, (char *)"[MAIN] ");
  pthread_key_create(&duplicate_path_buffer, ((void *)0));
  rv = process_args(argc, argv);
  if (3 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Log level: %s\n", log_level_name[log_level]); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  if (rv) {
    rv--;
    goto DONE;
  }
  if (start_path_state == 2) {
    rv = 1;
    goto DONE;
  }
  if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Claimed CPU cores: %d\n", cpu_cores()); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  max_open_files = get_file_limit() - 10;
  if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Max open files: %d\n", max_open_files); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  signal(10, &handle_signal);
  signal(12, &handle_signal);
  if (trace_file != ((void *)0)) {
    trace_file_fd = open(trace_file, 0100 | 01000 | 02000 | 01,
                         0400 | 0200 | (0400 >> 3));
    if (trace_file_fd < 0) {
      printf("error: unable to create trace-file [%s]\n", trace_file);
      goto DONE;
    }
  }
  switch (operation) {
    case 1: scan(); break;
    case 2: operation_refresh(); break;
    case 3: operation_report(); break;
    case 5: operation_uniques(); break;
    case 15: show_license(); break;
    case 16: printf("2.0-dev" "\n"); break;
    case 6: operation_dups(); break;
    case 4: operation_file(); break;
    case 7: operation_ls(); break;
    case 10: operation_shell_script(); break;
    case 11: rv = operation_validate(); break;
    case 13: show_usage(); break;
    case 14: show_usage(); break;
    case 12: show_help(); break;
    case 17: testing(); break;
    case 8: operation_hash_file(); break;
    case 9: operation_cache(); break;
    case 18: operation_info(); break;
    case -1: show_help(); rv = 1; break;
    default:
      printf("error: unknown operation [%d]\n", operation);
      rv = 1;
  }
 DONE:
  if (free_file_path) { free(file_path); }
  if (free_db_path) { free(db_path); }
  if (free_cache_db_path) { free(cache_db_path); }
  if (path_sep_string) { free(path_sep_string); }
  free_size_tree();
  free_size_list();
  free_path_block();
  free_filecompare();
  free_scanlist();
  free_start_paths();
  free_read_list();
  free_dirtree();
  free_path_buffer();
  pthread_key_delete(thread_name);
  stats_time_total = get_current_time_millis() - stats_main_start;
  if (3 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Total time: %ld ms\n", stats_time_total); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  if (trace_file_fd != -1) {
    close(trace_file_fd);
    trace_file_fd = -1;
  }
  if (stats_file != ((void *)0)) {
    save_stats();
  }
  if (log_level >= 0) {
    if (operation == 1 ||
        operation == 2 || operation == 15 ||
        operation == 16 || operation == 11 ||
        operation == 13 || operation == 14 ||
        operation == 12) {
      if (!strcmp("dev", "2.0-dev" + strlen("2.0-dev") - 3)) {
        if (isatty(fileno(stdout))) {
          fprintf(stdout, "\nNote: This is a development version of dupd ("
                  "2.0-dev" ") (" "41a45edbb0762fda94dcc840e91e7986d7e48f51" ")\n");
          fprintf(stdout,
                  "May contain known bugs or unstable work in progress!\n");
          fprintf(stdout,
                  "If stability is desired, use a release version of dupd.\n");
        }
      }
    }
  }
  return(rv);
}

canonical_original_code:
int main(int argc, char *argv[])
{
  stats_main_start = get_current_time_millis();
  int rv = 0;
  pthread_key_create(&thread_name, ((void *)0));
  pthread_setspecific(thread_name, (char *)"[MAIN] ");
  pthread_key_create(&duplicate_path_buffer, ((void *)0));
  rv = process_args(argc, argv);
  if (3 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Log level: %s\n", log_level_name[log_level]); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  if (rv) {
    rv--;
    goto DONE;
  }
  if (start_path_state == 2) {
    rv = 1;
    goto DONE;
  }
  if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Claimed CPU cores: %d\n", cpu_cores()); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  max_open_files = get_file_limit() - 10;
  if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Max open files: %d\n", max_open_files); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  signal(10, &handle_signal);
  signal(12, &handle_signal);
  if (trace_file != ((void *)0)) {
    trace_file_fd = open(trace_file, 0100 | 01000 | 02000 | 01,
                         0400 | 0200 | (0400 >> 3));
    if (trace_file_fd < 0) {
      printf("error: unable to create trace-file [%s]\n", trace_file);
      goto DONE;
    }
  }
  switch (operation) {
    case 1: scan(); break;
    case 2: operation_refresh(); break;
    case 3: operation_report(); break;
    case 5: operation_uniques(); break;
    case 15: show_license(); break;
    case 16: printf("2.0-dev" "\n"); break;
    case 6: operation_dups(); break;
    case 4: operation_file(); break;
    case 7: operation_ls(); break;
    case 10: operation_shell_script(); break;
    case 11: rv = operation_validate(); break;
    case 13: show_usage(); break;
    case 14: show_usage(); break;
    case 12: show_help(); break;
    case 17: testing(); break;
    case 8: operation_hash_file(); break;
    case 9: operation_cache(); break;
    case 18: operation_info(); break;
    case -1: show_help(); rv = 1; break;
    default:
      printf("error: unknown operation [%d]\n", operation);
      rv = 1;
  }
 DONE:
  if (free_file_path) { free(file_path); }
  if (free_db_path) { free(db_path); }
  if (free_cache_db_path) { free(cache_db_path); }
  if (path_sep_string) { free(path_sep_string); }
  free_size_tree();
  free_size_list();
  free_path_block();
  free_filecompare();
  free_scanlist();
  free_start_paths();
  free_read_list();
  free_dirtree();
  free_path_buffer();
  pthread_key_delete(thread_name);
  stats_time_total = get_current_time_millis() - stats_main_start;
  if (3 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Total time: %ld ms\n", stats_time_total); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  if (trace_file_fd != -1) {
    close(trace_file_fd);
    trace_file_fd = -1;
  }
  if (stats_file != ((void *)0)) {
    save_stats();
  }
  if (log_level >= 0) {
    if (operation == 1 ||
        operation == 2 || operation == 15 ||
        operation == 16 || operation == 11 ||
        operation == 13 || operation == 14 ||
        operation == 12) {
      if (!strcmp("dev", "2.0-dev" + strlen("2.0-dev") - 3)) {
        if (isatty(fileno(stdout))) {
          fprintf(stdout, "\nNote: This is a development version of dupd ("
                  "2.0-dev" ") (" "41a45edbb0762fda94dcc840e91e7986d7e48f51" ")\n");
          fprintf(stdout,
                  "May contain known bugs or unstable work in progress!\n");
          fprintf(stdout,
                  "If stability is desired, use a release version of dupd.\n");
        }
      }
    }
  }
  return(rv);
}

variable_types: rv int


repo: jvirkki/dupd

decompiled_code:
__int64 __fastcall pb_get_first_entry(__int64 a1)
{
return a1 + 32;
}

canonical_decompiled_code:
__int64 __fastcall func0(__int64 a1)
{
return a1 + 32;
}

original_code:
static inline struct path_list_entry *
pb_get_first_entry(struct path_list_head * head)
{
  return (struct path_list_entry *)
    ((char *)head + sizeof(struct path_list_head));
}

canonical_original_code:
static inline struct path_list_entry *pb_get_first_entry(struct path_list_head *head)
{
  return (struct path_list_entry *)
    ((char *)head + sizeof(struct path_list_head));
}

variable_types: struct path_list_head { struct size_list { struct path_list_head *path_list; struct size_list *next; unsigned long size; int fully_read; union pthread_mutex_t { struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; unsigned int __nusers; int __kind; short __spins; short __elision; struct __pthread_internal_list { struct __pthread_internal_list *__prev; struct __pthread_internal_list *__next; } __list; } __data; char __size[40]; long __align; } lock; } *sizelist; struct path_list_entry *last_entry; unsigned int wanted_bufsize; unsigned int list_size; unsigned int buffer_ready; unsigned char state; unsigned char hash_passes; unsigned char have_cached_hashes; } *

return_type: struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } *

user_defined_types: struct path_list_head { struct size_list *sizelist; struct path_list_entry *last_entry; unsigned int wanted_bufsize; unsigned int list_size; unsigned int buffer_ready; unsigned char state; unsigned char hash_passes; unsigned char have_cached_hashes; }

user_defined_types: struct path_list_entry { struct path_list_entry *next; struct block_list *blocks; struct direntry *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; }

user_defined_types: struct size_list { struct path_list_head *path_list; struct size_list *next; unsigned long size; int fully_read; union pthread_mutex_t lock; }

user_defined_types: struct block_list { unsigned char count; struct block_list_entry entry[]; }

user_defined_types: union pthread_mutex_t { struct __pthread_mutex_s __data; char __size[40]; long __align; }

user_defined_types: struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; unsigned int __nusers; int __kind; short __spins; short __elision; struct __pthread_internal_list __list; }


decompiled_code:
unsigned int __fastcall d_cond_wait(pthread_cond_t *a1, pthread_mutex_t *a2)
{
unsigned int result; // eax

result = pthread_cond_wait(a1, a2);
if ( result )
{
printf("error: pthread_cond_wait == %d\n", result);
exit(1);
}
return result;
}

canonical_decompiled_code:
unsigned int __fastcall func1(pthread_cond_t *a1, pthread_mutex_t *a2)
{
unsigned int result; // eax

result = pthread_cond_wait(a1, a2);
if ( result )
{
printf("error: pthread_cond_wait == %d\n", result);
exit(1);
}
return result;
}

original_code:
static inline void d_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
{
  int rv = pthread_cond_wait(cond, mutex);
  if (rv != 0) {
    printf("error: pthread_cond_wait == %d\n", rv);
    exit(1);
  }
}

canonical_original_code:
static inline void d_cond_wait(union pthread_cond_t *cond, union pthread_mutex_t *mutex)
{
  int rv = pthread_cond_wait(cond, mutex);
  if (rv != 0) {
    printf("error: pthread_cond_wait == %d\n", rv);
    exit(1);
  }
}

variable_types: union pthread_cond_t { struct __pthread_cond_s { union { unsigned long long __wseq; struct { unsigned int __low; unsigned int __high; } __wseq32; }; union { unsigned long long __g1_start; struct { unsigned int __low; unsigned int __high; } __g1_start32; }; unsigned int __g_refs[2]; unsigned int __g_size[2]; unsigned int __g1_orig_size; unsigned int __wrefs; unsigned int __g_signals[2]; } __data; char __size[48]; long long __align; } *

variable_types: union pthread_mutex_t { struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; unsigned int __nusers; int __kind; short __spins; short __elision; struct __pthread_internal_list { struct __pthread_internal_list *__prev; struct __pthread_internal_list *__next; } __list; } __data; char __size[40]; long __align; } *

return_type: void

user_defined_types: union pthread_cond_t { struct __pthread_cond_s __data; char __size[48]; long long __align; }


decompiled_code:
unsigned int __fastcall d_mutex_lock(pthread_mutex_t *a1, const char *a2)
{
unsigned int result; // eax

result = pthread_mutex_lock(a1);
if ( result )
{
printf("error: %s: pthread_mutex_lock == %d\n", a2, result);
exit(1);
}
return result;
}

canonical_decompiled_code:
unsigned int __fastcall func2(pthread_mutex_t *a1, const char *a2)
{
unsigned int result; // eax

result = pthread_mutex_lock(a1);
if ( result )
{
printf("error: %s: pthread_mutex_lock == %d\n", a2, result);
exit(1);
}
return result;
}

original_code:
static inline void d_mutex_lock(pthread_mutex_t * mutex, char * line)
{
  int rv = pthread_mutex_lock(mutex);
  if (rv != 0) {
    printf("error: %s: pthread_mutex_lock == %d\n", line, rv);
    exit(1);
  }
}

canonical_original_code:
static inline void d_mutex_lock(union pthread_mutex_t *mutex, char *line)
{
  int rv = pthread_mutex_lock(mutex);
  if (rv != 0) {
    printf("error: %s: pthread_mutex_lock == %d\n", line, rv);
    exit(1);
  }
}

variable_types:
line
char *

user_defined_types: struct __pthread_internal_list { struct __pthread_internal_list *__prev; struct __pthread_internal_list *__next; }


decompiled_code:
unsigned int __fastcall d_mutex_unlock(pthread_mutex_t *a1)
{
unsigned int result; // eax

result = pthread_mutex_unlock(a1);
if ( result )
{
printf("error: pthread_mutex_unlock == %d\n", result);
exit(1);
}
return result;
}

canonical_decompiled_code:
unsigned int __fastcall func3(pthread_mutex_t *a1)
{
unsigned int result; // eax

result = pthread_mutex_unlock(a1);
if ( result )
{
printf("error: pthread_mutex_unlock == %d\n", result);
exit(1);
}
return result;
}

original_code:
static inline void d_mutex_unlock(pthread_mutex_t * mutex)
{
  int rv = pthread_mutex_unlock(mutex);
  if (rv != 0) {
    printf("error: pthread_mutex_unlock == %d\n", rv);
    exit(1);
  }
}

canonical_original_code:
static inline void d_mutex_unlock(union pthread_mutex_t *mutex)
{
  int rv = pthread_mutex_unlock(mutex);
  if (rv != 0) {
    printf("error: pthread_mutex_unlock == %d\n", rv);
    exit(1);
  }
}


decompiled_code:
__int64 __fastcall update_node_hash(__int64 a1, __int64 a2)
{
if ( !*(_QWORD *)(a1 + 32) )
*(_QWORD *)(a1 + 32) = hash_fn_buf_init();
hash_fn_buf_update(*(_QWORD *)(a1 + 32), *(_QWORD *)(a1 + 24), *(unsigned int *)(a1 + 64));
return hash_fn_get_partial(*(_QWORD *)(a1 + 32), a2);
}

canonical_decompiled_code:
__int64 __fastcall func4(__int64 a1, __int64 a2)
{
if ( !*(_QWORD *)(a1 + 32) )
*(_QWORD *)(a1 + 32) = hash_fn_buf_init();
hash_fn_buf_update(*(_QWORD *)(a1 + 32), *(_QWORD *)(a1 + 24), *(unsigned int *)(a1 + 64));
return hash_fn_get_partial(*(_QWORD *)(a1 + 32), a2);
}

original_code:
static void update_node_hash(struct path_list_entry * node, char * hash_out)
{
  if (node->hash_ctx == ((void *)0)) {
    node->hash_ctx = hash_fn_buf_init();
  }
  hash_fn_buf_update(node->hash_ctx, node->buffer, node->data_in_buffer);
  hash_fn_get_partial(node->hash_ctx, hash_out);
}

canonical_original_code:
static void update_node_hash(struct path_list_entry *node, char *hash_out)
{
  if (node->hash_ctx == ((void *)0)) {
    node->hash_ctx = hash_fn_buf_init();
  }
  hash_fn_buf_update(node->hash_ctx, node->buffer, node->data_in_buffer);
  hash_fn_get_partial(node->hash_ctx, hash_out);
}

variable_types: struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } *


user_defined_types: struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; }

user_defined_types: struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; }


decompiled_code:
__int64 __fastcall rl_compare_i(const void *a1, const void *a2)
{
return (unsigned int)*((_QWORD *)a1 + 3) - *((_DWORD *)a2 + 6);
}

canonical_decompiled_code:
__int64 __fastcall func1(const void *a1, const void *a2)
{
return (unsigned int)*((_QWORD *)a1 + 3) - *((_DWORD *)a2 + 6);
}

original_code:
static int rl_compare_i(const void * a, const void * b)
{
  struct read_list_entry * f = (struct read_list_entry *)a;
  struct read_list_entry * s = (struct read_list_entry *)b;
  return f->inode - s->inode;
}

canonical_original_code:
static int rl_compare_i(void *a, void *b)
{
  struct read_list_entry *f = (struct read_list_entry *)a;
  struct read_list_entry *s = (struct read_list_entry *)b;
  return f->inode - s->inode;
}

variable_types:
a
void *

variable_types:
b
void *

variable_types: struct read_list_entry { struct path_list_head { struct size_list { struct path_list_head *path_list; struct size_list *next; unsigned long size; int fully_read; union pthread_mutex_t { struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; unsigned int __nusers; int __kind; short __spins; short __elision; struct __pthread_internal_list { struct __pthread_internal_list *__prev; struct __pthread_internal_list *__next; } __list; } __data; char __size[40]; long __align; } lock; } *sizelist; struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } *last_entry; unsigned int wanted_bufsize; unsigned int list_size; unsigned int buffer_ready; unsigned char state; unsigned char hash_passes; unsigned char have_cached_hashes; } *pathlist_head; struct path_list_entry *pathlist_self; unsigned long block; unsigned long inode; unsigned char done; } *

return_type: int

user_defined_types: struct read_list_entry { struct path_list_head *pathlist_head; struct path_list_entry *pathlist_self; unsigned long block; unsigned long inode; unsigned char done; }


decompiled_code:
__int64 __fastcall rl_compare_b(const void *a1, const void *a2)
{
unsigned __int64 v2; // rcx
unsigned __int64 v3; // rdx
__int64 result; // rax

v2 = *((_QWORD *)a1 + 2);
v3 = *((_QWORD *)a2 + 2);
result = 1LL;
if ( v2 <= v3 )
result = (unsigned int)-(v2 < v3);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func2(const void *a1, const void *a2)
{
unsigned __int64 v2; // rcx
unsigned __int64 v3; // rdx
__int64 result; // rax

v2 = *((_QWORD *)a1 + 2);
v3 = *((_QWORD *)a2 + 2);
result = 1LL;
if ( v2 <= v3 )
result = (unsigned int)-(v2 < v3);
return result;
}

original_code:
static int rl_compare_b(const void * a, const void * b)
{
  struct read_list_entry * f = (struct read_list_entry *)a;
  struct read_list_entry * s = (struct read_list_entry *)b;
  if (f->block > s->block) { return 1; }
  if (f->block < s->block) { return -1; }
  return 0;
}

canonical_original_code:
static int rl_compare_b(void *a, void *b)
{
  struct read_list_entry *f = (struct read_list_entry *)a;
  struct read_list_entry *s = (struct read_list_entry *)b;
  if (f->block > s->block) { return 1; }
  if (f->block < s->block) { return -1; }
  return 0;
}


original_code:
static uint64_t
add_all_blocks_from_group(struct path_list_head * plhead,
                          struct read_list_entry * tmp_read_list,
                          uint64_t * tmp_index)
{
  uint64_t n = 0;
  struct path_list_entry * entry = pb_get_first_entry(plhead);
  while (entry != ((void *)0)) {
    if (entry->state == 51) {
      for (uint8_t i = 0; i < entry->blocks->count; i++) {
        tmp_read_list[*tmp_index].pathlist_head = plhead;
        tmp_read_list[*tmp_index].pathlist_self = entry;
        tmp_read_list[*tmp_index].block = entry->blocks->entry[i].block;
        tmp_read_list[*tmp_index].inode = 0;
        tmp_read_list[*tmp_index].done = 0;
        (*tmp_index)++;
        n++;
      }
    }
    entry = entry->next;
  }
  return n;
}

canonical_original_code:
static unsigned long add_all_blocks_from_group(struct path_list_head *plhead, struct read_list_entry *tmp_read_list, unsigned long *tmp_index)
{
  unsigned long n = 0;
  struct path_list_entry *entry = pb_get_first_entry(plhead);
  while (entry != ((void *)0)) {
    if (entry->state == 51) {
      for (unsigned char i = 0; i < entry->blocks->count; i++) {
        tmp_read_list[*tmp_index].pathlist_head = plhead;
        tmp_read_list[*tmp_index].pathlist_self = entry;
        tmp_read_list[*tmp_index].block = entry->blocks->entry[i].block;
        tmp_read_list[*tmp_index].inode = 0;
        tmp_read_list[*tmp_index].done = 0;
        (*tmp_index)++;
        n++;
      }
    }
    entry = entry->next;
  }
  return n;
}

variable_types: struct path_list_head { struct size_list { struct path_list_head *path_list; struct size_list *next; unsigned long size; int fully_read; union pthread_mutex_t { struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; unsigned int __nusers; int __kind; short __spins; short __elision; struct __pthread_internal_list { struct __pthread_internal_list *__prev; struct __pthread_internal_list *__next; } __list; } __data; char __size[40]; long __align; } lock; } *sizelist; struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } *last_entry; unsigned int wanted_bufsize; unsigned int list_size; unsigned int buffer_ready; unsigned char state; unsigned char hash_passes; unsigned char have_cached_hashes; } *

variable_types: struct read_list_entry { struct path_list_head *pathlist_head; struct path_list_entry *pathlist_self; unsigned long block; unsigned long inode; unsigned char done; } *

variable_types:
n
unsigned long

variable_types:
i
unsigned char

return_type: unsigned long


decompiled_code:
void free_inode_read_list()
{
if ( inode_read_list )
{
dec_stats_readlist((unsigned int)(40 * inode_read_list_size));
free(inode_read_list);
inode_read_list = 0LL;
inode_read_list_size = 0LL;
inode_read_list_end = 0LL;
}
}

canonical_decompiled_code:
void func4()
{
if ( inode_read_list )
{
dec_stats_readlist((unsigned int)(40 * inode_read_list_size));
free(inode_read_list);
inode_read_list = 0LL;
inode_read_list_size = 0LL;
inode_read_list_end = 0LL;
}
}

original_code:
static void free_inode_read_list()
{
  if (inode_read_list != ((void *)0)) {
    dec_stats_readlist(sizeof(struct read_list_entry) * inode_read_list_size);
    free(inode_read_list);
    inode_read_list = ((void *)0);
    inode_read_list_size = 0;
    inode_read_list_end = 0;
  }
}


decompiled_code:
void __fastcall add_one_to_inode_read_list(__int64 a1, __int64 a2, __int64 a3)
{
size_t v3; // rcx
size_t v4; // rax
char *v5; // rax
size_t v6; // rax

if ( hardlink_is_unique )
{
v3 = inode_read_list_end;
v4 = 40 * inode_read_list_end;
*(_QWORD *)((char *)inode_read_list + v4) = a1;
v5 = (char *)inode_read_list + v4;
*((_QWORD *)v5 + 1) = a2;
*((_QWORD *)v5 + 2) = a3;
*((_QWORD *)v5 + 3) = a3;
v5[32] = 0;
inode_read_list_end = v3 + 1;
if ( v3 + 1 == inode_read_list_size )
{
inc_stats_readlist((unsigned int)(40 * inode_read_list_size));
v6 = inode_read_list_size;
inode_read_list_size *= 2LL;
inode_read_list = realloc(inode_read_list, 80 * v6);
}
}
}

canonical_decompiled_code:
void __fastcall func5(__int64 a1, __int64 a2, __int64 a3)
{
size_t v3; // rcx
size_t v4; // rax
char *v5; // rax
size_t v6; // rax

if ( hardlink_is_unique )
{
v3 = inode_read_list_end;
v4 = 40 * inode_read_list_end;
*(_QWORD *)((char *)inode_read_list + v4) = a1;
v5 = (char *)inode_read_list + v4;
*((_QWORD *)v5 + 1) = a2;
*((_QWORD *)v5 + 2) = a3;
*((_QWORD *)v5 + 3) = a3;
v5[32] = 0;
inode_read_list_end = v3 + 1;
if ( v3 + 1 == inode_read_list_size )
{
inc_stats_readlist((unsigned int)(40 * inode_read_list_size));
v6 = inode_read_list_size;
inode_read_list_size *= 2LL;
inode_read_list = realloc(inode_read_list, 80 * v6);
}
}
}

original_code:
static void add_one_to_inode_read_list(struct path_list_head * head,
                                       struct path_list_entry * entry,
                                       ino_t inode)
{
  if (hardlink_is_unique) {
    inode_read_list[inode_read_list_end].pathlist_head = head;
    inode_read_list[inode_read_list_end].pathlist_self = entry;
    inode_read_list[inode_read_list_end].block = inode;
    inode_read_list[inode_read_list_end].inode = inode;
    inode_read_list[inode_read_list_end].done = 0;
    inode_read_list_end++;
    if (inode_read_list_end == inode_read_list_size) {
      inc_stats_readlist(sizeof(struct read_list_entry) * inode_read_list_size);
      inode_read_list_size *= 2;
      inode_read_list = (struct read_list_entry *)
        realloc(inode_read_list, sizeof(struct read_list_entry) *
                inode_read_list_size);
    }
  }
}

canonical_original_code:
static void add_one_to_inode_read_list(struct path_list_head *head, struct path_list_entry *entry, unsigned long inode)
{
  if (hardlink_is_unique) {
    inode_read_list[inode_read_list_end].pathlist_head = head;
    inode_read_list[inode_read_list_end].pathlist_self = entry;
    inode_read_list[inode_read_list_end].block = inode;
    inode_read_list[inode_read_list_end].inode = inode;
    inode_read_list[inode_read_list_end].done = 0;
    inode_read_list_end++;
    if (inode_read_list_end == inode_read_list_size) {
      inc_stats_readlist(sizeof(struct read_list_entry) * inode_read_list_size);
      inode_read_list_size *= 2;
      inode_read_list = (struct read_list_entry *)
        realloc(inode_read_list, sizeof(struct read_list_entry) *
                inode_read_list_size);
    }
  }
}

variable_types:
entry
struct path_list_entry *

variable_types:
inode
unsigned long


decompiled_code:
void init_read_list()
{
int v0; // ebx

if ( hardlink_is_unique )
{
inode_read_list_size = 100000LL;
if ( x_small_buffers )
inode_read_list_size = 8LL;
inode_read_list_end = 0LL;
v0 = inode_read_list_size;
inode_read_list = calloc(inode_read_list_size, 0x28uLL);
inc_stats_readlist((unsigned int)(40 * v0));
}
}

canonical_decompiled_code:
void func8()
{
int v0; // ebx

if ( hardlink_is_unique )
{
inode_read_list_size = 100000LL;
if ( x_small_buffers )
inode_read_list_size = 8LL;
inode_read_list_end = 0LL;
v0 = inode_read_list_size;
inode_read_list = calloc(inode_read_list_size, 0x28uLL);
inc_stats_readlist((unsigned int)(40 * v0));
}
}

original_code:
void init_read_list()
{
  if (hardlink_is_unique) {
    inode_read_list_size = 100000;
    if (x_small_buffers) { inode_read_list_size = 8; }
    inode_read_list_end = 0;
    inode_read_list =
      (struct read_list_entry *)calloc(inode_read_list_size,
                                       sizeof(struct read_list_entry));
    inc_stats_readlist(sizeof(struct read_list_entry) * inode_read_list_size);
  }
}


decompiled_code:
void free_read_list()
{
if ( read_list )
{
dec_stats_readlist((unsigned int)(40 * read_block_counter));
free(read_list);
read_list = 0LL;
read_list_end = 0LL;
}
}

canonical_decompiled_code:
void func9()
{
if ( read_list )
{
dec_stats_readlist((unsigned int)(40 * read_block_counter));
free(read_list);
read_list = 0LL;
read_list_end = 0LL;
}
}

original_code:
void free_read_list()
{
  if (read_list != ((void *)0)) {
    dec_stats_readlist(sizeof(struct read_list_entry) * read_block_counter);
    free(read_list);
    read_list = ((void *)0);
    read_list_end = 0;
  }
}


decompiled_code:
void __fastcall add_to_read_list(__int64 a1, __int64 a2, __int64 a3)
{
unsigned __int8 *v3; // rax

v3 = *(unsigned __int8 **)(a2 + 8);
if ( !v3 )
{
puts("error: add_to_read_list but no block(s)");
dump_path_list("block missing", 0LL, a1, 1LL);
exit(1);
}
read_block_counter += *v3;
if ( hardlink_is_unique )
add_one_to_inode_read_list(a1, a2, a3);
}

canonical_decompiled_code:
void __fastcall func10(__int64 a1, __int64 a2, __int64 a3)
{
unsigned __int8 *v3; // rax

v3 = *(unsigned __int8 **)(a2 + 8);
if ( !v3 )
{
puts("error: add_to_read_list but no block(s)");
dump_path_list("block missing", 0LL, a1, 1LL);
exit(1);
}
read_block_counter += *v3;
if ( hardlink_is_unique )
func5(a1, a2, a3);
}

original_code:
void add_to_read_list(struct path_list_head * head,
                      struct path_list_entry * entry, ino_t inode)
{
  if (entry->blocks == ((void *)0)) {
    printf("error: add_to_read_list but no block(s)\n");
    dump_path_list("block missing", 0, head, 1);
    exit(1);
  }
  read_block_counter += entry->blocks->count;
  if (hardlink_is_unique) {
    add_one_to_inode_read_list(head, entry, inode);
  }
}

canonical_original_code:
void add_to_read_list(struct path_list_head *head, struct path_list_entry *entry, unsigned long inode)
{
  if (entry->blocks == ((void *)0)) {
    printf("error: add_to_read_list but no block(s)\n");
    dump_path_list("block missing", 0, head, 1);
    exit(1);
  }
  read_block_counter += entry->blocks->count;
  if (hardlink_is_unique) {
    add_one_to_inode_read_list(head, entry, inode);
  }
}


decompiled_code:
int sort_read_list()
{
int v0; // ebx
void *v1; // r12
int v2; // ebx
void *v3; // rbp
__int64 *v4; // rbx
__int64 v5; // r13
__int64 v6; // r14
__int64 v7; // rdx
size_t v8; // rbp
__int64 v9; // rdi
int v10; // er12
__int64 v11; // rbx
char *v12; // rax
const char *v13; // rax
__int64 *v14; // rbx
__int64 v15; // r13
__int64 v16; // r14
const char *v17; // rax
unsigned __int64 v18; // rax
__int64 *v19; // rbx
__int64 *v20; // rbx
__int64 v21; // r13
__int64 v22; // r14
const char *v23; // rax
unsigned __int64 v24; // rax
__int64 v25; // r13
const char *v26; // rax
__int64 *v27; // rbx
int result; // eax
unsigned int v29; // ebx
const char *v30; // rax
__int64 v31; // r13
const char *v32; // rax
const char *v33; // rax
char v34[4096]; // [rsp+0h] [rbp-1038h] BYREF
size_t v35; // [rsp+1000h] [rbp-38h] BYREF
__int64 v36[6]; // [rsp+1008h] [rbp-30h] BYREF

if ( hardlink_is_unique )
{
qsort(inode_read_list, inode_read_list_end, 0x28uLL, (__compar_fn_t)rl_compare_i);
if ( inode_read_list_end )
{
v7 = 0LL;
v8 = 0LL;
do
{
v11 = 40 * v8;
v12 = (char *)inode_read_list + 40 * v8;
if ( *((_QWORD *)v12 + 3) == v7 )
{
build_path(*((_QWORD *)v12 + 1), v34);
if ( log_level > 7 )
{
pthread_mutex_lock(&logger_lock);
v13 = (const char *)get_thread_name();
printf("%s", v13);
printf("Skipping [%s] due to duplicate inode.\n", v34);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
v9 = *((_QWORD *)inode_read_list + 5 * v8);
v10 = *(_DWORD *)(v9 + 20);
s_files_hl_skip += v10 - mark_path_entry_ignore_hardlink(v9, *(_QWORD *)((char *)inode_read_list + v11 + 8));
}
v7 = *(_QWORD *)((char *)inode_read_list + v11 + 24);
++v8;
}
while ( inode_read_list_end > v8 );
}
free_inode_read_list();
}
v0 = read_block_counter;
v1 = malloc(40 * read_block_counter);
inc_stats_readlist((unsigned int)(40 * v0));
v36[0] = 0LL;
v2 = read_block_counter;
v3 = malloc(40 * read_block_counter);
inc_stats_readlist((unsigned int)(40 * v2));
v35 = 0LL;
v4 = (__int64 *)size_list_head;
if ( size_list_head )
{
v5 = 0LL;
v6 = 0LL;
do
{
if ( v4[2] <= (unsigned __int64)hash_one_block_size )
{
v6 += add_all_blocks_from_group(*v4, (__int64)v3, &v35);
++v5;
}
v4 = (__int64 *)v4[1];
}
while ( v4 );
sort_and_transfer(v3, &v35, (__int64)v1, v36);
if ( v5 && log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v17 = (const char *)get_thread_name();
printf("%s", v17);
printf("read_list: (#1 small files): SETS %lu, BLOCKS %lu\n", v5, v6);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
else
{
sort_and_transfer(v3, &v35, (__int64)v1, v36);
}
v35 = 0LL;
v14 = (__int64 *)size_list_head;
if ( size_list_head )
{
v15 = 0LL;
v16 = 0LL;
do
{
if ( *(_DWORD *)(*v14 + 20) <= 0x200u )
{
v18 = v14[2];
if ( v18 > hash_one_block_size && v18 <= round1_max_bytes )
{
v16 += add_all_blocks_from_group(*v14, (__int64)v3, &v35);
++v15;
}
}
v14 = (__int64 *)v14[1];
}
while ( v14 );
sort_and_transfer(v3, &v35, (__int64)v1, v36);
if ( v15 && log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v23 = (const char *)get_thread_name();
printf("%s", v23);
printf("read_list: (#2 medium files): SETS %lu, BLOCKS %lu\n", v15, v16);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
else
{
sort_and_transfer(v3, &v35, (__int64)v1, v36);
}
v35 = 0LL;
v19 = (__int64 *)size_list_head;
if ( size_list_head )
{
do
{
if ( *(_DWORD *)(*v19 + 20) > 0x200u )
{
v24 = v19[2];
if ( v24 > hash_one_block_size && v24 <= round1_max_bytes )
{
v35 = 0LL;
v25 = add_all_blocks_from_group(*v19, (__int64)v3, &v35);
sort_and_transfer(v3, &v35, (__int64)v1, v36);
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v26 = (const char *)get_thread_name();
printf("%s", v26);
printf("read_list: (#3 large set, size: %lu): SETS 1, BLOCKS %lu\n", v19[2], v25);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
}
v19 = (__int64 *)v19[1];
}
while ( v19 );
}
v35 = 0LL;
v20 = (__int64 *)size_list_head;
if ( size_list_head )
{
v21 = 0LL;
v22 = 0LL;
do
{
if ( *(_DWORD *)(*v20 + 20) <= 8u && v20[2] > (unsigned __int64)round1_max_bytes )
{
v22 += add_all_blocks_from_group(*v20, (__int64)v3, &v35);
++v21;
}
v20 = (__int64 *)v20[1];
}
while ( v20 );
sort_and_transfer(v3, &v35, (__int64)v1, v36);
if ( v21 && log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v30 = (const char *)get_thread_name();
printf("%s", v30);
printf("read_list: (#4 large files): SETS %lu, BLOCKS %lu\n", v21, v22);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
else
{
sort_and_transfer(v3, &v35, (__int64)v1, v36);
}
v35 = 0LL;
v27 = (__int64 *)size_list_head;
if ( size_list_head )
{
do
{
if ( *(_DWORD *)(*v27 + 20) > 8u && v27[2] > (unsigned __int64)round1_max_bytes )
{
v35 = 0LL;
v31 = add_all_blocks_from_group(*v27, (__int64)v3, &v35);
sort_and_transfer(v3, &v35, (__int64)v1, v36);
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v32 = (const char *)get_thread_name();
printf("%s", v32);
printf("read_list: (#5 large set, size: %lu): SETS 1, BLOCKS %lu\n", v27[2], v31);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
v27 = (__int64 *)v27[1];
}
while ( v27 );
}
free(v3);
v35 = 0LL;
dec_stats_readlist((unsigned int)(40 * read_block_counter));
read_list = v1;
result = v36[0];
read_list_end = v36[0];
if ( using_fiemap )
{
result = (unsigned int)(100 * stats_fiemap_zero_blocks) / stats_fiemap_total_blocks;
v29 = result;
if ( result > 5 && s_total_files_seen > 0x64u )
{
using_fiemap = 0;
if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v33 = (const char *)get_thread_name();
printf("%s", v33);
printf("Turning off using_fiemap, %d%% zero blocks\n", v29);
fflush(stdout);
result = pthread_mutex_unlock(&logger_lock);
}
}
}
if ( log_level > 11 )
{
puts("read_list after final sort");
result = dump_read_list(0);
}
return result;
}

canonical_decompiled_code:
int func11()
{
int v0; // ebx
void *v1; // r12
int v2; // ebx
void *v3; // rbp
__int64 *v4; // rbx
__int64 v5; // r13
__int64 v6; // r14
__int64 v7; // rdx
size_t v8; // rbp
__int64 v9; // rdi
int v10; // er12
__int64 v11; // rbx
char *v12; // rax
const char *v13; // rax
__int64 *v14; // rbx
__int64 v15; // r13
__int64 v16; // r14
const char *v17; // rax
unsigned __int64 v18; // rax
__int64 *v19; // rbx
__int64 *v20; // rbx
__int64 v21; // r13
__int64 v22; // r14
const char *v23; // rax
unsigned __int64 v24; // rax
__int64 v25; // r13
const char *v26; // rax
__int64 *v27; // rbx
int result; // eax
unsigned int v29; // ebx
const char *v30; // rax
__int64 v31; // r13
const char *v32; // rax
const char *v33; // rax
char v34[4096]; // [rsp+0h] [rbp-1038h] BYREF
size_t v35; // [rsp+1000h] [rbp-38h] BYREF
__int64 v36[6]; // [rsp+1008h] [rbp-30h] BYREF

if ( hardlink_is_unique )
{
qsort(inode_read_list, inode_read_list_end, 0x28uLL, (__compar_fn_t)rl_compare_i);
if ( inode_read_list_end )
{
v7 = 0LL;
v8 = 0LL;
do
{
v11 = 40 * v8;
v12 = (char *)inode_read_list + 40 * v8;
if ( *((_QWORD *)v12 + 3) == v7 )
{
build_path(*((_QWORD *)v12 + 1), v34);
if ( log_level > 7 )
{
pthread_mutex_lock(&logger_lock);
v13 = (const char *)get_thread_name();
printf("%s", v13);
printf("Skipping [%s] due to duplicate inode.\n", v34);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
v9 = *((_QWORD *)inode_read_list + 5 * v8);
v10 = *(_DWORD *)(v9 + 20);
s_files_hl_skip += v10 - mark_path_entry_ignore_hardlink(v9, *(_QWORD *)((char *)inode_read_list + v11 + 8));
}
v7 = *(_QWORD *)((char *)inode_read_list + v11 + 24);
++v8;
}
while ( inode_read_list_end > v8 );
}
func4();
}
v0 = read_block_counter;
v1 = malloc(40 * read_block_counter);
inc_stats_readlist((unsigned int)(40 * v0));
v36[0] = 0LL;
v2 = read_block_counter;
v3 = malloc(40 * read_block_counter);
inc_stats_readlist((unsigned int)(40 * v2));
v35 = 0LL;
v4 = (__int64 *)size_list_head;
if ( size_list_head )
{
v5 = 0LL;
v6 = 0LL;
do
{
if ( v4[2] <= (unsigned __int64)hash_one_block_size )
{
v6 += func3(*v4, (__int64)v3, &v35);
++v5;
}
v4 = (__int64 *)v4[1];
}
while ( v4 );
func7(v3, &v35, (__int64)v1, v36);
if ( v5 && log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v17 = (const char *)get_thread_name();
printf("%s", v17);
printf("read_list: (#1 small files): SETS %lu, BLOCKS %lu\n", v5, v6);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
else
{
func7(v3, &v35, (__int64)v1, v36);
}
v35 = 0LL;
v14 = (__int64 *)size_list_head;
if ( size_list_head )
{
v15 = 0LL;
v16 = 0LL;
do
{
if ( *(_DWORD *)(*v14 + 20) <= 0x200u )
{
v18 = v14[2];
if ( v18 > hash_one_block_size && v18 <= round1_max_bytes )
{
v16 += func3(*v14, (__int64)v3, &v35);
++v15;
}
}
v14 = (__int64 *)v14[1];
}
while ( v14 );
func7(v3, &v35, (__int64)v1, v36);
if ( v15 && log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v23 = (const char *)get_thread_name();
printf("%s", v23);
printf("read_list: (#2 medium files): SETS %lu, BLOCKS %lu\n", v15, v16);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
else
{
func7(v3, &v35, (__int64)v1, v36);
}
v35 = 0LL;
v19 = (__int64 *)size_list_head;
if ( size_list_head )
{
do
{
if ( *(_DWORD *)(*v19 + 20) > 0x200u )
{
v24 = v19[2];
if ( v24 > hash_one_block_size && v24 <= round1_max_bytes )
{
v35 = 0LL;
v25 = func3(*v19, (__int64)v3, &v35);
func7(v3, &v35, (__int64)v1, v36);
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v26 = (const char *)get_thread_name();
printf("%s", v26);
printf("read_list: (#3 large set, size: %lu): SETS 1, BLOCKS %lu\n", v19[2], v25);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
}
v19 = (__int64 *)v19[1];
}
while ( v19 );
}
v35 = 0LL;
v20 = (__int64 *)size_list_head;
if ( size_list_head )
{
v21 = 0LL;
v22 = 0LL;
do
{
if ( *(_DWORD *)(*v20 + 20) <= 8u && v20[2] > (unsigned __int64)round1_max_bytes )
{
v22 += func3(*v20, (__int64)v3, &v35);
++v21;
}
v20 = (__int64 *)v20[1];
}
while ( v20 );
func7(v3, &v35, (__int64)v1, v36);
if ( v21 && log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v30 = (const char *)get_thread_name();
printf("%s", v30);
printf("read_list: (#4 large files): SETS %lu, BLOCKS %lu\n", v21, v22);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
else
{
func7(v3, &v35, (__int64)v1, v36);
}
v35 = 0LL;
v27 = (__int64 *)size_list_head;
if ( size_list_head )
{
do
{
if ( *(_DWORD *)(*v27 + 20) > 8u && v27[2] > (unsigned __int64)round1_max_bytes )
{
v35 = 0LL;
v31 = func3(*v27, (__int64)v3, &v35);
func7(v3, &v35, (__int64)v1, v36);
if ( log_level > 3 )
{
pthread_mutex_lock(&logger_lock);
v32 = (const char *)get_thread_name();
printf("%s", v32);
printf("read_list: (#5 large set, size: %lu): SETS 1, BLOCKS %lu\n", v27[2], v31);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
v27 = (__int64 *)v27[1];
}
while ( v27 );
}
free(v3);
v35 = 0LL;
dec_stats_readlist((unsigned int)(40 * read_block_counter));
read_list = v1;
result = v36[0];
read_list_end = v36[0];
if ( using_fiemap )
{
result = (unsigned int)(100 * stats_fiemap_zero_blocks) / stats_fiemap_total_blocks;
v29 = result;
if ( result > 5 && s_total_files_seen > 0x64u )
{
using_fiemap = 0;
if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v33 = (const char *)get_thread_name();
printf("%s", v33);
printf("Turning off using_fiemap, %d%% zero blocks\n", v29);
fflush(stdout);
result = pthread_mutex_unlock(&logger_lock);
}
}
}
if ( log_level > 11 )
{
puts("read_list after final sort");
result = func6(0);
}
return result;
}

original_code:
void sort_read_list()
{
  if (hardlink_is_unique) {
    qsort(inode_read_list, inode_read_list_end,
          sizeof(struct read_list_entry), rl_compare_i);
    char path[4096];
    uint64_t i;
    ino_t p_inode = 0;
    for (i = 0; i < inode_read_list_end; i++) {
      if (inode_read_list[i].inode == p_inode) {
        build_path(inode_read_list[i].pathlist_self, path);
        if (8 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Skipping [%s] due to duplicate inode.\n", path); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
        int before = inode_read_list[i].pathlist_head->list_size;
        int after =
          mark_path_entry_ignore_hardlink(inode_read_list[i].pathlist_head,
                                          inode_read_list[i].pathlist_self);
        s_files_hl_skip += (before - after);
      }
      p_inode = inode_read_list[i].inode;
    }
    free_inode_read_list();
  }
  struct read_list_entry * the_read_list = (struct read_list_entry *)
    malloc(sizeof(struct read_list_entry) * read_block_counter);
  inc_stats_readlist(sizeof(struct read_list_entry) * read_block_counter);
  uint64_t read_list_index = 0;
  struct read_list_entry * tmp_read_list = (struct read_list_entry *)
    malloc(sizeof(struct read_list_entry) * read_block_counter);
  inc_stats_readlist(sizeof(struct read_list_entry) * read_block_counter);
  uint64_t tmp_index = 0;
  uint64_t block_counter = 0;
  uint64_t set_counter = 0;
  struct size_list * szl = ((void *)0);
  tmp_index = 0;
  block_counter = 0;
  set_counter = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->size <= hash_one_block_size) {
      block_counter +=
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      set_counter++;
    }
    szl = szl->next;
  }
  sort_and_transfer(tmp_read_list, &tmp_index,the_read_list, &read_list_index);
  if (set_counter > 0) {
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#1 small files): " "SETS %" "l" "u" ", BLOCKS %" "l" "u" "\n", set_counter, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  }
  tmp_index = 0;
  block_counter = 0;
  set_counter = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->path_list->list_size <= 512 &&
        szl->size > hash_one_block_size && szl->size <= round1_max_bytes) {
      block_counter +=
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      set_counter++;
    }
    szl = szl->next;
  }
  sort_and_transfer(tmp_read_list, &tmp_index,the_read_list, &read_list_index);
  if (set_counter > 0) {
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#2 medium files): " "SETS %" "l" "u" ", BLOCKS %" "l" "u" "\n", set_counter, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  }
  tmp_index = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->path_list->list_size > 512 &&
        szl->size > hash_one_block_size && szl->size <= round1_max_bytes) {
      tmp_index = 0;
      block_counter =
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      sort_and_transfer(tmp_read_list, &tmp_index,
                        the_read_list, &read_list_index);
      if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#3 large set, size: %" "l" "u" "): " "SETS 1, BLOCKS %" "l" "u" "\n", szl->size, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    }
    szl = szl->next;
  }
  tmp_index = 0;
  block_counter = 0;
  set_counter = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->path_list->list_size <= 8 &&
        szl->size > round1_max_bytes) {
      block_counter +=
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      set_counter++;
    }
    szl = szl->next;
  }
  sort_and_transfer(tmp_read_list, &tmp_index,the_read_list, &read_list_index);
  if (set_counter > 0) {
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#4 large files): " "SETS %" "l" "u" ", BLOCKS %" "l" "u" "\n", set_counter, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  }
  tmp_index = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->path_list->list_size > 8 &&
        szl->size > round1_max_bytes) {
      tmp_index = 0;
      block_counter =
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      sort_and_transfer(tmp_read_list, &tmp_index,
                        the_read_list, &read_list_index);
      if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#5 large set, size: %" "l" "u" "): " "SETS 1, BLOCKS %" "l" "u" "\n", szl->size, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    }
    szl = szl->next;
  }
  free(tmp_read_list);
  tmp_read_list = ((void *)0);
  tmp_index = 0;
  dec_stats_readlist(sizeof(struct read_list_entry) * read_block_counter);
  read_list = the_read_list;
  read_list_end = read_list_index;
  if (using_fiemap) {
    int zeropct = (100 * stats_fiemap_zero_blocks) / stats_fiemap_total_blocks;
    if (zeropct > 5 && s_total_files_seen > 100) {
      using_fiemap = 0;
      if (3 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Turning off using_fiemap, %d%% zero blocks\n", zeropct); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    }
  }
  if (log_level >= 12) {
    printf("read_list after final sort\n");
    dump_read_list(0);
  }
}

canonical_original_code:
void sort_read_list()
{
  if (hardlink_is_unique) {
    qsort(inode_read_list, inode_read_list_end,
          sizeof(struct read_list_entry), rl_compare_i);
    char path[4096];
    unsigned long i;
    unsigned long p_inode = 0;
    for (i = 0; i < inode_read_list_end; i++) {
      if (inode_read_list[i].inode == p_inode) {
        build_path(inode_read_list[i].pathlist_self, path);
        if (8 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Skipping [%s] due to duplicate inode.\n", path); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
        int before = inode_read_list[i].pathlist_head->list_size;
        int after = mark_path_entry_ignore_hardlink(inode_read_list[i].pathlist_head,
                                          inode_read_list[i].pathlist_self);
        s_files_hl_skip += (before - after);
      }
      p_inode = inode_read_list[i].inode;
    }
    free_inode_read_list();
  }
  struct read_list_entry *the_read_list = (struct read_list_entry *)
    malloc(sizeof(struct read_list_entry) * read_block_counter);
  inc_stats_readlist(sizeof(struct read_list_entry) * read_block_counter);
  unsigned long read_list_index = 0;
  struct read_list_entry *tmp_read_list = (struct read_list_entry *)
    malloc(sizeof(struct read_list_entry) * read_block_counter);
  inc_stats_readlist(sizeof(struct read_list_entry) * read_block_counter);
  unsigned long tmp_index = 0;
  unsigned long block_counter = 0;
  unsigned long set_counter = 0;
  struct size_list *szl = ((void *)0);
  tmp_index = 0;
  block_counter = 0;
  set_counter = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->size <= hash_one_block_size) {
      block_counter +=
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      set_counter++;
    }
    szl = szl->next;
  }
  sort_and_transfer(tmp_read_list, &tmp_index,the_read_list, &read_list_index);
  if (set_counter > 0) {
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#1 small files): " "SETS %" "l" "u" ", BLOCKS %" "l" "u" "\n", set_counter, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  }
  tmp_index = 0;
  block_counter = 0;
  set_counter = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->path_list->list_size <= 512 &&
        szl->size > hash_one_block_size && szl->size <= round1_max_bytes) {
      block_counter +=
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      set_counter++;
    }
    szl = szl->next;
  }
  sort_and_transfer(tmp_read_list, &tmp_index,the_read_list, &read_list_index);
  if (set_counter > 0) {
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#2 medium files): " "SETS %" "l" "u" ", BLOCKS %" "l" "u" "\n", set_counter, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  }
  tmp_index = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->path_list->list_size > 512 &&
        szl->size > hash_one_block_size && szl->size <= round1_max_bytes) {
      tmp_index = 0;
      block_counter =
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      sort_and_transfer(tmp_read_list, &tmp_index,
                        the_read_list, &read_list_index);
      if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#3 large set, size: %" "l" "u" "): " "SETS 1, BLOCKS %" "l" "u" "\n", szl->size, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    }
    szl = szl->next;
  }
  tmp_index = 0;
  block_counter = 0;
  set_counter = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->path_list->list_size <= 8 &&
        szl->size > round1_max_bytes) {
      block_counter +=
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      set_counter++;
    }
    szl = szl->next;
  }
  sort_and_transfer(tmp_read_list, &tmp_index,the_read_list, &read_list_index);
  if (set_counter > 0) {
    if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#4 large files): " "SETS %" "l" "u" ", BLOCKS %" "l" "u" "\n", set_counter, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  }
  tmp_index = 0;
  szl = size_list_head;
  while (szl != ((void *)0)) {
    if (szl->path_list->list_size > 8 &&
        szl->size > round1_max_bytes) {
      tmp_index = 0;
      block_counter =
        add_all_blocks_from_group(szl->path_list, tmp_read_list, &tmp_index);
      sort_and_transfer(tmp_read_list, &tmp_index,
                        the_read_list, &read_list_index);
      if (4 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("read_list: (#5 large set, size: %" "l" "u" "): " "SETS 1, BLOCKS %" "l" "u" "\n", szl->size, block_counter); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    }
    szl = szl->next;
  }
  free(tmp_read_list);
  tmp_read_list = ((void *)0);
  tmp_index = 0;
  dec_stats_readlist(sizeof(struct read_list_entry) * read_block_counter);
  read_list = the_read_list;
  read_list_end = read_list_index;
  if (using_fiemap) {
    int zeropct = (100 * stats_fiemap_zero_blocks) / stats_fiemap_total_blocks;
    if (zeropct > 5 && s_total_files_seen > 100) {
      using_fiemap = 0;
      if (3 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("Turning off using_fiemap, %d%% zero blocks\n", zeropct); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    }
  }
  if (log_level >= 12) {
    printf("read_list after final sort\n");
    dump_read_list(0);
  }
}

variable_types:
path
char [4096]

variable_types:
i
unsigned long

variable_types: before int

variable_types: after int

variable_types: struct size_list { struct path_list_head { struct size_list *sizelist; struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } *last_entry; unsigned int wanted_bufsize; unsigned int list_size; unsigned int buffer_ready; unsigned char state; unsigned char hash_passes; unsigned char have_cached_hashes; } *path_list; struct size_list *next; unsigned long size; int fully_read; union pthread_mutex_t { struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; unsigned int __nusers; int __kind; short __spins; short __elision; struct __pthread_internal_list { struct __pthread_internal_list *__prev; struct __pthread_internal_list *__next; } __list; } __data; char __size[40]; long __align; } lock; } *

variable_types: zeropct int


decompiled_code:
__int64 test_hash_table()
{
const char *v1; // rax

if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v1 = (const char *)get_thread_name();
printf("%s", v1);
puts("=== hash table ===");
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
init_path_block();
init_dirtree();
test_hash_table_basics();
free_dirtree();
return free_path_block();
}

canonical_decompiled_code:
__int64 func2()
{
const char *v1; // rax

if ( log_level > 2 )
{
pthread_mutex_lock(&logger_lock);
v1 = (const char *)get_thread_name();
printf("%s", v1);
puts("=== hash table ===");
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
init_path_block();
init_dirtree();
func1();
free_dirtree();
return free_path_block();
}

original_code:
void test_hash_table()
{
  if (3 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("=== hash table ===\n"); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  init_path_block();
  init_dirtree();
  test_hash_table_basics();
  free_dirtree();
  free_path_block();
}


decompiled_code:
__int64 __fastcall dupd_memcmp(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v3; // rax

if ( !a3 )
return 0LL;
v3 = 0LL;
while ( *(_BYTE *)(a1 + v3) == *(_BYTE *)(a2 + v3) )
{
if ( ++v3 == a3 )
return 0LL;
}
return 1LL;
}

canonical_decompiled_code:
__int64 __fastcall func0(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v3; // rax

if ( !a3 )
return 0LL;
v3 = 0LL;
while ( *(_BYTE *)(a1 + v3) == *(_BYTE *)(a2 + v3) )
{
if ( ++v3 == a3 )
return 0LL;
}
return 1LL;
}

original_code:
static inline int dupd_memcmp(const char * b1, const char * b2, size_t n)
{
  while (n) {
    if (*b1++ != *b2++) {
      return 1;
    }
    n--;
  }
  return 0;
}

canonical_original_code:
static inline int dupd_memcmp(char *b1, char *b2, unsigned long n)
{
  while (n) {
    if (*b1++ != *b2++) {
      return 1;
    }
    n--;
  }
  return 0;
}


original_code:
static void reset_hash_list_entry(struct hash_list * hl)
{
  if (hl == ((void *)0)) {
    return;
  }
  hl->hash_valid = 0;
  hl->hash[0] = 0;
  hl->next_index = 0;
}

canonical_original_code:
static void reset_hash_list_entry(struct hash_list *hl)
{
  if (hl == ((void *)0)) {
    return;
  }
  hl->hash_valid = 0;
  hl->hash[0] = 0;
  hl->next_index = 0;
}

variable_types: struct hash_list { int hash_valid; char hash[64]; struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } **entries; int capacity; int next_index; struct hash_list *next; } *

user_defined_types: struct hash_list { int hash_valid; char hash[64]; struct path_list_entry **entries; int capacity; int next_index; struct hash_list *next; }


original_code:
static struct hash_list * new_hash_list_node()
{
  uint32_t bytes = sizeof(struct hash_list);
  struct hash_list * hl = (struct hash_list *)malloc(sizeof(struct hash_list));
  hl->hash_valid = 0;
  hl->hash[0] = 0;
  hl->entries = (struct path_list_entry **)
    malloc(sizeof(struct path_list_entry *) * 4);
  bytes += sizeof(struct path_list_entry *) * 4;
  hl->capacity = 4;
  hl->next_index = 0;
  hl->next = ((void *)0);
  inc_stats_hashtable(bytes);
  return hl;
}

canonical_original_code:
static struct hash_list *new_hash_list_node()
{
  unsigned int bytes = sizeof(struct hash_list);
  struct hash_list *hl = (struct hash_list *)malloc(sizeof(struct hash_list));
  hl->hash_valid = 0;
  hl->hash[0] = 0;
  hl->entries = (struct path_list_entry **)
    malloc(sizeof(struct path_list_entry *) * 4);
  bytes += sizeof(struct path_list_entry *) * 4;
  hl->capacity = 4;
  hl->next_index = 0;
  hl->next = ((void *)0);
  inc_stats_hashtable(bytes);
  return hl;
}

variable_types:
bytes
unsigned int

return_type: struct hash_list { int hash_valid; char hash[64]; struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } **entries; int capacity; int next_index; struct hash_list *next; } *


decompiled_code:
_QWORD *get_path_buffer_info()
{
_QWORD *v0; // rbx

v0 = pthread_getspecific(duplicate_path_buffer);
if ( !v0 )
{
v0 = malloc(0x10uLL);
*(_DWORD *)v0 = 0x4000;
v0[1] = malloc(0x4000uLL);
pthread_setspecific(duplicate_path_buffer, v0);
}
return v0;
}

canonical_decompiled_code:
_QWORD *func3()
{
_QWORD *v0; // rbx

v0 = pthread_getspecific(duplicate_path_buffer);
if ( !v0 )
{
v0 = malloc(0x10uLL);
*(_DWORD *)v0 = 0x4000;
v0[1] = malloc(0x4000uLL);
pthread_setspecific(duplicate_path_buffer, v0);
}
return v0;
}

original_code:
static struct path_buffer_info * get_path_buffer_info()
{
  struct path_buffer_info * pbi = pthread_getspecific(duplicate_path_buffer);
  if (pbi == ((void *)0)) {
    pbi = (struct path_buffer_info *)malloc(sizeof(struct path_buffer_info));
    pbi->size = 4096 * 4;
    pbi->buf = (char *)malloc(pbi->size);
    pthread_setspecific(duplicate_path_buffer, pbi);
  }
  return pbi;
}

canonical_original_code:
static struct path_buffer_info *get_path_buffer_info()
{
  struct path_buffer_info *pbi = pthread_getspecific(duplicate_path_buffer);
  if (pbi == ((void *)0)) {
    pbi = (struct path_buffer_info *)malloc(sizeof(struct path_buffer_info));
    pbi->size = 4096 * 4;
    pbi->buf = (char *)malloc(pbi->size);
    pthread_setspecific(duplicate_path_buffer, pbi);
  }
  return pbi;
}

variable_types: struct path_buffer_info { int size; char *buf; } *


decompiled_code:
__int64 __fastcall print_hash_list_entry(unsigned int a1, unsigned int *a2)
{
unsigned int *v2; // rbp
__int64 result; // rax
const char *v4; // rax
const char *v5; // rax
__int64 v6; // rbx
const char *v7; // rax
char v8[4120]; // [rsp+0h] [rbp-1018h] BYREF

v2 = a2;
result = 0LL;
if ( a2 )
{
while ( 1 )
{
if ( !*v2 )
return result;
if ( (_DWORD)result )
goto LABEL_4;
if ( log_level > 9 )
break;
LABEL_14:
if ( (int)v2[21] > 0 )
{
v6 = 0LL;
do
{
build_path(*(_QWORD *)(*((_QWORD *)v2 + 9) + 8 * v6), v8);
if ( log_level > 9 )
{
pthread_mutex_lock(&logger_lock);
v7 = (const char *)get_thread_name();
printf("%s", v7);
printf(" [%s]\n", v8);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
++v6;
}
while ( (int)v2[21] > (int)v6 );
}
v2 = (unsigned int *)*((_QWORD *)v2 + 11);
result = 1LL;
if ( !v2 )
return result;
}
pthread_mutex_lock(&logger_lock);
v4 = (const char *)get_thread_name();
printf("%s", v4);
printf(" ---[ %d ]\n", a1);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
LABEL_4:
if ( log_level > 9 )
{
pthread_mutex_lock(&logger_lock);
v5 = (const char *)get_thread_name();
printf("%s", v5);
printf("hash_valid: %d, next_index: %d ", *v2, v2[21]);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
if ( log_level > 9 )
memdump("hash", v2 + 1, hash_bufsize);
}
goto LABEL_14;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(unsigned int a1, unsigned int *a2)
{
unsigned int *v2; // rbp
__int64 result; // rax
const char *v4; // rax
const char *v5; // rax
__int64 v6; // rbx
const char *v7; // rax
char v8[4120]; // [rsp+0h] [rbp-1018h] BYREF

v2 = a2;
result = 0LL;
if ( a2 )
{
while ( 1 )
{
if ( !*v2 )
return result;
if ( (_DWORD)result )
goto LABEL_4;
if ( log_level > 9 )
break;
LABEL_14:
if ( (int)v2[21] > 0 )
{
v6 = 0LL;
do
{
build_path(*(_QWORD *)(*((_QWORD *)v2 + 9) + 8 * v6), v8);
if ( log_level > 9 )
{
pthread_mutex_lock(&logger_lock);
v7 = (const char *)get_thread_name();
printf("%s", v7);
printf(" [%s]\n", v8);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
++v6;
}
while ( (int)v2[21] > (int)v6 );
}
v2 = (unsigned int *)*((_QWORD *)v2 + 11);
result = 1LL;
if ( !v2 )
return result;
}
pthread_mutex_lock(&logger_lock);
v4 = (const char *)get_thread_name();
printf("%s", v4);
printf(" ---[ %d ]\n", a1);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
LABEL_4:
if ( log_level > 9 )
{
pthread_mutex_lock(&logger_lock);
v5 = (const char *)get_thread_name();
printf("%s", v5);
printf("hash_valid: %d, next_index: %d ", *v2, v2[21]);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
if ( log_level > 9 )
memdump("hash", v2 + 1, hash_bufsize);
}
goto LABEL_14;
}
return result;
}

original_code:
static void print_hash_list_entry(int n, struct hash_list * src)
{
  char file[4096];
  struct path_list_entry * entry;
  struct hash_list * p = src;
  int header = 0;
  while (p != ((void *)0) && p->hash_valid) {
    if (!header) {
      if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("  ---[ %d ]\n", n); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
      header = 1;
    }
    if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("hash_valid: %d, next_index: %d   ", p->hash_valid, p->next_index); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    if (log_level >= 10) {
      memdump("hash", p->hash, hash_bufsize);
    }
    for (int j=0; j < p->next_index; j++) {
      entry = *(p->entries + j);
      build_path(entry, file);
      if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("  [%s]\n", file); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    }
    p = p->next;
  }
}

canonical_original_code:
static void print_hash_list_entry(int n, struct hash_list *src)
{
  char file[4096];
  struct path_list_entry *entry;
  struct hash_list *p = src;
  int header = 0;
  while (p != ((void *)0) && p->hash_valid) {
    if (!header) {
      if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("  ---[ %d ]\n", n); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
      header = 1;
    }
    if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("hash_valid: %d, next_index: %d   ", p->hash_valid, p->next_index); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    if (log_level >= 10) {
      memdump("hash", p->hash, hash_bufsize);
    }
    for (int j = 0; j < p->next_index; j++) {
      entry = *(p->entries + j);
      build_path(entry, file);
      if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("  [%s]\n", file); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    }
    p = p->next;
  }
}

variable_types: n int

variable_types:
file
char [4096]

variable_types: struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } *

variable_types: header int

variable_types: j int


decompiled_code:
_BYTE *init_hash_table()
{
_BYTE *v0; // rbx
_QWORD *v1; // rax
_QWORD *v2; // rcx
_QWORD *v3; // rdx

v0 = malloc(0x10uLL);
v0[10] = 0;
*((_WORD *)v0 + 4) = 256;
v1 = malloc(0x800uLL);
v2 = v1;
v3 = v1 + 256;
do
*v1++ = 0LL;
while ( v1 != v3 );
*(_QWORD *)v0 = v2;
inc_stats_hashtable(2064LL);
return v0;
}

canonical_decompiled_code:
_BYTE *func7()
{
_BYTE *v0; // rbx
_QWORD *v1; // rax
_QWORD *v2; // rcx
_QWORD *v3; // rdx

v0 = malloc(0x10uLL);
v0[10] = 0;
*((_WORD *)v0 + 4) = 256;
v1 = malloc(0x800uLL);
v2 = v1;
v3 = v1 + 256;
do
*v1++ = 0LL;
while ( v1 != v3 );
*(_QWORD *)v0 = v2;
inc_stats_hashtable(2064LL);
return v0;
}

original_code:
struct hash_table * init_hash_table()
{
  struct hash_table * hl = ((void *)0);
  uint32_t bytes = sizeof(struct hash_table);
  hl = (struct hash_table *)malloc(sizeof(struct hash_table));
  hl->has_dups = 0;
  hl->entries = 256;
  struct hash_list ** hll = malloc(256 * sizeof(struct hash_list *));
  bytes += 256 * sizeof(struct hash_list *);
  for (int n = 0; n <= 255; n++) {
    hll[n] = ((void *)0);
  }
  hl->table = hll;
  inc_stats_hashtable(bytes);
  return hl;
}

canonical_original_code:
struct hash_table *init_hash_table()
{
  struct hash_table *hl = ((void *)0);
  unsigned int bytes = sizeof(struct hash_table);
  hl = (struct hash_table *)malloc(sizeof(struct hash_table));
  hl->has_dups = 0;
  hl->entries = 256;
  struct hash_list **hll = malloc(256 * sizeof(struct hash_list *));
  bytes += 256 * sizeof(struct hash_list *);
  for (int n = 0; n <= 255; n++) {
    hll[n] = ((void *)0);
  }
  hl->table = hll;
  inc_stats_hashtable(bytes);
  return hl;
}

variable_types: struct hash_table { struct hash_list { int hash_valid; char hash[64]; struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } **entries; int capacity; int next_index; struct hash_list *next; } **table; unsigned short entries; unsigned char has_dups; } *

user_defined_types: struct hash_table { struct hash_list **table; unsigned short entries; unsigned char has_dups; }


decompiled_code:
void __fastcall reset_hash_table(__int64 a1)
{
__int64 i; // rbx

if ( a1 )
{
*(_BYTE *)(a1 + 10) = 0;
for ( i = 0LL; i != 2048; i += 8LL )
reset_hash_list_entry(*(_QWORD *)(*(_QWORD *)a1 + i));
}
}

original_code:
void reset_hash_table(struct hash_table * hl)
{
  if (hl == ((void *)0)) {
    return;
  }
  hl->has_dups = 0;
  for (int n = 0; n <= 255; n++) {
    reset_hash_list_entry(hl->table[n]);
  }
}

canonical_original_code:
void reset_hash_table(struct hash_table *hl)
{
  if (hl == ((void *)0)) {
    return;
  }
  hl->has_dups = 0;
  for (int n = 0; n <= 255; n++) {
    reset_hash_list_entry(hl->table[n]);
  }
}


decompiled_code:
__int64 __fastcall free_hash_table(void *ptr)
{
__int64 v1; // r14
int v2; // er12
__int64 i; // rbx
__int64 v4; // rbp
int v5; // er13

v1 = 0LL;
v2 = 0;
do
{
for ( i = *(_QWORD *)(*(_QWORD *)ptr + v1); i; v2 += v5 )
{
v4 = i;
i = *(_QWORD *)(i + 88);
free(*(void **)(v4 + 72));
v5 = 8 * *(_DWORD *)(v4 + 80) + 96;
free((void *)v4);
}
*(_QWORD *)(*(_QWORD *)ptr + v1) = 0LL;
v1 += 8LL;
}
while ( v1 != 2048 );
free(*(void **)ptr);
free(ptr);
return dec_stats_hashtable((unsigned int)(v2 + 2064));
}

original_code:
void free_hash_table(struct hash_table * hl)
{
  struct hash_list * me;
  struct hash_list * p;
  uint32_t bytes = 0;
  for (int n = 0; n <= 255; n++) {
    p = hl->table[n];
    me = p;
    while (p != ((void *)0)) {
      p = p->next;
      free(me->entries);
      bytes += me->capacity * sizeof(struct path_list_entry *);
      free(me);
      bytes += sizeof(struct hash_list);
      me = p;
    }
    hl->table[n] = ((void *)0);
  }
  free(hl->table);
  bytes += 256 * sizeof(struct hash_list *);
  free(hl);
  bytes += sizeof(struct hash_table);
  dec_stats_hashtable(bytes);
}

canonical_original_code:
void free_hash_table(struct hash_table *hl)
{
  struct hash_list *me;
  struct hash_list *p;
  unsigned int bytes = 0;
  for (int n = 0; n <= 255; n++) {
    p = hl->table[n];
    me = p;
    while (p != ((void *)0)) {
      p = p->next;
      free(me->entries);
      bytes += me->capacity * sizeof(struct path_list_entry *);
      free(me);
      bytes += sizeof(struct hash_list);
      me = p;
    }
    hl->table[n] = ((void *)0);
  }
  free(hl->table);
  bytes += 256 * sizeof(struct hash_list *);
  free(hl);
  bytes += sizeof(struct hash_table);
  dec_stats_hashtable(bytes);
}


decompiled_code:
void __fastcall add_hash_table(__int64 a1, __int64 a2, __int64 a3, unsigned int a4, __int64 a5)
{
const char *v8; // rax
char v9[4096]; // [rsp+0h] [rbp-1068h] BYREF
char v10[104]; // [rsp+1000h] [rbp-68h] BYREF

build_path(a2, v9);
if ( (unsigned int)hash_fn(v9, v10, a3, a4, a5) )
{
if ( log_level > 7 )
{
pthread_mutex_lock(&logger_lock);
v8 = (const char *)get_thread_name();
printf("%s", v8);
printf("SKIP [%s]: Unable to compute hash\n", v9);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
else
{
add_to_hash_table(a1, a2, v10);
}
}

canonical_decompiled_code:
void __fastcall func10(__int64 a1, __int64 a2, __int64 a3, unsigned int a4, __int64 a5)
{
const char *v8; // rax
char v9[4096]; // [rsp+0h] [rbp-1068h] BYREF
char v10[104]; // [rsp+1000h] [rbp-68h] BYREF

build_path(a2, v9);
if ( (unsigned int)hash_fn(v9, v10, a3, a4, a5) )
{
if ( log_level > 7 )
{
pthread_mutex_lock(&logger_lock);
v8 = (const char *)get_thread_name();
printf("%s", v8);
printf("SKIP [%s]: Unable to compute hash\n", v9);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
}
else
{
func6(a1, a2, v10);
}
}

original_code:
void add_hash_table(struct hash_table * hl, struct path_list_entry * file,
                    uint64_t blocks, int bsize, uint64_t skip)
{
  char hash_out[64];
  char path[4096];
  build_path(file, path);
  int rv = hash_fn(path, hash_out, blocks, bsize, skip);
  if (rv != 0) {
    if (8 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("SKIP [%s]: Unable to compute hash\n", path); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    return;
  }
  add_to_hash_table(hl, file, hash_out);
}

canonical_original_code:
void add_hash_table(struct hash_table *hl, struct path_list_entry *file, unsigned long blocks, int bsize, unsigned long skip)
{
  char hash_out[64];
  char path[4096];
  build_path(file, path);
  int rv = hash_fn(path, hash_out, blocks, bsize, skip);
  if (rv != 0) {
    if (8 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("SKIP [%s]: Unable to compute hash\n", path); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
    return;
  }
  add_to_hash_table(hl, file, hash_out);
}

variable_types:
file
struct path_list_entry *

variable_types:
blocks
unsigned long

variable_types: bsize int

variable_types:
skip
unsigned long

variable_types: rv int


decompiled_code:
void free_path_buffer()
{
void **v0; // rax
void **v1; // rbx

v0 = (void **)pthread_getspecific(duplicate_path_buffer);
if ( v0 )
{
v1 = v0;
pthread_setspecific(duplicate_path_buffer, 0LL);
free(v1[1]);
free(v1);
}
}

canonical_decompiled_code:
void func12()
{
void **v0; // rax
void **v1; // rbx

v0 = (void **)pthread_getspecific(duplicate_path_buffer);
if ( v0 )
{
v1 = v0;
pthread_setspecific(duplicate_path_buffer, 0LL);
free(v1[1]);
free(v1);
}
}

original_code:
void free_path_buffer()
{
  struct path_buffer_info * pbi = pthread_getspecific(duplicate_path_buffer);
  if (pbi != ((void *)0)) {
    pthread_setspecific(duplicate_path_buffer, ((void *)0));
    free(pbi->buf);
    free(pbi);
  }
}

canonical_original_code:
void free_path_buffer()
{
  struct path_buffer_info *pbi = pthread_getspecific(duplicate_path_buffer);
  if (pbi != ((void *)0)) {
    pthread_setspecific(duplicate_path_buffer, ((void *)0));
    free(pbi->buf);
    free(pbi);
  }
}

user_defined_types: struct path_buffer_info { int size; char *buf; }


decompiled_code:
__int64 __fastcall print_hash_table(unsigned __int8 *a1)
{
__int64 i; // rbx
const char *v2; // rax
__int64 result; // rax
unsigned int *v4; // rsi

if ( log_level > 9 )
{
pthread_mutex_lock(&logger_lock);
v2 = (const char *)get_thread_name();
printf("%s", v2);
printf("=====hash_table at %p, has_dups: %d\n", a1, a1[10]);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
for ( i = 0LL; i != 256; ++i )
{
result = *(_QWORD *)a1;
v4 = *(unsigned int **)(*(_QWORD *)a1 + 8 * i);
if ( v4 )
result = print_hash_list_entry(i, v4);
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func14(unsigned __int8 *a1)
{
__int64 i; // rbx
const char *v2; // rax
__int64 result; // rax
unsigned int *v4; // rsi

if ( log_level > 9 )
{
pthread_mutex_lock(&logger_lock);
v2 = (const char *)get_thread_name();
printf("%s", v2);
printf("=====hash_table at %p, has_dups: %d\n", a1, a1[10]);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
for ( i = 0LL; i != 256; ++i )
{
result = *(_QWORD *)a1;
v4 = *(unsigned int **)(*(_QWORD *)a1 + 8 * i);
if ( v4 )
result = func4(i, v4);
}
return result;
}

original_code:
void print_hash_table(struct hash_table * src)
{
  if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("=====hash_table at %p, has_dups: %d\n", src, src->has_dups); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  for (int n = 0; n < 256; n++) {
    if (src->table[n] != ((void *)0)) {
      print_hash_list_entry(n, src->table[n]);
    }
  }
}

canonical_original_code:
void print_hash_table(struct hash_table *src)
{
  if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("=====hash_table at %p, has_dups: %d\n", src, src->has_dups); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  for (int n = 0; n < 256; n++) {
    if (src->table[n] != ((void *)0)) {
      print_hash_list_entry(n, src->table[n]);
    }
  }
}


decompiled_code:
__int64 __fastcall skim_uniques(__int64 a1, _QWORD *a2)
{
__int64 v3; // rsi
__int64 v4; // r12
unsigned int v5; // er13
__int64 i; // rbx
__int64 v7; // rsi
__int64 v8; // r15
const char *v9; // rax

v3 = *(_QWORD *)(*(_QWORD *)a1 + 16LL);
if ( v3 == debug_size )
dump_path_list("ENTER skim_uniques", v3, a1, 1LL);
v4 = 0LL;
v5 = 0;
do
{
for ( i = *(_QWORD *)(*a2 + v4); i; i = *(_QWORD *)(i + 88) )
{
if ( !*(_DWORD *)i )
break;
v7 = *(_QWORD *)(*(_QWORD *)a1 + 16LL);
if ( v7 == debug_size )
dump_path_list("skim_uniques", v7, a1, 1LL);
if ( *(_DWORD *)(i + 84) == 1 )
{
v8 = **(_QWORD **)(i + 72);
if ( log_level > 9 )
{
pthread_mutex_lock(&logger_lock);
v9 = (const char *)get_thread_name();
printf("%s", v9);
puts("skim_uniques: marking a single entry list unique");
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
mark_path_entry_unique(a1, v8);
++v5;
increase_unique_counter(1LL);
}
}
v4 += 8LL;
}
while ( v4 != 2048 );
return v5;
}

canonical_decompiled_code:
__int64 __fastcall func15(__int64 a1, _QWORD *a2)
{
__int64 v3; // rsi
__int64 v4; // r12
unsigned int v5; // er13
__int64 i; // rbx
__int64 v7; // rsi
__int64 v8; // r15
const char *v9; // rax

v3 = *(_QWORD *)(*(_QWORD *)a1 + 16LL);
if ( v3 == debug_size )
dump_path_list("ENTER skim_uniques", v3, a1, 1LL);
v4 = 0LL;
v5 = 0;
do
{
for ( i = *(_QWORD *)(*a2 + v4); i; i = *(_QWORD *)(i + 88) )
{
if ( !*(_DWORD *)i )
break;
v7 = *(_QWORD *)(*(_QWORD *)a1 + 16LL);
if ( v7 == debug_size )
dump_path_list("skim_uniques", v7, a1, 1LL);
if ( *(_DWORD *)(i + 84) == 1 )
{
v8 = **(_QWORD **)(i + 72);
if ( log_level > 9 )
{
pthread_mutex_lock(&logger_lock);
v9 = (const char *)get_thread_name();
printf("%s", v9);
puts("skim_uniques: marking a single entry list unique");
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
mark_path_entry_unique(a1, v8);
++v5;
increase_unique_counter(1LL);
}
}
v4 += 8LL;
}
while ( v4 != 2048 );
return v5;
}

original_code:
int skim_uniques(struct path_list_head * head, struct hash_table * src)
{
  struct path_list_entry * entry;
  int skimmed = 0;
  struct hash_list * p;
  if (debug_size == head->sizelist->size) {
    dump_path_list("ENTER skim_uniques", head->sizelist->size, head, 1);
  }
  for (int n = 0; n <= 255; n++) {
    if (src->table[n] != ((void *)0)) {
      p = src->table[n];
      while (p != ((void *)0) && p->hash_valid) {
        if (debug_size == head->sizelist->size) {
          dump_path_list("skim_uniques", head->sizelist->size, head, 1);
        }
        if (p->next_index == 1) {
          entry = *(p->entries);
          if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("skim_uniques: marking a single entry list unique\n"); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
          mark_path_entry_unique(head, entry);
          skimmed++;
          increase_unique_counter(1);
        }
        p = p->next;
      }
    }
  }
  return skimmed;
}

canonical_original_code:
int skim_uniques(struct path_list_head *head, struct hash_table *src)
{
  struct path_list_entry *entry;
  int skimmed = 0;
  struct hash_list *p;
  if (debug_size == head->sizelist->size) {
    dump_path_list("ENTER skim_uniques", head->sizelist->size, head, 1);
  }
  for (int n = 0; n <= 255; n++) {
    if (src->table[n] != ((void *)0)) {
      p = src->table[n];
      while (p != ((void *)0) && p->hash_valid) {
        if (debug_size == head->sizelist->size) {
          dump_path_list("skim_uniques", head->sizelist->size, head, 1);
        }
        if (p->next_index == 1) {
          entry = *(p->entries);
          if (10 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("skim_uniques: marking a single entry list unique\n"); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
          mark_path_entry_unique(head, entry);
          skimmed++;
          increase_unique_counter(1);
        }
        p = p->next;
      }
    }
  }
  return skimmed;
}

variable_types: struct path_list_head { struct size_list { struct path_list_head *path_list; struct size_list *next; unsigned long size; int fully_read; union pthread_mutex_t { struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; unsigned int __nusers; int __kind; short __spins; short __elision; struct __pthread_internal_list { struct __pthread_internal_list *__prev; struct __pthread_internal_list *__next; } __list; } __data; char __size[40]; long __align; } lock; } *sizelist; struct path_list_entry { struct path_list_entry *next; struct block_list { unsigned char count; struct block_list_entry { unsigned long start_pos; unsigned long len; unsigned long block; } entry[]; } *blocks; struct direntry { struct direntry *parent; char *name; unsigned short total_size; unsigned char name_size; } *dir; char *buffer; void *hash_ctx; unsigned long file_pos; unsigned long next_read_byte; unsigned int next_buffer_pos; unsigned int bufsize; unsigned int data_in_buffer; int fd; unsigned char state; unsigned char filename_size; unsigned char next_read_block; } *last_entry; unsigned int wanted_bufsize; unsigned int list_size; unsigned int buffer_ready; unsigned char state; unsigned char hash_passes; unsigned char have_cached_hashes; } *

variable_types: struct hash_table { struct hash_list { int hash_valid; char hash[64]; struct path_list_entry **entries; int capacity; int next_index; struct hash_list *next; } **table; unsigned short entries; unsigned char has_dups; } *

variable_types: skimmed int


decompiled_code:
__int64 __fastcall hash_table_has_dups(__int64 a1)
{
return *(unsigned __int8 *)(a1 + 10);
}

canonical_decompiled_code:
__int64 __fastcall func16(__int64 a1)
{
return *(unsigned __int8 *)(a1 + 10);
}

original_code:
inline int hash_table_has_dups(struct hash_table * hl)
{
  return hl->has_dups;
}

canonical_original_code:
inline int hash_table_has_dups(struct hash_table *hl)
{
  return hl->has_dups;
}


decompiled_code:
__time_t get_current_time_millis()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return 1000 * v1.tv_sec + v1.tv_usec / 1000;
}

canonical_decompiled_code:
__time_t func0()
{
struct timeval v1; // [rsp+0h] [rbp-18h] BYREF

gettimeofday(&v1, 0LL);
return 1000 * v1.tv_sec + v1.tv_usec / 1000;
}

original_code:
uint64_t get_current_time_millis()
{
  struct timeval tp;
  gettimeofday(&tp, ((void *)0));
  return (tp.tv_sec * 1000L) + (tp.tv_usec / 1000L);
}

canonical_original_code:
unsigned long get_current_time_millis()
{
  struct timeval tp;
  gettimeofday(&tp, ((void *)0));
  return (tp.tv_sec * 1000L) + (tp.tv_usec / 1000L);
}

variable_types: struct timeval { long tv_sec; long tv_usec; }


decompiled_code:
int __fastcall time_string(char *a1, int a2, __int64 a3)
{
int result; // eax

if ( a2 <= 12 )
{
puts("error: time_string buffer too small");
exit((int)&loc_1);
}
if ( a3 <= 10000 )
result = snprintf(a1, a2, "%8ld ms", a3);
else
result = snprintf(a1, a2, "%9ld s", a3 / 1000);
return result;
}

canonical_decompiled_code:
int __fastcall func1(char *a1, int a2, __int64 a3)
{
int result; // eax

if ( a2 <= 12 )
{
puts("error: time_string buffer too small");
exit((int)&loc_1);
}
if ( a3 <= 10000 )
result = snprintf(a1, a2, "%8ld ms", a3);
else
result = snprintf(a1, a2, "%9ld s", a3 / 1000);
return result;
}

original_code:
void time_string(char * out, int len, long ms)
{
  if (len < 13) {
    printf("error: time_string buffer too small\n");
    exit(1);
  }
  if (ms > 10000) {
    snprintf(out, len, "%9ld s", ms / 1000);
  } else {
    snprintf(out, len, "%8ld ms", ms);
  }
}

canonical_original_code:
void time_string(char *out, int len, long ms)
{
  if (len < 13) {
    printf("error: time_string buffer too small\n");
    exit(1);
  }
  if (ms > 10000) {
    snprintf(out, len, "%9ld s", ms / 1000);
  } else {
    snprintf(out, len, "%8ld ms", ms);
  }
}

variable_types:
out
char *

variable_types: len int

variable_types: ms long


decompiled_code:
__int64 __fastcall slow_down(int a1, int a2)
{
__int64 v2; // rbx
unsigned int v4; // eax
int v5; // edx

v2 = 0LL;
if ( !(rand() % a1) )
{
v4 = get_current_time_millis();
srand(v4);
v5 = rand() % a2 + 1;
v2 = v5;
usleep(1000 * v5);
}
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func2(int a1, int a2)
{
__int64 v2; // rbx
unsigned int v4; // eax
int v5; // edx

v2 = 0LL;
if ( !(rand() % a1) )
{
v4 = func0();
srand(v4);
v5 = rand() % a2 + 1;
v2 = v5;
usleep(1000 * v5);
}
return v2;
}

original_code:
long slow_down(int prob, int max_delay_ms)
{
  if (rand() % prob == 0) {
    srand((int)get_current_time_millis());
    long millis = 1 + (rand() % max_delay_ms);
    usleep(1000 * millis);
    return millis;
  }
  return 0;
}

variable_types: prob int

variable_types: millis long

return_type: long


decompiled_code:
__int64 cpu_cores()
{
return sysconf(84);
}

canonical_decompiled_code:
__int64 func3()
{
return sysconf(84);
}

original_code:
int cpu_cores()
{
  return sysconf(_SC_NPROCESSORS_ONLN);
}


decompiled_code:
__int64 total_ram()
{
__int64 v0; // rbx
__int64 result; // rax

v0 = sysconf(85);
result = v0 * sysconf(30);
if ( !result )
result = 0x100000000LL;
return result;
}

canonical_decompiled_code:
__int64 func4()
{
__int64 v0; // rbx
__int64 result; // rax

v0 = sysconf(85);
result = v0 * sysconf(30);
if ( !result )
result = 0x100000000LL;
return result;
}

original_code:
uint64_t total_ram()
{
  uint64_t ram = (uint64_t)sysconf(_SC_PHYS_PAGES) * (uint64_t)sysconf(_SC_PAGESIZE);
  if (ram == 0) { ram = 4UL * (1024 * 1024 * 1024); }
  return ram;
}

canonical_original_code:
unsigned long total_ram()
{
  unsigned long ram = (uint64_t)sysconf(_SC_PHYS_PAGES) * (uint64_t)sysconf(_SC_PAGESIZE);
  if (ram == 0) { ram = 4UL * (1024 * 1024 * 1024); }
  return ram;
}

variable_types:
ram
unsigned long


memdump

decompiled_code:
int __fastcall memdump(const char *a1, unsigned __int8 *a2, int a3)
{
unsigned __int8 *v3; // rbx
unsigned __int8 *v5; // rbp

v3 = a2;
if ( a1 )
printf("%s: ", a1);
if ( a3 > 0 )
{
v5 = &a2[a3];
do
printf("%02x ", *v3++);
while ( v3 != v5 );
}
return putchar(10);
}

canonical_decompiled_code:
int __fastcall func5(const char *a1, unsigned __int8 *a2, int a3)
{
unsigned __int8 *v3; // rbx
unsigned __int8 *v5; // rbp

v3 = a2;
if ( a1 )
printf("%s: ", a1);
if ( a3 > 0 )
{
v5 = &a2[a3];
do
printf("%02x ", *v3++);
while ( v3 != v5 );
}
return putchar(10);
}

original_code:
void memdump(char * text, char * ptr, int bytes)
{
  int i;
  unsigned char * p = (unsigned char *)ptr;
  if (text != ((void *)0)) {
    printf("%s: ", text);
  }
  for (i=0; i<bytes; i++) {
    printf("%02x ", *p++);
  }
  printf("\n");
}

canonical_original_code:
void memdump(char *text, char *ptr, int bytes)
{
  int i;
  unsigned char *p = (unsigned char *)ptr;
  if (text != ((void *)0)) {
    printf("%s: ", text);
  }
  for (i=0; i<bytes; i++) {
    printf("%02x ", *p++);
  }
  printf("\n");
}

variable_types:
text
char *

variable_types:
ptr
char *

variable_types: bytes int

variable_types: i int

variable_types:
p
unsigned char *


decompiled_code:
const char *get_thread_name()
{
const char *result; // rax

result = (const char *)&unk_D4C;
if ( log_level > 6 )
{
result = (const char *)pthread_getspecific(thread_name);
if ( !result )
result = "*** UNNAMED THREAD ***";
}
return result;
}

canonical_decompiled_code:
const char *func6()
{
const char *result; // rax

result = (const char *)&unk_D4C;
if ( log_level > 6 )
{
result = (const char *)pthread_getspecific(thread_name);
if ( !result )
result = "*** UNNAMED THREAD ***";
}
return result;
}

original_code:
char * get_thread_name()
{
  if (log_level >= 7) {
    char * name = pthread_getspecific(thread_name);
    if (name == ((void *)0)) {
      return "*** UNNAMED THREAD ***";
    } else {
      return name;
    }
  }
  return "";
}

canonical_original_code:
char *get_thread_name()
{
  if (log_level >= 7) {
    char *name = pthread_getspecific(thread_name);
    if (name == ((void *)0)) {
      return "*** UNNAMED THREAD ***";
    } else {
      return name;
    }
  }
  return "";
}

variable_types:
name
char *

return_type: char *


decompiled_code:
__int64 __fastcall get_file_info(const char *a1, struct stat64 *a2)
{
unsigned int v2; // ebp
const char *v4; // rax

if ( !a1 || !*a1 )
{
puts("get_file_info called on null or empty path!");
exit(1);
}
v2 = lstat64(a1, a2);
if ( v2 )
return (unsigned int)-1;
if ( log_level > 12 )
{
pthread_mutex_lock(&logger_lock);
v4 = get_thread_name();
printf("%s", v4);
printf("stat: %s: size: %lu c_time: %lu\n", a1, a2->st_size, a2->st_ctim.tv_sec);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func7(const char *a1, struct stat64 *a2)
{
unsigned int v2; // ebp
const char *v4; // rax

if ( !a1 || !*a1 )
{
puts("get_file_info called on null or empty path!");
exit(1);
}
v2 = lstat64(a1, a2);
if ( v2 )
return (unsigned int)-1;
if ( log_level > 12 )
{
pthread_mutex_lock(&logger_lock);
v4 = func6();
printf("%s", v4);
printf("stat: %s: size: %lu c_time: %lu\n", a1, a2->st_size, a2->st_ctim.tv_sec);
fflush(stdout);
pthread_mutex_unlock(&logger_lock);
}
return v2;
}

original_code:
int get_file_info(const char * path, struct stat * info)
{
  if (path == ((void *)0) || path[0] == 0) {
    printf("get_file_info called on null or empty path!\n");
    exit(1);
  }
  int rv = lstat(path, info);
  if (rv) {
    return -1;
  }
  if (13 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("stat: %s: size: %" "l" "u" " c_time: %" "l" "u" "\n", path, info->st_size, (uint64_t)info->st_ctim.tv_sec); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  return 0;
}

canonical_original_code:
int get_file_info(char *path, struct stat *info)
{
  if (path == ((void *)0) || path[0] == 0) {
    printf("get_file_info called on null or empty path!\n");
    exit(1);
  }
  int rv = lstat(path, info);
  if (rv) {
    return -1;
  }
  if (13 <= log_level) { pthread_mutex_lock(&logger_lock); printf("%s", get_thread_name()); printf("stat: %s: size: %" "l" "u" " c_time: %" "l" "u" "\n", path, info->st_size, (unsigned long)info->st_ctim.tv_sec); fflush(stdout); pthread_mutex_unlock(&logger_lock); };
  return 0;
}

variable_types:
path
char *

variable_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec { long tv_sec; long tv_nsec; } st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; } *

variable_types: rv int

user_defined_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }